Skip to content

Commit

Permalink
feat: Add code for receiver (watcher function)
Browse files Browse the repository at this point in the history
  • Loading branch information
b0m313 committed Jan 2, 2024
1 parent 746a83f commit e37c233
Show file tree
Hide file tree
Showing 10 changed files with 794 additions and 0 deletions.
57 changes: 57 additions & 0 deletions nimbus-operator/cleanup/cleanup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 Authors of Nimbus

package cleanup

/*
import (
"context"
"github.com/go-logr/logr"
"sigs.k8s.io/controller-runtime/pkg/client"
intentv1 "github.com/5GSEC/nimbus/pkg/api/v1"
general "github.com/5GSEC/nimbus/pkg/controllers/general"
policy "github.com/5GSEC/nimbus/pkg/controllers/policy"
)
// Cleanup is a function to clean up SecurityIntent resources.
// It removes all policies associated with each SecurityIntent before deleting the SecurityIntent itself.
func Cleanup(ctx context.Context, k8sClient client.Client, logger logr.Logger) error {
// Logging the start of the cleanup process.
logger.Info("Performing cleanup")
var securityIntentBindings intentv1.SecurityIntentBindingList
if err := k8sClient.List(ctx, &securityIntentBindings); err != nil {
logger.Error(err, "Unable to list SecurityIntentBinding resources for cleanup")
return err
}
if len(securityIntentBindings.Items) == 0 {
logger.Info("No SecurityIntentBinding resources found for cleanup")
return nil
}
npc := policy.NewNetworkPolicyController(k8sClient, nil)
// Iterating over each SecurityIntent to delete associated policies.
for _, binding := range securityIntentBindings.Items {
bindingCopy := binding
bindingInfo := &general.BindingInfo{
Binding: &bindingCopy,
}
// Deleting network policies associated with the current SecurityIntent.
if err := npc.DeletePolicy(ctx, bindingInfo); err != nil {
logger.Error(err, "Failed to delete network policy for SecurityIntentBinding", "Name", bindingCopy.Name)
return err
}
if err := k8sClient.Delete(ctx, &bindingCopy); err != nil {
logger.Error(err, "Failed to delete SecurityIntentBinding", "Name", bindingCopy.Name)
continue
}
}
return nil
}
*/
151 changes: 151 additions & 0 deletions nimbus-operator/cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 Authors of Nimbus

package main

import (
"flag"
"os"

// Importing all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can utilize them.
_ "k8s.io/client-go/plugin/pkg/client/auth"

"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"

// Importing custom API types and controllers
v1 "github.com/5GSEC/nimbus/nimbus-operator/api/v1"
nimbuspolicy "github.com/5GSEC/nimbus/nimbus-operator/exporter/nimbuspolicy"
securityintent "github.com/5GSEC/nimbus/nimbus-operator/receiver/securityintent"
securityintentbinding "github.com/5GSEC/nimbus/nimbus-operator/receiver/securityintentbinding"
watcher "github.com/5GSEC/nimbus/nimbus-operator/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
)

// Global variables for scheme registration and setup logging.
var (
scheme = runtime.NewScheme() // Scheme for registering API types for client and server.
setupLog = ctrl.Log.WithName("setup") // Logger for setup process.
)

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
}

func main() {
// Flags for command line parameters such as metrics address, leader election, etc.
var metricsAddr string
var enableLeaderElection bool
var probeAddr string

flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
opts := zap.Options{
Development: true,
}
opts.BindFlags(flag.CommandLine)
flag.Parse()

// Setting the logger with the provided options.
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

// Creating a new manager which will manage all the controllers.
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: metricsserver.Options{BindAddress: metricsAddr},
HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: "44502a2e.security.nimbus.com",
// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
// when the Manager ends. This requires the binary to immediately end when the
// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
// speeds up voluntary leader transitions as the new leader don't have to wait
// LeaseDuration time first.
//
// In the default scaffold provided, the program ends immediately after
// the manager stops, so would be fine to enable this option. However,
// if you are doing or is intended to do any operation such as perform cleanups
// after the manager stops then its usage might be unsafe.
// LeaderElectionReleaseOnCancel: true,
})
if err != nil {
setupLog.Error(err, "Unable to start manager")
os.Exit(1)
}

