From ee8db0aaaecdf272936deb2f37938b0b9ed1055d Mon Sep 17 00:00:00 2001 From: b0m313 <13.spring.03@gmail.com> Date: Tue, 2 Jan 2024 18:18:30 +0000 Subject: [PATCH] feat: Move the policy generation code for the adapter and create a simple HTTP server. --- nimbus-kubearmor/processor/network_policy.go | 63 +++ .../processor/policy_controller.go | 79 ++++ nimbus-kubearmor/processor/system_policy.go | 62 +++ .../processor/utils/utils_policy.go | 425 ++++++++++++++++++ nimbus-kubearmor/receiver/server/server.go | 64 +++ 5 files changed, 693 insertions(+) create mode 100644 nimbus-kubearmor/processor/network_policy.go create mode 100644 nimbus-kubearmor/processor/policy_controller.go create mode 100644 nimbus-kubearmor/processor/system_policy.go create mode 100644 nimbus-kubearmor/processor/utils/utils_policy.go create mode 100644 nimbus-kubearmor/receiver/server/server.go diff --git a/nimbus-kubearmor/processor/network_policy.go b/nimbus-kubearmor/processor/network_policy.go new file mode 100644 index 00000000..e207c804 --- /dev/null +++ b/nimbus-kubearmor/processor/network_policy.go @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package policy + +import ( + "context" + + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" + + general "github.com/5GSEC/nimbus/pkg/controllers/general" + utils "github.com/5GSEC/nimbus/pkg/controllers/utils" +) + +// NetworkPolicyController struct to handle network policies. +type NetworkPolicyController struct { + Client client.Client // Client to interact with Kubernetes API. + Scheme *runtime.Scheme // Scheme defines the runtime scheme of the Kubernetes objects. +} + +// NewNetworkPolicyController creates a new instance of NetworkPolicyController. +func NewNetworkPolicyController(client client.Client, scheme *runtime.Scheme) *NetworkPolicyController { + return &NetworkPolicyController{ + Client: client, + Scheme: scheme, + } +} + +// HandlePolicy processes the network policies defined in the SecurityIntent resource. +func (npc *NetworkPolicyController) HandlePolicy(ctx context.Context, bindingInfo *general.BindingInfo) error { + log := log.FromContext(ctx) + log.Info("Handling Network Policy", "BindingName", bindingInfo.Binding.Name) + + // Build and apply/update Cilium Network Policy based on BindingInfo. + ciliumPolicySpec := utils.BuildCiliumNetworkPolicySpec(ctx, bindingInfo).(*ciliumv2.CiliumNetworkPolicy) + err := utils.ApplyOrUpdatePolicy(ctx, npc.Client, ciliumPolicySpec, bindingInfo.Binding.Name) + if err != nil { + log.Error(err, "Failed to apply Cilium Network Policy", "Name", bindingInfo.Binding.Name) + return err + } + + log.Info("Applied Network Policy", "PolicyName", bindingInfo.Binding.Name) + return nil +} + +// DeletePolicy removes the network policy associated with the SecurityIntent resource. +func (npc *NetworkPolicyController) DeletePolicy(ctx context.Context, bindingInfo *general.BindingInfo) error { + log := log.FromContext(ctx) + + // Modified line: Merged variable declaration with assignment + err := utils.DeletePolicy(ctx, npc.Client, "CiliumNetworkPolicy", bindingInfo.Binding.Name, bindingInfo.Binding.Namespace) + if err != nil { + log.Error(err, "Failed to delete Cilium Network Policy", "Name", bindingInfo.Binding.Name) + return err + } + + log.Info("Deleted Network Policy", "PolicyName", bindingInfo.Binding.Name) + return nil +} diff --git a/nimbus-kubearmor/processor/policy_controller.go b/nimbus-kubearmor/processor/policy_controller.go new file mode 100644 index 00000000..1effee67 --- /dev/null +++ b/nimbus-kubearmor/processor/policy_controller.go @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package policy + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + general "github.com/5GSEC/nimbus/pkg/controllers/general" +) + +// Constant for the finalizer name used in the SecurityIntent resource. +// const securityIntentFinalizer = "finalizer.securityintent.intent.security.nimbus.com" + +// PolicyController struct handles different types of policies. +type PolicyController struct { + Client client.Client // Client for interacting with Kubernetes API. + Scheme *runtime.Scheme // Scheme defines the runtime scheme of the Kubernetes objects. + NetworkPolicyController *NetworkPolicyController // Controller for handling network policies. + SystemPolicyController *SystemPolicyController // Controller for handling system policies. +} + +// NewPolicyController creates a new instance of PolicyController. +func NewPolicyController(client client.Client, scheme *runtime.Scheme) *PolicyController { + if client == nil || scheme == nil { + fmt.Println("PolicyController: Client or Scheme is nil") + return nil + } + + return &PolicyController{ + Client: client, + Scheme: scheme, + NetworkPolicyController: NewNetworkPolicyController(client, scheme), + SystemPolicyController: NewSystemPolicyController(client, scheme), + } +} + +// Reconcile handles the reconciliation logic for the SecurityIntent and SecurityIntentBinding resources. +func (pc *PolicyController) Reconcile(ctx context.Context, bindingInfo *general.BindingInfo) error { + log := log.FromContext(ctx) + + var intentRequestType string + if len(bindingInfo.Binding.Spec.IntentRequests) > 0 { + intentRequestType = bindingInfo.Binding.Spec.IntentRequests[0].Type + } + + log.Info("Processing policy", "BindingName", bindingInfo.Binding.Name, "IntentType", intentRequestType) + + var err error + switch intentRequestType { + case "network": + err = pc.NetworkPolicyController.HandlePolicy(ctx, bindingInfo) + if err != nil { + log.Error(err, "Failed to apply network policy", "BindingName", bindingInfo.Binding.Name) + return err + } + case "system": + err = pc.SystemPolicyController.HandlePolicy(ctx, bindingInfo) + if err != nil { + log.Error(err, "Failed to apply system policy", "BindingName", bindingInfo.Binding.Name) + return err + } + default: + err = fmt.Errorf("unknown policy type: %s", intentRequestType) + log.Error(err, "Unknown policy type", "Type", intentRequestType) + return err + } + if err != nil { + log.Error(err, "Failed to apply policy", "BindingName", bindingInfo.Binding.Name) + return err + } + + return nil +} diff --git a/nimbus-kubearmor/processor/system_policy.go b/nimbus-kubearmor/processor/system_policy.go new file mode 100644 index 00000000..3d8c1403 --- /dev/null +++ b/nimbus-kubearmor/processor/system_policy.go @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package policy + +import ( + "context" + + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + general "github.com/5GSEC/nimbus/pkg/controllers/general" + utils "github.com/5GSEC/nimbus/pkg/controllers/utils" +) + +// SystemPolicyController is a struct to handle system policies. +type SystemPolicyController struct { + Client client.Client // Client for interacting with Kubernetes API. + Scheme *runtime.Scheme // Scheme defines the runtime scheme of the Kubernetes objects. +} + +// NewSystemPolicyController creates a new instance of SystemPolicyController. +func NewSystemPolicyController(client client.Client, scheme *runtime.Scheme) *SystemPolicyController { + return &SystemPolicyController{ + Client: client, + Scheme: scheme, + } +} + +// HandlePolicy processes the system policy as defined in SecurityIntent. +func (spc *SystemPolicyController) HandlePolicy(ctx context.Context, bindingInfo *general.BindingInfo) error { + log := log.FromContext(ctx) // Logger with context. + log.Info("Handling System Policy", "BindingName", bindingInfo.Binding.Name) + + // Build KubeArmorPolicy based on BindingInfo + kubearmorPolicy := utils.BuildKubeArmorPolicySpec(ctx, bindingInfo) + + err := utils.ApplyOrUpdatePolicy(ctx, spc.Client, kubearmorPolicy, bindingInfo.Binding.Name) + if err != nil { + log.Error(err, "Failed to apply KubeArmorPolicy", "Name", bindingInfo.Binding.Name) + return err + } + + log.Info("Applied KubeArmorPolicy", "PolicyName", bindingInfo.Binding.Name) + return nil +} + +// DeletePolicy removes the system policy associated with the SecurityIntent resource. +func (spc *SystemPolicyController) DeletePolicy(ctx context.Context, bindingInfo *general.BindingInfo) error { + log := log.FromContext(ctx) + + // Delete KubeArmor Policy + err := utils.DeletePolicy(ctx, spc.Client, "KubeArmorPolicy", bindingInfo.Binding.Name, bindingInfo.Binding.Namespace) + if err != nil { + log.Error(err, "Failed to delete KubeArmor Policy", "Name", bindingInfo.Binding.Name) + return err + } + + log.Info("Deleted System Policy", "PolicyName", bindingInfo.Binding.Name) + return nil +} diff --git a/nimbus-kubearmor/processor/utils/utils_policy.go b/nimbus-kubearmor/processor/utils/utils_policy.go new file mode 100644 index 00000000..e4e918f2 --- /dev/null +++ b/nimbus-kubearmor/processor/utils/utils_policy.go @@ -0,0 +1,425 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package utils + +import ( + "context" + "fmt" + "reflect" + "strings" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + + general "github.com/5GSEC/nimbus/pkg/controllers/general" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + client "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" + "github.com/cilium/cilium/pkg/policy/api" + kubearmorv1 "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/api/security.kubearmor.com/v1" +) + +// --------------------------------------------------- +// -------- Creation of Policy Specifications -------- +// --------------------------------------------------- + +// BuildKubeArmorPolicySpec creates a policy specification (either KubeArmorPolicy or KubeArmorHostPolicy) +// based on the provided SecurityIntent and the type of policy. +// BuildKubeArmorPolicySpec creates a KubeArmor policy specification based on the provided SecurityIntentBinding. +func BuildKubeArmorPolicySpec(ctx context.Context, bindingInfo *general.BindingInfo) *kubearmorv1.KubeArmorPolicy { + log := log.FromContext(ctx) + log.Info("Creating KubeArmorPolicy", "BindingName", bindingInfo.Binding.Name) + + intent := bindingInfo.Intent[0] + + return &kubearmorv1.KubeArmorPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: bindingInfo.Binding.Name, + Namespace: bindingInfo.Binding.Namespace, + }, + Spec: kubearmorv1.KubeArmorPolicySpec{ + Selector: kubearmorv1.SelectorType{ + MatchLabels: extractMatchLabels(bindingInfo), + }, + Process: extractToKubeArmorPolicyProcessType(bindingInfo), + File: extractToKubeArmorPolicyFileType(bindingInfo), + Capabilities: extractToKubeArmorPolicyCapabilitiesType(bindingInfo), + Network: extractToKubeArmorPolicyNetworkType(bindingInfo), + // TODO: To discuss + //Network: convertToKubeArmorHostPolicyNetworkType(extractNetworkPolicy(intent)), + Action: kubearmorv1.ActionType(intent.Spec.Intent.Action), + }, + } +} + +// BuildCiliumNetworkPolicySpec creates a Cilium network policy specification based on the provided BindingInfo. +func BuildCiliumNetworkPolicySpec(ctx context.Context, bindingInfo *general.BindingInfo) interface{} { + log := log.FromContext(ctx) + log.Info("Creating CiliumNetworkPolicy", "Name", bindingInfo.Binding.Name) + + endpointSelector := getEndpointSelector(ctx, bindingInfo) + ingressDenyRules := getIngressDenyRules(bindingInfo) + + policy := &ciliumv2.CiliumNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: bindingInfo.Binding.Name, + Namespace: bindingInfo.Binding.Namespace, + }, + Spec: &api.Rule{ + EndpointSelector: endpointSelector, + IngressDeny: ingressDenyRules, + }, + } + return policy +} + +// TODO: To discuss +//func convertToKubeArmorHostPolicyNetworkType(slice []interface{}) kubearmorv1.MatchHostNetworkProtocolType { +// var result kubearmorv1.MatchHostNetworkProtocolType +// for _, item := range slice { +// str, ok := item.(string) +// if !ok { +// continue // or appropriate error handling +// } +// // Requires explicit type conversion to MatchNetworkProtocolStringType +// protocol := kubearmorv1.MatchNetworkProtocolStringType(str) +// result.MatchProtocols = append(result.MatchProtocols, kubearmorv1.MatchNetworkProtocolType{ +// Protocol: protocol, +// }) +// } +// return result +//} + +// -------------------------------------- +// -------- Utility Functions ---------- +// -------------------------------------- + +// extractMatchLabelsFromBinding extracts matchLabels from the SecurityIntentBinding. +func extractMatchLabels(bindingInfo *general.BindingInfo) map[string]string { + matchLabels := make(map[string]string) + for _, filter := range bindingInfo.Binding.Spec.Selector.Any { + for key, val := range filter.Resources.MatchLabels { + matchLabels[key] = val + } + } + + for _, filter := range bindingInfo.Binding.Spec.Selector.All { + for key, val := range filter.Resources.MatchLabels { + matchLabels[key] = val + } + } + + // Remove 'any:', 'all:', 'cel:' prefixes from the keys + processedLabels := make(map[string]string) + for key, val := range matchLabels { + processedKey := removeReservedPrefixes(key) + processedLabels[processedKey] = val + } + + return processedLabels +} + +func extractToKubeArmorPolicyProcessType(bindingInfo *general.BindingInfo) kubearmorv1.ProcessType { + intent := bindingInfo.Intent[0] + + var processType kubearmorv1.ProcessType + for _, resource := range intent.Spec.Intent.Resource { + for _, process := range resource.Process { + for _, match := range process.MatchPaths { + if path := match.Path; path != "" && strings.HasPrefix(path, "/") { + processType.MatchPaths = append(processType.MatchPaths, kubearmorv1.ProcessPathType{ + Path: kubearmorv1.MatchPathType(path), + }) + } + } + for _, dir := range process.MatchDirectories { + var fromSources []kubearmorv1.MatchSourceType + for _, source := range dir.FromSource { + fromSources = append(fromSources, kubearmorv1.MatchSourceType{ + Path: kubearmorv1.MatchPathType(source.Path), + }) + } + if dir.Directory != "" || len(fromSources) > 0 { + processType.MatchDirectories = append(processType.MatchDirectories, kubearmorv1.ProcessDirectoryType{ // Adjusted type here + Directory: kubearmorv1.MatchDirectoryType(dir.Directory), + Recursive: dir.Recursive, + FromSource: fromSources, + }) + } + } + for _, pattern := range process.MatchPatterns { + if pattern.Pattern != "" { + processType.MatchPatterns = append(processType.MatchPatterns, kubearmorv1.ProcessPatternType{ + Pattern: pattern.Pattern, + }) + } + } + } + } + return processType +} + +func extractToKubeArmorPolicyFileType(bindingInfo *general.BindingInfo) kubearmorv1.FileType { + intent := bindingInfo.Intent[0] + + var fileType kubearmorv1.FileType + + for _, resource := range intent.Spec.Intent.Resource { + for _, file := range resource.File { + for _, path := range file.MatchPaths { + if path.Path != "" { + fileType.MatchPaths = append(fileType.MatchPaths, kubearmorv1.FilePathType{ + Path: kubearmorv1.MatchPathType(path.Path), + }) + } + } + + for _, dir := range file.MatchDirectories { + var fromSources []kubearmorv1.MatchSourceType + for _, source := range dir.FromSource { + fromSources = append(fromSources, kubearmorv1.MatchSourceType{ + Path: kubearmorv1.MatchPathType(source.Path), + }) + } + if dir.Directory != "" || len(fromSources) > 0 { + fileType.MatchDirectories = append(fileType.MatchDirectories, kubearmorv1.FileDirectoryType{ + Directory: kubearmorv1.MatchDirectoryType(dir.Directory), + Recursive: dir.Recursive, + FromSource: fromSources, + }) + } + } + } + } + + return fileType +} + +func extractToKubeArmorPolicyCapabilitiesType(bindingInfo *general.BindingInfo) kubearmorv1.CapabilitiesType { + var capabilitiesType kubearmorv1.CapabilitiesType + intent := bindingInfo.Intent[0] + + if len(intent.Spec.Intent.Resource) > 0 && len(intent.Spec.Intent.Resource[0].Capabilities) > 0 { + for _, capability := range intent.Spec.Intent.Resource[0].Capabilities { + for _, matchCapability := range capability.MatchCapabilities { + if matchCapability.Capability != "" { + capabilitiesType.MatchCapabilities = append(capabilitiesType.MatchCapabilities, kubearmorv1.MatchCapabilitiesType{ + Capability: kubearmorv1.MatchCapabilitiesStringType(matchCapability.Capability), + }) + } + } + } + } else { + capabilitiesType.MatchCapabilities = append(capabilitiesType.MatchCapabilities, kubearmorv1.MatchCapabilitiesType{ + Capability: "lease", + }) + } + return capabilitiesType +} + +func extractToKubeArmorPolicyNetworkType(bindingInfo *general.BindingInfo) kubearmorv1.NetworkType { + var networkType kubearmorv1.NetworkType + intent := bindingInfo.Intent[0] + + if len(intent.Spec.Intent.Resource) > 0 && len(intent.Spec.Intent.Resource[0].Network) > 0 { + for _, network := range intent.Spec.Intent.Resource[0].Network { + for _, matchProtocol := range network.MatchProtocols { + var fromSources []kubearmorv1.MatchSourceType + for _, source := range matchProtocol.FromSource { + fromSources = append(fromSources, kubearmorv1.MatchSourceType{ + Path: kubearmorv1.MatchPathType(source.Path), + }) + } + if matchProtocol.Protocol != "" { + networkType.MatchProtocols = append(networkType.MatchProtocols, kubearmorv1.MatchNetworkProtocolType{ + Protocol: kubearmorv1.MatchNetworkProtocolStringType(matchProtocol.Protocol), + FromSource: fromSources, + }) + } + } + } + } else { + networkType.MatchProtocols = append(networkType.MatchProtocols, kubearmorv1.MatchNetworkProtocolType{ + Protocol: "raw", + }) + } + return networkType +} + +// getEndpointSelector creates an endpoint selector from the SecurityIntent. +func getEndpointSelector(ctx context.Context, bindingInfo *general.BindingInfo) api.EndpointSelector { + + matchLabels := make(map[string]string) + /// Extract matched labels from BindingInfo + for _, filter := range bindingInfo.Binding.Spec.Selector.Any { + for key, val := range filter.Resources.MatchLabels { + matchLabels[key] = val + } + } + + for _, filter := range bindingInfo.Binding.Spec.Selector.All { + for key, val := range filter.Resources.MatchLabels { + matchLabels[key] = val + } + } + + processedLabels := make(map[string]string) + for key, val := range matchLabels { + processedKey := removeReservedPrefixes(key) + processedLabels[processedKey] = val + } + + // Create an Endpoint Selector based on processed labels + return api.NewESFromMatchRequirements(processedLabels, nil) +} + +func removeReservedPrefixes(key string) string { + for _, prefix := range []string{"any:", "all:", "cel:"} { + for strings.HasPrefix(key, prefix) { + key = strings.TrimPrefix(key, prefix) + } + } + return strings.TrimSpace(key) +} + +// getIngressDenyRules generates ingress deny rules from SecurityIntent specified in BindingInfo. +func getIngressDenyRules(bindingInfo *general.BindingInfo) []api.IngressDenyRule { + intent := bindingInfo.Intent[0] + + var ingressDenyRules []api.IngressDenyRule + + for _, resource := range intent.Spec.Intent.Resource { + ingressRule := api.IngressDenyRule{} + + for _, cidrSet := range resource.FromCIDRSet { + ingressRule.FromCIDRSet = append(ingressRule.FromCIDRSet, api.CIDRRule{ + Cidr: api.CIDR(cidrSet.CIDR), + }) + } + + for _, toPort := range resource.ToPorts { + var ports []api.PortProtocol + for _, port := range toPort.Ports { + ports = append(ports, api.PortProtocol{ + Port: port.Port, + Protocol: parseProtocol(port.Protocol), + }) + } + ingressRule.ToPorts = api.PortDenyRules{ + { + Ports: ports, + }, + } + } + + ingressDenyRules = append(ingressDenyRules, ingressRule) + } + + return ingressDenyRules +} + +func parseProtocol(protocol string) api.L4Proto { + // Convert protocol string to L4Proto type. + switch strings.ToUpper(protocol) { + case "TCP": + return api.ProtoTCP + case "UDP": + return api.ProtoUDP + case "ICMP": + return api.ProtoICMP + default: + return api.ProtoTCP + } +} + +// ---------------------------------------- +// -------- Apply & Update Policy -------- +// ---------------------------------------- + +// ApplyOrUpdatePolicy applies or updates the given policy. +func ApplyOrUpdatePolicy(ctx context.Context, c client.Client, policy client.Object, policyName string) error { + // Update the policy if it already exists, otherwise create a new one. + log := log.FromContext(ctx) + + var existingPolicy client.Object + var policySpec interface{} + + switch p := policy.(type) { + case *kubearmorv1.KubeArmorPolicy: + existingPolicy = &kubearmorv1.KubeArmorPolicy{} + policySpec = p.Spec + case *kubearmorv1.KubeArmorHostPolicy: + existingPolicy = &kubearmorv1.KubeArmorHostPolicy{} + policySpec = p.Spec + case *ciliumv2.CiliumNetworkPolicy: + existingPolicy = &ciliumv2.CiliumNetworkPolicy{} + policySpec = p.Spec + default: + return fmt.Errorf("unsupported policy type") + } + + err := c.Get(ctx, types.NamespacedName{Name: policyName, Namespace: policy.GetNamespace()}, existingPolicy) + if err != nil && !errors.IsNotFound(err) { + // Other error handling + log.Error(err, "Failed to get existing policy", "policy", policyName) + return err + } + + if errors.IsNotFound(err) { + // Create a policy if it doesn't exist + if err := c.Create(ctx, policy); err != nil { + log.Error(err, "Failed to apply policy", "policy", policyName) + return err + } + log.Info("Policy created", "Name", policyName) + } else { + // Update if policy already exists (compares specs only) + existingSpec := reflect.ValueOf(existingPolicy).Elem().FieldByName("Spec").Interface() + if !reflect.DeepEqual(policySpec, existingSpec) { + reflect.ValueOf(existingPolicy).Elem().FieldByName("Spec").Set(reflect.ValueOf(policySpec)) + if err := c.Update(ctx, existingPolicy); err != nil { + log.Error(err, "Failed to update policy", "policy", policyName) + return err + } + log.Info("Policy updated", "Name", policyName) + } else { + log.Info("Policy unchanged", "Name", policyName) + } + } + return nil +} + +// ---------------------------------------- +// ----------- Delete Policy ------------- +// ---------------------------------------- + +// DeletePolicy deletes a policy based on type, name, and namespace. +func DeletePolicy(ctx context.Context, c client.Client, policyType, name, namespace string) error { + // Process the deletion request based on policy type. + + var policy client.Object + log := log.FromContext(ctx) + + switch policyType { + case "KubeArmorPolicy": + policy = &kubearmorv1.KubeArmorPolicy{} + case "KubeArmorHostPolicy": + policy = &kubearmorv1.KubeArmorHostPolicy{} + case "CiliumNetworkPolicy": + policy = &ciliumv2.CiliumNetworkPolicy{} + default: + return fmt.Errorf("Unknown policy type: %s", policyType) + } + + policy.SetName(name) + policy.SetNamespace(namespace) + + if err := c.Delete(ctx, policy); client.IgnoreNotFound(err) != nil { + log.Error(err, "Failed to delete policy", "Type", policyType, "Name", name, "Namespace", namespace) + return err + } + return nil +} diff --git a/nimbus-kubearmor/receiver/server/server.go b/nimbus-kubearmor/receiver/server/server.go new file mode 100644 index 00000000..78b2dd91 --- /dev/null +++ b/nimbus-kubearmor/receiver/server/server.go @@ -0,0 +1,64 @@ +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "sync" +) + +var ( + // 저장된 Nimbus Policy를 저장하는 메모리 저장소 + nimbusPolicies []interface{} + lock sync.Mutex +) + +func main() { + http.HandleFunc("/api/v1/nimbus/export", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "POST" { + http.Error(w, "Only POST method is accepted", http.StatusMethodNotAllowed) + return + } + + body, err := ioutil.ReadAll(r.Body) + if err != nil { + http.Error(w, "Error reading request body", http.StatusInternalServerError) + return + } + defer r.Body.Close() + + var data interface{} + err = json.Unmarshal(body, &data) + if err != nil { + http.Error(w, "Error unmarshalling request body", http.StatusBadRequest) + return + } + + // 수신된 Nimbus Policy 저장 + lock.Lock() + nimbusPolicies = append(nimbusPolicies, data) + lock.Unlock() + + fmt.Printf("Received Nimbus Policy: %+v\n", data) + w.WriteHeader(http.StatusOK) + }) + + // 저장된 Nimbus Policies를 조회하는 API + http.HandleFunc("/api/v1/nimbus/policies", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + http.Error(w, "Only GET method is accepted", http.StatusMethodNotAllowed) + return + } + + lock.Lock() + defer lock.Unlock() + if err := json.NewEncoder(w).Encode(nimbusPolicies); err != nil { + http.Error(w, "Error encoding response", http.StatusInternalServerError) + } + }) + + log.Println("Server starting on port 13000...") + log.Fatal(http.ListenAndServe(":13000", nil)) +}