// WithAudit decorates a http.Handler with audit logging information for all the // requests coming to the server. Each audit log contains two entries: // 1. the request line containing: // - unique id allowing to match the response line (see 2) // - source ip of the request // - HTTP method being invoked // - original user invoking the operation // - impersonated user for the operation // - namespace of the request or <none> // - uri is the full URI as requested // 2. the response line containing: // - the unique id from 1 // - response code func WithAudit(handler http.Handler, attributeGetter apiserver.RequestAttributeGetter, out io.Writer) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { attribs := attributeGetter.GetAttribs(req) asuser := req.Header.Get(authenticationapi.ImpersonateUserHeader) if len(asuser) == 0 { asuser = "******" } asgroups := "<lookup>" requestedGroups := req.Header[authenticationapi.ImpersonateGroupHeader] if len(requestedGroups) > 0 { quotedGroups := make([]string, len(requestedGroups)) for i, group := range requestedGroups { quotedGroups[i] = fmt.Sprintf("%q", group) } asgroups = strings.Join(quotedGroups, ", ") } namespace := attribs.GetNamespace() if len(namespace) == 0 { namespace = "<none>" } id := uuid.NewRandom().String() line := fmt.Sprintf("%s AUDIT: id=%q ip=%q method=%q user=%q as=%q asgroups=%q namespace=%q uri=%q\n", time.Now().Format(time.RFC3339Nano), id, utilnet.GetClientIP(req), req.Method, attribs.GetUser().GetName(), 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) } respWriter := decorateResponseWriter(w, out, id) handler.ServeHTTP(respWriter, req) }) }
// WithAudit decorates a http.Handler with audit logging information for all the // requests coming to the server. Each audit log contains two entries: // 1. the request line containing: // - unique id allowing to match the response line (see 2) // - source ip of the request // - HTTP method being invoked // - original user invoking the operation // - impersonated user for the operation // - namespace of the request or <none> // - uri is the full URI as requested // 2. the response line containing: // - the unique id from 1 // - response code func WithAudit(handler http.Handler, attributeGetter apiserver.RequestAttributeGetter, out io.Writer) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { attribs := attributeGetter.GetAttribs(req) asuser := req.Header.Get("Impersonate-User") if len(asuser) == 0 { asuser = "******" } namespace := attribs.GetNamespace() if len(namespace) == 0 { namespace = "<none>" } id := uuid.NewRandom().String() line := fmt.Sprintf("%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, attribs.GetUser().GetName(), asuser, 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) } respWriter := decorateResponseWriter(w, out, id) handler.ServeHTTP(respWriter, req) }) }