diff --git a/pkg/apiserver/filters/audit.go b/pkg/apiserver/filters/audit.go index 852940d102c..94338c77583 100644 --- a/pkg/apiserver/filters/audit.go +++ b/pkg/apiserver/filters/audit.go @@ -104,9 +104,13 @@ func WithAudit(handler http.Handler, requestContextMapper api.RequestContextMapp return } + username := "" groups := "" - if userGroups := attribs.GetUser().GetGroups(); len(userGroups) > 0 { - groups = auditStringSlice(userGroups) + if attribs.GetUser() != nil { + username = attribs.GetUser().GetName() + if userGroups := attribs.GetUser().GetGroups(); len(userGroups) > 0 { + groups = auditStringSlice(userGroups) + } } asuser := req.Header.Get(authenticationapi.ImpersonateUserHeader) if len(asuser) == 0 { @@ -124,7 +128,7 @@ func WithAudit(handler http.Handler, requestContextMapper api.RequestContextMapp id := uuid.NewRandom().String() line := fmt.Sprintf("%s AUDIT: id=%q ip=%q method=%q user=%q groups=%q as=%q asgroups=%q namespace=%q uri=%q\n", - time.Now().Format(time.RFC3339Nano), id, utilnet.GetClientIP(req), req.Method, attribs.GetUser().GetName(), groups, asuser, asgroups, namespace, req.URL) + time.Now().Format(time.RFC3339Nano), id, utilnet.GetClientIP(req), req.Method, username, groups, asuser, asgroups, namespace, req.URL) if _, err := fmt.Fprint(out, line); err != nil { glog.Errorf("Unable to write audit log: %s, the error is: %v", line, err) } diff --git a/pkg/apiserver/filters/audit_test.go b/pkg/apiserver/filters/audit_test.go index 327a2ab44ef..ed5d2afb442 100644 --- a/pkg/apiserver/filters/audit_test.go +++ b/pkg/apiserver/filters/audit_test.go @@ -123,3 +123,31 @@ func (m *fakeRequestContextMapper) Get(req *http.Request) (api.Context, bool) { func (*fakeRequestContextMapper) Update(req *http.Request, context api.Context) error { return nil } + +func TestAuditNoPanicOnNilUser(t *testing.T) { + var buf bytes.Buffer + + handler := WithAudit(&fakeHTTPHandler{}, &fakeRequestContextMapper{}, &buf) + + req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) + req.RemoteAddr = "127.0.0.1" + handler.ServeHTTP(httptest.NewRecorder(), req) + line := strings.Split(strings.TrimSpace(buf.String()), "\n") + if len(line) != 2 { + t.Fatalf("Unexpected amount of lines in audit log: %d", len(line)) + } + match, err := regexp.MatchString(`[\d\:\-\.\+TZ]+ AUDIT: id="[\w-]+" ip="127.0.0.1" method="GET" user="" groups="" as="" asgroups="" namespace="default" uri="/api/v1/namespaces/default/pods"`, line[0]) + if err != nil { + t.Errorf("Unexpected error matching first line: %v", err) + } + if !match { + t.Errorf("Unexpected first line of audit: %s", line[0]) + } + match, err = regexp.MatchString(`[\d\:\-\.\+TZ]+ AUDIT: id="[\w-]+" response="200"`, line[1]) + if err != nil { + t.Errorf("Unexpected error matching second line: %v", err) + } + if !match { + t.Errorf("Unexpected second line of audit: %s", line[1]) + } +}