Skip to content

Commit

Permalink
feat(app): Updated the request handler to skip other parts of the pip…
Browse files Browse the repository at this point in the history
…eline when the noop authenticator is ran.
  • Loading branch information
robertotting authored and mmellison committed Jul 15, 2024
1 parent bb1d0b5 commit 992d66f
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
19 changes: 19 additions & 0 deletions api/decision_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ func TestDecisionAPI(t *testing.T) {
ts := httptest.NewServer(n)
defer ts.Close()

ruleNoOpAuthenticatorWithMutator := rule.Rule{
Match: &rule.Match{Methods: []string{"GET"}, URL: ts.URL + "/authn-noop-mutator/<[0-9]+>"},
Authenticators: []rule.Handler{{Handler: "noop"}},
Authorizer: rule.Handler{Handler: "allow"},
Mutators: []rule.Handler{{Handler: "id_token"}},
Upstream: rule.Upstream{URL: ""},
}

ruleNoOpAuthenticator := rule.Rule{
Match: &rule.Match{Methods: []string{"GET"}, URL: ts.URL + "/authn-noop/<[0-9]+>"},
Authenticators: []rule.Handler{{Handler: "noop"}},
Expand Down Expand Up @@ -105,6 +113,17 @@ func TestDecisionAPI(t *testing.T) {
rulesGlob: []rule.Rule{ruleNoOpAuthenticatorGLOB, ruleNoOpAuthenticatorGLOB},
code: http.StatusInternalServerError,
},
{
d: "should pass and skip mutator with noop authenticator",
url: ts.URL + "/decisions" + "/authn-noop-mutator/1234",
rulesRegexp: []rule.Rule{ruleNoOpAuthenticatorWithMutator},
rulesGlob: []rule.Rule{ruleNoOpAuthenticatorWithMutator},
code: http.StatusOK,
transform: func(r *http.Request) {
r.Header.Add("Authorization", "basic user:pass")
},
authz: "basic user:pass",
},
{
d: "should pass",
url: ts.URL + "/decisions" + "/authn-noop/1234",
Expand Down
13 changes: 13 additions & 0 deletions proxy/request_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ func (d *requestHandler) HandleRequest(r *http.Request, rl *rule.Rule) (session
return nil, err
}

useNoopAuthenticator := false
for _, a := range rl.Authenticators {
anh, err := d.r.PipelineAuthenticator(a.Handler)
if err != nil {
Expand Down Expand Up @@ -225,6 +226,10 @@ func (d *requestHandler) HandleRequest(r *http.Request, rl *rule.Rule) (session
return nil, err
}
} else {
// If we hit the no-op authenticator then make a note of it
if anh.GetID() == "noop" {
useNoopAuthenticator = true
}
// The first authenticator that matches must return the session
found = true
fields["subject"] = session.Subject
Expand All @@ -242,6 +247,14 @@ func (d *requestHandler) HandleRequest(r *http.Request, rl *rule.Rule) (session
return nil, err
}

if useNoopAuthenticator {
// This is essentially what the noop mutator does so if we choose to
// use noop authentication and skip other parts of the pipeline then
// we need to set the session from the request headers
session.Header = r.Header
return session, nil
}

azh, err := d.r.PipelineAuthorizer(rl.Authorizer.Handler)
if err != nil {
d.r.Logger().WithError(err).
Expand Down
54 changes: 54 additions & 0 deletions proxy/request_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ func newTestRequest(u string) *http.Request {
return &http.Request{URL: x.ParseURLOrPanic(u), Method: "GET", Header: TestHeader}
}

func newTestRequestWithBasicAuth(u string) *http.Request {
headers := TestHeader.Clone()
headers.Add("Authorization", "Basic dXNlcm5hbWU6c2VjcmV0Cg==")
return &http.Request{URL: x.ParseURLOrPanic(u), Method: "GET", Header: headers}
}

func TestHandleError(t *testing.T) {
for k, tc := range []struct {
d string
Expand Down Expand Up @@ -443,6 +449,54 @@ func TestRequestHandler(t *testing.T) {
}
}

func TestRequestHandlerWithNoopAuthorizer(t *testing.T) {
for k, tc := range []struct {
d string
setup func()
rule rule.Rule
r *http.Request
expectErr bool
}{
{
d: "should skip other authorizers / mutators when noop is enabled",
setup: func() {
viper.Set(configuration.ViperKeyAuthenticatorNoopIsEnabled, true)
viper.Set(configuration.ViperKeyAuthorizerAllowIsEnabled, false)
viper.Set(configuration.ViperKeyMutatorNoopIsEnabled, false)
},
// TODO: Test for Basic Auth header to come through...
r: newTestRequestWithBasicAuth("http://localhost"),
rule: rule.Rule{
Authenticators: []rule.Handler{{Handler: "noop"}},
Authorizer: rule.Handler{Handler: "allow"},
Mutators: []rule.Handler{{Handler: "invalid-id"}},
},
},
// TODO: Could we create a test that asserts if a given handler was NOT evaluated
// not sure based on the current setup...
} {
t.Run(fmt.Sprintf("case=%d/description=%s", k, tc.d), func(t *testing.T) {

conf := internal.NewConfigurationWithDefaults()
reg := internal.NewRegistry(conf)

if tc.setup != nil {
tc.setup()
}

session, err := reg.ProxyRequestHandler().HandleRequest(tc.r, &tc.rule)
t.Logf("Found the session: %+v", session)
user, pass, ok := tc.r.BasicAuth()
t.Logf("Request headers: %+v, %s:%s %v", tc.r.Header, user, pass, ok)
if tc.expectErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}

func TestInitializeSession(t *testing.T) {
for k, tc := range []struct {
d string
Expand Down

0 comments on commit 992d66f

Please sign in to comment.