Skip to content

Commit

Permalink
Functionalize X-Pel-NS header and add header gen tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jhiemstrawisc committed Jul 17, 2024
1 parent d09291e commit 8d3be5c
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 7 deletions.
18 changes: 11 additions & 7 deletions director/director.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,14 @@ func generateXTokenGenHeader(ginCtx *gin.Context, namespaceAd server_structs.Nam
}
}

func generateXNamespaceHeader(ginCtx *gin.Context, namespaceAd server_structs.NamespaceAdV2, collUrl string) {
xPelicanNamespace := fmt.Sprintf("namespace=%s, require-token=%v", namespaceAd.Path, !namespaceAd.Caps.PublicReads)
if collUrl != "" {
xPelicanNamespace += fmt.Sprintf(", collections-url=%s", collUrl)
}
ginCtx.Writer.Header()["X-Pelican-Namespace"] = []string{xPelicanNamespace}
}

func getFinalRedirectURL(rurl url.URL, requstParams url.Values) string {
rQuery := rurl.Query()
for key, vals := range requstParams {
Expand Down Expand Up @@ -471,11 +479,8 @@ func redirectToCache(ginCtx *gin.Context) {
colUrl = originAdsWObject[0].URL.String()
}
}
xPelicanNamespace := fmt.Sprintf("namespace=%s, require-token=%v", namespaceAd.Path, !namespaceAd.Caps.PublicReads)
if colUrl != "" {
xPelicanNamespace += fmt.Sprintf(", collections-url=%s", colUrl)
}
ginCtx.Writer.Header()["X-Pelican-Namespace"] = []string{xPelicanNamespace}
generateXNamespaceHeader(ginCtx, namespaceAd, colUrl)

// Note we only append the `authz` query parameter in the case of the redirect response and not the
// duplicate link metadata above. This is purposeful: the Link header might get too long if we repeat
// the token 20 times for 20 caches. This means a "normal HTTP client" will correctly redirect but
Expand Down Expand Up @@ -644,8 +649,7 @@ func redirectToOrigin(ginCtx *gin.Context) {
colUrl = availableOriginAds[0].URL.String()
}
}
ginCtx.Writer.Header()["X-Pelican-Namespace"] = []string{fmt.Sprintf("namespace=%s, require-token=%v, collections-url=%s",
namespaceAd.Path, !namespaceAd.Caps.PublicReads, colUrl)}
generateXNamespaceHeader(ginCtx, namespaceAd, colUrl)

var redirectURL url.URL

Expand Down
96 changes: 96 additions & 0 deletions director/director_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1311,6 +1311,102 @@ func TestRedirects(t *testing.T) {
assert.NotEmpty(t, c.Writer.Header().Get("X-Pelican-Namespace"))
})
}
func TestHeaderGenFuncs(t *testing.T) {
issUrl := url.URL{
Scheme: "https",
Host: "my-issuer.com",
}
tGen := server_structs.TokenGen{
Strategy: server_structs.OAuthStrategy,
MaxScopeDepth: 3,
CredentialIssuer: issUrl,
}

tIss := server_structs.TokenIssuer{
BasePaths: []string{"/my/server"},
IssuerUrl: issUrl,
}
authedNamespaceAd := server_structs.NamespaceAdV2{
Caps: server_structs.Capabilities{
PublicReads: false,
Reads: true,
},
Generation: []server_structs.TokenGen{tGen},
Issuer: []server_structs.TokenIssuer{tIss},
Path: "/my/server",
}

publicNamespaceAd := server_structs.NamespaceAdV2{
Caps: server_structs.Capabilities{
PublicReads: true,
},
Path: "/different/server",
}

authReq, _ := http.NewRequest("GET", "/my/server", nil)
authReq.Header.Add("User-Agent", "pelican-v7.999.999")
authReq.Header.Add("X-Real-Ip", "128.104.153.60")

pubReq, _ := http.NewRequest("GET", "/different/server", nil)
pubReq.Header.Add("User-Agent", "pelican-v7.999.999")
pubReq.Header.Add("X-Real-Ip", "128.104.153.60")

// recorder := httptest.NewRecorder()
t.Run("test-x-pel-auth", func(t *testing.T) {
authedRecorder := httptest.NewRecorder()
cAuth, _ := gin.CreateTestContext(authedRecorder)
cAuth.Request = authReq
generateXAuthHeader(cAuth, authedNamespaceAd)
assert.NotEmpty(t, cAuth.Writer.Header().Get("X-Pelican-Authorization"))
assert.Contains(t, cAuth.Writer.Header().Get("X-Pelican-Authorization"), "issuer=https://my-issuer.com")

pubRecorder := httptest.NewRecorder()
cPub, _ := gin.CreateTestContext(pubRecorder)
cPub.Request = pubReq
generateXAuthHeader(cPub, publicNamespaceAd)
assert.Empty(t, cPub.Writer.Header().Get("X-Pelican-Authorization"))
})

t.Run("test-x-pel-tok-gen", func(t *testing.T) {
authedRecorder := httptest.NewRecorder()
cAuth, _ := gin.CreateTestContext(authedRecorder)
cAuth.Request = authReq

generateXTokenGenHeader(cAuth, authedNamespaceAd)
assert.NotEmpty(t, cAuth.Writer.Header().Get("X-Pelican-Token-Generation"))
assert.Contains(t, cAuth.Writer.Header().Get("X-Pelican-Token-Generation"), "issuer=https://my-issuer.com")
assert.Contains(t, cAuth.Writer.Header().Get("X-Pelican-Token-Generation"), "strategy=OAuth2")
assert.Contains(t, cAuth.Writer.Header().Get("X-Pelican-Token-Generation"), "max-scope-depth=3")

pubRecorder := httptest.NewRecorder()
cPub, _ := gin.CreateTestContext(pubRecorder)
cPub.Request = pubReq
generateXTokenGenHeader(cPub, publicNamespaceAd)
assert.Empty(t, cPub.Writer.Header().Get("X-Pelican-Token-Generation"))
})

t.Run("test-x-pel-namespace", func(t *testing.T) {
authedRecorder := httptest.NewRecorder()
cAuth, _ := gin.CreateTestContext(authedRecorder)
cAuth.Request = authReq

collUrl := "https://my-origin.com"
generateXNamespaceHeader(cAuth, authedNamespaceAd, collUrl)
assert.NotEmpty(t, cAuth.Writer.Header().Get("X-Pelican-Namespace"))
assert.Contains(t, cAuth.Writer.Header().Get("X-Pelican-Namespace"), "namespace=/my/server")
assert.Contains(t, cAuth.Writer.Header().Get("X-Pelican-Namespace"), "require-token=true")
assert.Contains(t, cAuth.Writer.Header().Get("X-Pelican-Namespace"), "collections-url=https://my-origin.com")

pubRecorder := httptest.NewRecorder()
cPub, _ := gin.CreateTestContext(pubRecorder)
cPub.Request = pubReq
generateXNamespaceHeader(cPub, publicNamespaceAd, "")
assert.NotEmpty(t, cPub.Writer.Header().Get("X-Pelican-Namespace"))
assert.Contains(t, cPub.Writer.Header().Get("X-Pelican-Namespace"), "namespace=/different/server")
assert.Contains(t, cPub.Writer.Header().Get("X-Pelican-Namespace"), "require-token=false")
assert.NotContains(t, cPub.Writer.Header().Get("X-Pelican-Namespace"), "collections-url")
})
}

func TestGetHealthTestFile(t *testing.T) {
router := gin.Default()
Expand Down

0 comments on commit 8d3be5c

Please sign in to comment.