Merge pull request #2129 from wanjunlei/master

add auditing events search api
This commit is contained in:
KubeSphere CI Bot
2020-06-01 11:45:37 +08:00
committed by GitHub
18 changed files with 1258 additions and 8 deletions

View File

@@ -0,0 +1,94 @@
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package auditing
import (
"kubesphere.io/kubesphere/pkg/api/auditing/v1alpha1"
"kubesphere.io/kubesphere/pkg/simple/client/auditing"
"kubesphere.io/kubesphere/pkg/utils/stringutils"
"strconv"
)
type Interface interface {
Events(queryParam *v1alpha1.Query, MutateFilterFunc func(*auditing.Filter)) (*v1alpha1.APIResponse, error)
}
type eventsOperator struct {
client auditing.Client
}
func NewEventsOperator(client auditing.Client) Interface {
return &eventsOperator{client}
}
func (eo *eventsOperator) Events(queryParam *v1alpha1.Query,
MutateFilterFunc func(*auditing.Filter)) (*v1alpha1.APIResponse, error) {
filter := &auditing.Filter{
ObjectRefNames: stringutils.Split(queryParam.ObjectRefNameFilter, ","),
ObjectRefNameFuzzy: stringutils.Split(queryParam.ObjectRefNameSearch, ","),
Levels: stringutils.Split(queryParam.LevelFilter, ","),
Verbs: stringutils.Split(queryParam.VerbFilter, ","),
Users: stringutils.Split(queryParam.UserFilter, ","),
UserFuzzy: stringutils.Split(queryParam.UserSearch, ","),
GroupFuzzy: stringutils.Split(queryParam.GroupSearch, ","),
SourceIpFuzzy: stringutils.Split(queryParam.SourceIpSearch, ","),
ObjectRefResources: stringutils.Split(queryParam.ObjectRefResourceFilter, ","),
ObjectRefSubresources: stringutils.Split(queryParam.ObjectRefSubresourceFilter, ","),
StartTime: queryParam.StartTime,
EndTime: queryParam.EndTime,
}
if MutateFilterFunc != nil {
MutateFilterFunc(filter)
}
cs := stringutils.Split(queryParam.ResponesStatusFilter, ",")
for _, c := range cs {
code, err := strconv.ParseInt(c, 10, 64)
if err != nil {
continue
}
filter.ResponseStatus = append(filter.ResponseStatus, int32(code))
}
var ar v1alpha1.APIResponse
var err error
switch queryParam.Operation {
case "histogram":
if len(filter.ObjectRefNamespaceMap) == 0 {
ar.Histogram = &auditing.Histogram{}
} else {
ar.Histogram, err = eo.client.CountOverTime(filter, queryParam.Interval)
}
case "statistics":
if len(filter.ObjectRefNamespaceMap) == 0 {
ar.Statistics = &auditing.Statistics{}
} else {
ar.Statistics, err = eo.client.StatisticsOnResources(filter)
}
default:
if len(filter.ObjectRefNamespaceMap) == 0 {
ar.Events = &auditing.Events{}
} else {
ar.Events, err = eo.client.SearchAuditingEvent(filter, queryParam.From, queryParam.Size, queryParam.Sort)
}
}
if err != nil {
return nil, err
}
return &ar, nil
}

View File

