diff --git a/pkg/apiserver/auditing/backend.go b/pkg/apiserver/auditing/backend.go index fd6a5cdb5..4c847ee74 100644 --- a/pkg/apiserver/auditing/backend.go +++ b/pkg/apiserver/auditing/backend.go @@ -86,12 +86,14 @@ func (b *Backend) worker() { <-b.semCh }() - bs, err := json.Marshal(event) + bs, err := b.eventToBytes(event) if err != nil { - klog.Errorf("json marshal error, %s", err) + klog.V(6).Infof("json marshal error, %s", err) return } + klog.V(8).Infof("%s", string(bs)) + response, err := b.client.Post(b.url, "application/json", bytes.NewBuffer(bs)) if err != nil { klog.Errorf("send audit event[%s] error, %s", event.Items[0].AuditID, err) @@ -107,3 +109,21 @@ func (b *Backend) worker() { go send(event) } } + +func (b *Backend) eventToBytes(event *v1alpha1.EventList) ([]byte, error) { + + bs, err := json.Marshal(event) + if err != nil { + // Normally, the serialization failure is caused by the failure of ResponseObject serialization. + // To ensure the integrity of the auditing event to the greatest extent, + // it is necessary to delete ResponseObject and and then try to serialize again. + if event.Items[0].ResponseObject != nil { + event.Items[0].ResponseObject = nil + return json.Marshal(event) + } + + return nil, err + } + + return bs, err +} diff --git a/pkg/apiserver/auditing/types.go b/pkg/apiserver/auditing/types.go index 353072df0..f73939b7a 100644 --- a/pkg/apiserver/auditing/types.go +++ b/pkg/apiserver/auditing/types.go @@ -122,6 +122,19 @@ func (a *auditing) LogRequestObject(req *http.Request, info *request.RequestInfo }, } + // Handle the devops request which request url matched /devops/{devops}/kind. + if len(info.Parts) >= 3 && info.Parts[0] == "devops" { + e.ObjectRef.Subresource = "" + e.Devops = info.Parts[1] + // set resource as kind + e.ObjectRef.Resource = info.Parts[2] + + // If the request url matched /devops/{devops}/kind/{kind}, set resource name as {kind} + if len(info.Parts) >= 4 { + e.ObjectRef.Name = info.Parts[3] + } + } + ips := make([]string, 1) ips[0] = iputil.RemoteIp(req) e.SourceIPs = ips @@ -137,7 +150,7 @@ func (a *auditing) LogRequestObject(req *http.Request, info *request.RequestInfo } } - if e.Level.GreaterOrEqual(audit.LevelRequest) && req.ContentLength > 0 { + if (e.Level.GreaterOrEqual(audit.LevelRequest) || e.Verb == "create") && req.ContentLength > 0 { body, err := ioutil.ReadAll(req.Body) if err != nil { klog.Error(err) @@ -145,7 +158,18 @@ func (a *auditing) LogRequestObject(req *http.Request, info *request.RequestInfo } _ = req.Body.Close() req.Body = ioutil.NopCloser(bytes.NewBuffer(body)) - e.RequestObject = &runtime.Unknown{Raw: body} + + if e.Level.GreaterOrEqual(audit.LevelRequest) { + e.RequestObject = &runtime.Unknown{Raw: body} + } + + // For resource creating request, get resource name from the request body. + if info.Verb == "create" { + obj := &auditv1alpha1.Object{} + if err := json.Unmarshal(body, obj); err == nil { + e.ObjectRef.Name = obj.Name + } + } } return e @@ -153,11 +177,6 @@ func (a *auditing) LogRequestObject(req *http.Request, info *request.RequestInfo func (a *auditing) LogResponseObject(e *auditv1alpha1.Event, resp *ResponseCapture, info *request.RequestInfo) { - // Auditing should igonre k8s request when k8s auditing is enabled. - if info.IsKubernetesRequest && a.K8sAuditingEnabled() { - return - } - e.StageTimestamp = v1.NewMicroTime(time.Now()) e.ResponseStatus = &v1.Status{Code: int32(resp.StatusCode())} if e.Level.GreaterOrEqual(audit.LevelRequestResponse) { @@ -168,10 +187,6 @@ func (a *auditing) LogResponseObject(e *auditv1alpha1.Event, resp *ResponseCaptu } func (a *auditing) cacheEvent(e auditv1alpha1.Event) { - if klog.V(8) { - bs, _ := json.Marshal(e) - klog.Infof("%s", string(bs)) - } eventList := &auditv1alpha1.EventList{} eventList.Items = append(eventList.Items, e) diff --git a/pkg/apiserver/auditing/v1alpha1/event.go b/pkg/apiserver/auditing/v1alpha1/event.go index ae1294ae6..a48d1ecc2 100644 --- a/pkg/apiserver/auditing/v1alpha1/event.go +++ b/pkg/apiserver/auditing/v1alpha1/event.go @@ -1,6 +1,9 @@ package v1alpha1 -import "k8s.io/apiserver/pkg/apis/audit" +import ( + "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apiserver/pkg/apis/audit" +) type Event struct { // Devops project @@ -18,3 +21,7 @@ type Event struct { type EventList struct { Items []Event } + +type Object struct { + v1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` +} diff --git a/pkg/apiserver/filters/auditing.go b/pkg/apiserver/filters/auditing.go index 17a734275..e17d84de0 100644 --- a/pkg/apiserver/filters/auditing.go +++ b/pkg/apiserver/filters/auditing.go @@ -26,6 +26,12 @@ func WithAuditing(handler http.Handler, a auditing.Auditing) http.Handler { return } + // Auditing should igonre k8s request when k8s auditing is enabled. + if info.IsKubernetesRequest && a.K8sAuditingEnabled() { + handler.ServeHTTP(w, req) + return + } + e := a.LogRequestObject(req, info) req = req.WithContext(request.WithAuditEvent(req.Context(), e)) resp := auditing.NewResponseCapture(w)