-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add code for exporter (httpexporter, nimbuspolicy watcher)
- Loading branch information
Showing
3 changed files
with
241 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2023 Authors of Nimbus | ||
|
||
// Initialize HTTP Client: Set up the client for HTTP communication. | ||
// Format Nimbus Policy Data: Convert Nimbus Policy data into JSON format. | ||
// Send Data: Send the converted data to the adapter's URL using a POST request. | ||
// Process Response: Handle the response from the adapter and log as necessary. | ||
|
||
package httpexporter | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
|
||
v1 "github.com/5GSEC/nimbus/nimbus-operator/api/v1" | ||
) | ||
|
||
// HttpNimbusExporter struct defines the HTTP client and the URL for exporting Nimbus policies. | ||
type HttpNimbusExporter struct { | ||
client *http.Client | ||
url string | ||
} | ||
|
||
// NewHttpNimbusExporter creates a new HttpNimbusExporter with the provided URL. | ||
func NewHttpNimbusExporter(url string) *HttpNimbusExporter { | ||
return &HttpNimbusExporter{ | ||
client: &http.Client{}, | ||
url: url, | ||
} | ||
} | ||
|
||
// ExportNimbusPolicy exports a NimbusPolicy to a remote server via HTTP POST. | ||
func (h *HttpNimbusExporter) ExportNimbusPolicy(ctx context.Context, policy *v1.NimbusPolicy) error { | ||
// Convert the NimbusPolicy into JSON format. | ||
data, err := json.Marshal(policy) | ||
if err != nil { | ||
return fmt.Errorf("failed to marshal NimbusPolicy: %v", err) | ||
} | ||
|
||
// Create a new HTTP POST request with the policy data. | ||
req, err := http.NewRequestWithContext(ctx, "POST", h.url, bytes.NewBuffer(data)) | ||
if err != nil { | ||
return fmt.Errorf("failed to create request: %v", err) | ||
} | ||
req.Header.Set("Content-Type", "application/json") | ||
|
||
// Send the request to the server. | ||
resp, err := h.client.Do(req) | ||
if err != nil { | ||
return fmt.Errorf("failed to send request: %v", err) | ||
} | ||
defer resp.Body.Close() | ||
|
||
// Check if the response status is OK (HTTP 200). | ||
if resp.StatusCode != http.StatusOK { | ||
return fmt.Errorf("non-OK response received: %v", resp.Status) | ||
} | ||
|
||
return nil | ||
} |
101 changes: 101 additions & 0 deletions
101
nimbus-operator/exporter/nimbuspolicy/nimbuspolicy_controller.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2023 Authors of Nimbus | ||
|
||
package nimbuspolicy | ||
|
||
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" | ||
"github.com/5GSEC/nimbus/nimbus-operator/exporter/httpexporter" | ||
watcher "github.com/5GSEC/nimbus/nimbus-operator/receiver/watcher" | ||
) | ||
|
||
// NimbusPolicyReconciler reconciles a NimbusPolicy object. | ||
type NimbusPolicyReconciler struct { | ||
client.Client | ||
Scheme *runtime.Scheme | ||
WatcherNimbusPolicy *watcher.WatcherNimbusPolicy | ||
} | ||
|
||
// NewNimbusPolicyReconciler creates a new instance of NimbusPolicyReconciler. | ||
// It initializes the WatcherNimbusPolicy which watches and reacts to changes in NimbusPolicy objects. | ||
func NewNimbusPolicyReconciler(client client.Client, scheme *runtime.Scheme) *NimbusPolicyReconciler { | ||
if client == nil { | ||
fmt.Println("NimbusPolicyReconciler: Client is nil") | ||
return nil | ||
} | ||
|
||
watcherNimbusPolicy, err := watcher.NewWatcherNimbusPolicy(client) | ||
if err != nil { | ||
fmt.Println("NimbusPolicyReconciler: Failed to initialize WatcherNimbusPolicy:", err) | ||
return nil | ||
} | ||
|
||
return &NimbusPolicyReconciler{ | ||
Client: client, | ||
Scheme: scheme, | ||
WatcherNimbusPolicy: watcherNimbusPolicy, | ||
} | ||
} | ||
|
||
//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=nimbuspolicies,verbs=get;list;watch;create;update;patch;delete | ||
//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=nimbuspolicies/status,verbs=get;update;patch | ||
//+kubebuilder:rbac:groups=intent.security.nimbus.com,resources=nimbuspolicies/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 NimbusPolicy 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/reconcile | ||
func (r *NimbusPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { | ||
log := log.FromContext(ctx) | ||
|
||
if r.WatcherNimbusPolicy == nil { | ||
fmt.Println("NimbusPolicyReconciler: WatcherNimbusPolicy is nil") | ||
return ctrl.Result{}, fmt.Errorf("WatcherNimbusPolicy is not properly initialized") | ||
} | ||
|
||
nimPol, err := r.WatcherNimbusPolicy.Reconcile(ctx, req) | ||
if err != nil { | ||
log.Error(err, "Error in WatcherNimbusPolicy.Reconcile", "Request", req.NamespacedName) | ||
return ctrl.Result{}, err | ||
} | ||
|
||
if nimPol != nil { | ||
log.Info("NimbusPolicy resource found", "Name", req.Name, "Namespace", req.Namespace) | ||
} else { | ||
log.Info("NimbusPolicy resource not found", "Name", req.Name, "Namespace", req.Namespace) | ||
} | ||
|
||
// Exporting the NimbusPolicy if it is found. | ||
if nimPol != nil { | ||
exporter := httpexporter.NewHttpNimbusExporter("http://localhost:13000/api/v1/nimbus/export") // Update the URL as needed. | ||
err := exporter.ExportNimbusPolicy(ctx, nimPol) | ||
if err != nil { | ||
log.Error(err, "Failed to export NimbusPolicy") | ||
return ctrl.Result{}, err | ||
} | ||
log.Info("NimbusPolicy exported successfully") | ||
} | ||
|
||
return ctrl.Result{}, nil | ||
} | ||
|
||
// SetupWithManager sets up the controller with the Manager. | ||
// It registers the NimbusPolicyReconciler to manage NimbusPolicy resources. | ||
func (r *NimbusPolicyReconciler) SetupWithManager(mgr ctrl.Manager) error { | ||
return ctrl.NewControllerManagedBy(mgr). | ||
For(&v1.NimbusPolicy{}). | ||
Complete(r) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 nimbuspolicy | ||
|
||
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()) | ||
}) |