diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index bf21aa1d..ff468549 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -3,6 +3,13 @@ package localbuild import ( "context" "embed" + "encoding/json" + "fmt" + "golang.org/x/crypto/bcrypt" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + "time" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/globals" @@ -15,6 +22,10 @@ import ( //go:embed resources/argo/* var installArgoFS embed.FS +const ( + argocdDevModePassword = "developer" +) + func RawArgocdInstallResources(templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) { return k8s.BuildCustomizedManifests(config.FilePath, "resources/argo", installArgoFS, scheme, templateData) } @@ -53,7 +64,51 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque if result, err := argocd.Install(ctx, resource, r.Client, r.Scheme, r.Config); err != nil { return result, err } - resource.Status.ArgoCD.Available = true + + // Let's patch the existing argocd admin secret if devmode is enabled to set the default password + if r.Config.DevMode { + kubeClient, err := k8s.GetKubeClient() + if err != nil { + return ctrl.Result{}, fmt.Errorf("getting kube client: %w", err) + } + + s := v1.Secret{} + err = kubeClient.Get(ctx, client.ObjectKey{Name: "argocd-secret", Namespace: "argocd"}, &s) + if err != nil { + return ctrl.Result{}, fmt.Errorf("getting argocd secret: %w", err) + } + + // Hash password using bcrypt + password := argocdDevModePassword + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return ctrl.Result{}, fmt.Errorf("Error hashing password: %w", err) + } + // Get the current date in the desired format + passwordMtime := time.Now().Format("2006-01-02T15:04:05Z") + + // Prepare the patch for the Secret's `stringData` field + patchData := map[string]interface{}{ + "stringData": map[string]string{ + "admin.password": string(hashedPassword), + "admin.passwordMtime": passwordMtime, + }, + } + // Convert patch data to JSON + patchBytes, err := json.Marshal(patchData) + if err != nil { + return ctrl.Result{}, fmt.Errorf("Error marshalling patch data:", err) + } + + // Patching the argocd-secret with the hashed password + err = kubeClient.Patch(ctx, &s, client.RawPatch(types.StrategicMergePatchType, patchBytes)) + if err != nil { + return ctrl.Result{}, fmt.Errorf("Error patching the Secret:", err) + } else { + return ctrl.Result{}, nil + } + } + return ctrl.Result{}, nil } diff --git a/pkg/k8s/util.go b/pkg/k8s/util.go index df40195a..7b01a8c1 100644 --- a/pkg/k8s/util.go +++ b/pkg/k8s/util.go @@ -2,13 +2,22 @@ package k8s import ( "embed" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/util/homedir" "os" + "path/filepath" + ctrl "sigs.k8s.io/controller-runtime" "github.com/cnoe-io/idpbuilder/pkg/util" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) +var ( + setupLog = ctrl.Log.WithName("k8s") +) + func BuildCustomizedManifests(filePath, fsPath string, resourceFS embed.FS, scheme *runtime.Scheme, templateData any) ([][]byte, error) { rawResources, err := util.ConvertFSToBytes(resourceFS, fsPath, templateData) if err != nil { @@ -58,3 +67,33 @@ func applyOverrides(filePath string, originalFiles [][]byte, scheme *runtime.Sch return ConvertYamlToObjectsWithOverride(scheme, originalFiles, rendered) } + +func GetKubeConfig(kubeConfigPath ...string) (*rest.Config, error) { + // Set default path if no path is provided + path := filepath.Join(homedir.HomeDir(), ".kube", "config") + + if len(kubeConfigPath) > 0 { + path = kubeConfigPath[0] + } + + kubeConfig, err := clientcmd.BuildConfigFromFlags("", path) + if err != nil { + setupLog.Error(err, "Error building kubeconfig from kind cluster") + return nil, err + } + return kubeConfig, nil +} + +func GetKubeClient(kubeConfigPath ...string) (client.Client, error) { + kubeCfg, err := GetKubeConfig(kubeConfigPath...) + if err != nil { + setupLog.Error(err, "Error getting kubeconfig") + return nil, err + } + kubeClient, err := client.New(kubeCfg, client.Options{Scheme: GetScheme()}) + if err != nil { + setupLog.Error(err, "Error creating kubernetes client") + return nil, err + } + return kubeClient, nil +}