Skip to content

Commit

Permalink
fix(adapters): Make adapters to update their policies info in NP status
Browse files Browse the repository at this point in the history
Signed-off-by: Anurag Rajawat <[email protected]>
  • Loading branch information
anurag-rajawat committed Feb 14, 2024
1 parent ac7a09d commit aa038aa
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 18 deletions.
6 changes: 2 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ require (
)

require (
github.com/5GSEC/nimbus/pkg/adapter/nimbus-kubearmor v0.0.0-20240208144202-ef6c819f09b3 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/kubearmor/KubeArmor/pkg/KubeArmorController v0.0.0-20240125171707-8e6641511fe3 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
Expand Down Expand Up @@ -49,7 +47,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.18.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.46.0 // indirect
Expand All @@ -71,7 +69,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.29.1 // indirect
k8s.io/api v0.29.1
k8s.io/apiextensions-apiserver v0.29.1 // indirect
k8s.io/component-base v0.29.1 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
github.com/5GSEC/nimbus/pkg/adapter/nimbus-kubearmor v0.0.0-20240208144202-ef6c819f09b3 h1:dcJ9kZy7Kn/uh36QxLdTLn0L0UtG744uFAJHwCDUDdU=
github.com/5GSEC/nimbus/pkg/adapter/nimbus-kubearmor v0.0.0-20240208144202-ef6c819f09b3/go.mod h1:TTZsB7iLwzcTzW9CjkqIUpvx8ShiQM7bSNDH7mYnV8w=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down Expand Up @@ -68,8 +66,6 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kubearmor/KubeArmor/pkg/KubeArmorController v0.0.0-20240125171707-8e6641511fe3 h1:xDg2EAk7rV3psrUkwC7JqY6pzOutWwh4VuUEybypcrA=
github.com/kubearmor/KubeArmor/pkg/KubeArmorController v0.0.0-20240125171707-8e6641511fe3/go.mod h1:Z7ZPkMwtVcjSaDigSekvooXRxapWsLAVVmX3ltL673k=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down
2 changes: 0 additions & 2 deletions pkg/adapter/nimbus-kubearmor/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
github.com/5GSEC/nimbus v0.0.0-20240129090659-01178b5c28c7 h1:adBGcrCAKeU7PLiz6m2c+3c8uuL5UPkHN5O6FHJQm7I=
github.com/5GSEC/nimbus v0.0.0-20240129090659-01178b5c28c7/go.mod h1:VXo/w78XDmQEunuZYIsDyGDthCKealQR13X9OkY25D0=
github.com/5GSEC/nimbus v0.0.0-20240208070656-624660f34768 h1:v2fY3lWXydstfekQSHs9n0TpNnTteC7Iws3ojwGtFJk=
github.com/5GSEC/nimbus v0.0.0-20240208070656-624660f34768/go.mod h1:yw79m9f1+f3tBSZCMQKbNVKL39Q71FyGyoa8nClo1Hs=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down
17 changes: 15 additions & 2 deletions pkg/adapter/nimbus-kubearmor/manager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (

var (
scheme = runtime.NewScheme()
np intentv1.NimbusPolicy
k8sClient client.Client
)

Expand Down Expand Up @@ -81,6 +80,7 @@ func Run(ctx context.Context) {
func reconcileKsp(ctx context.Context, kspName, namespace string, deleted bool) {
logger := log.FromContext(ctx)
npName := adapterutil.ExtractNpName(kspName)
var np intentv1.NimbusPolicy
err := k8sClient.Get(ctx, types.NamespacedName{Name: npName, Namespace: namespace}, &np)
if err != nil {
if !errors.IsNotFound(err) {
Expand All @@ -98,13 +98,14 @@ func reconcileKsp(ctx context.Context, kspName, namespace string, deleted bool)

func createOrUpdateKsp(ctx context.Context, npName, npNamespace string) {
logger := log.FromContext(ctx)
var np intentv1.NimbusPolicy
if err := k8sClient.Get(ctx, types.NamespacedName{Name: npName, Namespace: npNamespace}, &np); err != nil {
logger.Error(err, "failed to get NimbusPolicy", "NimbusPolicy.Name", npName, "NimbusPolicy.Namespace", npNamespace)
return
}

if adapterutil.IsOrphan(np.GetOwnerReferences(), "SecurityIntentBinding") {
logger.V(4).Info("Ignoring orphan NimbusPolicy", "NimbusPolicy.Name", np.GetName(), "NimbusPolicy.Namespace", np.GetNamespace())
logger.V(4).Info("Ignoring orphan NimbusPolicy", "NimbusPolicy.Name", npName, "NimbusPolicy.Namespace", npNamespace)
return
}

Expand Down Expand Up @@ -140,6 +141,18 @@ func createOrUpdateKsp(ctx context.Context, npName, npNamespace string) {
}
logger.Info("KubeArmorPolicy configured", "KubeArmorPolicy.Name", existingKsp.Name, "KubeArmorPolicy.Namespace", existingKsp.Namespace)
}

// Due to adapters' dependency on nimbus module, the docker image build is
// failing. The relevant code is commented out below (lines 151-153). We shall
// uncomment this code in a subsequent PR.

// Every adapter is responsible for updating the status field of the
// corresponding NimbusPolicy with the number and names of successfully created
// policies. This provides feedback to users about the translation and deployment
// of their security intent.
//if err = adapterutil.UpdateNpStatus(ctx, k8sClient, "KubeArmorPolicy/"+ksp.Name, np.Name, np.Namespace); err != nil {
// logger.Error(err, "failed to update KubeArmorPolicies status in NimbusPolicy")
//}
}
}

Expand Down
1 change: 0 additions & 1 deletion pkg/adapter/nimbus-netpol/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.11.2 // indirect
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
Expand Down
3 changes: 1 addition & 2 deletions pkg/adapter/nimbus-netpol/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
github.com/5GSEC/nimbus v0.0.0-20240129090659-01178b5c28c7 h1:adBGcrCAKeU7PLiz6m2c+3c8uuL5UPkHN5O6FHJQm7I=
github.com/5GSEC/nimbus v0.0.0-20240129090659-01178b5c28c7/go.mod h1:VXo/w78XDmQEunuZYIsDyGDthCKealQR13X9OkY25D0=
github.com/5GSEC/nimbus v0.0.0-20240208070656-624660f34768 h1:v2fY3lWXydstfekQSHs9n0TpNnTteC7Iws3ojwGtFJk=
github.com/5GSEC/nimbus v0.0.0-20240208070656-624660f34768/go.mod h1:yw79m9f1+f3tBSZCMQKbNVKL39Q71FyGyoa8nClo1Hs=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down Expand Up @@ -154,6 +152,7 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
41 changes: 40 additions & 1 deletion pkg/adapter/nimbus-netpol/manager/netpols_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"fmt"

"github.com/go-logr/logr"
netv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
Expand All @@ -28,7 +29,6 @@ import (

var (
scheme = runtime.NewScheme()
np intentv1.NimbusPolicy
k8sClient client.Client
)

Expand Down Expand Up @@ -80,6 +80,7 @@ func Run(ctx context.Context) {
func reconcileNetPol(ctx context.Context, netpolName, namespace string, deleted bool) {
logger := log.FromContext(ctx)
npName := adapterutil.ExtractNpName(netpolName)
var np intentv1.NimbusPolicy
err := k8sClient.Get(ctx, types.NamespacedName{Name: npName, Namespace: namespace}, &np)
if err != nil {
if !errors.IsNotFound(err) {
Expand All @@ -97,6 +98,7 @@ func reconcileNetPol(ctx context.Context, netpolName, namespace string, deleted

func createOrUpdateNetworkPolicy(ctx context.Context, npName, npNamespace string) {
logger := log.FromContext(ctx)
var np intentv1.NimbusPolicy
if err := k8sClient.Get(ctx, types.NamespacedName{Name: npName, Namespace: npNamespace}, &np); err != nil {
logger.Error(err, "failed to get NimbusPolicy", "NimbusPolicy.Name", npName[0], "NimbusPolicy.Namespace", npName[1])
return
Expand All @@ -108,6 +110,7 @@ func createOrUpdateNetworkPolicy(ctx context.Context, npName, npNamespace string
}

netPols := processor.BuildNetPolsFrom(logger, np)
deleteUnnecessaryNetpols(ctx, netPols, npNamespace, logger)
// Iterate using a separate index variable to avoid aliasing
for idx := range netPols {
netpol := netPols[idx]
Expand Down Expand Up @@ -138,6 +141,18 @@ func createOrUpdateNetworkPolicy(ctx context.Context, npName, npNamespace string
}
logger.Info("NetworkPolicy configured", "NetworkPolicy.Name", netpol.Name, "NetworkPolicy.Namespace", netpol.Namespace)
}

// Due to adapters' dependency on nimbus module, the docker image build is
// failing. The relevant code is commented out below (lines 151-153). We shall
// uncomment this code in a subsequent PR.

// Every adapter is responsible for updating the status field of the
// corresponding NimbusPolicy with the number and names of successfully created
// policies. This provides feedback to users about the translation and deployment
// of their security intent.
//if err = adapterutil.UpdateNpStatus(ctx, k8sClient, "NetworkPolicy/"+netpol.Name, np.Name, np.Namespace); err != nil {
// logger.Error(err, "failed to update NetworkPolicies status in NimbusPolicy")
//}
}
}

Expand All @@ -161,3 +176,27 @@ func deleteNetworkPolicy(ctx context.Context, npName, npNamespace string) {
)
}
}

func deleteUnnecessaryNetpols(ctx context.Context, netPols []netv1.NetworkPolicy, namespace string, logger logr.Logger) {
var existingNetpols netv1.NetworkPolicyList
if err := k8sClient.List(ctx, &existingNetpols, client.InNamespace(namespace)); err != nil {
logger.Error(err, "failed to list NetworkPolicies for cleanup")
return
}

netpolsToDeleteName := make(map[string]bool)
for _, netpol := range netPols {
netpolsToDeleteName[netpol.Name] = true
}

for idx := range existingNetpols.Items {
existingNetpol := existingNetpols.Items[idx]
if _, needed := netpolsToDeleteName[existingNetpol.Name]; !needed {
if err := k8sClient.Delete(ctx, &existingNetpol); err != nil {
logger.Error(err, "failed to delete unnecessary NetworkPolicy", "NetworkPolicy.Name", existingNetpol.Name, "NetworkPolicy.Namespace", existingNetpol.Namespace)
} else {
logger.Info("Deleted unnecessary NetworkPolicy", "NetworkPolicy.Name", existingNetpol.Name, "NetworkPolicy.Namespace", existingNetpol.Namespace)
}
}
}
}
55 changes: 53 additions & 2 deletions pkg/adapter/util/nimbuspolicy_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,61 @@
package util

import (
"context"
"strings"

"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/util/retry"
"sigs.k8s.io/controller-runtime/pkg/client"

intentv1 "github.com/5GSEC/nimbus/api/v1"
)

func ExtractNpName(kspName string) string {
words := strings.Split(kspName, "-")
// ExtractNpName extracts the actual NimbusPolicy name from a formatted policy
// name.
func ExtractNpName(policyName string) string {
words := strings.Split(policyName, "-")
return strings.Join(words[:len(words)-1], "-")
}

// UpdateNpStatus updates the provided NimbusPolicy status with the number and
// names of its descendant policies that were created.
func UpdateNpStatus(ctx context.Context, k8sClient client.Client, currPolicyFullName, npName, namespace string) error {
// Since multiple adapters may attempt to update the NimbusPolicy status
// concurrently, potentially leading to conflicts. To ensure data consistency,
// retry on write failures. On conflict, the update is retried with an
// exponential backoff strategy. This provides resilience against potential
// issues while preventing indefinite retries in case of persistent conflicts.
if retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
latestNp := &intentv1.NimbusPolicy{}
if err := k8sClient.Get(ctx, types.NamespacedName{Name: npName, Namespace: namespace}, latestNp); err != nil {
return nil
}

updateCountAndPoliciesName(latestNp, currPolicyFullName)
if err := k8sClient.Status().Update(ctx, latestNp); err != nil {
return err
}

return nil
}); retryErr != nil {
return retryErr
}
return nil
}

func updateCountAndPoliciesName(latestNp *intentv1.NimbusPolicy, currPolicyFullName string) {
if !contains(latestNp.Status.Policies, currPolicyFullName) {
latestNp.Status.NumberOfAdapterPolicies++
latestNp.Status.Policies = append(latestNp.Status.Policies, currPolicyFullName)
}
}

func contains(existingPolicies []string, policy string) bool {
for _, existingPolicy := range existingPolicies {
if existingPolicy == policy {
return true
}
}
return false
}

0 comments on commit aa038aa

Please sign in to comment.