Skip to content

Commit

Permalink
refactor(core): Refactor processor and binders
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 11, 2024
1 parent 8ee375f commit 285b287
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ func (r *ClusterSecurityIntentBindingReconciler) Reconcile(ctx context.Context,
logger.Info("ClusterSecurityIntentBinding found", "ClusterSecurityIntentBinding.Name", csib.Name)
}

bindingInfo := intentbinder.MatchAndBindIntentsGlobal(ctx, r.Client, csib)
clusterNp, err := policybuilder.BuildClusterNimbusPolicy(ctx, r.Client, r.Scheme, bindingInfo)
intents := intentbinder.ExtractIntents(ctx, r.Client, csib)
clusterNp, err := policybuilder.BuildClusterNimbusPolicy(ctx, r.Scheme, csib, intents)
if err != nil {
logger.Error(err, "failed to build ClusterNimbusPolicy")
return ctrl.Result{}, err
Expand Down
4 changes: 2 additions & 2 deletions internal/controller/securityintentbinding_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ func (r *SecurityIntentBindingReconciler) Reconcile(ctx context.Context, req ctr
logger.Info("SecurityIntentBinding found", "SecurityIntentBinding.Name", sib.Name, "SecurityIntentBinding.Namespace", sib.Namespace)
}

bindingInfo := intentbinder.MatchAndBindIntents(ctx, r.Client, sib)
nimbusPolicy, err := policybuilder.BuildNimbusPolicy(ctx, r.Client, r.Scheme, bindingInfo)
intents := intentbinder.ExtractIntents(ctx, r.Client, sib)
nimbusPolicy, err := policybuilder.BuildNimbusPolicy(ctx, r.Scheme, sib, intents)
if err != nil {
logger.Error(err, "failed to build NimbusPolicy")
return ctrl.Result{}, err
Expand Down
3 changes: 3 additions & 0 deletions internal/controller/utils.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 Authors of Nimbus

package controller

import (
Expand Down
44 changes: 28 additions & 16 deletions pkg/processor/intentbinder/intent_binder.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,41 @@ func NewBindingInfo(intentNames []string, bindingNames []string, bindingNamespac
}
}

func MatchAndBindIntents(ctx context.Context, client client.Client, bindings *v1.SecurityIntentBinding) *BindingInfo {
func ExtractIntents(ctx context.Context, c client.Client, object client.Object) []v1.SecurityIntent {
logger := log.FromContext(ctx)
logger.Info("SecurityIntent and SecurityIntentBinding matching started")
var intents []v1.SecurityIntent
var givenIntents []v1.MatchIntent
var isSibIntents bool

var matchedIntents []string
var matchedBindings []string
var matchedBindingNamespaces []string
switch obj := object.(type) {
case *v1.SecurityIntentBinding:
givenIntents = obj.Spec.Intents
isSibIntents = true
case *v1.ClusterSecurityIntentBinding:
givenIntents = obj.Spec.Intents
}

for _, intentRef := range bindings.Spec.Intents {
var intent v1.SecurityIntent
if err := client.Get(ctx, types.NamespacedName{Name: intentRef.Name, Namespace: bindings.Namespace}, &intent); err != nil {
logger.Info("failed to get SecurityIntent", "SecurityIntent.Name", intentRef.Name)
for _, intent := range givenIntents {
var si v1.SecurityIntent
if err := c.Get(ctx, types.NamespacedName{Name: intent.Name}, &si); err != nil {
logger.V(2).Info("failed to get SecurityIntent", "SecurityIntent.Name", intent.Name)
continue
}
matchedIntents = append(matchedIntents, intent.Name)
intents = append(intents, si)
}

// Adding names and namespaces of SecurityIntentBinding.
matchedBindings = append(matchedBindings, bindings.Name)
matchedBindingNamespaces = append(matchedBindingNamespaces, bindings.Namespace)

logger.Info("Matching completed", "Matched SecurityIntents", matchedIntents, "Matched SecurityIntentsBindings", matchedBindings)
return NewBindingInfo(matchedIntents, matchedBindings, matchedBindingNamespaces)
// Check for SecurityIntent inconsistency in given bindings vs available
// SecurityIntent in cluster.
if isSibIntents {
if len(intents) != len(object.(*v1.SecurityIntentBinding).Spec.Intents) {
return nil
}
} else {
if len(intents) != len(object.(*v1.ClusterSecurityIntentBinding).Spec.Intents) {
return nil
}
}
return intents
}

func MatchAndBindIntentsGlobal(ctx context.Context, client client.Client, clusterBinding *v1.ClusterSecurityIntentBinding) *BindingInfo {
Expand Down
61 changes: 14 additions & 47 deletions pkg/processor/policybuilder/clusternimbuspolicy_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,27 @@ package policybuilder

import (
"context"
"fmt"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"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"
)

func BuildClusterNimbusPolicy(ctx context.Context, client client.Client, scheme *runtime.Scheme, clusterBindingInfo *intentbinder.BindingInfo) (*v1.ClusterNimbusPolicy, error) {
// BuildClusterNimbusPolicy generates a ClusterNimbusPolicy based on
// SecurityIntents and ClusterSecurityIntentBinding.
func BuildClusterNimbusPolicy(ctx context.Context, scheme *runtime.Scheme, csib *v1.ClusterSecurityIntentBinding, securityIntents []v1.SecurityIntent) (*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")
}

for _, intent := range securityIntents {
rule := v1.Rule{
RuleAction: intent.Spec.Intent.Action,
Params: map[string][]string{},
Params: intent.Spec.Intent.Params,
}

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
Expand All @@ -52,36 +35,30 @@ func BuildClusterNimbusPolicy(ctx context.Context, client client.Client, scheme
nimbusRules = append(nimbusRules, nimbusRule)
}

binding, err := fetchClusterBinding(ctx, client, clusterBindingInfo.BindingNames[0])
if err != nil {
return nil, err
}

clusterBindingSelector := extractClusterBindingSelector(binding.Spec.Selector)
clusterBindingSelector := extractClusterBindingSelector(csib.Spec.Selector)

clusterNimbusPolicy := &v1.ClusterNimbusPolicy{
clusterNp := &v1.ClusterNimbusPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: binding.Name,
Name: csib.Name,
Labels: csib.Labels,
},
Spec: v1.ClusterNimbusPolicySpec{
Selector: clusterBindingSelector,
NimbusRules: nimbusRules,
},
Status: v1.ClusterNimbusPolicyStatus{
Status: "Pending",
},
}

if err = ctrl.SetControllerReference(&binding, clusterNimbusPolicy, scheme); err != nil {
logger.Error(err, "failed to set OwnerReference")
if err := ctrl.SetControllerReference(csib, clusterNp, scheme); err != nil {
logger.Error(err, "failed to set ClusterNimbusPolicy OwnerReference")
return nil, err
}

logger.Info("ClusterNimbusPolicy built successfully", "ClusterNimbusPolicy", clusterNimbusPolicy)
return clusterNimbusPolicy, nil
logger.Info("ClusterNimbusPolicy built successfully", "ClusterNimbusPolicy.Name", clusterNp.Name)
return clusterNp, nil
}

func extractClusterBindingSelector(cwSelector v1.CwSelector) v1.CwSelector {
// TODO: Process CEL
var clusterBindingSelector v1.CwSelector
for _, resource := range cwSelector.Resources {
var cwresource v1.CwResource
Expand All @@ -93,13 +70,3 @@ func extractClusterBindingSelector(cwSelector v1.CwSelector) v1.CwSelector {
}
return clusterBindingSelector
}

func fetchClusterBinding(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
}
16 changes: 0 additions & 16 deletions pkg/processor/policybuilder/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,14 @@
package policybuilder

import (
"context"
"fmt"

"github.com/google/cel-go/cel"
"github.com/google/cel-go/checker/decls"
"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"
)

// FetchIntentByName fetches a SecurityIntent by its name.
func FetchIntentByName(ctx context.Context, client client.Client, name string) (*v1.SecurityIntent, error) {
logger := log.FromContext(ctx)

var intent v1.SecurityIntent
if err := client.Get(ctx, types.NamespacedName{Name: name}, &intent); err != nil {
logger.Error(err, "Failed to get SecurityIntent")
return nil, err
}
return &intent, nil
}

// ProcessCEL processes CEL expressions to generate matchLabels.
func ProcessCEL(expressions []string) (map[string]string, error) {
env, err := cel.NewEnv(
Expand Down
75 changes: 16 additions & 59 deletions pkg/processor/policybuilder/nimbuspolicy_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,105 +9,62 @@ import (

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"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"
)

// BuildNimbusPolicy generates a NimbusPolicy based on SecurityIntent and SecurityIntentBinding.
func BuildNimbusPolicy(ctx context.Context, client client.Client, scheme *runtime.Scheme, bindingInfo *intentbinder.BindingInfo) (*v1.NimbusPolicy, error) {
// BuildNimbusPolicy generates a NimbusPolicy based on given SecurityIntents and
// SecurityIntentBinding.
func BuildNimbusPolicy(ctx context.Context, scheme *runtime.Scheme, sib *v1.SecurityIntentBinding, securityIntents []v1.SecurityIntent) (*v1.NimbusPolicy, error) {
logger := log.FromContext(ctx)
logger.Info("Building NimbusPolicy")
var nimbusRules []v1.NimbusRules

var nimbusRulesList []v1.NimbusRules

// Iterate over intent names to build rules.
for _, intentName := range bindingInfo.IntentNames {
intent, err := FetchIntentByName(ctx, client, intentName)
if err != nil {
return nil, err
}

// Checks if arrays in bindingInfo are empty.
if len(bindingInfo.IntentNames) == 0 || len(bindingInfo.BindingNames) == 0 {
fmt.Println("No intents or bindings to process")
return nil, fmt.Errorf("no intents or bindings to process")
}

// Constructs a rule from the intent parameters.
for _, intent := range securityIntents {
rule := v1.Rule{
RuleAction: intent.Spec.Intent.Action,
Params: map[string][]string{},
}

for key, val := range intent.Spec.Intent.Params {
rule.Params[key] = val
Params: intent.Spec.Intent.Params,
}

nimbusRule := v1.NimbusRules{
ID: intent.Spec.Intent.ID,
Type: "", // Set Type if necessary
Description: intent.Spec.Intent.Description,
Rule: rule,
}
nimbusRulesList = append(nimbusRulesList, nimbusRule)
nimbusRules = append(nimbusRules, nimbusRule)
}

// Fetches the binding to extract selector.
bindingName := bindingInfo.BindingNames[0]
bindingNamespace := bindingInfo.BindingNamespaces[0]
binding, err := fetchBinding(ctx, client, bindingName, bindingNamespace)
// Todo: What about CEL?
matchLabels, err := extractSelector(sib.Spec.Selector)
if err != nil {
return nil, err
}

// Extracts match labels from the binding selector.
matchLabels, err := extractSelector(binding.Spec.Selector)
if err != nil {
return nil, err
}

// Creates a NimbusPolicy.
nimbusPolicy := &v1.NimbusPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: binding.Name,
Namespace: binding.Namespace,
Name: sib.Name,
Namespace: sib.Namespace,
Labels: sib.Labels,
},
Spec: v1.NimbusPolicySpec{
Selector: v1.NimbusSelector{
MatchLabels: matchLabels,
},
NimbusRules: nimbusRulesList,
},
Status: v1.NimbusPolicyStatus{
Status: "Pending",
NimbusRules: nimbusRules,
},
}

if err = ctrl.SetControllerReference(binding, nimbusPolicy, scheme); err != nil {
logger.Error(err, "failed to set OwnerReference")
if err = ctrl.SetControllerReference(sib, nimbusPolicy, scheme); err != nil {
logger.Error(err, "failed to set NimbusPolicy OwnerReference")
return nil, err
}

logger.Info("NimbusPolicy built successfully", "Policy", nimbusPolicy)
logger.Info("NimbusPolicy built successfully", "NimbusPolicy.Name", nimbusPolicy.Name, "NimbusPolicy.Namespace", nimbusPolicy.Namespace)
return nimbusPolicy, nil
}

// fetchBinding fetches a SecurityIntentBinding by its name and namespace.
func fetchBinding(ctx context.Context, client client.Client, name string, namespace string) (*v1.SecurityIntentBinding, error) {
logger := log.FromContext(ctx)
var binding v1.SecurityIntentBinding
if err := client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, &binding); err != nil {
logger.Error(err, "Failed to get SecurityIntentBinding")
return nil, err
}
return &binding, nil
}

// 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.
Expand Down

0 comments on commit 285b287

Please sign in to comment.