k8s.io/apiserver@v0.31.1/pkg/endpoints/filters/authn_audit_test.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package filters 18 19 import ( 20 "crypto/tls" 21 "crypto/x509" 22 "net/http" 23 "net/http/httptest" 24 "strings" 25 "testing" 26 27 auditinternal "k8s.io/apiserver/pkg/apis/audit" 28 "k8s.io/apiserver/pkg/audit/policy" 29 ) 30 31 func TestFailedAuthnAudit(t *testing.T) { 32 sink := &fakeAuditSink{} 33 fakeRuleEvaluator := policy.NewFakePolicyRuleEvaluator(auditinternal.LevelRequestResponse, nil) 34 handler := WithFailedAuthenticationAudit( 35 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 36 http.Error(w, "", http.StatusUnauthorized) 37 }), 38 sink, fakeRuleEvaluator) 39 req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) 40 req.RemoteAddr = "127.0.0.1" 41 req = withTestContext(req, nil, nil) 42 req.SetBasicAuth("username", "password") 43 handler.ServeHTTP(httptest.NewRecorder(), req) 44 45 if len(sink.events) != 1 { 46 t.Fatalf("Unexpected number of audit events generated, expected 1, got: %d", len(sink.events)) 47 } 48 ev := sink.events[0] 49 if ev.ResponseStatus.Code != http.StatusUnauthorized { 50 t.Errorf("Unexpected response code, expected unauthorized, got %d", ev.ResponseStatus.Code) 51 } 52 if !strings.Contains(ev.ResponseStatus.Message, "basic") { 53 t.Errorf("Expected response status message to contain basic auth method, got %s", ev.ResponseStatus.Message) 54 } 55 if ev.Verb != "list" { 56 t.Errorf("Unexpected verb, expected list, got %s", ev.Verb) 57 } 58 if ev.RequestURI != "/api/v1/namespaces/default/pods" { 59 t.Errorf("Unexpected user, expected /api/v1/namespaces/default/pods, got %s", ev.RequestURI) 60 } 61 } 62 63 func TestFailedMultipleAuthnAudit(t *testing.T) { 64 sink := &fakeAuditSink{} 65 fakeRuleEvaluator := policy.NewFakePolicyRuleEvaluator(auditinternal.LevelRequestResponse, nil) 66 handler := WithFailedAuthenticationAudit( 67 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 68 http.Error(w, "", http.StatusUnauthorized) 69 }), 70 sink, fakeRuleEvaluator) 71 req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) 72 req.RemoteAddr = "127.0.0.1" 73 req = withTestContext(req, nil, nil) 74 req.SetBasicAuth("username", "password") 75 req.TLS = &tls.ConnectionState{PeerCertificates: []*x509.Certificate{{}}} 76 handler.ServeHTTP(httptest.NewRecorder(), req) 77 78 if len(sink.events) != 1 { 79 t.Fatalf("Unexpected number of audit events generated, expected 1, got: %d", len(sink.events)) 80 } 81 ev := sink.events[0] 82 if ev.ResponseStatus.Code != http.StatusUnauthorized { 83 t.Errorf("Unexpected response code, expected unauthorized, got %d", ev.ResponseStatus.Code) 84 } 85 if !strings.Contains(ev.ResponseStatus.Message, "basic") || !strings.Contains(ev.ResponseStatus.Message, "x509") { 86 t.Errorf("Expected response status message to contain basic and x509 auth method, got %s", ev.ResponseStatus.Message) 87 } 88 if ev.Verb != "list" { 89 t.Errorf("Unexpected verb, expected list, got %s", ev.Verb) 90 } 91 if ev.RequestURI != "/api/v1/namespaces/default/pods" { 92 t.Errorf("Unexpected user, expected /api/v1/namespaces/default/pods, got %s", ev.RequestURI) 93 } 94 } 95 96 func TestFailedAuthnAuditWithoutAuthorization(t *testing.T) { 97 sink := &fakeAuditSink{} 98 fakeRuleEvaluator := policy.NewFakePolicyRuleEvaluator(auditinternal.LevelRequestResponse, nil) 99 handler := WithFailedAuthenticationAudit( 100 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 101 http.Error(w, "", http.StatusUnauthorized) 102 }), 103 sink, fakeRuleEvaluator) 104 req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) 105 req.RemoteAddr = "127.0.0.1" 106 req = withTestContext(req, nil, nil) 107 handler.ServeHTTP(httptest.NewRecorder(), req) 108 109 if len(sink.events) != 1 { 110 t.Fatalf("Unexpected number of audit events generated, expected 1, got: %d", len(sink.events)) 111 } 112 ev := sink.events[0] 113 if ev.ResponseStatus.Code != http.StatusUnauthorized { 114 t.Errorf("Unexpected response code, expected unauthorized, got %d", ev.ResponseStatus.Code) 115 } 116 if !strings.Contains(ev.ResponseStatus.Message, "no credentials provided") { 117 t.Errorf("Expected response status message to contain no credentials provided, got %s", ev.ResponseStatus.Message) 118 } 119 if ev.Verb != "list" { 120 t.Errorf("Unexpected verb, expected list, got %s", ev.Verb) 121 } 122 if ev.RequestURI != "/api/v1/namespaces/default/pods" { 123 t.Errorf("Unexpected user, expected /api/v1/namespaces/default/pods, got %s", ev.RequestURI) 124 } 125 } 126 127 func TestFailedAuthnAuditOmitted(t *testing.T) { 128 sink := &fakeAuditSink{} 129 fakeRuleEvaluator := policy.NewFakePolicyRuleEvaluator(auditinternal.LevelRequestResponse, []auditinternal.Stage{auditinternal.StageResponseStarted}) 130 handler := WithFailedAuthenticationAudit( 131 http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 132 http.Error(w, "", http.StatusUnauthorized) 133 }), 134 sink, fakeRuleEvaluator) 135 req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) 136 req.RemoteAddr = "127.0.0.1" 137 req = withTestContext(req, nil, nil) 138 handler.ServeHTTP(httptest.NewRecorder(), req) 139 140 if len(sink.events) != 0 { 141 t.Fatalf("Unexpected number of audit events generated, expected 0, got: %d", len(sink.events)) 142 } 143 }