watcherController, err := watcher.NewWatcherController(mgr.GetClient())
if err != nil {
setupLog.Error(err, "Unable to create WatcherController")
os.Exit(1)
}

if err = (&securityintent.SecurityIntentReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
WatcherController: watcherController,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "Unable to create controller", "controller", "SecurityIntent")
os.Exit(1)
}

if err = (&securityintentbinding.SecurityIntentBindingReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
WatcherController: watcherController,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "Unable to create controller", "controller", "SecurityIntentBinding")
os.Exit(1)
}

nimbusPolicyReconciler := nimbuspolicy.NewNimbusPolicyReconciler(mgr.GetClient(), mgr.GetScheme())
if err != nil {
setupLog.Error(err, "Unable to create NimbusPolicyReconciler")
os.Exit(1)
}
watcherNimbusPolicy, err := watcher.NewWatcherNimbusPolicy(mgr.GetClient())
if err != nil {
setupLog.Error(err, "Unable to create WatcherNimbusPolicy")
os.Exit(1)
}
nimbusPolicyReconciler.WatcherNimbusPolicy = watcherNimbusPolicy
if err = nimbusPolicyReconciler.SetupWithManager(mgr); err != nil {
setupLog.Error(err, "Unable to set up NimbusPolicyReconciler with manager", "controller", "NimbusPolicy")
os.Exit(1)
}
//+kubebuilder:scaffold:builder

// Adding health and readiness checks.
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
setupLog.Error(err, "Unable to set up health check")
os.Exit(1)
}
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
setupLog.Error(err, "Unable to set up ready check")
os.Exit(1)
}

// Starting the controller manager.
setupLog.Info("Starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "Problem running manager")
os.Exit(1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 Authors of Nimbus

package securityintent

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/nimbus-operator/api/v1"
watcher "github.com/5GSEC/nimbus/nimbus-operator/receiver/watcher"
)

type SecurityIntentReconciler struct {
client.Client
Scheme *runtime.Scheme
WatcherController *watcher.WatcherController
}

// NewSecurityIntentReconciler creates a new SecurityIntentReconciler.
func NewSecurityIntentReconciler(client client.Client, scheme *runtime.Scheme) *SecurityIntentReconciler {
if client == nil {
fmt.Println("SecurityIntentReconciler: Client is nil")
return nil
}

WatcherController, err := watcher.NewWatcherController(client)
if err != nil {
fmt.Println("SecurityIntentReconciler: Failed to initialize WatcherController:", err)
return nil
}

return &SecurityIntentReconciler{
Client: client,
Scheme: scheme,
WatcherController: WatcherController,
}
}

//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=securityintents,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=securityintents/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=securityintents/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.
// TODO(user): Modify the Reconcile function to compare the state specified by
// the SecurityIntent object against the actual cluster state, and then
// perform operations to make the cluster state reflect the state specified by
// the user.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcil

// Reconcile handles the reconciliation of the SecurityIntent resources.
func (r *SecurityIntentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)

if r.WatcherController == nil {
fmt.Println("SecurityIntentReconciler: WatcherController is nil")
return ctrl.Result{}, fmt.Errorf("WatcherController is not properly initialized")
}

intent, err := r.WatcherController.WatcherIntent.Reconcile(ctx, req)
if err != nil {
log.Error(err, "Error in WatcherIntent.Reconcile", "Request", req.NamespacedName)
return ctrl.Result{}, err
}

if intent != nil {
log.Info("SecurityIntent resource found", "Name", req.Name, "Namespace", req.Namespace)
} else {
log.Info("SecurityIntent resource not found", "Name", req.Name, "Namespace", req.Namespace)
}

return ctrl.Result{}, nil
}

// SetupWithManager sets up the reconciler with the provided manager.
func (r *SecurityIntentReconciler) SetupWithManager(mgr ctrl.Manager) error {
// Set up the controller to manage SecurityIntent resources.
return ctrl.NewControllerManagedBy(mgr).
For(&v1.SecurityIntent{}).
Complete(r)
}
77 changes: 77 additions & 0 deletions nimbus-operator/receiver/securityintent/suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 Authors of Nimbus

package securityintent

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())
})
Loading

0 comments on commit e37c233

Please sign in to comment.