Skip to content

Commit

Permalink
fix: nimbus policy status issue (#180)
Browse files Browse the repository at this point in the history
* - nimbus policy status updated
 - ksps are created
 - kyverno policies are created

* - Add nimbus policy details to Csib Status

* - Added e2e test for matchAll csib
 - Fixed issues with integration tests

* - Update test docs

* - Removed the check for the kyverno cluster policy status.
  • Loading branch information
shivaccuknox authored Jun 12, 2024
1 parent 3a141ab commit 545b49c
Show file tree
Hide file tree
Showing 27 changed files with 638 additions and 74 deletions.
13 changes: 8 additions & 5 deletions api/v1alpha1/clustersecurityintentbinding_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ type ClusterSecurityIntentBindingSpec struct {

// ClusterSecurityIntentBindingStatus defines the observed state of ClusterSecurityIntentBinding
type ClusterSecurityIntentBindingStatus struct {
Status string `json:"status"`
LastUpdated metav1.Time `json:"lastUpdated,omitempty"`
NumberOfBoundIntents int32 `json:"numberOfBoundIntents"`
BoundIntents []string `json:"boundIntents,omitempty"`
ClusterNimbusPolicy string `json:"clusterNimbusPolicy"`
Status string `json:"status"`
LastUpdated metav1.Time `json:"lastUpdated,omitempty"`
NumberOfBoundIntents int32 `json:"numberOfBoundIntents"`
BoundIntents []string `json:"boundIntents,omitempty"`
ClusterNimbusPolicy string `json:"clusterNimbusPolicy"`
NumberOfNimbusPolicies int32 `json:"numberOfNimbusPolicies"`
NimbusPolicyNamespaces []string `json:"nimbusPolicyNamespaces,omitempty"`
}

//+kubebuilder:object:root=true
Expand All @@ -40,6 +42,7 @@ type ClusterSecurityIntentBindingStatus struct {
//+kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.status"
//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
//+kubebuilder:printcolumn:name="Intents",type="integer",JSONPath=".status.numberOfBoundIntents"
//+kubebuilder:printcolumn:name="NimbusPolicies",type="integer",JSONPath=".status.numberofNimbusPolicies"
//+kubebuilder:printcolumn:name="ClusterNimbusPolicy",type="string",JSONPath=".status.clusterNimbusPolicy"
//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ spec:
- jsonPath: .status.numberOfBoundIntents
name: Intents
type: integer
- jsonPath: .status.numberofNimbusPolicies
name: NimbusPolicies
type: integer
- jsonPath: .status.clusterNimbusPolicy
name: ClusterNimbusPolicy
type: string
Expand Down Expand Up @@ -115,14 +118,22 @@ spec:
lastUpdated:
format: date-time
type: string
nimbusPolicyNamespaces:
items:
type: string
type: array
numberOfBoundIntents:
format: int32
type: integer
numberOfNimbusPolicies:
format: int32
type: integer
status:
type: string
required:
- clusterNimbusPolicy
- numberOfBoundIntents
- numberOfNimbusPolicies
- status
type: object
type: object
Expand Down
11 changes: 11 additions & 0 deletions deployments/nimbus/templates/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ spec:
- jsonPath: .status.numberOfBoundIntents
name: Intents
type: integer
- jsonPath: .status.numberofNimbusPolicies
name: NimbusPolicies
type: integer
- jsonPath: .status.clusterNimbusPolicy
name: ClusterNimbusPolicy
type: string
Expand Down Expand Up @@ -250,14 +253,22 @@ spec:
lastUpdated:
format: date-time
type: string
nimbusPolicyNamespaces:
items:
type: string
type: array
numberOfBoundIntents:
format: int32
type: integer
numberOfNimbusPolicies:
format: int32
type: integer
status:
type: string
required:
- clusterNimbusPolicy
- numberOfBoundIntents
- numberOfNimbusPolicies
- status
type: object
type: object
Expand Down
64 changes: 64 additions & 0 deletions internal/controller/clustersecurityintentbinding_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ func (r *ClusterSecurityIntentBindingReconciler) Reconcile(ctx context.Context,
return requeueWithError(err)
}

if err = r.updateCsibStatusWithNpNamespacesInfo(ctx, logger, req); err != nil {
return requeueWithError(err)
}

return doNotRequeue()
}

Expand Down Expand Up @@ -486,6 +490,18 @@ func (r *ClusterSecurityIntentBindingReconciler) createOrUpdateNp(ctx context.Co

func (r *ClusterSecurityIntentBindingReconciler) updateNpStatus(ctx context.Context, logger logr.Logger, req ctrl.Request, status string) error {
np := &v1alpha1.NimbusPolicy{}

// Get the np object. This might take multiple retries since object might have been just created
if retryErr := retry.OnError(retry.DefaultRetry, apierrors.IsNotFound, func() error {
if err := r.Get(ctx, req.NamespacedName, np); err != nil {
return err
}
return nil
}); retryErr != nil {
logger.Error(retryErr, "failed to fetch NimbusPolicy", "NimbusPolicy.Name", req.Name)
return retryErr
}

if retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
if err := r.Get(ctx, req.NamespacedName, np); err != nil {
return err
Expand Down Expand Up @@ -678,6 +694,8 @@ func (r *ClusterSecurityIntentBindingReconciler) updateCSibStatusWithBoundSisAnd
latestCsib.Status.NumberOfBoundIntents = 0
latestCsib.Status.BoundIntents = nil
latestCsib.Status.ClusterNimbusPolicy = ""
latestCsib.Status.NumberOfNimbusPolicies = 0
latestCsib.Status.NimbusPolicyNamespaces = nil
if err := r.Status().Update(ctx, latestCsib); err != nil {
logger.Error(err, "failed to update ClusterSecurityIntentBinding status", "ClusterSecurityIntentBinding.Name", latestCsib.Name)
return err
Expand All @@ -697,3 +715,49 @@ func (r *ClusterSecurityIntentBindingReconciler) updateCSibStatusWithBoundSisAnd

return nil
}

func (r *ClusterSecurityIntentBindingReconciler) updateCsibStatusWithNpNamespacesInfo(ctx context.Context, logger logr.Logger, req ctrl.Request) error {
latestCsib := &v1alpha1.ClusterSecurityIntentBinding{}
if err := r.Get(ctx, req.NamespacedName, latestCsib); err != nil && !apierrors.IsNotFound(err) {
logger.Error(err, "failed to fetch ClusterSecurityIntentBinding", "ClusterSecurityIntentBinding.Name", req.Name)
return err
}

latestCwnp := &v1alpha1.ClusterNimbusPolicy{}
if retryErr := retry.OnError(retry.DefaultRetry, apierrors.IsNotFound, func() error {
if err := r.Get(ctx, req.NamespacedName, latestCwnp); err != nil {
return err
}
return nil
}); retryErr != nil {
if !apierrors.IsNotFound(retryErr) {
logger.Error(retryErr, "failed to fetch ClusterNimbusPolicy", "ClusterNimbusPolicy.Name", req.Name)
return retryErr
}

// Remove outdated SecurityIntent(s) and ClusterNimbusPolicy info
latestCsib.Status.NumberOfBoundIntents = 0
latestCsib.Status.BoundIntents = nil
latestCsib.Status.ClusterNimbusPolicy = ""
latestCsib.Status.NumberOfNimbusPolicies = 0
latestCsib.Status.NimbusPolicyNamespaces = nil
if err := r.Status().Update(ctx, latestCsib); err != nil {
logger.Error(err, "failed to update ClusterSecurityIntentBinding status", "ClusterSecurityIntentBinding.Name", latestCsib.Name)
return err
}
return nil
}

// Update necessary fields of ClusterSecurityIntentBinding status.
// The other fields will remain the same
npNamespaces := extractNPNamespacesFromCsib(ctx, r.Client, req.Name)
latestCsib.Status.NumberOfNimbusPolicies = int32(len(npNamespaces))
latestCsib.Status.NimbusPolicyNamespaces = npNamespaces

if err := r.Status().Update(ctx, latestCsib); err != nil {
logger.Error(err, "failed to update ClusterSecurityIntentBinding status", "ClusterSecurityIntentBinding.Name", latestCsib.Name)
return err
}

return nil
}
20 changes: 20 additions & 0 deletions internal/controller/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,26 @@ func extractBoundIntentsNameFromCSib(ctx context.Context, c client.Client, name
return boundIntentsName
}

func extractNPNamespacesFromCsib(ctx context.Context, c client.Client, name string) []string {
logger := log.FromContext(ctx)

var npNs []string

nps := &v1alpha1.NimbusPolicyList{}
if err := c.List(ctx, nps); err != nil {
logger.Error(err, "failed to list Nimbus Policies")
return nil
}

for _, np := range nps.Items {
if np.Name == "nimbus-ctlr-gen-"+name {
npNs = append(npNs, np.Namespace)
}
}

return npNs
}

func ownerExists(c client.Client, controllee client.Object) bool {
// Don't even try to look if it has no ControllerRef.
controller := metav1.GetControllerOf(controllee)
Expand Down
2 changes: 1 addition & 1 deletion pkg/adapter/nimbus-kubearmor/manager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func createOrUpdateKsp(ctx context.Context, npName, npNamespace string) {
return
}

if adapterutil.IsOrphan(np.GetOwnerReferences(), "SecurityIntentBinding") {
if adapterutil.IsOrphan(np.GetOwnerReferences(), "SecurityIntentBinding", "ClusterSecurityIntentBinding") {
logger.V(4).Info("Ignoring orphan NimbusPolicy", "NimbusPolicy.Name", npName, "NimbusPolicy.Namespace", npNamespace)
return
}
Expand Down
43 changes: 37 additions & 6 deletions pkg/adapter/nimbus-kyverno/processor/kcpbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ func buildKcpFor(id string, cnp *v1alpha1.ClusterNimbusPolicy) kyvernov1.Cluster
}
}

var nsBlackList = []string{"kube-system"}

func clusterEscapeToHost(cnp *v1alpha1.ClusterNimbusPolicy, rule v1alpha1.Rule) kyvernov1.ClusterPolicy {
var psa_level api.Level = api.LevelBaseline

Expand All @@ -70,22 +72,51 @@ func clusterEscapeToHost(cnp *v1alpha1.ClusterNimbusPolicy, rule v1alpha1.Rule)
var matchFilters, excludeFilters []kyvernov1.ResourceFilter
var resourceFilter kyvernov1.ResourceFilter

// exclude kube-system
resourceFilter = kyvernov1.ResourceFilter{
ResourceDescription: kyvernov1.ResourceDescription{
Namespaces: nsBlackList,
},
}
excludeFilters = append(excludeFilters, resourceFilter)

if len(cnp.Spec.NsSelector.MatchNames) > 0 {
if len(cnp.Spec.WorkloadSelector.MatchLabels) > 0 {
resourceFilter = kyvernov1.ResourceFilter{
ResourceDescription: kyvernov1.ResourceDescription{
Kinds: []string{
"v1/Pod",
},
Namespaces: cnp.Spec.NsSelector.MatchNames,
Selector: &metav1.LabelSelector{
MatchLabels: cnp.Spec.WorkloadSelector.MatchLabels,
},
},
}

} else {
resourceFilter = kyvernov1.ResourceFilter{
ResourceDescription: kyvernov1.ResourceDescription{
Kinds: []string{
"v1/Pod",
},
Namespaces: cnp.Spec.NsSelector.MatchNames,
},
}
}
matchFilters = append(matchFilters, resourceFilter)

} else if len(cnp.Spec.NsSelector.ExcludeNames) > 0 {

resourceFilter = kyvernov1.ResourceFilter{
ResourceDescription: kyvernov1.ResourceDescription{
Kinds: []string{
"v1/Pod",
},
Namespaces: cnp.Spec.NsSelector.MatchNames,
Selector: &metav1.LabelSelector{
MatchLabels: cnp.Spec.WorkloadSelector.MatchLabels,
},
},
}
matchFilters = append(matchFilters, resourceFilter)
}

if len(cnp.Spec.NsSelector.ExcludeNames) > 0 {
resourceFilter = kyvernov1.ResourceFilter{
ResourceDescription: kyvernov1.ResourceDescription{
Namespaces: cnp.Spec.NsSelector.ExcludeNames,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@
| 12 | [4. Create the management, regional namespaces](#step-4. Create the management, regional namespaces) | 0 | 1 | 0 | 0 |
| 13 | [Verify ClusterNimbusPolicy presence](#step-Verify ClusterNimbusPolicy presence) | 0 | 1 | 0 | 0 |
| 14 | [Verify NimbusPolicy absence in dev namespace](#step-Verify NimbusPolicy absence in dev namespace) | 0 | 1 | 0 | 0 |
| 15 | [Verify NimbusPolicy absence in dev namespace](#step-Verify NimbusPolicy absence in dev namespace) | 0 | 1 | 0 | 0 |
| 16 | [Verify NimbusPolicy absence in prod namespace](#step-Verify NimbusPolicy absence in prod namespace) | 0 | 1 | 0 | 0 |
| 17 | [Verify NimbusPolicy absence in regional namespace](#step-Verify NimbusPolicy absence in regional namespace) | 0 | 1 | 0 | 0 |
| 15 | [Verify NimbusPolicy absence in prod namespace](#step-Verify NimbusPolicy absence in prod namespace) | 0 | 1 | 0 | 0 |
| 16 | [Verify NimbusPolicy absence in regional namespace](#step-Verify NimbusPolicy absence in regional namespace) | 0 | 1 | 0 | 0 |

### Step: `1. Create prod, dev, staging Namespaces`

Expand Down Expand Up @@ -166,16 +165,6 @@
|:-:|---|:-:|:-:|---|
| 1 | `script` | 0 | 0 | *No description* |

### Step: `Verify NimbusPolicy absence in dev namespace`

*No description*

#### Try

| # | Operation | Bindings | Outputs | Description |
|:-:|---|:-:|:-:|---|
| 1 | `script` | 0 | 0 | *No description* |

### Step: `Verify NimbusPolicy absence in prod namespace`

*No description*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ spec:
- name: "Verify NimbusPolicy absence in dev namespace"
try:
- script:
content: kubectl -n dev get np nimbus-ctrl-gen-escape-to-host
content: kubectl -n dev get np nimbus-ctlr-gen-escape-to-host
check:
($error != null): true

- name: "Verify NimbusPolicy absence in staging namespace"
try:
- script:
content: kubectl -n staging get np nimbus-ctrl-gen-escape-to-host
content: kubectl -n staging get np nimbus-ctlr-gen-escape-to-host
check:
($error != null): true

Expand All @@ -65,14 +65,14 @@ spec:
- name: "Verify NimbusPolicy absence in dev namespace"
try:
- script:
content: kubectl -n dev get np nimbus-ctrl-gen-escape-to-host
content: kubectl -n dev get np nimbus-ctlr-gen-escape-to-host
check:
($error != null): true

- name: "Verify NimbusPolicy absence in prod namespace"
try:
- script:
content: kubectl -n prod get np nimbus-ctrl-gen-escape-to-host
content: kubectl -n prod get np nimbus-ctlr-gen-escape-to-host
check:
($error != null): true

Expand All @@ -89,27 +89,20 @@ spec:
- name: "Verify NimbusPolicy absence in dev namespace"
try:
- script:
content: kubectl -n dev get np nimbus-ctrl-gen-escape-to-host
content: kubectl -n dev get np nimbus-ctlr-gen-escape-to-host
check:
($error != null): true

- name: "Verify NimbusPolicy absence in prod namespace"
try:
- script:
content: kubectl -n prod get np nimbus-ctrl-gen-escape-to-host
check:
($error != null): true

- name: "Verify NimbusPolicy absence in prod namespace"
try:
- script:
content: kubectl -n prod get np nimbus-ctrl-gen-escape-to-host
content: kubectl -n prod get np nimbus-ctlr-gen-escape-to-host
check:
($error != null): true

- name: "Verify NimbusPolicy absence in regional namespace"
try:
- script:
content: kubectl -n regional get np nimbus-ctrl-gen-escape-to-host
content: kubectl -n regional get np nimbus-ctlr-gen-escape-to-host
check:
($error != null): true
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ spec:
- name: escape-to-host
selector:
nsSelector:
matchNames:
excludeNames:
- dev
- prod
- regional
Loading

0 comments on commit 545b49c

Please sign in to comment.