@@ -27,6 +27,7 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
auditingv1alpha1 "kubesphere.io/kubesphere/pkg/api/auditing/v1alpha1"
eventsv1alpha1 "kubesphere.io/kubesphere/pkg/api/events/v1alpha1"
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/api/logging/v1alpha2"
clusterv1alpha1 "kubesphere.io/kubesphere/pkg/apis/cluster/v1alpha1"
@@ -37,11 +38,13 @@ import (
"kubesphere.io/kubesphere/pkg/apiserver/query"
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/auditing"
"kubesphere.io/kubesphere/pkg/models/events"
"kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/models/logging"
resources "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
resourcesv1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
auditingclient "kubesphere.io/kubesphere/pkg/simple/client/auditing"
eventsclient "kubesphere.io/kubesphere/pkg/simple/client/events"
loggingclient "kubesphere.io/kubesphere/pkg/simple/client/logging"
"kubesphere.io/kubesphere/pkg/utils/stringutils"
@@ -62,6 +65,7 @@ type Interface interface {
Events(user user.Info, queryParam *eventsv1alpha1.Query) (*eventsv1alpha1.APIResponse, error)
QueryLogs(user user.Info, query *loggingv1alpha2.Query) (*loggingv1alpha2.APIResponse, error)
ExportLogs(user user.Info, query *loggingv1alpha2.Query, writer io.Writer) error
Auditing(user user.Info, queryParam *auditingv1alpha1.Query) (*auditingv1alpha1.APIResponse, error)
}
type tenantOperator struct {
@@ -72,9 +76,10 @@ type tenantOperator struct {
resourceGetter *resourcesv1alpha3.ResourceGetter
events events.Interface
lo logging.LoggingOperator
auditing auditing.Interface
}
func New(informers informers.InformerFactory, k8sclient kubernetes.Interface, ksclient kubesphere.Interface, evtsClient eventsclient.Client, loggingClient loggingclient.Interface) Interface {
func New(informers informers.InformerFactory, k8sclient kubernetes.Interface, ksclient kubesphere.Interface, evtsClient eventsclient.Client, loggingClient loggingclient.Interface, auditingclient auditingclient.Client) Interface {
amOperator := am.NewReadOnlyOperator(informers)
authorizer := authorizerfactory.NewRBACAuthorizer(amOperator)
return &tenantOperator{
@@ -85,6 +90,7 @@ func New(informers informers.InformerFactory, k8sclient kubernetes.Interface, ks
ksclient: ksclient,
events: events.NewEventsOperator(evtsClient),
lo: logging.NewLoggingOperator(loggingClient),
auditing: auditing.NewEventsOperator(auditingclient),
}
}
@@ -523,6 +529,48 @@ func (t *tenantOperator) ExportLogs(user user.Info, query *loggingv1alpha2.Query
}
}
func (t *tenantOperator) Auditing(user user.Info, queryParam *auditingv1alpha1.Query) (*auditingv1alpha1.APIResponse, error) {
iNamespaces, err := t.listIntersectedNamespaces(user,
stringutils.Split(queryParam.WorkspaceFilter, ","),
stringutils.Split(queryParam.WorkspaceSearch, ","),
stringutils.Split(queryParam.ObjectRefNamespaceFilter, ","),
stringutils.Split(queryParam.ObjectRefNamespaceSearch, ","))
if err != nil {
klog.Error(err)
return nil, err
}
namespaceCreateTimeMap := make(map[string]time.Time)
for _, ns := range iNamespaces {
namespaceCreateTimeMap[ns.Name] = ns.CreationTimestamp.Time
}
// If there are no ns and ws query conditions,
// those events with empty `ObjectRef.Namespace` will also be listed when user can list all namespaces
if len(queryParam.WorkspaceFilter) == 0 && len(queryParam.ObjectRefNamespaceFilter) == 0 &&
len(queryParam.WorkspaceSearch) == 0 && len(queryParam.ObjectRefNamespaceSearch) == 0 {
listEvts := authorizer.AttributesRecord{
User: user,
Verb: "list",
APIGroup: "",
APIVersion: "v1",
Resource: "namespaces",
ResourceRequest: true,
}
decision, _, err := t.authorizer.Authorize(listEvts)
if err != nil {
klog.Error(err)
return nil, err
}
if decision == authorizer.DecisionAllow {
namespaceCreateTimeMap[""] = time.Time{}
}
}
return t.auditing.Events(queryParam, func(filter *auditingclient.Filter) {
filter.ObjectRefNamespaceMap = namespaceCreateTimeMap
})
}
func contains(objects []runtime.Object, object runtime.Object) bool {
for _, item := range objects {
if item == object {

View File

@@ -328,5 +328,5 @@ func prepare() Interface {
RoleBindings().Informer().GetIndexer().Add(roleBinding)
}
return New(fakeInformerFactory, nil, nil, nil, nil)
return New(fakeInformerFactory, nil, nil, nil, nil, nil)
}