Skip to content

Commit

Permalink
Add prefix support
Browse files Browse the repository at this point in the history
Signed-off-by: Kevin Fox <Kevin.Fox@pnnl.gov>
  • Loading branch information
kfox1111 committed Dec 15, 2024
1 parent f35e79b commit 6f5e7e9
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 16 deletions.
5 changes: 5 additions & 0 deletions support/oidc-discovery-provider/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ type Config struct {
// AdvertisedURL specifies the absolute urls to return in documents. Use this if you are fronting the
// discovery provider with a load balancer or reverse proxy
AdvertisedURL string `hcl:"advertised_url"`

// Prefix specifies the prefix to strip from requests to route to the server.
// Example: if Prefix is /foo then a request to http://127.0.0.1/foo/.well-known/openid-configuration and
// http://127.0.0.1/foo/keys will function with the server.
Prefix string `hcl:"prefix"`
}

type ServingCertFileConfig struct {
Expand Down
22 changes: 18 additions & 4 deletions support/oidc-discovery-provider/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ type Handler struct {
log logrus.FieldLogger
jwtIssuer string
advertisedURL string
prefix string

http.Handler
}

func NewHandler(log logrus.FieldLogger, domainPolicy DomainPolicy, source JWKSSource, allowInsecureScheme bool, setKeyUse bool, jwtIssuer string, advertisedURL string) *Handler {
func NewHandler(log logrus.FieldLogger, domainPolicy DomainPolicy, source JWKSSource, allowInsecureScheme bool, setKeyUse bool, jwtIssuer string, advertisedURL string, prefix string) *Handler {
h := &Handler{
domainPolicy: domainPolicy,
source: source,
Expand All @@ -39,11 +40,24 @@ func NewHandler(log logrus.FieldLogger, domainPolicy DomainPolicy, source JWKSSo
log: log,
jwtIssuer: jwtIssuer,
advertisedURL: advertisedURL,
prefix: prefix,
}

if prefix == "" {
prefix = "/"
}
mux := http.NewServeMux()
mux.Handle("/.well-known/openid-configuration", handlers.ProxyHeaders(http.HandlerFunc(h.serveWellKnown)))
mux.Handle("/keys", http.HandlerFunc(h.serveKeys))
wkPath, err := url.JoinPath(prefix, "/.well-known/openid-configuration")
if err != nil {
return nil
}
jwksPath, err := url.JoinPath(prefix, "/keys")
if err != nil {
return nil
}

mux.Handle(wkPath, handlers.ProxyHeaders(http.HandlerFunc(h.serveWellKnown)))
mux.Handle(jwksPath, http.HandlerFunc(h.serveKeys))

h.Handler = mux
return h
Expand Down Expand Up @@ -73,7 +87,7 @@ func (h *Handler) serveWellKnown(w http.ResponseWriter, r *http.Request) {
}
if h.advertisedURL != "" {
tmpURL, _ := url.Parse(h.advertisedURL)
keysPath, err := url.JoinPath(tmpURL.Path, "/keys")
keysPath, err := url.JoinPath(tmpURL.Path, h.prefix, "keys")
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
Expand Down
142 changes: 131 additions & 11 deletions support/oidc-discovery-provider/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func TestHandlerHTTPS(t *testing.T) {
require.NoError(t, err)
w := httptest.NewRecorder()

h := NewHandler(log, domainAllowlist(t, "localhost", "domain.test"), source, false, testCase.setKeyUse, "", "")
h := NewHandler(log, domainAllowlist(t, "localhost", "domain.test"), source, false, testCase.setKeyUse, "", "", "")
h.ServeHTTP(w, r)

t.Logf("HEADERS: %q", w.Header())
Expand Down Expand Up @@ -286,7 +286,7 @@ func TestHandlerHTTPInsecure(t *testing.T) {
require.NoError(t, err)
w := httptest.NewRecorder()

h := NewHandler(log, domainAllowlist(t, "localhost", "domain.test"), source, true, false, "", "")
h := NewHandler(log, domainAllowlist(t, "localhost", "domain.test"), source, true, false, "", "", "")
h.ServeHTTP(w, r)

t.Logf("HEADERS: %q", w.Header())
Expand Down Expand Up @@ -456,7 +456,7 @@ func TestHandlerHTTP(t *testing.T) {
require.NoError(t, err)
w := httptest.NewRecorder()

h := NewHandler(log, domainAllowlist(t, "domain.test", "xn--n38h.test"), source, false, false, "", "")
h := NewHandler(log, domainAllowlist(t, "domain.test", "xn--n38h.test"), source, false, false, "", "", "")
h.ServeHTTP(w, r)

t.Logf("HEADERS: %q", w.Header())
Expand Down Expand Up @@ -568,7 +568,7 @@ func TestHandlerProxied(t *testing.T) {
r.Header.Add("X-Forwarded-Scheme", "https")
r.Header.Add("X-Forwarded-Host", "domain.test")
w := httptest.NewRecorder()
h := NewHandler(log, domainAllowlist(t, "domain.test"), source, false, false, "", "")
h := NewHandler(log, domainAllowlist(t, "domain.test"), source, false, false, "", "", "")
h.ServeHTTP(w, r)
t.Logf("HEADERS: %q", w.Header())
assert.Equal(t, testCase.code, w.Code)
Expand Down Expand Up @@ -708,7 +708,7 @@ func TestHandlerJWTIssuer(t *testing.T) {
r.Header.Add("X-Forwarded-Host", "domain.test")
w := httptest.NewRecorder()

h := NewHandler(log, domainAllowlist(t, "domain.test"), source, false, false, testCase.jwtIssuer, "")
h := NewHandler(log, domainAllowlist(t, "domain.test"), source, false, false, testCase.jwtIssuer, "", "")
h.ServeHTTP(w, r)

t.Logf("HEADERS: %q", w.Header())
Expand All @@ -732,7 +732,7 @@ func TestHandlerAdvertisedURL(t *testing.T) {
body string
}{
{
name: "GET well-known HTTPS JWT Issuer",
name: "GET well-known advertised url with path, without trailing forward-slash and https",
advertisedURL: "https://domain.test/some/issuer/path/issuer1",
method: "GET",
path: "/.well-known/openid-configuration",
Expand All @@ -753,7 +753,7 @@ func TestHandlerAdvertisedURL(t *testing.T) {
}`,
},
{
name: "GET well-known HTTP JWT Issuer",
name: "GET well-known advertised url with path and without trailing forward-slash",
advertisedURL: "http://domain.test/some/issuer/path/issuer1",
method: "GET",
path: "/.well-known/openid-configuration",
Expand All @@ -774,7 +774,7 @@ func TestHandlerAdvertisedURL(t *testing.T) {
}`,
},
{
name: "GET well-known JWT Issuer with trailing forward-slash",
name: "GET well-known advertised url with path and trailing forward-slash",
advertisedURL: "http://domain.test/some/issuer/path/issuer1/",
method: "GET",
path: "/.well-known/openid-configuration",
Expand All @@ -795,7 +795,7 @@ func TestHandlerAdvertisedURL(t *testing.T) {
}`,
},
{
name: "GET well-known JWT Issuer without a path with trailing forward-slash",
name: "GET well-known advertised url with trailing forward-slash",
advertisedURL: "http://domain.test/",
method: "GET",
path: "/.well-known/openid-configuration",
Expand All @@ -816,7 +816,7 @@ func TestHandlerAdvertisedURL(t *testing.T) {
}`,
},
{
name: "GET well-known JWT Issuer without a path",
name: "GET well-known advertised url without a path",
advertisedURL: "http://domain.test",
method: "GET",
path: "/.well-known/openid-configuration",
Expand Down Expand Up @@ -849,7 +849,127 @@ func TestHandlerAdvertisedURL(t *testing.T) {
r.Header.Add("X-Forwarded-Host", "domain.test")
w := httptest.NewRecorder()

h := NewHandler(log, domainAllowlist(t, "domain.test"), source, false, false, "", testCase.advertisedURL)
h := NewHandler(log, domainAllowlist(t, "domain.test"), source, false, false, "", testCase.advertisedURL, "")
h.ServeHTTP(w, r)

t.Logf("HEADERS: %q", w.Header())
assert.Equal(t, testCase.code, w.Code)
assert.Equal(t, testCase.body, w.Body.String())
})
}
}
func TestHandlerPrefix(t *testing.T) {
log, _ := test.NewNullLogger()
log.Level = logrus.DebugLevel
testCases := []struct {
name string
prefix string
method string
path string
jwks *jose.JSONWebKeySet
modTime time.Time
pollTime time.Time
code int
body string
}{
{
name: "GET well-known No Prefix",
prefix: "",
method: "GET",
path: "/.well-known/openid-configuration",
code: http.StatusOK,
body: `{
"issuer": "https://domain.test",
"jwks_uri": "https://domain.test/keys",
"authorization_endpoint": "",
"response_types_supported": [
"id_token"
],
"subject_types_supported": [],
"id_token_signing_alg_values_supported": [
"RS256",
"ES256",
"ES384"
]
}`,
},
{
name: "GET well-known Prefix /",
prefix: "/",
method: "GET",
path: "/.well-known/openid-configuration",
code: http.StatusOK,
body: `{
"issuer": "https://domain.test",
"jwks_uri": "https://domain.test/keys",
"authorization_endpoint": "",
"response_types_supported": [
"id_token"
],
"subject_types_supported": [],
"id_token_signing_alg_values_supported": [
"RS256",
"ES256",
"ES384"
]
}`,
},
{
name: "GET well-known Prefix without slash",
prefix: "/some/issuer/path/issuer1",
method: "GET",
path: "/some/issuer/path/issuer1/.well-known/openid-configuration",
code: http.StatusOK,
body: `{
"issuer": "https://domain.test",
"jwks_uri": "https://domain.test/keys",
"authorization_endpoint": "",
"response_types_supported": [
"id_token"
],
"subject_types_supported": [],
"id_token_signing_alg_values_supported": [
"RS256",
"ES256",
"ES384"
]
}`,
},
{
name: "GET well-known Prefix wtih trailing forward-slash",

Check failure on line 939 in support/oidc-discovery-provider/handler_test.go

View workflow job for this annotation

GitHub Actions / lint (linux)

`wtih` is a misspelling of `with` (misspell)

Check failure on line 939 in support/oidc-discovery-provider/handler_test.go

View workflow job for this annotation

GitHub Actions / lint (windows)

`wtih` is a misspelling of `with` (misspell)
prefix: "/some/issuer/path/issuer1/",
method: "GET",
path: "/some/issuer/path/issuer1/.well-known/openid-configuration",
code: http.StatusOK,
body: `{
"issuer": "https://domain.test",
"jwks_uri": "https://domain.test/keys",
"authorization_endpoint": "",
"response_types_supported": [
"id_token"
],
"subject_types_supported": [],
"id_token_signing_alg_values_supported": [
"RS256",
"ES256",
"ES384"
]
}`,
},
}
for _, testCase := range testCases {
testCase := testCase
t.Run(testCase.name, func(t *testing.T) {
source := new(FakeKeySetSource)
source.SetKeySet(testCase.jwks, testCase.modTime, testCase.pollTime)

r, err := http.NewRequest(testCase.method, "http://localhost"+testCase.path, nil)
require.NoError(t, err)
r.Header.Add("X-Forwarded-Scheme", "https")
r.Header.Add("X-Forwarded-Host", "domain.test")
w := httptest.NewRecorder()

h := NewHandler(log, domainAllowlist(t, "domain.test"), source, false, false, "", "", testCase.prefix)
h.ServeHTTP(w, r)

t.Logf("HEADERS: %q", w.Header())
Expand Down
2 changes: 1 addition & 1 deletion support/oidc-discovery-provider/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func run(configPath string) error {
return err
}

var handler http.Handler = NewHandler(log, domainPolicy, source, config.AllowInsecureScheme, config.SetKeyUse, config.JWTIssuer, config.AdvertisedURL)
var handler http.Handler = NewHandler(log, domainPolicy, source, config.AllowInsecureScheme, config.SetKeyUse, config.JWTIssuer, config.AdvertisedURL, config.Prefix)
if config.LogRequests {
log.Info("Logging all requests")
handler = logHandler(log, handler)
Expand Down

0 comments on commit 6f5e7e9

Please sign in to comment.