Skip to content

Commit b1dfd24

Browse files
authored
Merge pull request kubernetes#82208 from yutedz/filter-audience
Verify the response audience matches one of apiAuds
2 parents 8126201 + d66d047 commit b1dfd24

File tree

2 files changed

+86
-6
lines changed

2 files changed

+86
-6
lines changed

staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,11 @@ func WithAuthentication(handler http.Handler, auth authenticator.Request, failed
9696
return
9797
}
9898

99-
// TODO(mikedanese): verify the response audience matches one of apiAuds if
100-
// non-empty
99+
if len(apiAuds) > 0 && len(resp.Audiences) > 0 && len(authenticator.Audiences(apiAuds).Intersect(resp.Audiences)) == 0 {
100+
klog.Errorf("Unable to match the audience: %v , accepted: %v", resp.Audiences, apiAuds)
101+
failed.ServeHTTP(w, req)
102+
return
103+
}
101104

102105
// authorization header is not required anymore in case of a successful authentication.
103106
req.Header.Del("Authorization")

staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication_test.go

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,92 @@ package filters
1818

1919
import (
2020
"errors"
21-
"net/http"
22-
"net/http/httptest"
23-
"testing"
24-
21+
"github.com/stretchr/testify/assert"
2522
"k8s.io/apiserver/pkg/authentication/authenticator"
2623
"k8s.io/apiserver/pkg/authentication/user"
2724
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
25+
"net/http"
26+
"net/http/httptest"
27+
"testing"
2828
)
2929

30+
func TestAuthenticateRequestWithAud(t *testing.T) {
31+
success, failed := 0, 0
32+
testcases := []struct {
33+
name string
34+
apiAuds []string
35+
respAuds []string
36+
expectSuccess bool
37+
}{
38+
{
39+
name: "no api audience and no audience in response",
40+
apiAuds: nil,
41+
respAuds: nil,
42+
expectSuccess: true,
43+
},
44+
{
45+
name: "audience in response",
46+
apiAuds: nil,
47+
respAuds: []string{"other"},
48+
expectSuccess: true,
49+
},
50+
{
51+
name: "with api audience",
52+
apiAuds: authenticator.Audiences([]string{"other"}),
53+
respAuds: nil,
54+
expectSuccess: true,
55+
},
56+
{
57+
name: "api audience matching response audience",
58+
apiAuds: authenticator.Audiences([]string{"other"}),
59+
respAuds: []string{"other"},
60+
expectSuccess: true,
61+
},
62+
{
63+
name: "api audience non-matching response audience",
64+
apiAuds: authenticator.Audiences([]string{"other"}),
65+
respAuds: []string{"some"},
66+
expectSuccess: false,
67+
},
68+
}
69+
for _, tc := range testcases {
70+
t.Run(tc.name, func(t *testing.T) {
71+
success, failed = 0, 0
72+
auth := WithAuthentication(
73+
http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) {
74+
if tc.expectSuccess {
75+
success = 1
76+
} else {
77+
t.Errorf("unexpected call to handler")
78+
}
79+
}),
80+
authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) {
81+
if req.Header.Get("Authorization") == "Something" {
82+
return &authenticator.Response{User: &user.DefaultInfo{Name: "user"}, Audiences: authenticator.Audiences(tc.respAuds)}, true, nil
83+
}
84+
return nil, false, errors.New("Authorization header is missing.")
85+
}),
86+
http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {
87+
if tc.expectSuccess {
88+
t.Errorf("unexpected call to failed")
89+
} else {
90+
failed = 1
91+
}
92+
}),
93+
tc.apiAuds,
94+
)
95+
auth.ServeHTTP(httptest.NewRecorder(), &http.Request{Header: map[string][]string{"Authorization": {"Something"}}})
96+
if tc.expectSuccess {
97+
assert.Equal(t, 1, success)
98+
assert.Equal(t, 0, failed)
99+
} else {
100+
assert.Equal(t, 0, success)
101+
assert.Equal(t, 1, failed)
102+
}
103+
})
104+
}
105+
}
106+
30107
func TestAuthenticateRequest(t *testing.T) {
31108
success := make(chan struct{})
32109
auth := WithAuthentication(

0 commit comments

Comments
 (0)