diff --git a/cmd/controller-manager/app/controllers.go b/cmd/controller-manager/app/controllers.go index 5b45cd98d..94064994c 100644 --- a/cmd/controller-manager/app/controllers.go +++ b/cmd/controller-manager/app/controllers.go @@ -20,6 +20,7 @@ import ( "fmt" "k8s.io/klog" "kubesphere.io/kubesphere/pkg/controller/application" + "kubesphere.io/kubesphere/pkg/controller/auditing" "kubesphere.io/kubesphere/pkg/controller/certificatesigningrequest" "kubesphere.io/kubesphere/pkg/controller/cluster" "kubesphere.io/kubesphere/pkg/controller/clusterrolebinding" @@ -161,6 +162,8 @@ func AddControllers( kubesphereInformer.Tenant().V1alpha1().Workspaces(), kubernetesInformer.Core().V1().Namespaces(), nsnpProvider) + auditingController := auditing.NewController(kubesphereInformer.Auditing().V1alpha1().Webhooks()) + controllers := map[string]manager.Runnable{ "virtualservice-controller": vsController, "destinationrule-controller": drController, @@ -178,6 +181,7 @@ func AddControllers( "csr-controller": csrController, "clusterrolebinding-controller": clusterRoleBindingController, "globalrolebinding-controller": globalRoleBindingController, + "auditing-controller": auditingController, } if storageCapabilityController.IsValidKubernetesVersion() { diff --git a/hack/generate_client.sh b/hack/generate_client.sh index 6e4b753fa..cc157212c 100755 --- a/hack/generate_client.sh +++ b/hack/generate_client.sh @@ -2,7 +2,7 @@ set -e -GV="network:v1alpha1 servicemesh:v1alpha2 tenant:v1alpha1 tenant:v1alpha2 devops:v1alpha1 iam:v1alpha2 devops:v1alpha3 cluster:v1alpha1 storage:v1alpha1" +GV="network:v1alpha1 servicemesh:v1alpha2 tenant:v1alpha1 tenant:v1alpha2 devops:v1alpha1 iam:v1alpha2 devops:v1alpha3 cluster:v1alpha1 storage:v1alpha1 auditing:v1alpha1" rm -rf ./pkg/client ./hack/generate_group.sh "client,lister,informer" kubesphere.io/kubesphere/pkg/client kubesphere.io/kubesphere/pkg/apis "$GV" --output-base=./ -h "$PWD/hack/boilerplate.go.txt" diff --git a/pkg/apis/addtoscheme_audting_v1alpha1.go b/pkg/apis/addtoscheme_audting_v1alpha1.go new file mode 100644 index 000000000..16e1d6aba --- /dev/null +++ b/pkg/apis/addtoscheme_audting_v1alpha1.go @@ -0,0 +1,25 @@ +/* +Copyright 2019 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 apis + +import ( + "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" +) + +func init() { + AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme) +} diff --git a/pkg/apis/auditing/group.go b/pkg/apis/auditing/group.go new file mode 100644 index 000000000..ad9d6c9eb --- /dev/null +++ b/pkg/apis/auditing/group.go @@ -0,0 +1,18 @@ +/* +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 contains auditing API versions +package auditing diff --git a/pkg/apis/auditing/v1alpha1/doc.go b/pkg/apis/auditing/v1alpha1/doc.go new file mode 100644 index 000000000..a8cd89e4e --- /dev/null +++ b/pkg/apis/auditing/v1alpha1/doc.go @@ -0,0 +1,19 @@ +/* +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 v1alpha1 contains API Schema definitions for the audit v1alpha1 API group +// +groupName=auditing.kubesphere.io +package v1alpha1 diff --git a/pkg/apis/auditing/v1alpha1/register.go b/pkg/apis/auditing/v1alpha1/register.go new file mode 100644 index 000000000..4e31bcce5 --- /dev/null +++ b/pkg/apis/auditing/v1alpha1/register.go @@ -0,0 +1,41 @@ +/* +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. +*/ + +// NOTE: Boilerplate only. Ignore this file. + +// Package v1alpha1 contains API Schema definitions for the audit v1alpha1 API group +// +k8s:deepcopy-gen=package,register +// +groupName=auditing.kubesphere.io +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "auditing.kubesphere.io", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + + AddToScheme = SchemeBuilder.AddToScheme +) + +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/pkg/apis/auditing/v1alpha1/rule_types.go b/pkg/apis/auditing/v1alpha1/rule_types.go new file mode 100644 index 000000000..8969ff28e --- /dev/null +++ b/pkg/apis/auditing/v1alpha1/rule_types.go @@ -0,0 +1,89 @@ +/* +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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +type PolicyRule struct { + // Rule name + Name string `json:"name,omitempty" protobuf:"bytes,8,opt,name=name"` + // Rule type, rule, macro,list,alias + Type string `json:"type,omitempty" protobuf:"bytes,8,opt,name=type"` + // Rule describe + Desc string `json:"desc,omitempty" protobuf:"bytes,8,opt,name=desc"` + // Rule condition + // This effective When the rule type is rule + Condition string `json:"condition,omitempty" protobuf:"bytes,8,opt,name=condition"` + // This effective When the rule type is macro + Macro string `json:"macro,omitempty" protobuf:"bytes,8,opt,name=macro"` + // This effective When the rule type is alias + Alias string `json:"alias,omitempty" protobuf:"bytes,8,opt,name=alias"` + // This effective When the rule type is list + List []string `json:"list,omitempty" protobuf:"bytes,8,opt,name=list"` + // Is the rule enable + Enable bool `json:"enable" protobuf:"bytes,8,opt,name=enable"` + // The output formater of message which send to user + Output string `json:"output,omitempty" protobuf:"bytes,8,opt,name=output"` + // Rule priority, DEBUG, INFO, WARNING + Priority string `json:"priority,omitempty" protobuf:"bytes,8,opt,name=priority"` +} + +// AuditRuleSpec defines the desired state of Rule +type RuleSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + PolicyRules []PolicyRule `json:"rules,omitempty" protobuf:"bytes,8,opt,name=rules"` +} + +// AuditRuleStatus defines the observed state of Rule +type RuleStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +// +genclient +// +genclient:noStatus +// +genclient:nonNamespaced +// +kubebuilder:object:root=true + +// Rule is the Schema for the rules API +type Rule struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RuleSpec `json:"spec,omitempty"` + Status RuleStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// AuditRuleList contains a list of Rule +type RuleList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Rule `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Rule{}, &RuleList{}) +} diff --git a/pkg/apis/auditing/v1alpha1/v1alpha1_suite_test.go b/pkg/apis/auditing/v1alpha1/v1alpha1_suite_test.go new file mode 100644 index 000000000..70d9a172a --- /dev/null +++ b/pkg/apis/auditing/v1alpha1/v1alpha1_suite_test.go @@ -0,0 +1,55 @@ +/* +Copyright 2019 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 v1alpha1 + +import ( + "log" + "os" + "path/filepath" + "testing" + + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" +) + +var cfg *rest.Config +var c client.Client + +func TestMain(m *testing.M) { + t := &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "..", "config", "crds")}, + } + + err := SchemeBuilder.AddToScheme(scheme.Scheme) + if err != nil { + log.Fatal(err) + } + + if cfg, err = t.Start(); err != nil { + log.Fatal(err) + } + + if c, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}); err != nil { + log.Fatal(err) + } + + code := m.Run() + t.Stop() + os.Exit(code) +} diff --git a/pkg/apis/auditing/v1alpha1/webhook_types.go b/pkg/apis/auditing/v1alpha1/webhook_types.go new file mode 100644 index 000000000..a4ac92fb7 --- /dev/null +++ b/pkg/apis/auditing/v1alpha1/webhook_types.go @@ -0,0 +1,155 @@ +/* +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 v1alpha1 + +import ( + "k8s.io/api/auditregistration/v1alpha1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// Receiver config which received the audit alert +type Receiver struct { + // Receiver name + // +optional + ReceicerName string `json:"name,omitempty" protobuf:"bytes,8,opt,name=name"` + // Receiver type, alertmanager or webhook + // +optional + ReceiverType string `json:"type,omitempty" protobuf:"bytes,8,opt,name=type"` + // ClientConfig holds the connection parameters for the webhook + // +optional + ReceiverConfig v1alpha1.WebhookClientConfig `json:"config,omitempty" protobuf:"bytes,8,opt,name=config"` +} + +type AuditSinkPolicy struct { + ArchivingRuleSelector *metav1.LabelSelector `json:"archivingRuleSelector,omitempty" protobuf:"bytes,8,opt,name=archivingRuleSelector"` + AlertingRuleSelector *metav1.LabelSelector `json:"alertingRuleSelector,omitempty" protobuf:"bytes,8,opt,name=alertingRuleSelector"` +} + +type DynamicAuditConfig struct { + // Throttle holds the options for throttling the webhook + // +optional + Throttle *v1alpha1.WebhookThrottleConfig `json:"throttle,omitempty" protobuf:"bytes,18,opt,name=throttle"` + // Policy defines the policy for selecting which events should be sent to the webhook + // +optional + Policy *v1alpha1.Policy `json:"policy,omitempty" protobuf:"bytes,18,opt,name=policy"` +} + +// WebhookSpec defines the desired state of Webhook +type WebhookSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Number of desired pods. This is a pointer to distinguish between explicit + // zero and not specified. Defaults to 1. + // +optional + Replicas *int32 `json:"replicas,omitempty" protobuf:"varint,1,opt,name=replicas"` + // The webhook docker image name. + // +optional + Image string `json:"image,omitempty" protobuf:"bytes,2,opt,name=image"` + // Image pull policy. + // One of Always, Never, IfNotPresent. + // Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + // Cannot be updated. + // More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + // +optional + ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty" protobuf:"bytes,14,opt,name=imagePullPolicy,casttype=PullPolicy"` + // ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. + // If specified, these secrets will be passed to individual puller implementations for them to use. For example, + // in the case of docker, only DockerConfig type secrets are honored. + // More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod + // +optional + // +patchMergeKey=name + // +patchStrategy=merge + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,15,rep,name=imagePullSecrets"` + // Arguments to the entrypoint.. + // It will be appended to the args and replace the default value. + // +optional + Args []string `json:"args,omitempty" protobuf:"bytes,3,rep,name=args"` + // NodeSelector is a selector which must be true for the pod to fit on a node. + // Selector which must match a node's labels for the pod to be scheduled on that node. + // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty" protobuf:"bytes,7,rep,name=nodeSelector"` + // If specified, the pod's scheduling constraints + // +optional + Affinity *corev1.Affinity `json:"affinity,omitempty" protobuf:"bytes,18,opt,name=affinity"` + // If specified, the pod's tolerations. + // +optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"` + // Compute Resources required by this container. + // Cannot be updated. + // More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + // +optional + Resources *corev1.ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,8,opt,name=resources"` + // Receiver contains the information to make a connection with the alertmanager + // +optional + Receivers []Receiver `json:"receivers,omitempty" protobuf:"bytes,8,opt,name=receivers"` + + // AuditSinkPolicy is a rule selector, only the rule matched this selector will be taked effect. + // +optional + *AuditSinkPolicy `json:"auditSinkPolicy,omitempty" protobuf:"bytes,8,opt,name=auditSinkPolicy"` + // Rule priority, DEBUG < INFO < WARNING + //Audit events will be stored only when the priority of the audit rule + // matching the audit event is greater than this. + Priority string `json:"priority,omitempty" protobuf:"bytes,8,opt,name=priority"` + // Audit type, static or dynamic. + AuditType string `json:"auditType,omitempty" protobuf:"bytes,8,opt,name=auditType"` + // The Level that all requests are recorded at. + // available options: None, Metadata, Request, RequestResponse + // default: Metadata + // +optional + AuditLevel v1alpha1.Level `json:"auditLevel" protobuf:"bytes,1,opt,name=auditLevel"` + // K8s auditing is enabled or not. + K8sAuditingEnable bool `json:"k8sAuditingEnable,omitempty" protobuf:"bytes,8,opt,name=priority"` +} + +// WebhookStatus defines the observed state of Webhook +type WebhookStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +// +genclient +// +genclient:noStatus +// +genclient:nonNamespaced +// +kubebuilder:object:root=true + +// Webhook is the Schema for the webhooks API +type Webhook struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec WebhookSpec `json:"spec,omitempty"` + Status WebhookStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// WebhookList contains a list of Webhook +type WebhookList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Webhook `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Webhook{}, &WebhookList{}) +} diff --git a/pkg/apis/auditing/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/auditing/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 000000000..2737ab625 --- /dev/null +++ b/pkg/apis/auditing/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,202 @@ +// +build !ignore_autogenerated + +/* + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Rule) DeepCopyInto(out *Rule) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rule. +func (in *Rule) DeepCopy() *Rule { + if in == nil { + return nil + } + out := new(Rule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Rule) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuleList) DeepCopyInto(out *RuleList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Rule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleList. +func (in *RuleList) DeepCopy() *RuleList { + if in == nil { + return nil + } + out := new(RuleList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RuleList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuleSpec) DeepCopyInto(out *RuleSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleSpec. +func (in *RuleSpec) DeepCopy() *RuleSpec { + if in == nil { + return nil + } + out := new(RuleSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuleStatus) DeepCopyInto(out *RuleStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleStatus. +func (in *RuleStatus) DeepCopy() *RuleStatus { + if in == nil { + return nil + } + out := new(RuleStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Webhook) DeepCopyInto(out *Webhook) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Webhook. +func (in *Webhook) DeepCopy() *Webhook { + if in == nil { + return nil + } + out := new(Webhook) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Webhook) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebhookList) DeepCopyInto(out *WebhookList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Webhook, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookList. +func (in *WebhookList) DeepCopy() *WebhookList { + if in == nil { + return nil + } + out := new(WebhookList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *WebhookList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebhookSpec) DeepCopyInto(out *WebhookSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookSpec. +func (in *WebhookSpec) DeepCopy() *WebhookSpec { + if in == nil { + return nil + } + out := new(WebhookSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebhookStatus) DeepCopyInto(out *WebhookStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookStatus. +func (in *WebhookStatus) DeepCopy() *WebhookStatus { + if in == nil { + return nil + } + out := new(WebhookStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index c569c769b..0afd5ec74 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -27,6 +27,7 @@ import ( unionauth "k8s.io/apiserver/pkg/authentication/request/union" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" "k8s.io/klog" + audit "kubesphere.io/kubesphere/pkg/apiserver/auditing" "kubesphere.io/kubesphere/pkg/apiserver/authentication/authenticators/basic" "kubesphere.io/kubesphere/pkg/apiserver/authentication/authenticators/jwttoken" "kubesphere.io/kubesphere/pkg/apiserver/authentication/request/anonymous" @@ -243,6 +244,10 @@ func (s *APIServer) buildHandlerChain() { handler := s.Server.Handler handler = filters.WithKubeAPIServer(handler, s.KubernetesClient.Config(), &errorResponder{}) + if s.Config.AuditingOptions.Enabled { + handler = filters.WithAuditing(handler, audit.NewAuditing(s.InformerFactory.KubeSphereSharedInformerFactory().Auditing().V1alpha1().Webhooks().Lister())) + } + if s.Config.MultiClusterOptions.Enable { clusterDispatcher := dispatch.NewClusterDispatch(s.InformerFactory.KubeSphereSharedInformerFactory().Cluster().V1alpha1().Clusters(), s.InformerFactory.KubeSphereSharedInformerFactory().Cluster().V1alpha1().Clusters().Lister()) diff --git a/pkg/apiserver/auditing/backend.go b/pkg/apiserver/auditing/backend.go new file mode 100644 index 000000000..558f6f395 --- /dev/null +++ b/pkg/apiserver/auditing/backend.go @@ -0,0 +1,118 @@ +package auditing + +import ( + "bytes" + "context" + "crypto/tls" + "encoding/json" + "k8s.io/klog" + "net/http" + "os" + "os/signal" + "time" +) + +const ( + WaitTimeout = time.Second + WebhookURL = "https://kube-auditing-webhook-svc.kubesphere-logging-system.svc:443" +) + +type Backend struct { + channelCapacity int + semCh chan interface{} + cache chan *EventList + client http.Client + sendTimeout time.Duration + waitTimeout time.Duration +} + +func NewBackend(channelCapacity int, cache chan *EventList, sendTimeout time.Duration) *Backend { + + b := Backend{ + semCh: make(chan interface{}, channelCapacity), + channelCapacity: channelCapacity, + waitTimeout: WaitTimeout, + cache: cache, + sendTimeout: sendTimeout, + } + + b.client = http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + }, + Timeout: b.sendTimeout, + } + + go b.worker() + + return &b +} + +func (b *Backend) worker() { + + // Stop when receiver signal Interrupt. + stopCh := b.SetupSignalHandler() + + for { + + var event *EventList + select { + case event = <-b.cache: + if event == nil { + break + } + case <-stopCh: + break + } + + send := func(event *EventList) { + ctx, cancel := context.WithTimeout(context.Background(), b.waitTimeout) + defer cancel() + + select { + case <-ctx.Done(): + klog.Errorf("get goroutine for audit(%s) timeout", event.Items[0].AuditID) + return + case b.semCh <- struct{}{}: + } + + defer func() { + <-b.semCh + }() + + bs, err := json.Marshal(event) + if err != nil { + klog.Errorf("json marshal error, %s", err) + return + } + + response, err := b.client.Post(WebhookURL, "application/json", bytes.NewBuffer(bs)) + if err != nil { + klog.Errorf("send audit event[%s] error, %s", event.Items[0].AuditID, err) + return + } + + if response.StatusCode != http.StatusOK { + klog.Errorf("send audit event[%s] error[%d]", event.Items[0].AuditID, response.StatusCode) + return + } + } + + go send(event) + } +} + +func (b *Backend) SetupSignalHandler() (stopCh <-chan struct{}) { + + stop := make(chan struct{}) + c := make(chan os.Signal, 2) + signal.Notify(c, []os.Signal{os.Interrupt}...) + go func() { + <-c + close(stop) + }() + + return stop +} diff --git a/pkg/apiserver/auditing/types.go b/pkg/apiserver/auditing/types.go new file mode 100644 index 000000000..374f8277c --- /dev/null +++ b/pkg/apiserver/auditing/types.go @@ -0,0 +1,235 @@ +package auditing + +import ( + "bytes" + "github.com/google/uuid" + "io/ioutil" + "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apiserver/pkg/apis/audit" + "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/apiserver/request" + "kubesphere.io/kubesphere/pkg/client/listers/auditing/v1alpha1" + "kubesphere.io/kubesphere/pkg/utils/iputil" + "net/http" + "time" +) + +const ( + DefaultWebhook = "kube-auditing-webhook" + DefaultCacheCapacity = 10000 + CacheTimeout = time.Second + SendTimeout = time.Second * 3 + ChannelCapacity = 10 +) + +type Auditing interface { + Enable() bool + K8sAuditingEnable() bool + LogRequestObject(req *http.Request) *Event + LogResponseObject(e *Event, resp *ResponseCapture, info *request.RequestInfo) +} + +type Event struct { + //The workspace which this audit event happened + Workspace string + //The devops project which this audit event happened + Cluster string + + audit.Event +} + +type EventList struct { + Items []Event +} + +type auditing struct { + lister v1alpha1.WebhookLister + cache chan *EventList + backend *Backend +} + +func NewAuditing(lister v1alpha1.WebhookLister) Auditing { + + a := &auditing{ + lister: lister, + cache: make(chan *EventList, DefaultCacheCapacity), + } + + a.backend = NewBackend(ChannelCapacity, a.cache, SendTimeout) + return a +} + +func (a *auditing) getAuditLevel() audit.Level { + wh, err := a.lister.Get(DefaultWebhook) + if err != nil { + klog.Error(err) + return audit.LevelNone + } + + return (audit.Level)(wh.Spec.AuditLevel) +} + +func (a *auditing) Enable() bool { + + level := a.getAuditLevel() + if level.Less(audit.LevelMetadata) { + return false + } + return true +} + +func (a *auditing) K8sAuditingEnable() bool { + wh, err := a.lister.Get(DefaultWebhook) + if err != nil { + klog.Error(err) + return false + } + + return wh.Spec.K8sAuditingEnable +} + +func (a *auditing) LogRequestObject(req *http.Request) *Event { + e := &Event{ + Event: audit.Event{ + Level: a.getAuditLevel(), + AuditID: types.UID(uuid.New().String()), + Stage: audit.StageResponseComplete, + ImpersonatedUser: nil, + UserAgent: req.UserAgent(), + RequestReceivedTimestamp: v1.NewMicroTime(time.Now()), + Annotations: nil, + }, + } + + ips := make([]string, 1) + ips[0] = iputil.RemoteIp(req) + e.SourceIPs = ips + + user, ok := request.UserFrom(req.Context()) + if ok { + e.User.Username = user.GetName() + e.User.UID = user.GetUID() + e.User.Groups = user.GetGroups() + + for k, v := range user.GetExtra() { + e.User.Extra[k] = v + } + } + + if e.Level.GreaterOrEqual(audit.LevelRequest) && req.ContentLength > 0 { + body, err := ioutil.ReadAll(req.Body) + if err != nil { + klog.Error(err) + return e + } + _ = req.Body.Close() + req.Body = ioutil.NopCloser(bytes.NewBuffer(body)) + e.RequestObject = &runtime.Unknown{Raw: body} + } + + return e +} + +func (a *auditing) LogResponseObject(e *Event, resp *ResponseCapture, info *request.RequestInfo) { + + // Auditing should igonre k8s request when k8s auditing is enabled. + if info.IsKubernetesRequest && a.K8sAuditingEnable() { + return + } + + e.StageTimestamp = v1.NewMicroTime(time.Now()) + e.ResponseStatus = &v1.Status{Code: int32(resp.StatusCode())} + if e.Level.GreaterOrEqual(audit.LevelRequestResponse) { + e.ResponseObject = &runtime.Unknown{Raw: resp.Bytes()} + } + + // If the request is not a standard request, or a resource request, + // or part of the audit information cannot be obtained through url, + // the function that handles the request can obtain RequestInfo from + // the context of the request, assign value to audit information, + // including name, verb, resource, subresource, etc like this. + // + // info, ok := request.RequestInfoFrom(request.Request.Context()) + // if ok { + // info.Verb = "post" + // info.Name = created.Name + // } + // + e.Workspace = info.Workspace + e.Cluster = info.Cluster + e.RequestURI = info.Path + e.Verb = info.Verb + e.ObjectRef = &audit.ObjectReference{ + Resource: info.Resource, + Namespace: info.Namespace, + Name: info.Name, + UID: "", + APIGroup: info.APIGroup, + APIVersion: info.APIVersion, + ResourceVersion: info.ResourceScope, + Subresource: info.Subresource, + } + + a.cacheEvent(*e) +} + +func (a *auditing) cacheEvent(e Event) { + eventList := &EventList{} + eventList.Items = append(eventList.Items, e) + select { + case a.cache <- eventList: + return + case <-time.After(CacheTimeout): + klog.Errorf("cache audit event %s timeout", e.AuditID) + break + } +} + +type ResponseCapture struct { + http.ResponseWriter + wroteHeader bool + status int + body *bytes.Buffer + StopCh chan interface{} +} + +func NewResponseCapture(w http.ResponseWriter) *ResponseCapture { + return &ResponseCapture{ + ResponseWriter: w, + wroteHeader: false, + body: new(bytes.Buffer), + StopCh: make(chan interface{}, 1), + } +} + +func (c *ResponseCapture) Header() http.Header { + return c.ResponseWriter.Header() +} + +func (c *ResponseCapture) Write(data []byte) (int, error) { + + defer func() { + c.StopCh <- struct{}{} + }() + + c.WriteHeader(http.StatusOK) + c.body.Write(data) + return c.ResponseWriter.Write(data) +} + +func (c *ResponseCapture) WriteHeader(statusCode int) { + if !c.wroteHeader { + c.status = statusCode + c.wroteHeader = true + } +} + +func (c *ResponseCapture) Bytes() []byte { + return c.body.Bytes() +} + +func (c *ResponseCapture) StatusCode() int { + return c.status +} diff --git a/pkg/apiserver/auditing/types_test.go b/pkg/apiserver/auditing/types_test.go new file mode 100644 index 000000000..e9d7ad888 --- /dev/null +++ b/pkg/apiserver/auditing/types_test.go @@ -0,0 +1,273 @@ +package auditing + +import ( + "encoding/json" + "github.com/stretchr/testify/assert" + "k8s.io/api/auditregistration/v1alpha1" + v1 "k8s.io/api/authentication/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apiserver/pkg/apis/audit" + "k8s.io/apiserver/pkg/authentication/user" + k8srequest "k8s.io/apiserver/pkg/endpoints/request" + auditingv1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" + "kubesphere.io/kubesphere/pkg/apiserver/request" + "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" + ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions" + "kubesphere.io/kubesphere/pkg/utils/iputil" + "net/http" + "net/url" + "testing" + "time" +) + +var noResyncPeriodFunc = func() time.Duration { return 0 } + +func TestGetAuditLevel(t *testing.T) { + webhook := &auditingv1alpha1.Webhook{ + TypeMeta: metav1.TypeMeta{ + APIVersion: auditingv1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "kube-auditing-webhook", + }, + Spec: auditingv1alpha1.WebhookSpec{ + AuditLevel: v1alpha1.LevelRequestResponse, + }, + } + + informer := ksinformers.NewSharedInformerFactory(fake.NewSimpleClientset(), noResyncPeriodFunc()) + + a := auditing{ + lister: informer.Auditing().V1alpha1().Webhooks().Lister(), + } + + err := informer.Auditing().V1alpha1().Webhooks().Informer().GetIndexer().Add(webhook) + if err != nil { + panic(err) + } + + assert.Equal(t, string(webhook.Spec.AuditLevel), string(a.getAuditLevel())) +} + +func TestAuditing_Enable(t *testing.T) { + webhook := &auditingv1alpha1.Webhook{ + TypeMeta: metav1.TypeMeta{ + APIVersion: auditingv1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "kube-auditing-webhook", + }, + Spec: auditingv1alpha1.WebhookSpec{ + AuditLevel: v1alpha1.LevelNone, + }, + } + + informer := ksinformers.NewSharedInformerFactory(fake.NewSimpleClientset(), noResyncPeriodFunc()) + + a := auditing{ + lister: informer.Auditing().V1alpha1().Webhooks().Lister(), + } + + err := informer.Auditing().V1alpha1().Webhooks().Informer().GetIndexer().Add(webhook) + if err != nil { + panic(err) + } + + assert.Equal(t, false, a.Enable()) +} + +func TestAuditing_K8sAuditingEnable(t *testing.T) { + webhook := &auditingv1alpha1.Webhook{ + TypeMeta: metav1.TypeMeta{ + APIVersion: auditingv1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "kube-auditing-webhook", + }, + Spec: auditingv1alpha1.WebhookSpec{ + AuditLevel: v1alpha1.LevelNone, + K8sAuditingEnable: true, + }, + } + + informer := ksinformers.NewSharedInformerFactory(fake.NewSimpleClientset(), noResyncPeriodFunc()) + + a := auditing{ + lister: informer.Auditing().V1alpha1().Webhooks().Lister(), + } + + err := informer.Auditing().V1alpha1().Webhooks().Informer().GetIndexer().Add(webhook) + if err != nil { + panic(err) + } + + assert.Equal(t, true, a.K8sAuditingEnable()) +} + +func TestAuditing_LogRequestObject(t *testing.T) { + webhook := &auditingv1alpha1.Webhook{ + TypeMeta: metav1.TypeMeta{ + APIVersion: auditingv1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "kube-auditing-webhook", + }, + Spec: auditingv1alpha1.WebhookSpec{ + AuditLevel: v1alpha1.LevelRequestResponse, + K8sAuditingEnable: true, + }, + } + + informer := ksinformers.NewSharedInformerFactory(fake.NewSimpleClientset(), noResyncPeriodFunc()) + + a := auditing{ + lister: informer.Auditing().V1alpha1().Webhooks().Lister(), + } + + err := informer.Auditing().V1alpha1().Webhooks().Informer().GetIndexer().Add(webhook) + if err != nil { + panic(err) + } + + req := &http.Request{} + u, err := url.Parse("http://139.198.121.143:32306//kapis/tenant.kubesphere.io/v1alpha2/workspaces") + if err != nil { + panic(err) + } + + req.URL = u + req.Header = http.Header{} + req.Header.Add(iputil.XClientIP, "192.168.0.2") + req = req.WithContext(request.WithUser(req.Context(), &user.DefaultInfo{ + Name: "admin", + Groups: []string{ + "system", + }, + })) + + e := a.LogRequestObject(req) + + expectedEvent := &Event{ + Event: audit.Event{ + AuditID: e.AuditID, + Level: "RequestResponse", + Stage: "ResponseComplete", + User: v1.UserInfo{ + Username: "admin", + Groups: []string{ + "system", + }, + }, + SourceIPs: []string{ + "192.168.0.2", + }, + + RequestReceivedTimestamp: e.RequestReceivedTimestamp, + }, + } + + assert.Equal(t, expectedEvent, e) +} + +func TestAuditing_LogResponseObject(t *testing.T) { + webhook := &auditingv1alpha1.Webhook{ + TypeMeta: metav1.TypeMeta{ + APIVersion: auditingv1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "kube-auditing-webhook", + }, + Spec: auditingv1alpha1.WebhookSpec{ + AuditLevel: v1alpha1.LevelMetadata, + K8sAuditingEnable: true, + }, + } + + informer := ksinformers.NewSharedInformerFactory(fake.NewSimpleClientset(), noResyncPeriodFunc()) + + a := auditing{ + lister: informer.Auditing().V1alpha1().Webhooks().Lister(), + } + + err := informer.Auditing().V1alpha1().Webhooks().Informer().GetIndexer().Add(webhook) + if err != nil { + panic(err) + } + + req := &http.Request{} + u, err := url.Parse("http://139.198.121.143:32306//kapis/tenant.kubesphere.io/v1alpha2/workspaces") + if err != nil { + panic(err) + } + + req.URL = u + req.Header = http.Header{} + req.Header.Add(iputil.XClientIP, "192.168.0.2") + req = req.WithContext(request.WithUser(req.Context(), &user.DefaultInfo{ + Name: "admin", + Groups: []string{ + "system", + }, + })) + + e := a.LogRequestObject(req) + + info := &request.RequestInfo{ + RequestInfo: &k8srequest.RequestInfo{ + IsResourceRequest: false, + Path: "/kapis/tenant.kubesphere.io/v1alpha2/workspaces", + Verb: "create", + APIGroup: "tenant.kubesphere.io", + APIVersion: "v1alpha2", + Resource: "workspaces", + Name: "test", + }, + } + + resp := &ResponseCapture{} + resp.WriteHeader(200) + + a.LogResponseObject(e, resp, info) + + expectedEvent := &Event{ + Event: audit.Event{ + Verb: "create", + AuditID: e.AuditID, + Level: "Metadata", + Stage: "ResponseComplete", + User: v1.UserInfo{ + Username: "admin", + Groups: []string{ + "system", + }, + }, + SourceIPs: []string{ + "192.168.0.2", + }, + ObjectRef: &audit.ObjectReference{ + Resource: "workspaces", + Name: "test", + APIGroup: "tenant.kubesphere.io", + APIVersion: "v1alpha2", + }, + + RequestReceivedTimestamp: e.RequestReceivedTimestamp, + StageTimestamp: e.StageTimestamp, + RequestURI: "/kapis/tenant.kubesphere.io/v1alpha2/workspaces", + ResponseStatus: &metav1.Status{ + Code: 200, + }, + }, + } + + expectedBs, err := json.Marshal(expectedEvent) + if err != nil { + panic(err) + } + bs, err := json.Marshal(e) + if err != nil { + panic(err) + } + + assert.EqualValues(t, string(expectedBs), string(bs)) +} diff --git a/pkg/apiserver/filters/auditing.go b/pkg/apiserver/filters/auditing.go new file mode 100644 index 000000000..e57bd5f09 --- /dev/null +++ b/pkg/apiserver/filters/auditing.go @@ -0,0 +1,42 @@ +package filters + +import ( + "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/apiserver/auditing" + "kubesphere.io/kubesphere/pkg/apiserver/request" + "net/http" +) + +func WithAuditing(handler http.Handler, a auditing.Auditing) http.Handler { + + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + + // When auditing level is LevelNone, request should not be auditing. + if !a.Enable() { + handler.ServeHTTP(w, req) + return + } + + e := a.LogRequestObject(req) + resp := auditing.NewResponseCapture(w) + + // Create a new goroutine to finish the request, and wait for the response body. + // The advantage of using goroutine is that recording the return value of the + // request will not affect the processing of the request, even if the auditing fails. + go handler.ServeHTTP(resp, req) + + select { + case <-req.Context().Done(): + klog.Error("Server timeout") + return + case <-resp.StopCh: + info, ok := request.RequestInfoFrom(req.Context()) + if !ok { + klog.Error("Unable to retrieve request info from request") + return + } + a.LogResponseObject(e, resp, info) + return + } + }) +} diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index 7e84ccd33..58337e535 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -24,6 +24,7 @@ import ( discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" + auditingv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/auditing/v1alpha1" clusterv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/cluster/v1alpha1" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha1" devopsv1alpha3 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha3" @@ -37,6 +38,7 @@ import ( type Interface interface { Discovery() discovery.DiscoveryInterface + AuditingV1alpha1() auditingv1alpha1.AuditingV1alpha1Interface ClusterV1alpha1() clusterv1alpha1.ClusterV1alpha1Interface DevopsV1alpha1() devopsv1alpha1.DevopsV1alpha1Interface DevopsV1alpha3() devopsv1alpha3.DevopsV1alpha3Interface @@ -52,6 +54,7 @@ type Interface interface { // version included in a Clientset. type Clientset struct { *discovery.DiscoveryClient + auditingV1alpha1 *auditingv1alpha1.AuditingV1alpha1Client clusterV1alpha1 *clusterv1alpha1.ClusterV1alpha1Client devopsV1alpha1 *devopsv1alpha1.DevopsV1alpha1Client devopsV1alpha3 *devopsv1alpha3.DevopsV1alpha3Client @@ -63,6 +66,11 @@ type Clientset struct { tenantV1alpha2 *tenantv1alpha2.TenantV1alpha2Client } +// AuditingV1alpha1 retrieves the AuditingV1alpha1Client +func (c *Clientset) AuditingV1alpha1() auditingv1alpha1.AuditingV1alpha1Interface { + return c.auditingV1alpha1 +} + // ClusterV1alpha1 retrieves the ClusterV1alpha1Client func (c *Clientset) ClusterV1alpha1() clusterv1alpha1.ClusterV1alpha1Interface { return c.clusterV1alpha1 @@ -129,6 +137,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { } var cs Clientset var err error + cs.auditingV1alpha1, err = auditingv1alpha1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.clusterV1alpha1, err = clusterv1alpha1.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -177,6 +189,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { // panics if there is an error in the config. func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset + cs.auditingV1alpha1 = auditingv1alpha1.NewForConfigOrDie(c) cs.clusterV1alpha1 = clusterv1alpha1.NewForConfigOrDie(c) cs.devopsV1alpha1 = devopsv1alpha1.NewForConfigOrDie(c) cs.devopsV1alpha3 = devopsv1alpha3.NewForConfigOrDie(c) @@ -194,6 +207,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { // New creates a new Clientset for the given RESTClient. func New(c rest.Interface) *Clientset { var cs Clientset + cs.auditingV1alpha1 = auditingv1alpha1.New(c) cs.clusterV1alpha1 = clusterv1alpha1.New(c) cs.devopsV1alpha1 = devopsv1alpha1.New(c) cs.devopsV1alpha3 = devopsv1alpha3.New(c) diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index 097e6231c..0331db2c5 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -25,6 +25,8 @@ import ( fakediscovery "k8s.io/client-go/discovery/fake" "k8s.io/client-go/testing" clientset "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + auditingv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/auditing/v1alpha1" + fakeauditingv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake" clusterv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/cluster/v1alpha1" fakeclusterv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/cluster/v1alpha1/fake" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha1" @@ -92,6 +94,11 @@ func (c *Clientset) Tracker() testing.ObjectTracker { var _ clientset.Interface = &Clientset{} +// AuditingV1alpha1 retrieves the AuditingV1alpha1Client +func (c *Clientset) AuditingV1alpha1() auditingv1alpha1.AuditingV1alpha1Interface { + return &fakeauditingv1alpha1.FakeAuditingV1alpha1{Fake: &c.Fake} +} + // ClusterV1alpha1 retrieves the ClusterV1alpha1Client func (c *Clientset) ClusterV1alpha1() clusterv1alpha1.ClusterV1alpha1Interface { return &fakeclusterv1alpha1.FakeClusterV1alpha1{Fake: &c.Fake} diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go index a13e057be..fff9dcf05 100644 --- a/pkg/client/clientset/versioned/fake/register.go +++ b/pkg/client/clientset/versioned/fake/register.go @@ -24,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + auditingv1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" clusterv1alpha1 "kubesphere.io/kubesphere/pkg/apis/cluster/v1alpha1" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" devopsv1alpha3 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3" @@ -39,6 +40,7 @@ var scheme = runtime.NewScheme() var codecs = serializer.NewCodecFactory(scheme) var parameterCodec = runtime.NewParameterCodec(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ + auditingv1alpha1.AddToScheme, clusterv1alpha1.AddToScheme, devopsv1alpha1.AddToScheme, devopsv1alpha3.AddToScheme, diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go index 3df91bba9..2328c7a5e 100644 --- a/pkg/client/clientset/versioned/scheme/register.go +++ b/pkg/client/clientset/versioned/scheme/register.go @@ -24,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + auditingv1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" clusterv1alpha1 "kubesphere.io/kubesphere/pkg/apis/cluster/v1alpha1" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" devopsv1alpha3 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3" @@ -39,6 +40,7 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) var localSchemeBuilder = runtime.SchemeBuilder{ + auditingv1alpha1.AddToScheme, clusterv1alpha1.AddToScheme, devopsv1alpha1.AddToScheme, devopsv1alpha3.AddToScheme, diff --git a/pkg/client/clientset/versioned/typed/auditing/v1alpha1/auditing_client.go b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/auditing_client.go new file mode 100644 index 000000000..aaf7b7d07 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/auditing_client.go @@ -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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + rest "k8s.io/client-go/rest" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" + "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +type AuditingV1alpha1Interface interface { + RESTClient() rest.Interface + RulesGetter + WebhooksGetter +} + +// AuditingV1alpha1Client is used to interact with features provided by the auditing.kubesphere.io group. +type AuditingV1alpha1Client struct { + restClient rest.Interface +} + +func (c *AuditingV1alpha1Client) Rules() RuleInterface { + return newRules(c) +} + +func (c *AuditingV1alpha1Client) Webhooks() WebhookInterface { + return newWebhooks(c) +} + +// NewForConfig creates a new AuditingV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*AuditingV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &AuditingV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new AuditingV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *AuditingV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new AuditingV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *AuditingV1alpha1Client { + return &AuditingV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *AuditingV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/client/clientset/versioned/typed/auditing/v1alpha1/doc.go b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/doc.go new file mode 100644 index 000000000..769278743 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/doc.go b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/doc.go new file mode 100644 index 000000000..7e36dbca8 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/fake_auditing_client.go b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/fake_auditing_client.go new file mode 100644 index 000000000..bd239b674 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/fake_auditing_client.go @@ -0,0 +1,44 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/auditing/v1alpha1" +) + +type FakeAuditingV1alpha1 struct { + *testing.Fake +} + +func (c *FakeAuditingV1alpha1) Rules() v1alpha1.RuleInterface { + return &FakeRules{c} +} + +func (c *FakeAuditingV1alpha1) Webhooks() v1alpha1.WebhookInterface { + return &FakeWebhooks{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeAuditingV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/fake_rule.go b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/fake_rule.go new file mode 100644 index 000000000..2f2bfd393 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/fake_rule.go @@ -0,0 +1,120 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" +) + +// FakeRules implements RuleInterface +type FakeRules struct { + Fake *FakeAuditingV1alpha1 +} + +var rulesResource = schema.GroupVersionResource{Group: "auditing.kubesphere.io", Version: "v1alpha1", Resource: "rules"} + +var rulesKind = schema.GroupVersionKind{Group: "auditing.kubesphere.io", Version: "v1alpha1", Kind: "Rule"} + +// Get takes name of the rule, and returns the corresponding rule object, and an error if there is any. +func (c *FakeRules) Get(name string, options v1.GetOptions) (result *v1alpha1.Rule, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(rulesResource, name), &v1alpha1.Rule{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Rule), err +} + +// List takes label and field selectors, and returns the list of Rules that match those selectors. +func (c *FakeRules) List(opts v1.ListOptions) (result *v1alpha1.RuleList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(rulesResource, rulesKind, opts), &v1alpha1.RuleList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.RuleList{ListMeta: obj.(*v1alpha1.RuleList).ListMeta} + for _, item := range obj.(*v1alpha1.RuleList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested rules. +func (c *FakeRules) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(rulesResource, opts)) +} + +// Create takes the representation of a rule and creates it. Returns the server's representation of the rule, and an error, if there is any. +func (c *FakeRules) Create(rule *v1alpha1.Rule) (result *v1alpha1.Rule, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(rulesResource, rule), &v1alpha1.Rule{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Rule), err +} + +// Update takes the representation of a rule and updates it. Returns the server's representation of the rule, and an error, if there is any. +func (c *FakeRules) Update(rule *v1alpha1.Rule) (result *v1alpha1.Rule, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(rulesResource, rule), &v1alpha1.Rule{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Rule), err +} + +// Delete takes name of the rule and deletes it. Returns an error if one occurs. +func (c *FakeRules) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(rulesResource, name), &v1alpha1.Rule{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeRules) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(rulesResource, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.RuleList{}) + return err +} + +// Patch applies the patch and returns the patched rule. +func (c *FakeRules) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Rule, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(rulesResource, name, pt, data, subresources...), &v1alpha1.Rule{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Rule), err +} diff --git a/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/fake_webhook.go b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/fake_webhook.go new file mode 100644 index 000000000..26fe8095a --- /dev/null +++ b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/fake/fake_webhook.go @@ -0,0 +1,120 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" +) + +// FakeWebhooks implements WebhookInterface +type FakeWebhooks struct { + Fake *FakeAuditingV1alpha1 +} + +var webhooksResource = schema.GroupVersionResource{Group: "auditing.kubesphere.io", Version: "v1alpha1", Resource: "webhooks"} + +var webhooksKind = schema.GroupVersionKind{Group: "auditing.kubesphere.io", Version: "v1alpha1", Kind: "Webhook"} + +// Get takes name of the webhook, and returns the corresponding webhook object, and an error if there is any. +func (c *FakeWebhooks) Get(name string, options v1.GetOptions) (result *v1alpha1.Webhook, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(webhooksResource, name), &v1alpha1.Webhook{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Webhook), err +} + +// List takes label and field selectors, and returns the list of Webhooks that match those selectors. +func (c *FakeWebhooks) List(opts v1.ListOptions) (result *v1alpha1.WebhookList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(webhooksResource, webhooksKind, opts), &v1alpha1.WebhookList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.WebhookList{ListMeta: obj.(*v1alpha1.WebhookList).ListMeta} + for _, item := range obj.(*v1alpha1.WebhookList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested webhooks. +func (c *FakeWebhooks) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(webhooksResource, opts)) +} + +// Create takes the representation of a webhook and creates it. Returns the server's representation of the webhook, and an error, if there is any. +func (c *FakeWebhooks) Create(webhook *v1alpha1.Webhook) (result *v1alpha1.Webhook, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(webhooksResource, webhook), &v1alpha1.Webhook{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Webhook), err +} + +// Update takes the representation of a webhook and updates it. Returns the server's representation of the webhook, and an error, if there is any. +func (c *FakeWebhooks) Update(webhook *v1alpha1.Webhook) (result *v1alpha1.Webhook, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(webhooksResource, webhook), &v1alpha1.Webhook{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Webhook), err +} + +// Delete takes name of the webhook and deletes it. Returns an error if one occurs. +func (c *FakeWebhooks) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(webhooksResource, name), &v1alpha1.Webhook{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeWebhooks) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(webhooksResource, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.WebhookList{}) + return err +} + +// Patch applies the patch and returns the patched webhook. +func (c *FakeWebhooks) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Webhook, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(webhooksResource, name, pt, data, subresources...), &v1alpha1.Webhook{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Webhook), err +} diff --git a/pkg/client/clientset/versioned/typed/auditing/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/generated_expansion.go new file mode 100644 index 000000000..d7ee8c185 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/generated_expansion.go @@ -0,0 +1,23 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type RuleExpansion interface{} + +type WebhookExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/auditing/v1alpha1/rule.go b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/rule.go new file mode 100644 index 000000000..e94ce50a1 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/rule.go @@ -0,0 +1,164 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" + scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +// RulesGetter has a method to return a RuleInterface. +// A group's client should implement this interface. +type RulesGetter interface { + Rules() RuleInterface +} + +// RuleInterface has methods to work with Rule resources. +type RuleInterface interface { + Create(*v1alpha1.Rule) (*v1alpha1.Rule, error) + Update(*v1alpha1.Rule) (*v1alpha1.Rule, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.Rule, error) + List(opts v1.ListOptions) (*v1alpha1.RuleList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Rule, err error) + RuleExpansion +} + +// rules implements RuleInterface +type rules struct { + client rest.Interface +} + +// newRules returns a Rules +func newRules(c *AuditingV1alpha1Client) *rules { + return &rules{ + client: c.RESTClient(), + } +} + +// Get takes name of the rule, and returns the corresponding rule object, and an error if there is any. +func (c *rules) Get(name string, options v1.GetOptions) (result *v1alpha1.Rule, err error) { + result = &v1alpha1.Rule{} + err = c.client.Get(). + Resource("rules"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Rules that match those selectors. +func (c *rules) List(opts v1.ListOptions) (result *v1alpha1.RuleList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.RuleList{} + err = c.client.Get(). + Resource("rules"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested rules. +func (c *rules) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("rules"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a rule and creates it. Returns the server's representation of the rule, and an error, if there is any. +func (c *rules) Create(rule *v1alpha1.Rule) (result *v1alpha1.Rule, err error) { + result = &v1alpha1.Rule{} + err = c.client.Post(). + Resource("rules"). + Body(rule). + Do(). + Into(result) + return +} + +// Update takes the representation of a rule and updates it. Returns the server's representation of the rule, and an error, if there is any. +func (c *rules) Update(rule *v1alpha1.Rule) (result *v1alpha1.Rule, err error) { + result = &v1alpha1.Rule{} + err = c.client.Put(). + Resource("rules"). + Name(rule.Name). + Body(rule). + Do(). + Into(result) + return +} + +// Delete takes name of the rule and deletes it. Returns an error if one occurs. +func (c *rules) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("rules"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *rules) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("rules"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched rule. +func (c *rules) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Rule, err error) { + result = &v1alpha1.Rule{} + err = c.client.Patch(pt). + Resource("rules"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/auditing/v1alpha1/webhook.go b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/webhook.go new file mode 100644 index 000000000..9fae7b692 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/auditing/v1alpha1/webhook.go @@ -0,0 +1,164 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" + scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +// WebhooksGetter has a method to return a WebhookInterface. +// A group's client should implement this interface. +type WebhooksGetter interface { + Webhooks() WebhookInterface +} + +// WebhookInterface has methods to work with Webhook resources. +type WebhookInterface interface { + Create(*v1alpha1.Webhook) (*v1alpha1.Webhook, error) + Update(*v1alpha1.Webhook) (*v1alpha1.Webhook, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.Webhook, error) + List(opts v1.ListOptions) (*v1alpha1.WebhookList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Webhook, err error) + WebhookExpansion +} + +// webhooks implements WebhookInterface +type webhooks struct { + client rest.Interface +} + +// newWebhooks returns a Webhooks +func newWebhooks(c *AuditingV1alpha1Client) *webhooks { + return &webhooks{ + client: c.RESTClient(), + } +} + +// Get takes name of the webhook, and returns the corresponding webhook object, and an error if there is any. +func (c *webhooks) Get(name string, options v1.GetOptions) (result *v1alpha1.Webhook, err error) { + result = &v1alpha1.Webhook{} + err = c.client.Get(). + Resource("webhooks"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Webhooks that match those selectors. +func (c *webhooks) List(opts v1.ListOptions) (result *v1alpha1.WebhookList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.WebhookList{} + err = c.client.Get(). + Resource("webhooks"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested webhooks. +func (c *webhooks) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("webhooks"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a webhook and creates it. Returns the server's representation of the webhook, and an error, if there is any. +func (c *webhooks) Create(webhook *v1alpha1.Webhook) (result *v1alpha1.Webhook, err error) { + result = &v1alpha1.Webhook{} + err = c.client.Post(). + Resource("webhooks"). + Body(webhook). + Do(). + Into(result) + return +} + +// Update takes the representation of a webhook and updates it. Returns the server's representation of the webhook, and an error, if there is any. +func (c *webhooks) Update(webhook *v1alpha1.Webhook) (result *v1alpha1.Webhook, err error) { + result = &v1alpha1.Webhook{} + err = c.client.Put(). + Resource("webhooks"). + Name(webhook.Name). + Body(webhook). + Do(). + Into(result) + return +} + +// Delete takes name of the webhook and deletes it. Returns an error if one occurs. +func (c *webhooks) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("webhooks"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *webhooks) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("webhooks"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched webhook. +func (c *webhooks) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Webhook, err error) { + result = &v1alpha1.Webhook{} + err = c.client.Patch(pt). + Resource("webhooks"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/informers/externalversions/auditing/interface.go b/pkg/client/informers/externalversions/auditing/interface.go new file mode 100644 index 000000000..79d34680f --- /dev/null +++ b/pkg/client/informers/externalversions/auditing/interface.go @@ -0,0 +1,46 @@ +/* +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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package auditing + +import ( + v1alpha1 "kubesphere.io/kubesphere/pkg/client/informers/externalversions/auditing/v1alpha1" + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/client/informers/externalversions/auditing/v1alpha1/interface.go b/pkg/client/informers/externalversions/auditing/v1alpha1/interface.go new file mode 100644 index 000000000..b1a5f2fe9 --- /dev/null +++ b/pkg/client/informers/externalversions/auditing/v1alpha1/interface.go @@ -0,0 +1,52 @@ +/* +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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // Rules returns a RuleInformer. + Rules() RuleInformer + // Webhooks returns a WebhookInformer. + Webhooks() WebhookInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// Rules returns a RuleInformer. +func (v *version) Rules() RuleInformer { + return &ruleInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// Webhooks returns a WebhookInformer. +func (v *version) Webhooks() WebhookInformer { + return &webhookInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/informers/externalversions/auditing/v1alpha1/rule.go b/pkg/client/informers/externalversions/auditing/v1alpha1/rule.go new file mode 100644 index 000000000..487ac3361 --- /dev/null +++ b/pkg/client/informers/externalversions/auditing/v1alpha1/rule.go @@ -0,0 +1,88 @@ +/* +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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + auditingv1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" + versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "kubesphere.io/kubesphere/pkg/client/listers/auditing/v1alpha1" +) + +// RuleInformer provides access to a shared informer and lister for +// Rules. +type RuleInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.RuleLister +} + +type ruleInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewRuleInformer constructs a new informer for Rule type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewRuleInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredRuleInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredRuleInformer constructs a new informer for Rule type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredRuleInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.AuditingV1alpha1().Rules().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.AuditingV1alpha1().Rules().Watch(options) + }, + }, + &auditingv1alpha1.Rule{}, + resyncPeriod, + indexers, + ) +} + +func (f *ruleInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredRuleInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *ruleInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&auditingv1alpha1.Rule{}, f.defaultInformer) +} + +func (f *ruleInformer) Lister() v1alpha1.RuleLister { + return v1alpha1.NewRuleLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/auditing/v1alpha1/webhook.go b/pkg/client/informers/externalversions/auditing/v1alpha1/webhook.go new file mode 100644 index 000000000..a5a5b0b2b --- /dev/null +++ b/pkg/client/informers/externalversions/auditing/v1alpha1/webhook.go @@ -0,0 +1,88 @@ +/* +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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + auditingv1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" + versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "kubesphere.io/kubesphere/pkg/client/listers/auditing/v1alpha1" +) + +// WebhookInformer provides access to a shared informer and lister for +// Webhooks. +type WebhookInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.WebhookLister +} + +type webhookInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewWebhookInformer constructs a new informer for Webhook type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewWebhookInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredWebhookInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredWebhookInformer constructs a new informer for Webhook type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredWebhookInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.AuditingV1alpha1().Webhooks().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.AuditingV1alpha1().Webhooks().Watch(options) + }, + }, + &auditingv1alpha1.Webhook{}, + resyncPeriod, + indexers, + ) +} + +func (f *webhookInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredWebhookInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *webhookInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&auditingv1alpha1.Webhook{}, f.defaultInformer) +} + +func (f *webhookInformer) Lister() v1alpha1.WebhookLister { + return v1alpha1.NewWebhookLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index 866649404..704195cb6 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -28,6 +28,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + auditing "kubesphere.io/kubesphere/pkg/client/informers/externalversions/auditing" cluster "kubesphere.io/kubesphere/pkg/client/informers/externalversions/cluster" devops "kubesphere.io/kubesphere/pkg/client/informers/externalversions/devops" iam "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam" @@ -178,6 +179,7 @@ type SharedInformerFactory interface { ForResource(resource schema.GroupVersionResource) (GenericInformer, error) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + Auditing() auditing.Interface Cluster() cluster.Interface Devops() devops.Interface Iam() iam.Interface @@ -187,6 +189,10 @@ type SharedInformerFactory interface { Tenant() tenant.Interface } +func (f *sharedInformerFactory) Auditing() auditing.Interface { + return auditing.New(f, f.namespace, f.tweakListOptions) +} + func (f *sharedInformerFactory) Cluster() cluster.Interface { return cluster.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 71d7a2028..46e13a473 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -23,7 +23,8 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" - v1alpha1 "kubesphere.io/kubesphere/pkg/apis/cluster/v1alpha1" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" + clusterv1alpha1 "kubesphere.io/kubesphere/pkg/apis/cluster/v1alpha1" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" v1alpha3 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3" v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" @@ -60,8 +61,14 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=cluster.kubesphere.io, Version=v1alpha1 - case v1alpha1.SchemeGroupVersion.WithResource("clusters"): + // Group=auditing.kubesphere.io, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("rules"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Auditing().V1alpha1().Rules().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("webhooks"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Auditing().V1alpha1().Webhooks().Informer()}, nil + + // Group=cluster.kubesphere.io, Version=v1alpha1 + case clusterv1alpha1.SchemeGroupVersion.WithResource("clusters"): return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1alpha1().Clusters().Informer()}, nil // Group=devops.kubesphere.io, Version=v1alpha1 diff --git a/pkg/client/listers/auditing/v1alpha1/expansion_generated.go b/pkg/client/listers/auditing/v1alpha1/expansion_generated.go new file mode 100644 index 000000000..5b4b62ddf --- /dev/null +++ b/pkg/client/listers/auditing/v1alpha1/expansion_generated.go @@ -0,0 +1,27 @@ +/* +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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// RuleListerExpansion allows custom methods to be added to +// RuleLister. +type RuleListerExpansion interface{} + +// WebhookListerExpansion allows custom methods to be added to +// WebhookLister. +type WebhookListerExpansion interface{} diff --git a/pkg/client/listers/auditing/v1alpha1/rule.go b/pkg/client/listers/auditing/v1alpha1/rule.go new file mode 100644 index 000000000..9f7dc8896 --- /dev/null +++ b/pkg/client/listers/auditing/v1alpha1/rule.go @@ -0,0 +1,65 @@ +/* +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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" +) + +// RuleLister helps list Rules. +type RuleLister interface { + // List lists all Rules in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.Rule, err error) + // Get retrieves the Rule from the index for a given name. + Get(name string) (*v1alpha1.Rule, error) + RuleListerExpansion +} + +// ruleLister implements the RuleLister interface. +type ruleLister struct { + indexer cache.Indexer +} + +// NewRuleLister returns a new RuleLister. +func NewRuleLister(indexer cache.Indexer) RuleLister { + return &ruleLister{indexer: indexer} +} + +// List lists all Rules in the indexer. +func (s *ruleLister) List(selector labels.Selector) (ret []*v1alpha1.Rule, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Rule)) + }) + return ret, err +} + +// Get retrieves the Rule from the index for a given name. +func (s *ruleLister) Get(name string) (*v1alpha1.Rule, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("rule"), name) + } + return obj.(*v1alpha1.Rule), nil +} diff --git a/pkg/client/listers/auditing/v1alpha1/webhook.go b/pkg/client/listers/auditing/v1alpha1/webhook.go new file mode 100644 index 000000000..6e484586d --- /dev/null +++ b/pkg/client/listers/auditing/v1alpha1/webhook.go @@ -0,0 +1,65 @@ +/* +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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/auditing/v1alpha1" +) + +// WebhookLister helps list Webhooks. +type WebhookLister interface { + // List lists all Webhooks in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.Webhook, err error) + // Get retrieves the Webhook from the index for a given name. + Get(name string) (*v1alpha1.Webhook, error) + WebhookListerExpansion +} + +// webhookLister implements the WebhookLister interface. +type webhookLister struct { + indexer cache.Indexer +} + +// NewWebhookLister returns a new WebhookLister. +func NewWebhookLister(indexer cache.Indexer) WebhookLister { + return &webhookLister{indexer: indexer} +} + +// List lists all Webhooks in the indexer. +func (s *webhookLister) List(selector labels.Selector) (ret []*v1alpha1.Webhook, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Webhook)) + }) + return ret, err +} + +// Get retrieves the Webhook from the index for a given name. +func (s *webhookLister) Get(name string) (*v1alpha1.Webhook, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("webhook"), name) + } + return obj.(*v1alpha1.Webhook), nil +} diff --git a/pkg/controller/auditing/auditing_controller.go b/pkg/controller/auditing/auditing_controller.go new file mode 100644 index 000000000..aa0a0c1f4 --- /dev/null +++ b/pkg/controller/auditing/auditing_controller.go @@ -0,0 +1,144 @@ +/* + + 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 ( + "fmt" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog" + kubespherescheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" + auditinginformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/auditing/v1alpha1" + auditinglister "kubesphere.io/kubesphere/pkg/client/listers/auditing/v1alpha1" + "time" +) + +type Controller struct { + auditingLister auditinglister.WebhookLister + auditingSynced cache.InformerSynced + workQueue workqueue.RateLimitingInterface +} + +func NewController(informer auditinginformer.WebhookInformer) *Controller { + // Create auditing webhook informer + + utilruntime.Must(kubespherescheme.AddToScheme(scheme.Scheme)) + + return &Controller{ + auditingLister: informer.Lister(), + auditingSynced: informer.Informer().HasSynced, + workQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "auditing"), + } +} + +func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error { + defer utilruntime.HandleCrash() + defer c.workQueue.ShutDown() + + //init client + + // Start the informer factories to begin populating the informer caches + klog.Info("Starting User controller") + + // Wait for the caches to be synced before starting workers + klog.Info("Waiting for informer caches to sync") + if ok := cache.WaitForCacheSync(stopCh, c.auditingSynced); !ok { + return fmt.Errorf("failed to wait for caches to sync") + } + + klog.Info("Starting workers") + // Launch two workers to process Foo resources + for i := 0; i < threadiness; i++ { + go wait.Until(c.runWorker, time.Second, stopCh) + } + + klog.Info("Started workers") + <-stopCh + klog.Info("Shutting down workers") + return nil +} + +func (c *Controller) enqueueUser(obj interface{}) { + var key string + var err error + if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil { + utilruntime.HandleError(err) + return + } + c.workQueue.Add(key) +} + +func (c *Controller) runWorker() { + for c.processNextWorkItem() { + } +} + +func (c *Controller) processNextWorkItem() bool { + obj, shutdown := c.workQueue.Get() + + if shutdown { + return false + } + + // We wrap this block in a func so we can defer c.workqueue.Done. + err := func(obj interface{}) error { + // We call Done here so the workqueue knows we have finished + // processing this item. We also must remember to call Forget if we + // do not want this work item being re-queued. For example, we do + // not call Forget if a transient error occurs, instead the item is + // put back on the workqueue and attempted again after a back-off + // period. + defer c.workQueue.Done(obj) + var key string + var ok bool + // We expect strings to come off the workqueue. These are of the + // form namespace/name. We do this as the delayed nature of the + // workqueue means the items in the informer cache may actually be + // more up to date that when the item was initially put onto the + // workqueue. + if key, ok = obj.(string); !ok { + // As the item in the workqueue is actually invalid, we call + // Forget here else we'd go into a loop of attempting to + // process a work item that is invalid. + c.workQueue.Forget(obj) + utilruntime.HandleError(fmt.Errorf("expected string in workqueue but got %#v", obj)) + return nil + } + + // Finally, if no error occurs we Forget this item so it does not + // get queued again until another change happens. + c.workQueue.Forget(obj) + klog.Infof("Successfully synced %s:%s", "key", key) + return nil + }(obj) + + if err != nil { + utilruntime.HandleError(err) + return true + } + + return true +} + +func (c *Controller) Start(stopCh <-chan struct{}) error { + return c.Run(4, stopCh) +} diff --git a/pkg/simple/client/auditing/elasticsearch/options.go b/pkg/simple/client/auditing/elasticsearch/options.go index 7809c25a5..b1be3a714 100644 --- a/pkg/simple/client/auditing/elasticsearch/options.go +++ b/pkg/simple/client/auditing/elasticsearch/options.go @@ -22,6 +22,7 @@ import ( ) type Options struct { + Enabled bool `json:"enabled" yaml:"enabled"` Host string `json:"host" yaml:"host"` IndexPrefix string `json:"indexPrefix,omitempty" yaml:"indexPrefix"` Version string `json:"version" yaml:"version"` @@ -47,6 +48,7 @@ func (s *Options) Validate() []error { } func (s *Options) AddFlags(fs *pflag.FlagSet, c *Options) { + fs.BoolVar(&s.Enabled, "auditing-enabled", c.Enabled, "Enable auditing component or not. ") fs.StringVar(&s.Host, "auditing-elasticsearch-host", c.Host, ""+ "Elasticsearch service host. KubeSphere is using elastic as auditing store, "+ "if this filed left blank, KubeSphere will use kubernetes builtin event API instead, and"+