diff --git a/pkg/apiserver/audit/audit.go b/pkg/apiserver/audit/audit.go index a50182d8f2..b2859014bc 100644 --- a/pkg/apiserver/audit/audit.go +++ b/pkg/apiserver/audit/audit.go @@ -26,7 +26,7 @@ import ( "github.com/pborman/uuid" - "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apiserver" utilnet "k8s.io/kubernetes/pkg/util/net" ) @@ -79,22 +79,21 @@ var _ http.Hijacker = &fancyResponseWriterDelegator{} // 2. the response line containing: // - the unique id from 1 // - response code -func WithAudit(handler http.Handler, requestContextMapper api.RequestContextMapper, out io.Writer) http.Handler { +func WithAudit(handler http.Handler, attributeGetter apiserver.RequestAttributeGetter, out io.Writer) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - ctx, _ := requestContextMapper.Get(req) - user, _ := api.UserFrom(ctx) + attribs := attributeGetter.GetAttribs(req) asuser := req.Header.Get("Impersonate-User") if len(asuser) == 0 { asuser = "" } - namespace := api.NamespaceValue(ctx) + namespace := attribs.GetNamespace() if len(namespace) == 0 { namespace = "" } id := uuid.NewRandom().String() fmt.Fprintf(out, "%s AUDIT: id=%q ip=%q method=%q user=%q as=%q namespace=%q uri=%q\n", - time.Now().Format(time.RFC3339Nano), id, utilnet.GetClientIP(req), req.Method, user.GetName(), asuser, namespace, req.URL) + time.Now().Format(time.RFC3339Nano), id, utilnet.GetClientIP(req), req.Method, attribs.GetUser().GetName(), asuser, namespace, req.URL) respWriter := decorateResponseWriter(w, out, id) handler.ServeHTTP(respWriter, req) }) diff --git a/pkg/apiserver/audit/audit_test.go b/pkg/apiserver/audit/audit_test.go index 8dea6cdbfe..3131f979d4 100644 --- a/pkg/apiserver/audit/audit_test.go +++ b/pkg/apiserver/audit/audit_test.go @@ -18,11 +18,20 @@ package audit import ( "bufio" + "bytes" "io/ioutil" "net" "net/http" + "net/http/httptest" "reflect" + "regexp" + "strings" "testing" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apiserver" + "k8s.io/kubernetes/pkg/auth/user" + "k8s.io/kubernetes/pkg/util/sets" ) type simpleResponseWriter struct { @@ -56,3 +65,48 @@ func TestConstructResponseWriter(t *testing.T) { t.Errorf("Expected fancyResponseWriterDelegator, got %v", reflect.TypeOf(v)) } } + +type fakeHTTPHandler struct{} + +func (*fakeHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + w.WriteHeader(200) +} + +type fakeRequestContextMapper struct{} + +func (*fakeRequestContextMapper) Get(req *http.Request) (api.Context, bool) { + return api.WithUser(api.NewContext(), &user.DefaultInfo{Name: "admin"}), true + +} + +func (*fakeRequestContextMapper) Update(req *http.Request, context api.Context) error { + return nil +} + +func TestAudit(t *testing.T) { + var buf bytes.Buffer + attributeGetter := apiserver.NewRequestAttributeGetter(&fakeRequestContextMapper{}, + &apiserver.RequestInfoResolver{APIPrefixes: sets.NewString("api", "apis"), GrouplessAPIPrefixes: sets.NewString("api")}) + handler := WithAudit(&fakeHTTPHandler{}, attributeGetter, &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\:\-\.\+]+ AUDIT: id="[\w-]+" ip="127.0.0.1" method="GET" user="admin" as="" 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\:\-\.\+]+ 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]) + } +} diff --git a/pkg/genericapiserver/config.go b/pkg/genericapiserver/config.go index 049c4bf98c..b367bd0c4a 100644 --- a/pkg/genericapiserver/config.go +++ b/pkg/genericapiserver/config.go @@ -384,7 +384,7 @@ func (c Config) New() (*GenericAPIServer, error) { MaxBackups: c.AuditLogMaxBackups, MaxSize: c.AuditLogMaxSize, } - handler = audit.WithAudit(handler, c.RequestContextMapper, writer) + handler = audit.WithAudit(handler, attributeGetter, writer) defer writer.Close() } handler = apiserver.WithImpersonation(handler, c.RequestContextMapper, c.Authorizer)