processing audit information of non-standard request
Signed-off-by: wanjunlei <wanjunlei@yunify.com>
This commit is contained in:
@@ -86,12 +86,14 @@ func (b *Backend) worker() {
|
|||||||
<-b.semCh
|
<-b.semCh
|
||||||
}()
|
}()
|
||||||
|
|
||||||
bs, err := json.Marshal(event)
|
bs, err := b.eventToBytes(event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("json marshal error, %s", err)
|
klog.V(6).Infof("json marshal error, %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
klog.V(8).Infof("%s", string(bs))
|
||||||
|
|
||||||
response, err := b.client.Post(b.url, "application/json", bytes.NewBuffer(bs))
|
response, err := b.client.Post(b.url, "application/json", bytes.NewBuffer(bs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("send audit event[%s] error, %s", event.Items[0].AuditID, err)
|
klog.Errorf("send audit event[%s] error, %s", event.Items[0].AuditID, err)
|
||||||
@@ -107,3 +109,27 @@ func (b *Backend) worker() {
|
|||||||
go send(event)
|
go send(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Backend) eventToBytes(event *v1alpha1.EventList) ([]byte, error) {
|
||||||
|
|
||||||
|
if bs, err := json.Marshal(event); err == nil {
|
||||||
|
return bs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normally, the serialization failure is caused by the failure of RequestObject or ResponseObject serialization.
|
||||||
|
// To ensure the integrity of the auditing event to the greatest extent,
|
||||||
|
// it is necessary to delete RequestObject or ResponseObject and and then try to serialize again.
|
||||||
|
if event.Items[0].RequestObject != nil {
|
||||||
|
if _, err := json.Marshal(event.Items[0].RequestObject); err != nil {
|
||||||
|
event.Items[0].RequestObject = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if event.Items[0].ResponseObject != nil {
|
||||||
|
if _, err := json.Marshal(event.Items[0].ResponseObject); err != nil {
|
||||||
|
event.Items[0].ResponseObject = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(event)
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 := make([]string, 1)
|
||||||
ips[0] = iputil.RemoteIp(req)
|
ips[0] = iputil.RemoteIp(req)
|
||||||
e.SourceIPs = ips
|
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)
|
body, err := ioutil.ReadAll(req.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
@@ -145,19 +158,25 @@ func (a *auditing) LogRequestObject(req *http.Request, info *request.RequestInfo
|
|||||||
}
|
}
|
||||||
_ = req.Body.Close()
|
_ = req.Body.Close()
|
||||||
req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
||||||
|
|
||||||
|
if e.Level.GreaterOrEqual(audit.LevelRequest) {
|
||||||
e.RequestObject = &runtime.Unknown{Raw: body}
|
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
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *auditing) LogResponseObject(e *auditv1alpha1.Event, resp *ResponseCapture, 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.StageTimestamp = v1.NewMicroTime(time.Now())
|
||||||
e.ResponseStatus = &v1.Status{Code: int32(resp.StatusCode())}
|
e.ResponseStatus = &v1.Status{Code: int32(resp.StatusCode())}
|
||||||
if e.Level.GreaterOrEqual(audit.LevelRequestResponse) {
|
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) {
|
func (a *auditing) cacheEvent(e auditv1alpha1.Event) {
|
||||||
if klog.V(8) {
|
|
||||||
bs, _ := json.Marshal(e)
|
|
||||||
klog.Infof("%s", string(bs))
|
|
||||||
}
|
|
||||||
|
|
||||||
eventList := &auditv1alpha1.EventList{}
|
eventList := &auditv1alpha1.EventList{}
|
||||||
eventList.Items = append(eventList.Items, e)
|
eventList.Items = append(eventList.Items, e)
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package v1alpha1
|
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 {
|
type Event struct {
|
||||||
// Devops project
|
// Devops project
|
||||||
@@ -18,3 +21,7 @@ type Event struct {
|
|||||||
type EventList struct {
|
type EventList struct {
|
||||||
Items []Event
|
Items []Event
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Object struct {
|
||||||
|
v1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ func WithAuditing(handler http.Handler, a auditing.Auditing) http.Handler {
|
|||||||
return
|
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)
|
e := a.LogRequestObject(req, info)
|
||||||
req = req.WithContext(request.WithAuditEvent(req.Context(), e))
|
req = req.WithContext(request.WithAuditEvent(req.Context(), e))
|
||||||
resp := auditing.NewResponseCapture(w)
|
resp := auditing.NewResponseCapture(w)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
log "k8s.io/klog"
|
log "k8s.io/klog"
|
||||||
"kubesphere.io/kubesphere/pkg/api"
|
"kubesphere.io/kubesphere/pkg/api"
|
||||||
|
"kubesphere.io/kubesphere/pkg/apiserver/request"
|
||||||
"kubesphere.io/kubesphere/pkg/models/devops"
|
"kubesphere.io/kubesphere/pkg/models/devops"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -92,6 +93,12 @@ func (h *ProjectPipelineHandler) StopPipeline(req *restful.Request, resp *restfu
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event := request.AuditEventFrom(req.Request.Context()); event != nil {
|
||||||
|
event.ObjectRef.Resource = "pipelines.runs"
|
||||||
|
event.ObjectRef.Name = pipelineName + "." + runId
|
||||||
|
event.Verb = "stop"
|
||||||
|
}
|
||||||
|
|
||||||
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
||||||
resp.WriteAsJson(res)
|
resp.WriteAsJson(res)
|
||||||
}
|
}
|
||||||
@@ -107,6 +114,12 @@ func (h *ProjectPipelineHandler) ReplayPipeline(req *restful.Request, resp *rest
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event := request.AuditEventFrom(req.Request.Context()); event != nil {
|
||||||
|
event.ObjectRef.Resource = "pipelines.runs"
|
||||||
|
event.ObjectRef.Name = pipelineName + "." + runId
|
||||||
|
event.Verb = "replay"
|
||||||
|
}
|
||||||
|
|
||||||
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
||||||
resp.WriteAsJson(res)
|
resp.WriteAsJson(res)
|
||||||
}
|
}
|
||||||
@@ -121,6 +134,11 @@ func (h *ProjectPipelineHandler) RunPipeline(req *restful.Request, resp *restful
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event := request.AuditEventFrom(req.Request.Context()); event != nil {
|
||||||
|
event.ObjectRef.Resource = "pipelines.runs"
|
||||||
|
event.ObjectRef.Name = pipelineName + "." + res.ID
|
||||||
|
}
|
||||||
|
|
||||||
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
||||||
resp.WriteAsJson(res)
|
resp.WriteAsJson(res)
|
||||||
}
|
}
|
||||||
@@ -215,6 +233,11 @@ func (h *ProjectPipelineHandler) SubmitInputStep(req *restful.Request, resp *res
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event := request.AuditEventFrom(req.Request.Context()); event != nil {
|
||||||
|
event.ObjectRef.Resource = "pipelines.runs.nodes.step"
|
||||||
|
event.ObjectRef.Name = pipelineName + "." + runId + "." + nodeId + "." + stepId
|
||||||
|
}
|
||||||
|
|
||||||
resp.Write(res)
|
resp.Write(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,6 +297,12 @@ func (h *ProjectPipelineHandler) StopBranchPipeline(req *restful.Request, resp *
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event := request.AuditEventFrom(req.Request.Context()); event != nil {
|
||||||
|
event.ObjectRef.Resource = "pipelines.branches.runs"
|
||||||
|
event.ObjectRef.Name = pipelineName + "." + branchName + "." + runId
|
||||||
|
event.Verb = "stop"
|
||||||
|
}
|
||||||
|
|
||||||
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
||||||
resp.WriteAsJson(res)
|
resp.WriteAsJson(res)
|
||||||
}
|
}
|
||||||
@@ -290,6 +319,12 @@ func (h *ProjectPipelineHandler) ReplayBranchPipeline(req *restful.Request, resp
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event := request.AuditEventFrom(req.Request.Context()); event != nil {
|
||||||
|
event.ObjectRef.Resource = "pipelines.branches.runs"
|
||||||
|
event.ObjectRef.Name = pipelineName + "." + branchName + "." + runId
|
||||||
|
event.Verb = "replay"
|
||||||
|
}
|
||||||
|
|
||||||
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
||||||
resp.WriteAsJson(res)
|
resp.WriteAsJson(res)
|
||||||
}
|
}
|
||||||
@@ -305,6 +340,11 @@ func (h *ProjectPipelineHandler) RunBranchPipeline(req *restful.Request, resp *r
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event := request.AuditEventFrom(req.Request.Context()); event != nil {
|
||||||
|
event.ObjectRef.Resource = "pipelines.branches.runs"
|
||||||
|
event.ObjectRef.Name = pipelineName + "." + branchName + "." + res.ID
|
||||||
|
}
|
||||||
|
|
||||||
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
|
||||||
resp.WriteAsJson(res)
|
resp.WriteAsJson(res)
|
||||||
}
|
}
|
||||||
@@ -407,6 +447,11 @@ func (h *ProjectPipelineHandler) SubmitBranchInputStep(req *restful.Request, res
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event := request.AuditEventFrom(req.Request.Context()); event != nil {
|
||||||
|
event.ObjectRef.Resource = "pipelines.branches.runs.nodes.steps"
|
||||||
|
event.ObjectRef.Name = pipelineName + "." + branchName + "." + runId + "." + nodeId + "." + stepId
|
||||||
|
}
|
||||||
|
|
||||||
resp.Write(res)
|
resp.Write(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||||
authoptions "kubesphere.io/kubesphere/pkg/apiserver/authentication/options"
|
authoptions "kubesphere.io/kubesphere/pkg/apiserver/authentication/options"
|
||||||
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
||||||
|
requestinfo "kubesphere.io/kubesphere/pkg/apiserver/request"
|
||||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||||
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
||||||
servererr "kubesphere.io/kubesphere/pkg/server/errors"
|
servererr "kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
@@ -821,6 +822,14 @@ func (h *iamHandler) CreateWorkspaceMembers(request *restful.Request, response *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event := requestinfo.AuditEventFrom(request.Request.Context()); event != nil {
|
||||||
|
name := ""
|
||||||
|
for _, member := range members {
|
||||||
|
name += member.Username + ", "
|
||||||
|
}
|
||||||
|
name = strings.TrimSuffix(name, ", ")
|
||||||
|
event.ObjectRef.Name = name
|
||||||
|
}
|
||||||
response.WriteEntity(members)
|
response.WriteEntity(members)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -899,6 +908,14 @@ func (h *iamHandler) CreateNamespaceMembers(request *restful.Request, response *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event := requestinfo.AuditEventFrom(request.Request.Context()); event != nil {
|
||||||
|
name := ""
|
||||||
|
for _, member := range members {
|
||||||
|
name += member.Username + ", "
|
||||||
|
}
|
||||||
|
name = strings.TrimSuffix(name, ", ")
|
||||||
|
event.ObjectRef.Name = name
|
||||||
|
}
|
||||||
response.WriteEntity(members)
|
response.WriteEntity(members)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -980,6 +997,14 @@ func (h *iamHandler) CreateClusterMembers(request *restful.Request, response *re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event := requestinfo.AuditEventFrom(request.Request.Context()); event != nil {
|
||||||
|
name := ""
|
||||||
|
for _, member := range members {
|
||||||
|
name += member.Username + ", "
|
||||||
|
}
|
||||||
|
name = strings.TrimSuffix(name, ", ")
|
||||||
|
event.ObjectRef.Name = name
|
||||||
|
}
|
||||||
response.WriteEntity(members)
|
response.WriteEntity(members)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user