diff --git a/Makefile b/Makefile index cfe1de19..c4dcddb1 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,10 @@ SHELL = /usr/bin/env bash -o pipefail .PHONY: all all: build +.PHONY: cleanup +cleanup: + @kubectl delete si --all && kubectl delete sib --all -A && kubectl delete csib --all -A && kubectl delete np --all -A && kubectl delete cwnp --all -A + ##@ General # The help target prints out all targets with their descriptions organized @@ -54,7 +58,7 @@ manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and Cust .PHONY: generate generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. - $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./pkg/..." + $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./api/..." .PHONY: fmt fmt: ## Run go fmt against code. @@ -181,4 +185,4 @@ $(CONTROLLER_GEN): $(LOCALBIN) .PHONY: envtest envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. $(ENVTEST): $(LOCALBIN) - test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest \ No newline at end of file + test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest diff --git a/PROJECT b/PROJECT index 9096c4eb..1d759f06 100644 --- a/PROJECT +++ b/PROJECT @@ -26,4 +26,20 @@ resources: kind: NimbusPolicy path: github.com/5GSEC/nimbus/api/v1 version: v1 +- api: + crdVersion: v1 + controller: true + domain: security.nimbus.com + group: intent + kind: ClusterNimbusPolicy + path: github.com/5GSEC/nimbus/api/v1 + version: v1 +- api: + crdVersion: v1 + controller: true + domain: security.nimbus.com + group: intent + kind: ClusterSecurityIntentBinding + path: github.com/5GSEC/nimbus/api/v1 + version: v1 version: "3" diff --git a/api/v1/clusternimbuspolicy_types.go b/api/v1/clusternimbuspolicy_types.go new file mode 100644 index 00000000..369d6048 --- /dev/null +++ b/api/v1/clusternimbuspolicy_types.go @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ClusterNimbusPolicySpec defines the desired state of ClusterNimbusPolicy +type ClusterNimbusPolicySpec struct { + Selector CwSelector `json:"selector"` + NimbusRules []NimbusRules `json:"rules"` +} + +// ClusterNimbusPolicyStatus defines the observed state of ClusterNimbusPolicy +type ClusterNimbusPolicyStatus struct { + Status string `json:"status"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +//+kubebuilder:resource:scope=Cluster,shortName="cwnp" +//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ClusterNimbusPolicy is the Schema for the clusternimbuspolicies API +type ClusterNimbusPolicy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ClusterNimbusPolicySpec `json:"spec,omitempty"` + Status ClusterNimbusPolicyStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// ClusterNimbusPolicyList contains a list of ClusterNimbusPolicy +type ClusterNimbusPolicyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ClusterNimbusPolicy `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ClusterNimbusPolicy{}, &ClusterNimbusPolicyList{}) +} diff --git a/api/v1/clustersecurityintentbinding_types.go b/api/v1/clustersecurityintentbinding_types.go new file mode 100644 index 00000000..515a8173 --- /dev/null +++ b/api/v1/clustersecurityintentbinding_types.go @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type CwResource struct { + Kind string `json:"kind"` + Name string `json:"name"` + Namespace string `json:"namespace,omitempty"` + MatchLabels map[string]string `json:"matchLabels,omitempty"` +} + +type CwSelector struct { + Resources []CwResource `json:"resources,omitempty"` + CEL []string `json:"cel,omitempty"` +} + +// ClusterSecurityIntentBindingSpec defines the desired state of ClusterSecurityIntentBinding +type ClusterSecurityIntentBindingSpec struct { + Intents []MatchIntent `json:"intents"` + Selector CwSelector `json:"selector"` +} + +// ClusterSecurityIntentBindingStatus defines the observed state of ClusterSecurityIntentBinding +type ClusterSecurityIntentBindingStatus struct { + Status string `json:"status"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +//+kubebuilder:resource:scope=Cluster,shortName="csib" +//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ClusterSecurityIntentBinding is the Schema for the clustersecurityintentbindings API +type ClusterSecurityIntentBinding struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ClusterSecurityIntentBindingSpec `json:"spec,omitempty"` + Status ClusterSecurityIntentBindingStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// ClusterSecurityIntentBindingList contains a list of ClusterSecurityIntentBinding +type ClusterSecurityIntentBindingList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ClusterSecurityIntentBinding `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ClusterSecurityIntentBinding{}, &ClusterSecurityIntentBindingList{}) +} diff --git a/api/v1/nimbuspolicy_types.go b/api/v1/nimbuspolicy_types.go index 8e85ff14..aa6bafdf 100644 --- a/api/v1/nimbuspolicy_types.go +++ b/api/v1/nimbuspolicy_types.go @@ -7,14 +7,8 @@ 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. - // NimbusPolicySpec defines the desired state of NimbusPolicy type NimbusPolicySpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file - // Selector specifies the target resources to which the policy applies Selector NimbusSelector `json:"selector"` @@ -30,107 +24,21 @@ type NimbusSelector struct { // NimbusRules represents a single policy rule with an ID, type, description, and detailed rule configurations. type NimbusRules struct { - Id string `json:"id"` + ID string `json:"id"` Type string `json:"type,omitempty"` Description string `json:"description,omitempty"` - Rule []Rule `json:"rule"` + Rule Rule `json:"rule"` } type Rule struct { - RuleAction string `json:"action"` - - // Network: MatchProtocols - MatchProtocols []MatchProtocol `json:"matchProtocols,omitempty"` - - // Process: MatchPaths, MatchDirectories, MatchPatterns - // File: MatchPaths, MatchDirectories, MatchPatterns - MatchPaths []MatchPath `json:"matchPaths,omitempty"` - MatchDirectories []MatchDirectory `json:"matchDirectories,omitempty"` - MatchPatterns []MatchPattern `json:"matchPatterns,omitempty"` - - // Capabilities: MatchCapabilities - MatchCapabilities []MatchCapability `json:"matchCapabilities,omitempty"` - - // Syscalls: MatchSyscalls - MatchSyscalls []MatchSyscall `json:"matchSyscalls,omitempty"` - MatchSyscallPaths []MatchSyscallPath `json:"matchSyscallPaths,omitempty"` - - FromCIDRSet []CIDRSet `json:"fromCIDRSet,omitempty"` - ToPorts []ToPort `json:"toPorts,omitempty"` -} - -// CIDRSet defines CIDR ranges for network policies -type CIDRSet struct { - CIDR string `json:"cidr,omitempty"` -} - -// ToPort defines ports and protocols for network policies -type ToPort struct { - Ports []Port `json:"ports,omitempty"` -} - -// Port defines a network port and its protocol -type Port struct { - Port string `json:"port,omitempty"` - Protocol string `json:"protocol,omitempty"` -} - -// MatchProtocol defines a protocol for network policies -type MatchProtocol struct { - Protocol string `json:"protocol,omitempty"` -} - -// MatchPath defines a path for process or file policies -type MatchPath struct { - Path string `json:"path,omitempty"` -} - -// MatchDirectory defines a directory for process or file policies -type MatchDirectory struct { - Directory string `json:"dir,omitempty"` - FromSource []NimbusFromSource `json:"fromSource,omitempty"` -} - -// MatchPattern defines a pattern for process policies -type MatchPattern struct { - Pattern string `json:"pattern,omitempty"` -} - -// MatchSyscall defines a syscall for syscall policies -type MatchSyscall struct { - Syscalls []string `json:"syscalls,omitempty"` - FromSource []SyscallFromSource `json:"fromSource,omitempty"` -} - -type MatchSyscallPath struct { - Path string `json:"path,omitempty"` - Recursive bool `json:"recursive,omitempty"` - Syscalls []string `json:"syscall,omitempty"` - FromSource []SyscallFromSource `json:"fromSource,omitempty"` -} - -type SyscallFromSource struct { - Path string `json:"path,omitempty"` - Dir string `json:"dir,omitempty"` -} - -// MatchCapability defines a capability for capabilities policies -type MatchCapability struct { - Capability string `json:"capability,omitempty"` - FromSource []NimbusFromSource `json:"fromSource,omitempty"` -} - -// FromSource defines a source path for directory-based policies -type NimbusFromSource struct { - Path string `json:"path,omitempty"` + RuleAction string `json:"action"` + Mode string `json:"mode,omitempty"` + Params map[string][]string `json:"params,omitempty"` } // NimbusPolicyStatus defines the observed state of NimbusPolicy type NimbusPolicyStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file - - PolicyStatus string `json:"status"` + Status string `json:"status"` } //+kubebuilder:object:root=true diff --git a/api/v1/securityintent_types.go b/api/v1/securityintent_types.go index dbc8b727..5dab7434 100644 --- a/api/v1/securityintent_types.go +++ b/api/v1/securityintent_types.go @@ -7,119 +7,50 @@ 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. - // SecurityIntentSpec defines the desired state of SecurityIntent type SecurityIntentSpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file - Intent Intent `json:"intent"` // Define the details of the security policy. } // Intent defines the security policy details type Intent struct { - Id string `json:"id"` - Description string `json:"description,omitempty"` - Action string `json:"action"` - Mode string `json:"mode"` - Severity int `json:"severity,omitempty"` - Tags []string `json:"tags,omitempty"` - Params []SecurityIntentParams `json:"params"` -} - -// Resource defines the resources that the security policy applies to -type SecurityIntentParams struct { - // Network: MatchProtocols - MatchProtocols []SecurityIntentMatchProtocol `json:"SecurityIntentMatchProtocols,omitempty"` - - // Process: MatchPaths, MatchDirectories, MatchPatterns - // File: MatchPaths, MatchDirectories - MatchPaths []SecurityIntentMatchPath `json:"matchPaths,omitempty"` - MatchDirectories []SecurityIntentMatchDirectory `json:"matchDirectories,omitempty"` - MatchPatterns []SecurityIntentMatchPattern `json:"matchPatterns,omitempty"` - - // Capabilities: MatchCapabilities - MatchCapabilities []SecurityIntentMatchCapability `json:"matchCapabilities,omitempty"` - - // Syscalls: MatchSyscalls - MatchSyscalls []SecurityIntentMatchSyscall `json:"matchSyscalls,omitempty"` - MatchSyscallPaths []SecurityIntentMatchSyscallPath `json:"matchSyscallPaths,omitempty"` - - FromCIDRSet []SecurityIntentCIDRSet `json:"fromCIDRSet,omitempty"` - ToPorts []SecurityIntentToPort `json:"toPorts,omitempty"` -} - -// CIDRSet defines CIDR ranges for network policies -type SecurityIntentCIDRSet struct { - CIDR string `json:"cidr,omitempty"` -} - -// ToPort defines ports and protocols for network policies -type SecurityIntentToPort struct { - Ports []SecurityIntentPort `json:"ports,omitempty"` -} - -// Port defines a network port and its protocol -type SecurityIntentPort struct { - Port string `json:"port,omitempty"` - Protocol string `json:"protocol,omitempty"` -} - -// SecurityIntentMatchProtocol defines a protocol for network policies -type SecurityIntentMatchProtocol struct { - Protocol string `json:"protocol,omitempty"` -} - -// MatchPath defines a path for process or file policies -type SecurityIntentMatchPath struct { - Path string `json:"path,omitempty"` -} + // ID is predefined in adapter ID pool. + // Used by security engines to generate corresponding security policies. + //+kubebuilder:validation:Pattern:="^[a-zA-Z0-9]*$" + ID string `json:"id"` -// MatchDirectory defines a directory for process or file policies -type SecurityIntentMatchDirectory struct { - Directory string `json:"dir,omitempty"` - FromSource []SecurityIntentFromSource `json:"fromSource,omitempty"` -} + // Description is human-readable explanation of the intent's purpose. + Description string `json:"description,omitempty"` -// MatchPattern defines a pattern for process policies -type SecurityIntentMatchPattern struct { - Pattern string `json:"pattern,omitempty"` -} + // Action defines how the security policy will be enforced. + Action string `json:"action"` -// MatchSyscall defines a syscall for syscall policies -type SecurityIntentMatchSyscall struct { - Syscalls []string `json:"syscalls,omitempty"` - FromSource []SyscallFromSource `json:"fromSource,omitempty"` -} + // Mode defines the enforcement behavior of the intent. + // Defaults to best-effort. + //+kubebuilder:default:="best-effort" + Mode string `json:"mode,omitempty"` -type SecurityIntentMatchSyscallPath struct { - Path string `json:"path,omitempty"` - Recursive bool `json:"recursive,omitempty"` - Syscalls []string `json:"syscall,omitempty"` - FromSource []SyscallFromSource `json:"fromSource,omitempty"` -} + // Severity defines the potential impact of a security violation related to the intent. + // Defaults to Low. + //+kubebuilder:default:=Low + Severity string `json:"severity,omitempty"` -// MatchCapability defines a capability for capabilities policies -type SecurityIntentMatchCapability struct { - Capability string `json:"capability,omitempty"` -} + // Tags are additional metadata for categorization and grouping of intents. + // Facilitates searching, filtering, and management of security policies. + Tags []string `json:"tags,omitempty"` -type SecurityIntentFromSource struct { - Path string `json:"path,omitempty"` + // Params are key-value pairs that allows fine-tuning of intents to specific requirements. + Params map[string][]string `json:"params,omitempty"` } // SecurityIntentStatus defines the observed state of SecurityIntent type SecurityIntentStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file - // This field can be updated to reflect the actual status of the application of the security intents + Status string `json:"status"` } // SecurityIntent is the Schema for the securityintents API // +kubebuilder:object:root=true -// +kubebuilder:resource: shortName="sit" +// +kubebuilder:resource:shortName="si",scope="Cluster" // +kubebuilder:subresource:status // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/api/v1/securityintentbinding_types.go b/api/v1/securityintentbinding_types.go index 0dcbfc52..ed8d2f31 100644 --- a/api/v1/securityintentbinding_types.go +++ b/api/v1/securityintentbinding_types.go @@ -7,19 +7,13 @@ 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. - // SecurityIntentBindingSpec defines the desired state of SecurityIntentBinding type SecurityIntentBindingSpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file - Intents []MatchIntent `json:"intents"` Selector Selector `json:"selector"` } -// Intent struct defines the request for a specific SecurityIntent +// MatchIntent struct defines the request for a specific SecurityIntent type MatchIntent struct { Name string `json:"name"` } @@ -45,8 +39,7 @@ type Resources struct { // SecurityIntentBindingStatus defines the observed state of SecurityIntentBinding type SecurityIntentBindingStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file + Status string `json:"status"` } // +kubebuilder:object:root=true @@ -62,6 +55,8 @@ type SecurityIntentBinding struct { Status SecurityIntentBindingStatus `json:"status,omitempty"` } +//+kubebuilder:object:root=true + // SecurityIntentBindingList contains a list of SecurityIntentBinding type SecurityIntentBindingList struct { metav1.TypeMeta `json:",inline"` diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 23f5b6cf..473a07be 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -12,173 +12,293 @@ import ( ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CIDRSet) DeepCopyInto(out *CIDRSet) { +func (in *ClusterNimbusPolicy) DeepCopyInto(out *ClusterNimbusPolicy) { *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CIDRSet. -func (in *CIDRSet) DeepCopy() *CIDRSet { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterNimbusPolicy. +func (in *ClusterNimbusPolicy) DeepCopy() *ClusterNimbusPolicy { if in == nil { return nil } - out := new(CIDRSet) + out := new(ClusterNimbusPolicy) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterNimbusPolicy) 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 *Intent) DeepCopyInto(out *Intent) { +func (in *ClusterNimbusPolicyList) DeepCopyInto(out *ClusterNimbusPolicyList) { *out = *in - if in.Tags != nil { - in, out := &in.Tags, &out.Tags - *out = make([]string, len(*in)) - copy(*out, *in) + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterNimbusPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } - if in.Params != nil { - in, out := &in.Params, &out.Params - *out = make([]SecurityIntentParams, len(*in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterNimbusPolicyList. +func (in *ClusterNimbusPolicyList) DeepCopy() *ClusterNimbusPolicyList { + if in == nil { + return nil + } + out := new(ClusterNimbusPolicyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterNimbusPolicyList) 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 *ClusterNimbusPolicySpec) DeepCopyInto(out *ClusterNimbusPolicySpec) { + *out = *in + in.Selector.DeepCopyInto(&out.Selector) + if in.NimbusRules != nil { + in, out := &in.NimbusRules, &out.NimbusRules + *out = make([]NimbusRules, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Intent. -func (in *Intent) DeepCopy() *Intent { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterNimbusPolicySpec. +func (in *ClusterNimbusPolicySpec) DeepCopy() *ClusterNimbusPolicySpec { if in == nil { return nil } - out := new(Intent) + out := new(ClusterNimbusPolicySpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MatchCapability) DeepCopyInto(out *MatchCapability) { +func (in *ClusterNimbusPolicyStatus) DeepCopyInto(out *ClusterNimbusPolicyStatus) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchCapability. -func (in *MatchCapability) DeepCopy() *MatchCapability { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterNimbusPolicyStatus. +func (in *ClusterNimbusPolicyStatus) DeepCopy() *ClusterNimbusPolicyStatus { if in == nil { return nil } - out := new(MatchCapability) + out := new(ClusterNimbusPolicyStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MatchDirectory) DeepCopyInto(out *MatchDirectory) { +func (in *ClusterSecurityIntentBinding) DeepCopyInto(out *ClusterSecurityIntentBinding) { *out = *in - if in.FromSource != nil { - in, out := &in.FromSource, &out.FromSource - *out = make([]NimbusFromSource, len(*in)) - copy(*out, *in) + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSecurityIntentBinding. +func (in *ClusterSecurityIntentBinding) DeepCopy() *ClusterSecurityIntentBinding { + if in == nil { + return nil } + out := new(ClusterSecurityIntentBinding) + in.DeepCopyInto(out) + return out } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchDirectory. -func (in *MatchDirectory) DeepCopy() *MatchDirectory { +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterSecurityIntentBinding) 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 *ClusterSecurityIntentBindingList) DeepCopyInto(out *ClusterSecurityIntentBindingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterSecurityIntentBinding, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSecurityIntentBindingList. +func (in *ClusterSecurityIntentBindingList) DeepCopy() *ClusterSecurityIntentBindingList { if in == nil { return nil } - out := new(MatchDirectory) + out := new(ClusterSecurityIntentBindingList) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterSecurityIntentBindingList) 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 *MatchIntent) DeepCopyInto(out *MatchIntent) { +func (in *ClusterSecurityIntentBindingSpec) DeepCopyInto(out *ClusterSecurityIntentBindingSpec) { *out = *in + if in.Intents != nil { + in, out := &in.Intents, &out.Intents + *out = make([]MatchIntent, len(*in)) + copy(*out, *in) + } + in.Selector.DeepCopyInto(&out.Selector) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchIntent. -func (in *MatchIntent) DeepCopy() *MatchIntent { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSecurityIntentBindingSpec. +func (in *ClusterSecurityIntentBindingSpec) DeepCopy() *ClusterSecurityIntentBindingSpec { if in == nil { return nil } - out := new(MatchIntent) + out := new(ClusterSecurityIntentBindingSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MatchPath) DeepCopyInto(out *MatchPath) { +func (in *ClusterSecurityIntentBindingStatus) DeepCopyInto(out *ClusterSecurityIntentBindingStatus) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchPath. -func (in *MatchPath) DeepCopy() *MatchPath { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSecurityIntentBindingStatus. +func (in *ClusterSecurityIntentBindingStatus) DeepCopy() *ClusterSecurityIntentBindingStatus { if in == nil { return nil } - out := new(MatchPath) + out := new(ClusterSecurityIntentBindingStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MatchPattern) DeepCopyInto(out *MatchPattern) { +func (in *CwResource) DeepCopyInto(out *CwResource) { *out = *in + if in.MatchLabels != nil { + in, out := &in.MatchLabels, &out.MatchLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchPattern. -func (in *MatchPattern) DeepCopy() *MatchPattern { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CwResource. +func (in *CwResource) DeepCopy() *CwResource { if in == nil { return nil } - out := new(MatchPattern) + out := new(CwResource) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MatchProtocol) DeepCopyInto(out *MatchProtocol) { +func (in *CwSelector) DeepCopyInto(out *CwSelector) { *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]CwResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.CEL != nil { + in, out := &in.CEL, &out.CEL + *out = make([]string, len(*in)) + copy(*out, *in) + } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchProtocol. -func (in *MatchProtocol) DeepCopy() *MatchProtocol { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CwSelector. +func (in *CwSelector) DeepCopy() *CwSelector { if in == nil { return nil } - out := new(MatchProtocol) + out := new(CwSelector) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MatchSyscall) DeepCopyInto(out *MatchSyscall) { +func (in *Intent) DeepCopyInto(out *Intent) { *out = *in - if in.Syscalls != nil { - in, out := &in.Syscalls, &out.Syscalls + if in.Tags != nil { + in, out := &in.Tags, &out.Tags *out = make([]string, len(*in)) copy(*out, *in) } + if in.Params != nil { + in, out := &in.Params, &out.Params + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchSyscall. -func (in *MatchSyscall) DeepCopy() *MatchSyscall { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Intent. +func (in *Intent) DeepCopy() *Intent { if in == nil { return nil } - out := new(MatchSyscall) + out := new(Intent) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NimbusFromSource) DeepCopyInto(out *NimbusFromSource) { +func (in *MatchIntent) DeepCopyInto(out *MatchIntent) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NimbusFromSource. -func (in *NimbusFromSource) DeepCopy() *NimbusFromSource { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchIntent. +func (in *MatchIntent) DeepCopy() *MatchIntent { if in == nil { return nil } - out := new(NimbusFromSource) + out := new(MatchIntent) in.DeepCopyInto(out) return out } @@ -283,13 +403,7 @@ func (in *NimbusPolicyStatus) DeepCopy() *NimbusPolicyStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NimbusRules) DeepCopyInto(out *NimbusRules) { *out = *in - if in.Rule != nil { - in, out := &in.Rule, &out.Rule - *out = make([]Rule, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } + in.Rule.DeepCopyInto(&out.Rule) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NimbusRules. @@ -324,21 +438,6 @@ func (in *NimbusSelector) DeepCopy() *NimbusSelector { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Port) DeepCopyInto(out *Port) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Port. -func (in *Port) DeepCopy() *Port { - if in == nil { - return nil - } - out := new(Port) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceFilter) DeepCopyInto(out *ResourceFilter) { *out = *in @@ -380,50 +479,20 @@ func (in *Resources) DeepCopy() *Resources { // 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 - if in.MatchProtocols != nil { - in, out := &in.MatchProtocols, &out.MatchProtocols - *out = make([]MatchProtocol, len(*in)) - copy(*out, *in) - } - if in.MatchPaths != nil { - in, out := &in.MatchPaths, &out.MatchPaths - *out = make([]MatchPath, len(*in)) - copy(*out, *in) - } - if in.MatchDirectories != nil { - in, out := &in.MatchDirectories, &out.MatchDirectories - *out = make([]MatchDirectory, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.MatchPatterns != nil { - in, out := &in.MatchPatterns, &out.MatchPatterns - *out = make([]MatchPattern, len(*in)) - copy(*out, *in) - } - if in.MatchCapabilities != nil { - in, out := &in.MatchCapabilities, &out.MatchCapabilities - *out = make([]MatchCapability, len(*in)) - copy(*out, *in) - } - if in.MatchSyscalls != nil { - in, out := &in.MatchSyscalls, &out.MatchSyscalls - *out = make([]MatchSyscall, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.FromCIDRSet != nil { - in, out := &in.FromCIDRSet, &out.FromCIDRSet - *out = make([]CIDRSet, len(*in)) - copy(*out, *in) - } - if in.ToPorts != nil { - in, out := &in.ToPorts, &out.ToPorts - *out = make([]ToPort, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) + if in.Params != nil { + in, out := &in.Params, &out.Params + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal } } } @@ -560,36 +629,6 @@ func (in *SecurityIntentBindingStatus) DeepCopy() *SecurityIntentBindingStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityIntentCIDRSet) DeepCopyInto(out *SecurityIntentCIDRSet) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityIntentCIDRSet. -func (in *SecurityIntentCIDRSet) DeepCopy() *SecurityIntentCIDRSet { - if in == nil { - return nil - } - out := new(SecurityIntentCIDRSet) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityIntentFromSource) DeepCopyInto(out *SecurityIntentFromSource) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityIntentFromSource. -func (in *SecurityIntentFromSource) DeepCopy() *SecurityIntentFromSource { - if in == nil { - return nil - } - out := new(SecurityIntentFromSource) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecurityIntentList) DeepCopyInto(out *SecurityIntentList) { *out = *in @@ -622,182 +661,6 @@ func (in *SecurityIntentList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityIntentMatchCapability) DeepCopyInto(out *SecurityIntentMatchCapability) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityIntentMatchCapability. -func (in *SecurityIntentMatchCapability) DeepCopy() *SecurityIntentMatchCapability { - if in == nil { - return nil - } - out := new(SecurityIntentMatchCapability) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityIntentMatchDirectory) DeepCopyInto(out *SecurityIntentMatchDirectory) { - *out = *in - if in.FromSource != nil { - in, out := &in.FromSource, &out.FromSource - *out = make([]SecurityIntentFromSource, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityIntentMatchDirectory. -func (in *SecurityIntentMatchDirectory) DeepCopy() *SecurityIntentMatchDirectory { - if in == nil { - return nil - } - out := new(SecurityIntentMatchDirectory) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityIntentMatchPath) DeepCopyInto(out *SecurityIntentMatchPath) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityIntentMatchPath. -func (in *SecurityIntentMatchPath) DeepCopy() *SecurityIntentMatchPath { - if in == nil { - return nil - } - out := new(SecurityIntentMatchPath) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityIntentMatchPattern) DeepCopyInto(out *SecurityIntentMatchPattern) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityIntentMatchPattern. -func (in *SecurityIntentMatchPattern) DeepCopy() *SecurityIntentMatchPattern { - if in == nil { - return nil - } - out := new(SecurityIntentMatchPattern) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityIntentMatchProtocol) DeepCopyInto(out *SecurityIntentMatchProtocol) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityIntentMatchProtocol. -func (in *SecurityIntentMatchProtocol) DeepCopy() *SecurityIntentMatchProtocol { - if in == nil { - return nil - } - out := new(SecurityIntentMatchProtocol) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityIntentMatchSyscall) DeepCopyInto(out *SecurityIntentMatchSyscall) { - *out = *in - if in.Syscalls != nil { - in, out := &in.Syscalls, &out.Syscalls - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityIntentMatchSyscall. -func (in *SecurityIntentMatchSyscall) DeepCopy() *SecurityIntentMatchSyscall { - if in == nil { - return nil - } - out := new(SecurityIntentMatchSyscall) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityIntentParams) DeepCopyInto(out *SecurityIntentParams) { - *out = *in - if in.MatchProtocols != nil { - in, out := &in.MatchProtocols, &out.MatchProtocols - *out = make([]SecurityIntentMatchProtocol, len(*in)) - copy(*out, *in) - } - if in.MatchPaths != nil { - in, out := &in.MatchPaths, &out.MatchPaths - *out = make([]SecurityIntentMatchPath, len(*in)) - copy(*out, *in) - } - if in.MatchDirectories != nil { - in, out := &in.MatchDirectories, &out.MatchDirectories - *out = make([]SecurityIntentMatchDirectory, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.MatchPatterns != nil { - in, out := &in.MatchPatterns, &out.MatchPatterns - *out = make([]SecurityIntentMatchPattern, len(*in)) - copy(*out, *in) - } - if in.MatchCapabilities != nil { - in, out := &in.MatchCapabilities, &out.MatchCapabilities - *out = make([]SecurityIntentMatchCapability, len(*in)) - copy(*out, *in) - } - if in.MatchSyscalls != nil { - in, out := &in.MatchSyscalls, &out.MatchSyscalls - *out = make([]SecurityIntentMatchSyscall, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.FromCIDRSet != nil { - in, out := &in.FromCIDRSet, &out.FromCIDRSet - *out = make([]SecurityIntentCIDRSet, len(*in)) - copy(*out, *in) - } - if in.ToPorts != nil { - in, out := &in.ToPorts, &out.ToPorts - *out = make([]SecurityIntentToPort, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityIntentParams. -func (in *SecurityIntentParams) DeepCopy() *SecurityIntentParams { - if in == nil { - return nil - } - out := new(SecurityIntentParams) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityIntentPort) DeepCopyInto(out *SecurityIntentPort) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityIntentPort. -func (in *SecurityIntentPort) DeepCopy() *SecurityIntentPort { - if in == nil { - return nil - } - out := new(SecurityIntentPort) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecurityIntentSpec) DeepCopyInto(out *SecurityIntentSpec) { *out = *in @@ -829,26 +692,6 @@ func (in *SecurityIntentStatus) DeepCopy() *SecurityIntentStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityIntentToPort) DeepCopyInto(out *SecurityIntentToPort) { - *out = *in - if in.Ports != nil { - in, out := &in.Ports, &out.Ports - *out = make([]SecurityIntentPort, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityIntentToPort. -func (in *SecurityIntentToPort) DeepCopy() *SecurityIntentToPort { - if in == nil { - return nil - } - out := new(SecurityIntentToPort) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Selector) DeepCopyInto(out *Selector) { *out = *in @@ -882,23 +725,3 @@ func (in *Selector) DeepCopy() *Selector { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ToPort) DeepCopyInto(out *ToPort) { - *out = *in - if in.Ports != nil { - in, out := &in.Ports, &out.Ports - *out = make([]Port, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ToPort. -func (in *ToPort) DeepCopy() *ToPort { - if in == nil { - return nil - } - out := new(ToPort) - in.DeepCopyInto(out) - return out -} diff --git a/cmd/main.go b/cmd/main.go index e4f898cb..c4ae2af3 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -20,15 +20,14 @@ import ( metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" // Importing custom API types and controllers + v1 "github.com/5GSEC/nimbus/api/v1" + "github.com/5GSEC/nimbus/internal/controller" "github.com/5GSEC/nimbus/pkg/exporter/nimbuspolicy" "github.com/5GSEC/nimbus/pkg/receiver/securityintent" "github.com/5GSEC/nimbus/pkg/receiver/securityintentbinding" "github.com/5GSEC/nimbus/pkg/receiver/watcher" - // Importing third-party Kubernetes resource types - ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" - kubearmorv1 "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/api/security.kubearmor.com/v1" //+kubebuilder:scaffold:imports ) @@ -42,8 +41,6 @@ func init() { // In init, various Kubernetes and custom resources are added to the scheme. utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(v1.AddToScheme(scheme)) - utilruntime.Must(ciliumv2.AddToScheme(scheme)) - utilruntime.Must(kubearmorv1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } @@ -115,6 +112,15 @@ func main() { os.Exit(1) } + if err = (&controller.ClusterSecurityIntentBindingReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + WatcherController: watcherController, + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "ClusterSecurityIntentBinding") + os.Exit(1) + } + nimbusPolicyReconciler := nimbuspolicy.NewNimbusPolicyReconciler(mgr.GetClient(), mgr.GetScheme()) if err != nil { setupLog.Error(err, "Unable to create NimbusPolicyReconciler") @@ -130,6 +136,18 @@ func main() { setupLog.Error(err, "Unable to set up NimbusPolicyReconciler with manager", "controller", "NimbusPolicy") os.Exit(1) } + + clusterNpReconciler := controller.NewClusterNimbusPolicyReconciler(mgr.GetClient(), mgr.GetScheme()) + clusterNpWatcher, err := watcher.NewClusterNimbusPolicy(mgr.GetClient()) + if err != nil { + setupLog.Error(err, "Unable to create ClusterNimbusPolicyWatcher") + os.Exit(1) + } + clusterNpReconciler.ClusterNimbusPolicyWatcher = clusterNpWatcher + if err = clusterNpReconciler.SetupWithManager(mgr); err != nil { + setupLog.Error(err, "Unable to setup ClusterNimbusPolicyReconciler with manager", "controller", "ClusterNimbusPolicy") + os.Exit(1) + } //+kubebuilder:scaffold:builder // Adding health and readiness checks. diff --git a/config/crd/bases/intent.security.nimbus.com_clusternimbuspolicies.yaml b/config/crd/bases/intent.security.nimbus.com_clusternimbuspolicies.yaml new file mode 100644 index 00000000..2cb89623 --- /dev/null +++ b/config/crd/bases/intent.security.nimbus.com_clusternimbuspolicies.yaml @@ -0,0 +1,112 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: clusternimbuspolicies.intent.security.nimbus.com +spec: + group: intent.security.nimbus.com + names: + kind: ClusterNimbusPolicy + listKind: ClusterNimbusPolicyList + plural: clusternimbuspolicies + shortNames: + - cwnp + singular: clusternimbuspolicy + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ClusterNimbusPolicy is the Schema for the clusternimbuspolicies + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ClusterNimbusPolicySpec defines the desired state of ClusterNimbusPolicy + properties: + rules: + items: + description: NimbusRules represents a single policy rule with an + ID, type, description, and detailed rule configurations. + properties: + description: + type: string + id: + type: string + rule: + properties: + action: + type: string + mode: + type: string + params: + additionalProperties: + items: + type: string + type: array + type: object + required: + - action + type: object + type: + type: string + required: + - id + - rule + type: object + type: array + selector: + properties: + cel: + items: + type: string + type: array + resources: + items: + properties: + kind: + type: string + matchLabels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + type: array + type: object + required: + - rules + - selector + type: object + status: + description: ClusterNimbusPolicyStatus defines the observed state of ClusterNimbusPolicy + properties: + status: + type: string + required: + - status + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/intent.security.nimbus.com_clustersecurityintentbindings.yaml b/config/crd/bases/intent.security.nimbus.com_clustersecurityintentbindings.yaml new file mode 100644 index 00000000..edc87267 --- /dev/null +++ b/config/crd/bases/intent.security.nimbus.com_clustersecurityintentbindings.yaml @@ -0,0 +1,94 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: clustersecurityintentbindings.intent.security.nimbus.com +spec: + group: intent.security.nimbus.com + names: + kind: ClusterSecurityIntentBinding + listKind: ClusterSecurityIntentBindingList + plural: clustersecurityintentbindings + shortNames: + - csib + singular: clustersecurityintentbinding + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ClusterSecurityIntentBinding is the Schema for the clustersecurityintentbindings + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ClusterSecurityIntentBindingSpec defines the desired state + of ClusterSecurityIntentBinding + properties: + intents: + items: + description: MatchIntent struct defines the request for a specific + SecurityIntent + properties: + name: + type: string + required: + - name + type: object + type: array + selector: + properties: + cel: + items: + type: string + type: array + resources: + items: + properties: + kind: + type: string + matchLabels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + type: array + type: object + required: + - intents + - selector + type: object + status: + description: ClusterSecurityIntentBindingStatus defines the observed state + of ClusterSecurityIntentBinding + properties: + status: + type: string + required: + - status + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/intent.security.nimbus.com_nimbuspolicies.yaml b/config/crd/bases/intent.security.nimbus.com_nimbuspolicies.yaml index 6ae591fe..714bf686 100644 --- a/config/crd/bases/intent.security.nimbus.com_nimbuspolicies.yaml +++ b/config/crd/bases/intent.security.nimbus.com_nimbuspolicies.yaml @@ -48,151 +48,20 @@ spec: id: type: string rule: - items: - properties: - action: - type: string - fromCIDRSet: + properties: + action: + type: string + mode: + type: string + params: + additionalProperties: items: - description: CIDRSet defines CIDR ranges for network - policies - properties: - cidr: - type: string - type: object + type: string type: array - matchCapabilities: - description: 'Capabilities: MatchCapabilities' - items: - description: MatchCapability defines a capability for - capabilities policies - properties: - capability: - type: string - fromSource: - items: - description: FromSource defines a source path - for directory-based policies - properties: - path: - type: string - type: object - type: array - type: object - type: array - matchDirectories: - items: - description: MatchDirectory defines a directory for - process or file policies - properties: - dir: - type: string - fromSource: - items: - description: FromSource defines a source path - for directory-based policies - properties: - path: - type: string - type: object - type: array - type: object - type: array - matchPaths: - description: 'Process: MatchPaths, MatchDirectories, MatchPatterns - File: MatchPaths, MatchDirectories, MatchPatterns' - items: - description: MatchPath defines a path for process or - file policies - properties: - path: - type: string - type: object - type: array - matchPatterns: - items: - description: MatchPattern defines a pattern for process - policies - properties: - pattern: - type: string - type: object - type: array - matchProtocols: - description: 'Network: MatchProtocols' - items: - description: MatchProtocol defines a protocol for network - policies - properties: - protocol: - type: string - type: object - type: array - matchSyscallPaths: - items: - properties: - fromSource: - items: - properties: - dir: - type: string - path: - type: string - type: object - type: array - path: - type: string - recursive: - type: boolean - syscall: - items: - type: string - type: array - type: object - type: array - matchSyscalls: - description: 'Syscalls: MatchSyscalls' - items: - description: MatchSyscall defines a syscall for syscall - policies - properties: - fromSource: - items: - properties: - dir: - type: string - path: - type: string - type: object - type: array - syscalls: - items: - type: string - type: array - type: object - type: array - toPorts: - items: - description: ToPort defines ports and protocols for - network policies - properties: - ports: - items: - description: Port defines a network port and its - protocol - properties: - port: - type: string - protocol: - type: string - type: object - type: array - type: object - type: array - required: - - action - type: object - type: array + type: object + required: + - action + type: object type: type: string required: diff --git a/config/crd/bases/intent.security.nimbus.com_securityintentbindings.yaml b/config/crd/bases/intent.security.nimbus.com_securityintentbindings.yaml index a66964c2..b9718d56 100644 --- a/config/crd/bases/intent.security.nimbus.com_securityintentbindings.yaml +++ b/config/crd/bases/intent.security.nimbus.com_securityintentbindings.yaml @@ -39,7 +39,8 @@ spec: properties: intents: items: - description: Intent struct defines the request for a specific SecurityIntent + description: MatchIntent struct defines the request for a specific + SecurityIntent properties: name: type: string @@ -100,6 +101,11 @@ spec: status: description: SecurityIntentBindingStatus defines the observed state of SecurityIntentBinding + properties: + status: + type: string + required: + - status type: object type: object served: true diff --git a/config/crd/bases/intent.security.nimbus.com_securityintents.yaml b/config/crd/bases/intent.security.nimbus.com_securityintents.yaml index 3b36be37..92bbbdbb 100644 --- a/config/crd/bases/intent.security.nimbus.com_securityintents.yaml +++ b/config/crd/bases/intent.security.nimbus.com_securityintents.yaml @@ -12,9 +12,9 @@ spec: listKind: SecurityIntentList plural: securityintents shortNames: - - sit + - si singular: securityintent - scope: Namespaced + scope: Cluster versions: - name: v1 schema: @@ -40,162 +40,56 @@ spec: description: Intent defines the security policy details properties: action: + description: Action defines how the security policy will be enforced. type: string description: + description: Description is human-readable explanation of the + intent's purpose. type: string id: + description: ID is predefined in adapter ID pool. Used by security + engines to generate corresponding security policies. + pattern: ^[a-zA-Z0-9]*$ type: string mode: + default: best-effort + description: Mode defines the enforcement behavior of the intent. + Defaults to best-effort. type: string params: - items: - description: Resource defines the resources that the security - policy applies to - properties: - SecurityIntentMatchProtocols: - description: 'Network: MatchProtocols' - items: - description: SecurityIntentMatchProtocol defines a protocol - for network policies - properties: - protocol: - type: string - type: object - type: array - fromCIDRSet: - items: - description: CIDRSet defines CIDR ranges for network policies - properties: - cidr: - type: string - type: object - type: array - matchCapabilities: - description: 'Capabilities: MatchCapabilities' - items: - description: MatchCapability defines a capability for - capabilities policies - properties: - capability: - type: string - type: object - type: array - matchDirectories: - items: - description: MatchDirectory defines a directory for process - or file policies - properties: - dir: - type: string - fromSource: - items: - properties: - path: - type: string - type: object - type: array - type: object - type: array - matchPaths: - description: 'Process: MatchPaths, MatchDirectories, MatchPatterns - File: MatchPaths, MatchDirectories' - items: - description: MatchPath defines a path for process or file - policies - properties: - path: - type: string - type: object - type: array - matchPatterns: - items: - description: MatchPattern defines a pattern for process - policies - properties: - pattern: - type: string - type: object - type: array - matchSyscallPaths: - items: - properties: - fromSource: - items: - properties: - dir: - type: string - path: - type: string - type: object - type: array - path: - type: string - recursive: - type: boolean - syscall: - items: - type: string - type: array - type: object - type: array - matchSyscalls: - description: 'Syscalls: MatchSyscalls' - items: - description: MatchSyscall defines a syscall for syscall - policies - properties: - fromSource: - items: - properties: - dir: - type: string - path: - type: string - type: object - type: array - syscalls: - items: - type: string - type: array - type: object - type: array - toPorts: - items: - description: ToPort defines ports and protocols for network - policies - properties: - ports: - items: - description: Port defines a network port and its - protocol - properties: - port: - type: string - protocol: - type: string - type: object - type: array - type: object - type: array - type: object - type: array + additionalProperties: + items: + type: string + type: array + description: Params are key-value pairs that allows fine-tuning + of intents to specific requirements. + type: object severity: - type: integer + default: Low + description: Severity defines the potential impact of a security + violation related to the intent. Defaults to Low. + type: string tags: + description: Tags are additional metadata for categorization and + grouping of intents. Facilitates searching, filtering, and management + of security policies. items: type: string type: array required: - action - id - - mode - - params type: object required: - intent type: object status: description: SecurityIntentStatus defines the observed state of SecurityIntent + properties: + status: + type: string + required: + - status type: object type: object served: true diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index f806adb0..2b445d20 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -5,6 +5,8 @@ resources: - bases/intent.security.nimbus.com_securityintents.yaml - bases/intent.security.nimbus.com_securityintentbindings.yaml - bases/intent.security.nimbus.com_nimbuspolicies.yaml +- bases/intent.security.nimbus.com_clusternimbuspolicies.yaml +- bases/intent.security.nimbus.com_clustersecurityintentbindings.yaml #+kubebuilder:scaffold:crdkustomizeresource patches: @@ -13,6 +15,8 @@ patches: #- path: patches/webhook_in_securityintents.yaml #- path: patches/webhook_in_securityintentbindings.yaml #- path: patches/webhook_in_nimbuspolicies.yaml +#- path: patches/webhook_in_clusternimbuspolicies.yaml +#- path: patches/webhook_in_clustersecurityintentbindings.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. @@ -20,6 +24,8 @@ patches: #- path: patches/cainjection_in_securityintents.yaml #- path: patches/cainjection_in_securityintentbindings.yaml #- path: patches/cainjection_in_nimbuspolicies.yaml +#- path: patches/cainjection_in_clusternimbuspolicies.yaml +#- path: patches/cainjection_in_clustersecurityintentbindings.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # [WEBHOOK] To enable webhook, uncomment the following section diff --git a/config/rbac/clusternimbuspolicy_editor_role.yaml b/config/rbac/clusternimbuspolicy_editor_role.yaml new file mode 100644 index 00000000..8dad8dd6 --- /dev/null +++ b/config/rbac/clusternimbuspolicy_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit clusternimbuspolicies. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: clusternimbuspolicy-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: nimbus + app.kubernetes.io/part-of: nimbus + app.kubernetes.io/managed-by: kustomize + name: clusternimbuspolicy-editor-role +rules: +- apiGroups: + - intent.security.nimbus.com + resources: + - clusternimbuspolicies + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - intent.security.nimbus.com + resources: + - clusternimbuspolicies/status + verbs: + - get diff --git a/config/rbac/clusternimbuspolicy_viewer_role.yaml b/config/rbac/clusternimbuspolicy_viewer_role.yaml new file mode 100644 index 00000000..ebada37c --- /dev/null +++ b/config/rbac/clusternimbuspolicy_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view clusternimbuspolicies. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: clusternimbuspolicy-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: nimbus + app.kubernetes.io/part-of: nimbus + app.kubernetes.io/managed-by: kustomize + name: clusternimbuspolicy-viewer-role +rules: +- apiGroups: + - intent.security.nimbus.com + resources: + - clusternimbuspolicies + verbs: + - get + - list + - watch +- apiGroups: + - intent.security.nimbus.com + resources: + - clusternimbuspolicies/status + verbs: + - get diff --git a/config/rbac/clustersecurityintentbinding_editor_role.yaml b/config/rbac/clustersecurityintentbinding_editor_role.yaml new file mode 100644 index 00000000..3a1c0e40 --- /dev/null +++ b/config/rbac/clustersecurityintentbinding_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit clustersecurityintentbindings. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: clustersecurityintentbinding-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: nimbus + app.kubernetes.io/part-of: nimbus + app.kubernetes.io/managed-by: kustomize + name: clustersecurityintentbinding-editor-role +rules: +- apiGroups: + - intent.security.nimbus.com + resources: + - clustersecurityintentbindings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - intent.security.nimbus.com + resources: + - clustersecurityintentbindings/status + verbs: + - get diff --git a/config/rbac/clustersecurityintentbinding_viewer_role.yaml b/config/rbac/clustersecurityintentbinding_viewer_role.yaml new file mode 100644 index 00000000..024fe1f3 --- /dev/null +++ b/config/rbac/clustersecurityintentbinding_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view clustersecurityintentbindings. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: clustersecurityintentbinding-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: nimbus + app.kubernetes.io/part-of: nimbus + app.kubernetes.io/managed-by: kustomize + name: clustersecurityintentbinding-viewer-role +rules: +- apiGroups: + - intent.security.nimbus.com + resources: + - clustersecurityintentbindings + verbs: + - get + - list + - watch +- apiGroups: + - intent.security.nimbus.com + resources: + - clustersecurityintentbindings/status + verbs: + - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 1a03f291..71cb4cdd 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -4,6 +4,58 @@ kind: ClusterRole metadata: name: manager-role rules: +- apiGroups: + - intent.security.nimbus.com + resources: + - clusternimbuspolicies + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - intent.security.nimbus.com + resources: + - clusternimbuspolicies/finalizers + verbs: + - update +- apiGroups: + - intent.security.nimbus.com + resources: + - clusternimbuspolicies/status + verbs: + - get + - patch + - update +- apiGroups: + - intent.security.nimbus.com + resources: + - clustersecurityintentbindings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - intent.security.nimbus.com + resources: + - clustersecurityintentbindings/finalizers + verbs: + - update +- apiGroups: + - intent.security.nimbus.com + resources: + - clustersecurityintentbindings/status + verbs: + - get + - patch + - update - apiGroups: - intent.security.nimbus.com resources: diff --git a/config/samples/intent_v1_clusternimbuspolicy.yaml b/config/samples/intent_v1_clusternimbuspolicy.yaml new file mode 100644 index 00000000..7f121e31 --- /dev/null +++ b/config/samples/intent_v1_clusternimbuspolicy.yaml @@ -0,0 +1,12 @@ +apiVersion: intent.security.nimbus.com/v1 +kind: ClusterNimbusPolicy +metadata: + labels: + app.kubernetes.io/name: clusternimbuspolicy + app.kubernetes.io/instance: clusternimbuspolicy-sample + app.kubernetes.io/part-of: nimbus + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: nimbus + name: clusternimbuspolicy-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/intent_v1_clustersecurityintentbinding.yaml b/config/samples/intent_v1_clustersecurityintentbinding.yaml new file mode 100644 index 00000000..4586379c --- /dev/null +++ b/config/samples/intent_v1_clustersecurityintentbinding.yaml @@ -0,0 +1,12 @@ +apiVersion: intent.security.nimbus.com/v1 +kind: ClusterSecurityIntentBinding +metadata: + labels: + app.kubernetes.io/name: clustersecurityintentbinding + app.kubernetes.io/instance: clustersecurityintentbinding-sample + app.kubernetes.io/part-of: nimbus + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: nimbus + name: clustersecurityintentbinding-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 7d11f0bc..352c9a18 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -3,4 +3,6 @@ resources: - intent_v1_securityintent.yaml - intent_v1_securityintentbinding.yaml - intent_v1_nimbuspolicy.yaml +- intent_v1_clusternimbuspolicy.yaml +- intent_v1_clustersecurityintentbinding.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/go.sum b/go.sum index b3554d78..f04cbd84 100644 --- a/go.sum +++ b/go.sum @@ -37,6 +37,7 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -52,12 +53,14 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/checkmate v1.0.3 h1:CQC5eOmlAZeEjPrVZY3ZwEBH64lHlx9mXYdUehEwI5w= +github.com/cilium/checkmate v1.0.3/go.mod h1:KiBTasf39/F2hf2yAmHw21YFl3hcEyP4Yk6filxc12A= github.com/cilium/cilium v1.14.3 h1:Nbya9Lr/k1A8Wty1oPdV+/k/qh3KoIeTb6tXRM2eLWg= github.com/cilium/cilium v1.14.3/go.mod h1:jcysu5KCmXET1lo3TeRq9cUvwQeFajcSRs4n6YfvTqM= github.com/cilium/ebpf v0.10.1-0.20230626090016-654491c8a500 h1:eAn1/gEVvcamZLoF4JKznmG2zKABsF7mRisyfQtwa3Q= @@ -69,9 +72,11 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -84,10 +89,13 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= +github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= +github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -393,10 +401,12 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= @@ -435,11 +445,13 @@ go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/ go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= +go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI= go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -493,6 +505,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/internal/controller/clusternimbuspolicy_controller.go b/internal/controller/clusternimbuspolicy_controller.go new file mode 100644 index 00000000..4b46135a --- /dev/null +++ b/internal/controller/clusternimbuspolicy_controller.go @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package controller + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + v1 "github.com/5GSEC/nimbus/api/v1" + "github.com/5GSEC/nimbus/pkg/receiver/watcher" +) + +// ClusterNimbusPolicyReconciler reconciles a ClusterNimbusPolicy object +type ClusterNimbusPolicyReconciler struct { + client.Client + Scheme *runtime.Scheme + ClusterNimbusPolicyWatcher *watcher.ClusterNimbusPolicy +} + +func NewClusterNimbusPolicyReconciler(client client.Client, scheme *runtime.Scheme) *ClusterNimbusPolicyReconciler { + if client == nil { + fmt.Println("ClusterNimbusPolicyReconciler: Client is nil") + return nil + } + + clusterNPWatcher, err := watcher.NewClusterNimbusPolicy(client) + if err != nil { + fmt.Println("ClusterNimbusPolicyReconciler: failed to initialize ClusterNimbusPolicy watcher", err) + return nil + } + return &ClusterNimbusPolicyReconciler{ + Client: client, + Scheme: scheme, + ClusterNimbusPolicyWatcher: clusterNPWatcher, + } +} + +//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=clusternimbuspolicies,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=clusternimbuspolicies/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=clusternimbuspolicies/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +func (r *ClusterNimbusPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + logger := log.FromContext(ctx) + if r.ClusterNimbusPolicyWatcher == nil { + logger.Info("ClusterNimbusPolicyReconciler.ClusterNimbusPolicyWatcher is nil", "WatcherController", r.ClusterNimbusPolicyWatcher) + return ctrl.Result{}, fmt.Errorf("WatcherController is not properly initialized") + } + + cwnp, err := r.ClusterNimbusPolicyWatcher.Reconcile(ctx, req) + if err != nil { + logger.Error(err, "failed to reconcile ClusterNimbusPolicy", "ClusterNimbusPolicy", req.Name) + return ctrl.Result{}, err + } + if cwnp != nil { + logger.Info("ClusterNimbusPolicy found", "Name", req.Name) + } else { + logger.Info("ClusterNimbusPolicy not found", "Name", req.Name) + } + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *ClusterNimbusPolicyReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&v1.ClusterNimbusPolicy{}). + Complete(r) +} diff --git a/internal/controller/clustersecurityintentbinding_controller.go b/internal/controller/clustersecurityintentbinding_controller.go new file mode 100644 index 00000000..00f873a7 --- /dev/null +++ b/internal/controller/clustersecurityintentbinding_controller.go @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package controller + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + v1 "github.com/5GSEC/nimbus/api/v1" + "github.com/5GSEC/nimbus/pkg/processor/intentbinder" + "github.com/5GSEC/nimbus/pkg/processor/nimbuspolicybuilder" + "github.com/5GSEC/nimbus/pkg/receiver/watcher" +) + +// ClusterSecurityIntentBindingReconciler reconciles a ClusterSecurityIntentBinding object +type ClusterSecurityIntentBindingReconciler struct { + client.Client + Scheme *runtime.Scheme + WatcherController *watcher.WatcherController +} + +//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=clustersecurityintentbindings,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=clustersecurityintentbindings/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=clustersecurityintentbindings/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +func (r *ClusterSecurityIntentBindingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + logger := log.FromContext(ctx) + if r.WatcherController == nil { + logger.Info("ClusterSecurityIntentBindingReconciler.WatcherController is nil", "WatcherController", r.WatcherController) + return ctrl.Result{}, fmt.Errorf("WatcherController is not properly initialized") + } + + // Todo: Change "Watcher" prefix to suffix. + clusterBinding, err := r.WatcherController.WatcherClusterBinding.Reconcile(ctx, req) + if err != nil { + logger.Error(err, "failed to reconcile ClusterSecurityIntentBinding", "ClusterSecurityIntentBinding", req.Name) + return ctrl.Result{}, err + } + + if clusterBinding != nil { + logger.Info("ClusterSecurityIntentBinding found", "Name", req.Name) + } else { + logger.Info("ClusterSecurityIntentBinding not found", "Name", req.Name) + // Delete associated ClusterNimbusPolicy if exists. + var clusterNp v1.ClusterNimbusPolicy + err = r.Get(ctx, types.NamespacedName{Name: req.Name}, &clusterNp) + if errors.IsNotFound(err) { + logger.Error(err, "failed to get ClusterNimbusPolicy for deletion", "ClusterNimbusPolicy", clusterNp.Name) + return ctrl.Result{}, err + } + if err == nil { + if err = r.Delete(ctx, &clusterNp); err != nil { + logger.Error(err, "failed to delete ClusterNimbusPolicy for deletion", "ClusterNimbusPolicy", clusterNp.Name) + return ctrl.Result{}, err + } + } + logger.Info("Deleted ClusterNimbusPolicy due to ClusterSecurityIntentBinding deletion", "ClusterNimbusPolicy", clusterNp.Name) + //Todo: Signal adapters to delete corresponding policies. + return ctrl.Result{}, nil + } + + clusterBindingInfo, err := intentbinder.MatchAndBindIntentsGlobal(ctx, r.Client, clusterBinding) + if err != nil { + logger.Error(err, "failed to match and bind intents") + return ctrl.Result{}, err + } + + cwnp, err := nimbuspolicybuilder.BuildClusterNimbusPolicy(ctx, r.Client, clusterBindingInfo) + if err != nil { + logger.Error(err, "failed to build ClusterNimbusPolicy") + return ctrl.Result{}, err + } + + if err = r.Create(ctx, cwnp); err != nil { + logger.Error(err, "failed to create ClusterNimbusPolicy", "ClusterNimbusPolicy", cwnp.Name) + return ctrl.Result{}, err + } + // Todo: Update Status + //cwnp.Status = v1.ClusterNimbusPolicyStatus{Status: "Created"} + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *ClusterSecurityIntentBindingReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&v1.ClusterSecurityIntentBinding{}). + Complete(r) +} diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go new file mode 100644 index 00000000..78ad8c82 --- /dev/null +++ b/internal/controller/suite_test.go @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package controller + +import ( + "fmt" + "path/filepath" + "runtime" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "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" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + intentv1 "github.com/5GSEC/nimbus/api/v1" + //+kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestControllers(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Controller Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: true, + + // The BinaryAssetsDirectory is only required if you want to run the tests directly + // without call the makefile target test. If not informed it will look for the + // default path defined in controller-runtime which is /usr/local/kubebuilder/. + // Note that you must have the required binaries setup under the bin directory to perform + // the tests directly. When we run make test it will be setup and used automatically. + BinaryAssetsDirectory: filepath.Join("..", "..", "bin", "k8s", + fmt.Sprintf("1.28.3-%s-%s", runtime.GOOS, runtime.GOARCH)), + } + + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = intentv1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/pkg/processor/intentbinder/intent_binder.go b/pkg/processor/intentbinder/intent_binder.go index 5651c05d..0cdbe334 100644 --- a/pkg/processor/intentbinder/intent_binder.go +++ b/pkg/processor/intentbinder/intent_binder.go @@ -6,61 +6,71 @@ package intentbinder import ( "context" - v1 "github.com/5GSEC/nimbus/api/v1" "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" + + v1 "github.com/5GSEC/nimbus/api/v1" ) // BindingInfo holds the names of matched SecurityIntent and SecurityIntentBinding. type BindingInfo struct { IntentNames []string - IntentNamespaces []string BindingNames []string BindingNamespaces []string } // NewBindingInfo creates a new instance of BindingInfo. -func NewBindingInfo(intentNames []string, intentNamespaces []string, bindingNames []string, bindingNamespaces []string) *BindingInfo { +func NewBindingInfo(intentNames []string, bindingNames []string, bindingNamespaces []string) *BindingInfo { return &BindingInfo{ IntentNames: intentNames, - IntentNamespaces: intentNamespaces, BindingNames: bindingNames, BindingNamespaces: bindingNamespaces, } } -func MatchAndBindIntents(ctx context.Context, client client.Client, req ctrl.Request, bindings *v1.SecurityIntentBinding) (*BindingInfo, error) { - log := log.FromContext(ctx) - log.Info("Starting intent and binding matching") +func MatchAndBindIntents(ctx context.Context, client client.Client, bindings *v1.SecurityIntentBinding) (*BindingInfo, error) { + logger := log.FromContext(ctx) + logger.Info("SecurityIntent and SecurityIntentBinding matching started") + + var matchedIntents []string + var matchedBindings []string + var matchedBindingNamespaces []string - // Fetching SecurityIntent objects. - var intents []*v1.SecurityIntent for _, intentRef := range bindings.Spec.Intents { - intent := &v1.SecurityIntent{} - if err := client.Get(ctx, types.NamespacedName{Name: intentRef.Name, Namespace: bindings.Namespace}, intent); err != nil { - log.Error(err, "Failed to get SecurityIntent", "Name", intentRef.Name) + var intent v1.SecurityIntent + if err := client.Get(ctx, types.NamespacedName{Name: intentRef.Name, Namespace: bindings.Namespace}, &intent); err != nil { + logger.Error(err, "failed to get SecurityIntent", "Name", intentRef.Name) continue } - intents = append(intents, intent) + matchedIntents = append(matchedIntents, intent.Name) } - var matchedIntentNames []string - var matchedIntentNamespaces []string - var matchedBindingNames []string - var matchedBindingNamespaces []string + // Adding names and namespaces of SecurityIntentBinding. + matchedBindings = append(matchedBindings, bindings.Name) + matchedBindingNamespaces = append(matchedBindingNamespaces, bindings.Namespace) - // Checking match for SecurityIntent and SecurityIntentBinding. - for _, intent := range intents { - matchedIntentNames = append(matchedIntentNames, intent.Name) - matchedIntentNamespaces = append(matchedIntentNamespaces, intent.Namespace) + logger.Info("Matching completed", "Matched SecurityIntents", matchedIntents, "Matched SecurityIntentsBindings", matchedBindings) + return NewBindingInfo(matchedIntents, matchedBindings, matchedBindingNamespaces), nil +} + +func MatchAndBindIntentsGlobal(ctx context.Context, client client.Client, clusterBinding *v1.ClusterSecurityIntentBinding) (*BindingInfo, error) { + logger := log.FromContext(ctx) + logger.Info("SecurityIntent and ClusterSecurityIntentBinding matching started") + + var matchedIntents []string + for _, intentRef := range clusterBinding.Spec.Intents { + var intent v1.SecurityIntent + if err := client.Get(ctx, types.NamespacedName{Name: intentRef.Name}, &intent); err != nil { + logger.Error(err, "failed to get SecurityIntent", "Name", intentRef.Name) + continue + } + matchedIntents = append(matchedIntents, intent.Name) } - // Adding names and namespaces of SecurityIntentBinding. - matchedBindingNames = append(matchedBindingNames, bindings.Name) - matchedBindingNamespaces = append(matchedBindingNamespaces, bindings.Namespace) + var matchedClusterBindings []string + matchedClusterBindings = append(matchedClusterBindings, clusterBinding.Name) - log.Info("Matching completed", "Matched Intent Names", matchedIntentNames, "Matched Binding Names", matchedBindingNames) - return NewBindingInfo(matchedIntentNames, matchedIntentNamespaces, matchedBindingNames, matchedBindingNamespaces), nil + logger.Info("Matching completed", "Matched SecurityIntents", matchedIntents, "Matched ClusterSecurityIntentBindings", matchedClusterBindings) + return NewBindingInfo(matchedIntents, matchedClusterBindings, nil), nil } diff --git a/pkg/processor/nimbuspolicybuilder/nimbuspolicy_builder.go b/pkg/processor/nimbuspolicybuilder/nimbuspolicy_builder.go index 0cb63a95..037f5466 100644 --- a/pkg/processor/nimbuspolicybuilder/nimbuspolicy_builder.go +++ b/pkg/processor/nimbuspolicybuilder/nimbuspolicy_builder.go @@ -9,39 +9,25 @@ import ( "github.com/google/cel-go/cel" "github.com/google/cel-go/checker/decls" - ctrl "sigs.k8s.io/controller-runtime" - - v1 "github.com/5GSEC/nimbus/api/v1" - "github.com/5GSEC/nimbus/pkg/processor/intentbinder" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" + + v1 "github.com/5GSEC/nimbus/api/v1" + "github.com/5GSEC/nimbus/pkg/processor/intentbinder" ) // BuildNimbusPolicy generates a NimbusPolicy based on SecurityIntent and SecurityIntentBinding. -func BuildNimbusPolicy(ctx context.Context, client client.Client, req ctrl.Request, bindingInfo *intentbinder.BindingInfo) (*v1.NimbusPolicy, error) { +func BuildNimbusPolicy(ctx context.Context, client client.Client, bindingInfo *intentbinder.BindingInfo) (*v1.NimbusPolicy, error) { log := log.FromContext(ctx) log.Info("Starting NimbusPolicy building") - // Validates bindingInfo. - if bindingInfo == nil || len(bindingInfo.IntentNames) == 0 || len(bindingInfo.IntentNamespaces) == 0 || - len(bindingInfo.BindingNames) == 0 || len(bindingInfo.BindingNamespaces) == 0 { - return nil, fmt.Errorf("invalid bindingInfo: one or more arrays are empty") - } - var nimbusRulesList []v1.NimbusRules // Iterate over intent names to build rules. - for i, intentName := range bindingInfo.IntentNames { - // Checks for array length consistency. - if i >= len(bindingInfo.IntentNamespaces) || i >= len(bindingInfo.BindingNames) || - i >= len(bindingInfo.BindingNamespaces) { - return nil, fmt.Errorf("index out of range in bindingInfo arrays") - } - - intentNamespace := bindingInfo.IntentNamespaces[i] - intent, err := fetchIntentByName(ctx, client, intentName, intentNamespace) + for _, intentName := range bindingInfo.IntentNames { + intent, err := fetchIntentByName(ctx, client, intentName) if err != nil { return nil, err } @@ -52,31 +38,22 @@ func BuildNimbusPolicy(ctx context.Context, client client.Client, req ctrl.Reque return nil, fmt.Errorf("no intents or bindings to process") } - var rules []v1.Rule - // Constructs a rule from the intent parameters. rule := v1.Rule{ - RuleAction: intent.Spec.Intent.Action, - MatchProtocols: []v1.MatchProtocol{}, - MatchPaths: []v1.MatchPath{}, - MatchDirectories: []v1.MatchDirectory{}, - MatchPatterns: []v1.MatchPattern{}, - MatchCapabilities: []v1.MatchCapability{}, - MatchSyscalls: []v1.MatchSyscall{}, - FromCIDRSet: []v1.CIDRSet{}, - ToPorts: []v1.ToPort{}, + RuleAction: intent.Spec.Intent.Action, + Mode: intent.Spec.Intent.Mode, + Params: map[string][]string{}, } - for _, param := range intent.Spec.Intent.Params { - processSecurityIntentParams(&rule, param) + for key, val := range intent.Spec.Intent.Params { + rule.Params[key] = val } - rules = append(rules, rule) nimbusRule := v1.NimbusRules{ - Id: intent.Spec.Intent.Id, + ID: intent.Spec.Intent.ID, Type: "", // Set Type if necessary Description: intent.Spec.Intent.Description, - Rule: rules, + Rule: rule, } nimbusRulesList = append(nimbusRulesList, nimbusRule) } @@ -108,7 +85,7 @@ func BuildNimbusPolicy(ctx context.Context, client client.Client, req ctrl.Reque NimbusRules: nimbusRulesList, }, Status: v1.NimbusPolicyStatus{ - PolicyStatus: "Pending", + Status: "Pending", }, } @@ -117,11 +94,11 @@ func BuildNimbusPolicy(ctx context.Context, client client.Client, req ctrl.Reque } // fetchIntentByName fetches a SecurityIntent by its name and namespace. -func fetchIntentByName(ctx context.Context, client client.Client, name string, namespace string) (*v1.SecurityIntent, error) { +func fetchIntentByName(ctx context.Context, client client.Client, name string) (*v1.SecurityIntent, error) { log := log.FromContext(ctx) var intent v1.SecurityIntent - if err := client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, &intent); err != nil { + if err := client.Get(ctx, types.NamespacedName{Name: name}, &intent); err != nil { log.Error(err, "Failed to get SecurityIntent") return nil, err } @@ -139,69 +116,6 @@ func fetchBindingByName(ctx context.Context, client client.Client, name string, return &binding, nil } -// processSecurityIntentParams processes the parameters of a SecurityIntent. -func processSecurityIntentParams(rule *v1.Rule, param v1.SecurityIntentParams) { - // Processes MatchProtocols. - for _, mp := range param.MatchProtocols { - rule.MatchProtocols = append(rule.MatchProtocols, v1.MatchProtocol(mp)) - - } - - // Processes MatchPaths. - for _, mp := range param.MatchPaths { - rule.MatchPaths = append(rule.MatchPaths, v1.MatchPath(mp)) - } - - // Processes MatchDirectories. - for _, md := range param.MatchDirectories { - rule.MatchDirectories = append(rule.MatchDirectories, v1.MatchDirectory{ - Directory: md.Directory, - FromSource: []v1.NimbusFromSource{}, - }) - } - - // Processes MatchPatterns. - for _, mp := range param.MatchPatterns { - rule.MatchPatterns = append(rule.MatchPatterns, v1.MatchPattern(mp)) - } - - // Processes MatchCapabilities. - for _, mc := range param.MatchCapabilities { - matchCapability := v1.MatchCapability{ - Capability: mc.Capability, - FromSource: []v1.NimbusFromSource{}, - } - rule.MatchCapabilities = append(rule.MatchCapabilities, matchCapability) - } - - // Processes MatchSyscalls and MatchSyscallPaths. - for _, ms := range param.MatchSyscalls { - var matchSyscall v1.MatchSyscall - matchSyscall.Syscalls = ms.Syscalls - rule.MatchSyscalls = append(rule.MatchSyscalls, matchSyscall) - } - - for _, msp := range param.MatchSyscallPaths { - rule.MatchSyscallPaths = append(rule.MatchSyscallPaths, v1.MatchSyscallPath(msp)) - } - - // Processes FromCIDRSet. - for _, fcs := range param.FromCIDRSet { - rule.FromCIDRSet = append(rule.FromCIDRSet, v1.CIDRSet(fcs)) - } - - // Processes ToPorts. - for _, tp := range param.ToPorts { - var ports []v1.Port - for _, p := range tp.Ports { - ports = append(ports, v1.Port(p)) - } - rule.ToPorts = append(rule.ToPorts, v1.ToPort{ - Ports: ports, - }) - } -} - // extractSelector extracts match labels from a Selector. func extractSelector(selector v1.Selector) (map[string]string, error) { matchLabels := make(map[string]string) // Initialize map for match labels. @@ -294,3 +208,85 @@ func ProcessMatchLabels(any, all []v1.ResourceFilter) (map[string]string, error) return matchLabels, nil } + +func BuildClusterNimbusPolicy(ctx context.Context, client client.Client, clusterBindingInfo *intentbinder.BindingInfo) (*v1.ClusterNimbusPolicy, error) { + logger := log.FromContext(ctx) + logger.Info("Building ClusterNimbusPolicy") + + var nimbusRules []v1.NimbusRules + for _, intentName := range clusterBindingInfo.IntentNames { + intent, err := fetchIntentByName(ctx, client, intentName) + if err != nil { + return nil, err + } + + if len(clusterBindingInfo.IntentNames) == 0 || len(clusterBindingInfo.BindingNames) == 0 { + logger.Info("No SecurityIntents or SecurityIntentsBindings to process") + return nil, fmt.Errorf("no SecurityIntents or SecurityIntentsBindings to process") + } + + rule := v1.Rule{ + RuleAction: intent.Spec.Intent.Action, + Mode: intent.Spec.Intent.Mode, + Params: map[string][]string{}, + } + + for key, val := range intent.Spec.Intent.Params { + rule.Params[key] = val + } + + nimbusRule := v1.NimbusRules{ + ID: intent.Spec.Intent.ID, + Type: "", // Set Type if necessary + Description: intent.Spec.Intent.Description, + Rule: rule, + } + nimbusRules = append(nimbusRules, nimbusRule) + } + + binding, err := fetchClusterBindingByName(ctx, client, clusterBindingInfo.BindingNames[0]) + if err != nil { + return nil, err + } + + clusterBindingSelector := extractClusterBindingSelector(binding.Spec.Selector) + + clusterNimbusPolicy := &v1.ClusterNimbusPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: binding.Name, + }, + Spec: v1.ClusterNimbusPolicySpec{ + Selector: clusterBindingSelector, + NimbusRules: nimbusRules, + }, + Status: v1.ClusterNimbusPolicyStatus{ + Status: "Pending", + }, + } + + logger.Info("ClusterNimbusPolicy built successfully", "ClusterNimbusPolicy", clusterNimbusPolicy) + return clusterNimbusPolicy, nil +} + +func extractClusterBindingSelector(cwSelector v1.CwSelector) v1.CwSelector { + var clusterBindingSelector v1.CwSelector + for _, resource := range cwSelector.Resources { + var cwresource v1.CwResource + cwresource.Kind = resource.Kind + cwresource.Name = resource.Name + cwresource.Namespace = resource.Namespace + cwresource.MatchLabels = resource.MatchLabels + clusterBindingSelector.Resources = append(clusterBindingSelector.Resources, cwresource) + } + return clusterBindingSelector +} + +func fetchClusterBindingByName(ctx context.Context, client client.Client, clusterBindingName string) (v1.ClusterSecurityIntentBinding, error) { + logger := log.FromContext(ctx) + var clusterBinding v1.ClusterSecurityIntentBinding + if err := client.Get(ctx, types.NamespacedName{Name: clusterBindingName}, &clusterBinding); err != nil { + logger.Error(err, "failed to get ClusterSecurityIntentBinding", "ClusterSecurityIntentBinding", clusterBindingName) + return v1.ClusterSecurityIntentBinding{}, err + } + return clusterBinding, nil +} diff --git a/pkg/receiver/securityintentbinding/securityintentbinding_controller.go b/pkg/receiver/securityintentbinding/securityintentbinding_controller.go index 9ed19902..bb95ebbf 100644 --- a/pkg/receiver/securityintentbinding/securityintentbinding_controller.go +++ b/pkg/receiver/securityintentbinding/securityintentbinding_controller.go @@ -14,11 +14,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" + kubearmorv1 "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/api/security.kubearmor.com/v1" + v1 "github.com/5GSEC/nimbus/api/v1" "github.com/5GSEC/nimbus/pkg/processor/intentbinder" "github.com/5GSEC/nimbus/pkg/processor/nimbuspolicybuilder" "github.com/5GSEC/nimbus/pkg/receiver/watcher" - kubearmorv1 "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/api/security.kubearmor.com/v1" ) // SecurityIntentBindingReconciler reconciles a SecurityIntentBinding object @@ -108,14 +109,14 @@ func (r *SecurityIntentBindingReconciler) Reconcile(ctx context.Context, req ctr } // Call the MatchAndBindIntents function to generate the binding information. - bindingInfo, err := intentbinder.MatchAndBindIntents(ctx, r.Client, req, binding) + bindingInfo, err := intentbinder.MatchAndBindIntents(ctx, r.Client, binding) if err != nil { log.Error(err, "Failed to match and bind intents") return ctrl.Result{}, err } // Create a NimbusPolicy. - nimbusPolicy, err := nimbuspolicybuilder.BuildNimbusPolicy(ctx, r.Client, req, bindingInfo) + nimbusPolicy, err := nimbuspolicybuilder.BuildNimbusPolicy(ctx, r.Client, bindingInfo) if err != nil { log.Error(err, "Failed to build NimbusPolicy") return ctrl.Result{}, err @@ -126,7 +127,7 @@ func (r *SecurityIntentBindingReconciler) Reconcile(ctx context.Context, req ctr log.Error(err, "Failed to create NimbusPolicy") return ctrl.Result{}, err } - + //Todo: Update status return ctrl.Result{}, nil } diff --git a/pkg/receiver/watcher/watch_clusterbinding.go b/pkg/receiver/watcher/watch_clusterbinding.go new file mode 100644 index 00000000..f42d0133 --- /dev/null +++ b/pkg/receiver/watcher/watch_clusterbinding.go @@ -0,0 +1,49 @@ +package watcher + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + v1 "github.com/5GSEC/nimbus/api/v1" +) + +type WatcherClusterBinding struct { + Client client.Client +} + +func NewWatcherClusterBinding(client client.Client) (*WatcherClusterBinding, error) { + if client == nil { + return nil, fmt.Errorf("WatcherClusterBinding: Client is nil") + } + + // Return a new WatcherBinding instance with the provided client. + return &WatcherClusterBinding{ + Client: client, + }, nil +} + +func (wcb *WatcherClusterBinding) Reconcile(ctx context.Context, req ctrl.Request) (*v1.ClusterSecurityIntentBinding, error) { + logger := log.FromContext(ctx) + if wcb == nil || wcb.Client == nil { + logger.Info("WatcherClusterBinding is nil or Client is nil in Reconcile") + return nil, fmt.Errorf("WatcherClusterBinding or Client is not initialized") + } + + clusterSib := &v1.ClusterSecurityIntentBinding{} + err := wcb.Client.Get(ctx, types.NamespacedName{Name: req.Name}, clusterSib) + + if err != nil { + if errors.IsNotFound(err) { + return nil, nil + } + logger.Error(err, "failed to get ClusterSecurityIntentBinding", "Name", req.Name) + return nil, err + } + return clusterSib, nil +} diff --git a/pkg/receiver/watcher/watch_clusternimbuspolicy.go b/pkg/receiver/watcher/watch_clusternimbuspolicy.go new file mode 100644 index 00000000..1e155960 --- /dev/null +++ b/pkg/receiver/watcher/watch_clusternimbuspolicy.go @@ -0,0 +1,47 @@ +package watcher + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + v1 "github.com/5GSEC/nimbus/api/v1" +) + +type ClusterNimbusPolicy struct { + Client client.Client +} + +func NewClusterNimbusPolicy(client client.Client) (*ClusterNimbusPolicy, error) { + if client == nil { + return nil, fmt.Errorf("ClusterNimbusPolicyWatcher: Client is nil") + } + return &ClusterNimbusPolicy{ + Client: client, + }, nil +} + +func (wcnp *ClusterNimbusPolicy) Reconcile(ctx context.Context, req ctrl.Request) (*v1.ClusterNimbusPolicy, error) { + logger := log.FromContext(ctx) + if wcnp == nil || wcnp.Client == nil { + logger.Info("ClusterNimbusPolicy watcher is nil or Client is nil") + return nil, fmt.Errorf("ClusterNimbusPolicy watcher or Client is not initialized") + } + + var cwnp v1.ClusterNimbusPolicy + err := wcnp.Client.Get(ctx, types.NamespacedName{Name: req.Name}, &cwnp) + if err != nil { + if errors.IsNotFound(err) { + logger.Info("ClusterNimbusPolicy resource not found. Ignoring since object must be deleted", "Name", req.Name) + return nil, nil + } + logger.Error(err, "failed to get ClusterNimbusPolicy", "Name", req.Name) + return nil, err + } + return &cwnp, nil +} diff --git a/pkg/receiver/watcher/watch_controller.go b/pkg/receiver/watcher/watch_controller.go index 2d7cc21c..d206e864 100644 --- a/pkg/receiver/watcher/watch_controller.go +++ b/pkg/receiver/watcher/watch_controller.go @@ -7,16 +7,19 @@ import ( "context" "fmt" - v1 "github.com/5GSEC/nimbus/api/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + v1 "github.com/5GSEC/nimbus/api/v1" ) // WatcherController is a struct that holds a Kubernetes client and a WatcherIntent. type WatcherController struct { - Client client.Client - WatcherIntent *WatcherIntent - WatcherBinding *WatcherBinding + Client client.Client + WatcherIntent *WatcherIntent + WatcherBinding *WatcherBinding + WatcherClusterBinding *WatcherClusterBinding } // NewWatcherController creates a new instance of WatcherController. @@ -35,29 +38,42 @@ func NewWatcherController(client client.Client) (*WatcherController, error) { return nil, fmt.Errorf("WatcherController: Error creating WatcherBinding: %v", err) } + watcherClusterSib, err := NewWatcherClusterBinding(client) + if err != nil { + return nil, fmt.Errorf("WatcherController: Error creating WatcherClusterBinding: %v", err) + } + return &WatcherController{ - Client: client, - WatcherIntent: watcherIntent, - WatcherBinding: watcherBinding, + Client: client, + WatcherIntent: watcherIntent, + WatcherBinding: watcherBinding, + WatcherClusterBinding: watcherClusterSib, }, nil } -func (wc *WatcherController) Reconcile(ctx context.Context, client client.Client, req ctrl.Request) (*v1.SecurityIntent, *v1.SecurityIntentBinding, error) { +func (wc *WatcherController) Reconcile(ctx context.Context, req ctrl.Request) (*v1.SecurityIntent, *v1.SecurityIntentBinding, *v1.ClusterSecurityIntentBinding, error) { + logger := log.FromContext(ctx) if wc == nil { - return nil, nil, fmt.Errorf("WatcherController is nil") + return nil, nil, nil, fmt.Errorf("WatcherController is nil") } intent, errIntent := wc.WatcherIntent.Reconcile(ctx, req) if errIntent != nil { fmt.Println("Failed to process SecurityIntent:", errIntent) - return nil, nil, errIntent + return nil, nil, nil, errIntent } binding, errBinding := wc.WatcherBinding.Reconcile(ctx, req) if errBinding != nil { fmt.Println("Failed to process SecurityIntentBinding:", errBinding) - return intent, nil, errBinding + return nil, nil, nil, errBinding + } + + clusterSib, err := wc.WatcherClusterBinding.Reconcile(ctx, req) + if err != nil { + logger.Error(err, "failed to reconcile ClusterSecurityIntentBinding", "ClusterSecurityIntentBinding", req.Name) + return nil, nil, nil, err } - return intent, binding, nil + return intent, binding, clusterSib, nil }