first controller implementation

This commit is contained in:
2025-03-19 22:36:42 +01:00
parent ce3a6dfc6d
commit 84f338426e
3 changed files with 99 additions and 2 deletions

View File

@ -21,13 +21,19 @@ package controller
import (
"context"
"encoding/base64"
"os"
"k8s.io/apimachinery/pkg/api/errors"
"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"
"github.com/bitwarden/sdk-go"
lerentisuploadfilter24euv1 "github.com/lerentis/bitwarden-crd-operator/api/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// BitwardenSecretReconciler reconciles a BitwardenSecret object
@ -50,9 +56,97 @@ type BitwardenSecretReconciler struct {
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.20.2/pkg/reconcile
func (r *BitwardenSecretReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
_ = log.FromContext(ctx)
olog := log.FromContext(ctx)
// TODO(user): your logic here
// Fetch the BitwardenSecret instance
var bitwardenSecret lerentisuploadfilter24euv1.BitwardenSecret
if err := r.Get(ctx, req.NamespacedName, &bitwardenSecret); err != nil {
if errors.IsNotFound(err) {
olog.Info("BitwardenSecret resource not found. Ignoring since object must be deleted.")
return ctrl.Result{}, nil
}
olog.Error(err, "Failed to get BitwardenSecret.")
return ctrl.Result{}, err
}
// Fetch secrets from Bitwarden
apiURL := os.Getenv("API_URL")
identityURL := os.Getenv("IDENTITY_URL")
client, _ := sdk.NewBitwardenClient(&apiURL, &identityURL)
accessToken := os.Getenv("ACCESS_TOKEN")
stateFile := os.Getenv("STATE_FILE")
err := client.AccessTokenLogin(accessToken, &stateFile)
if err != nil {
olog.Error(err, "Failed to authenticate with Bitwarden.")
return ctrl.Result{}, err
}
secretData := make(map[string][]byte)
for _, element := range bitwardenSecret.Spec.Content {
resp, err := client.Secrets().Get(bitwardenSecret.Spec.ID)
if err != nil {
olog.Error(err, "Failed to fetch item from Bitwarden.")
return ctrl.Result{}, err
}
item := resp.Value
var secretValue string
switch element.SecretScope {
case "login":
if element.SecretName == "username" {
secretValue = item.Login.Username
} else if element.SecretName == "password" {
secretValue = item.Login.Password
}
case "fields":
for _, field := range item.Fields {
if field.Name == element.SecretName {
secretValue = field.Value
break
}
}
case "attachment":
for _, attachment := range item.Attachments {
if attachment.FileName == element.SecretName {
secretValue = attachment.File
break
}
}
}
if secretValue != "" {
secretData[element.SecretRef] = []byte(base64.StdEncoding.EncodeToString([]byte(secretValue)))
}
}
// Create or update Kubernetes secret
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: bitwardenSecret.Spec.Name,
Namespace: bitwardenSecret.Spec.Namespace,
Labels: bitwardenSecret.Spec.Labels,
Annotations: bitwardenSecret.Spec.Annotations,
},
Data: secretData,
Type: corev1.SecretType(bitwardenSecret.Spec.SecretType),
}
if err := r.Client.Create(ctx, secret); err != nil && !errors.IsAlreadyExists(err) {
olog.Error(err, "Failed to create Secret.")
return ctrl.Result{}, err
}
if errors.IsAlreadyExists(err) {
if err := r.Client.Update(ctx, secret); err != nil {
olog.Error(err, "Failed to update Secret.")
return ctrl.Result{}, err
}
}
return ctrl.Result{}, nil
}