From 3a974cba169381c075be9563c10181ad7153280a Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 8 Nov 2024 14:24:00 +0100 Subject: [PATCH 01/41] WIP. Create default passwords when dev mode is set. #441 Signed-off-by: cmoulliard --- api/v1alpha1/localbuild_types.go | 1 + pkg/build/build.go | 3 +++ pkg/cmd/create/root.go | 4 ++++ pkg/controllers/localbuild/gitea.go | 17 ++++++++++++----- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/api/v1alpha1/localbuild_types.go b/api/v1alpha1/localbuild_types.go index 62d53ba6..0cc114f9 100644 --- a/api/v1alpha1/localbuild_types.go +++ b/api/v1alpha1/localbuild_types.go @@ -53,6 +53,7 @@ type BuildCustomizationSpec struct { Port string `json:"port,omitempty"` UsePathRouting bool `json:"usePathRouting,omitempty"` SelfSignedCert string `json:"selfSignedCert,omitempty"` + DevMode bool `json:"devMode,omitempty"` } type LocalbuildSpec struct { diff --git a/pkg/build/build.go b/pkg/build/build.go index 0da1cb4f..c6d4be99 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -28,6 +28,7 @@ var ( type Build struct { name string + devMode bool cfg v1alpha1.BuildCustomizationSpec kindConfigPath string kubeConfigPath string @@ -43,6 +44,7 @@ type Build struct { type NewBuildOptions struct { Name string + DevMode bool TemplateData v1alpha1.BuildCustomizationSpec KindConfigPath string KubeConfigPath string @@ -59,6 +61,7 @@ type NewBuildOptions struct { func NewBuild(opts NewBuildOptions) *Build { return &Build{ name: opts.Name, + devMode: opts.DevMode, kindConfigPath: opts.KindConfigPath, kubeConfigPath: opts.KubeConfigPath, kubeVersion: opts.KubeVersion, diff --git a/pkg/cmd/create/root.go b/pkg/cmd/create/root.go index 32212ccd..e3c15353 100644 --- a/pkg/cmd/create/root.go +++ b/pkg/cmd/create/root.go @@ -20,6 +20,7 @@ import ( const ( recreateClusterUsage = "Delete cluster first if it already exists." buildNameUsage = "Name for build (Prefix for kind cluster name, pod names, etc)." + devModeUsage = "When enabled, the platform will run the core packages with developer password." kubeVersionUsage = "Version of the kind kubernetes cluster to create." extraPortsMappingUsage = "List of extra ports to expose on the docker container and kubernetes cluster as nodePort " + "(e.g. \"22:32222,9090:39090,etc\")." @@ -40,6 +41,7 @@ var ( // Flags recreateCluster bool buildName string + devMode bool kubeVersion string extraPortsMapping string kindConfigPath string @@ -67,6 +69,7 @@ func init() { CreateCmd.PersistentFlags().StringVar(&buildName, "build-name", "localdev", buildNameUsage) CreateCmd.PersistentFlags().MarkDeprecated("build-name", "use --name instead.") CreateCmd.PersistentFlags().StringVar(&buildName, "name", "localdev", buildNameUsage) + CreateCmd.PersistentFlags().BoolVar(&devMode, "dev", false, devModeUsage) CreateCmd.PersistentFlags().StringVar(&kubeVersion, "kube-version", "v1.30.3", kubeVersionUsage) CreateCmd.PersistentFlags().StringVar(&extraPortsMapping, "extra-ports", "", extraPortsMappingUsage) CreateCmd.PersistentFlags().StringVar(&kindConfigPath, "kind-config", "", kindConfigPathUsage) @@ -132,6 +135,7 @@ func create(cmd *cobra.Command, args []string) error { opts := build.NewBuildOptions{ Name: buildName, + DevMode: devMode, KubeVersion: kubeVersion, KubeConfigPath: kubeConfigPath, KindConfigPath: kindConfigPath, diff --git a/pkg/controllers/localbuild/gitea.go b/pkg/controllers/localbuild/gitea.go index 79f844c8..7901a419 100644 --- a/pkg/controllers/localbuild/gitea.go +++ b/pkg/controllers/localbuild/gitea.go @@ -24,6 +24,7 @@ import ( ) const ( + giteaDevModePassword = "developer" // hardcoded values from what we have in the yaml installation file. giteaNamespace = "gitea" giteaAdminSecret = "gitea-credential" @@ -56,11 +57,17 @@ func giteaAdminSecretObject() corev1.Secret { } } -func newGiteaAdminSecret() (corev1.Secret, error) { - pass, err := util.GeneratePassword() - if err != nil { - return corev1.Secret{}, err +func newGiteaAdminSecret(devMode bool) (corev1.Secret, error) { + // Reuse the same password when dev mode is enabled + pass := giteaDevModePassword + if !devMode { + var err error + pass, err = util.GeneratePassword() + if err != nil { + return corev1.Secret{}, err + } } + obj := giteaAdminSecretObject() obj.StringData = map[string]string{ "username": v1alpha1.GiteaAdminUserName, @@ -93,7 +100,7 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ if err != nil { if k8serrors.IsNotFound(err) { - giteaCreds, err := newGiteaAdminSecret() + giteaCreds, err := newGiteaAdminSecret(resource.Spec.BuildCustomization.DevMode) if err != nil { return ctrl.Result{}, fmt.Errorf("generating gitea admin secret: %w", err) } From a9c683fdcd9436955179c1dfb69446fcb41cf856 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 8 Nov 2024 14:42:13 +0100 Subject: [PATCH 02/41] Set the devMode to BuildCustomization Signed-off-by: cmoulliard --- pkg/build/build.go | 2 -- pkg/cmd/create/root.go | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/build/build.go b/pkg/build/build.go index c6d4be99..79d09aee 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -44,7 +44,6 @@ type Build struct { type NewBuildOptions struct { Name string - DevMode bool TemplateData v1alpha1.BuildCustomizationSpec KindConfigPath string KubeConfigPath string @@ -61,7 +60,6 @@ type NewBuildOptions struct { func NewBuild(opts NewBuildOptions) *Build { return &Build{ name: opts.Name, - devMode: opts.DevMode, kindConfigPath: opts.KindConfigPath, kubeConfigPath: opts.KubeConfigPath, kubeVersion: opts.KubeVersion, diff --git a/pkg/cmd/create/root.go b/pkg/cmd/create/root.go index e3c15353..ace971a2 100644 --- a/pkg/cmd/create/root.go +++ b/pkg/cmd/create/root.go @@ -135,7 +135,6 @@ func create(cmd *cobra.Command, args []string) error { opts := build.NewBuildOptions{ Name: buildName, - DevMode: devMode, KubeVersion: kubeVersion, KubeConfigPath: kubeConfigPath, KindConfigPath: kindConfigPath, @@ -147,6 +146,7 @@ func create(cmd *cobra.Command, args []string) error { IngressHost: ingressHost, Port: port, UsePathRouting: pathRouting, + DevMode: devMode, }, CustomPackageDirs: absDirPaths, From 6d858519b907de579e5a6fa03a7b9161b52a5bbb Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 8 Nov 2024 14:51:22 +0100 Subject: [PATCH 03/41] Pass the proper object containing devMode to the function populating a new password. #441 Signed-off-by: cmoulliard --- pkg/build/build.go | 3 ++- pkg/controllers/localbuild/gitea.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/build/build.go b/pkg/build/build.go index 79d09aee..f30a82db 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -279,5 +279,6 @@ func isBuildCustomizationSpecEqual(s1, s2 v1alpha1.BuildCustomizationSpec) bool s1.IngressHost == s2.IngressHost && s1.Port == s2.Port && s1.UsePathRouting == s2.UsePathRouting && - s1.SelfSignedCert == s2.SelfSignedCert + s1.SelfSignedCert == s2.SelfSignedCert && + s1.DevMode == s2.DevMode } diff --git a/pkg/controllers/localbuild/gitea.go b/pkg/controllers/localbuild/gitea.go index 7901a419..0afbd19a 100644 --- a/pkg/controllers/localbuild/gitea.go +++ b/pkg/controllers/localbuild/gitea.go @@ -58,7 +58,7 @@ func giteaAdminSecretObject() corev1.Secret { } func newGiteaAdminSecret(devMode bool) (corev1.Secret, error) { - // Reuse the same password when dev mode is enabled + // Use a default password when dev mode is enabled to avoid to recreate a new one each time pass := giteaDevModePassword if !devMode { var err error @@ -100,7 +100,7 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ if err != nil { if k8serrors.IsNotFound(err) { - giteaCreds, err := newGiteaAdminSecret(resource.Spec.BuildCustomization.DevMode) + giteaCreds, err := newGiteaAdminSecret(r.Config.DevMode) if err != nil { return ctrl.Result{}, fmt.Errorf("generating gitea admin secret: %w", err) } From 8dedc1e248951bb76dc0607e04cc57098a8d2db2 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 8 Nov 2024 16:10:57 +0100 Subject: [PATCH 04/41] Adding the code to patch the argocd-secret to use the hashed password - developer. Create a kubeClient part of the k8s util package. #441 Signed-off-by: cmoulliard --- pkg/controllers/localbuild/argo.go | 57 +++++++++++++++++++++++++++++- pkg/k8s/util.go | 39 ++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) 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 +} From 704bc78d6896928e8c6f0f816b7512c4359c4780 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 8 Nov 2024 16:18:59 +0100 Subject: [PATCH 05/41] Use cost 0 as argocd code #441 Signed-off-by: cmoulliard --- pkg/controllers/localbuild/argo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index ff468549..5f1435ae 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -81,7 +81,7 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque // Hash password using bcrypt password := argocdDevModePassword - hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), 0) if err != nil { return ctrl.Result{}, fmt.Errorf("Error hashing password: %w", err) } From ee9dc064129da344b2808f907587b509d89d01a1 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 8 Nov 2024 17:12:27 +0100 Subject: [PATCH 06/41] Re-creating too the inital admin secret for argocd. #441 Signed-off-by: cmoulliard --- pkg/controllers/localbuild/argo.go | 56 +++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index 5f1435ae..3aec07aa 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -7,6 +7,7 @@ import ( "fmt" "golang.org/x/crypto/bcrypt" v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "time" @@ -23,7 +24,11 @@ import ( var installArgoFS embed.FS const ( - argocdDevModePassword = "developer" + argocdDevModePassword = "developer" + argocdAdminSecretName = "argocd-secret" + argocdInitialAdminSecretName = "argocd-initial-admin-secret" + argocdInitialAdminPasswordKey = "argocd-initial-admin-secret" + argocdNamespace = "argocd" ) func RawArgocdInstallResources(templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) { @@ -68,25 +73,13 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque // 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), 0) 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") + passwordMtime := time.Now().Format(time.RFC3339) // Prepare the patch for the Secret's `stringData` field patchData := map[string]interface{}{ @@ -101,13 +94,44 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque return ctrl.Result{}, fmt.Errorf("Error marshalling patch data:", err) } + kubeClient, err := k8s.GetKubeClient() + if err != nil { + return ctrl.Result{}, fmt.Errorf("getting kube client: %w", err) + } + + // Getting the argocd-secret + s := v1.Secret{} + err = kubeClient.Get(ctx, client.ObjectKey{Name: argocdAdminSecretName, Namespace: argocdNamespace}, &s) + if err != nil { + return ctrl.Result{}, fmt.Errorf("getting argocd secret: %w", 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 } + + adminSecret := v1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "Secret", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: argocdInitialAdminSecretName, + Namespace: argocdNamespace, + }, + StringData: map[string]string{ + argocdInitialAdminPasswordKey: argocdDevModePassword, + }, + } + + // Re-creating the initial admin password secret: argocd-initial-admin-secret as used with "idpbuilder get secrets -p argocd" + err = kubeClient.Create(ctx, &adminSecret) + if err != nil { + return ctrl.Result{}, fmt.Errorf("Error creating the initial admin secret:", err) + } + } return ctrl.Result{}, nil From d3922874f07172c28ccf7e6666d0e19d5e1b377d Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 8 Nov 2024 17:33:30 +0100 Subject: [PATCH 07/41] Move the current time function. Generate the missing field. #441 Signed-off-by: cmoulliard --- pkg/controllers/localbuild/argo.go | 11 ++++++----- .../resources/idpbuilder.cnoe.io_localbuilds.yaml | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index 3aec07aa..79017914 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -79,19 +79,18 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque if err != nil { return ctrl.Result{}, fmt.Errorf("Error hashing password: %w", err) } - passwordMtime := time.Now().Format(time.RFC3339) // Prepare the patch for the Secret's `stringData` field patchData := map[string]interface{}{ "stringData": map[string]string{ "admin.password": string(hashedPassword), - "admin.passwordMtime": passwordMtime, + "admin.passwordMtime": time.Now().Format(time.RFC3339), }, } // Convert patch data to JSON patchBytes, err := json.Marshal(patchData) if err != nil { - return ctrl.Result{}, fmt.Errorf("Error marshalling patch data:", err) + return ctrl.Result{}, fmt.Errorf("Error marshalling patch data: %w", err) } kubeClient, err := k8s.GetKubeClient() @@ -109,7 +108,7 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque // 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) + return ctrl.Result{}, fmt.Errorf("Error patching the Secret: %w", err) } adminSecret := v1.Secret{ @@ -129,7 +128,9 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque // Re-creating the initial admin password secret: argocd-initial-admin-secret as used with "idpbuilder get secrets -p argocd" err = kubeClient.Create(ctx, &adminSecret) if err != nil { - return ctrl.Result{}, fmt.Errorf("Error creating the initial admin secret:", err) + return ctrl.Result{}, fmt.Errorf("Error creating the initial admin secret: %w", err) + } else { + return ctrl.Result{}, nil } } diff --git a/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml b/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml index ab98210f..ba9e7ab1 100644 --- a/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml +++ b/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml @@ -41,6 +41,8 @@ spec: description: BuildCustomizationSpec fields cannot change once a cluster is created properties: + devMode: + type: boolean host: type: string ingressHost: From 0c6256413ebc36953dbeaf5de76f6fe0c5498d28 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Tue, 12 Nov 2024 11:11:01 +0100 Subject: [PATCH 08/41] Include needed argocd k8s resources and change the code to set the developer's password. #441 Signed-off-by: cmoulliard --- hack/argo-cd/argocd-cm.yaml | 1 + hack/argo-cd/argocd-rbac-dev.yaml | 12 +++++ hack/argo-cd/kustomization.yaml | 1 + pkg/controllers/localbuild/argo.go | 52 ++++++++++--------- .../localbuild/resources/argo/install.yaml | 14 +++++ 5 files changed, 55 insertions(+), 25 deletions(-) create mode 100644 hack/argo-cd/argocd-rbac-dev.yaml diff --git a/hack/argo-cd/argocd-cm.yaml b/hack/argo-cd/argocd-cm.yaml index 8b191064..1ccf0702 100644 --- a/hack/argo-cd/argocd-cm.yaml +++ b/hack/argo-cd/argocd-cm.yaml @@ -4,6 +4,7 @@ metadata: name: argocd-cm data: application.resourceTrackingMethod: annotation + accounts.developer: apiKey, login timeout.reconciliation: 60s resource.exclusions: | - kinds: diff --git a/hack/argo-cd/argocd-rbac-dev.yaml b/hack/argo-cd/argocd-rbac-dev.yaml new file mode 100644 index 00000000..37e3c105 --- /dev/null +++ b/hack/argo-cd/argocd-rbac-dev.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: argocd-rbac-cm + app.kubernetes.io/part-of: argocd + name: argocd-rbac-cm + namespace: argocd +data: + policy.csv: | + p, role:developer, applications, *, *, allow + g, developer, role:developer \ No newline at end of file diff --git a/hack/argo-cd/kustomization.yaml b/hack/argo-cd/kustomization.yaml index 25872b10..8f4672f3 100644 --- a/hack/argo-cd/kustomization.yaml +++ b/hack/argo-cd/kustomization.yaml @@ -2,6 +2,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - https://raw.githubusercontent.com/argoproj/argo-cd/v2.10.7/manifests/install.yaml + - argocd-rbac-dev.yaml patches: - path: dex-server.yaml diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index 79017914..b0f82aa1 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -7,7 +7,6 @@ import ( "fmt" "golang.org/x/crypto/bcrypt" v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "time" @@ -83,8 +82,8 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque // Prepare the patch for the Secret's `stringData` field patchData := map[string]interface{}{ "stringData": map[string]string{ - "admin.password": string(hashedPassword), - "admin.passwordMtime": time.Now().Format(time.RFC3339), + "account.developer.password": string(hashedPassword), + "account.developer.passwordMtime": time.Now().Format(time.RFC3339), }, } // Convert patch data to JSON @@ -105,33 +104,36 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque return ctrl.Result{}, fmt.Errorf("getting argocd secret: %w", err) } - // Patching the argocd-secret with the hashed password + // Patching the argocd-secret with the user's hashed password err = kubeClient.Patch(ctx, &s, client.RawPatch(types.StrategicMergePatchType, patchBytes)) if err != nil { return ctrl.Result{}, fmt.Errorf("Error patching the Secret: %w", err) } - adminSecret := v1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: argocdInitialAdminSecretName, - Namespace: argocdNamespace, - }, - StringData: map[string]string{ - argocdInitialAdminPasswordKey: argocdDevModePassword, - }, - } - - // Re-creating the initial admin password secret: argocd-initial-admin-secret as used with "idpbuilder get secrets -p argocd" - err = kubeClient.Create(ctx, &adminSecret) - if err != nil { - return ctrl.Result{}, fmt.Errorf("Error creating the initial admin secret: %w", err) - } else { - return ctrl.Result{}, nil - } + /* + This is not needed as we will not generate a new admin password + + adminSecret := v1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "Secret", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: argocdInitialAdminSecretName, + Namespace: argocdNamespace, + }, + StringData: map[string]string{ + argocdInitialAdminPasswordKey: argocdDevModePassword, + }, + } + + // Re-creating the initial admin password secret: argocd-initial-admin-secret as used with "idpbuilder get secrets -p argocd" + err = kubeClient.Create(ctx, &adminSecret) + if err != nil { + return ctrl.Result{}, fmt.Errorf("Error creating the initial admin secret: %w", err) + } else { + return ctrl.Result{}, nil + }*/ } diff --git a/pkg/controllers/localbuild/resources/argo/install.yaml b/pkg/controllers/localbuild/resources/argo/install.yaml index 28dae6ce..6eea371d 100644 --- a/pkg/controllers/localbuild/resources/argo/install.yaml +++ b/pkg/controllers/localbuild/resources/argo/install.yaml @@ -21081,6 +21081,20 @@ subjects: --- apiVersion: v1 data: + policy.csv: |- + p, role:developer, applications, *, *, allow + g, developer, role:developer +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: argocd-rbac-cm + app.kubernetes.io/part-of: argocd + name: argocd-rbac-cm + namespace: argocd +--- +apiVersion: v1 +data: + accounts.developer: apiKey, login application.resourceTrackingMethod: annotation resource.exclusions: | - kinds: From 1e1b9803be3b5d6601e69b7cc2ee8c42a1e7f291 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Tue, 12 Nov 2024 11:20:56 +0100 Subject: [PATCH 09/41] Fix wrong key as account should be accounts Signed-off-by: cmoulliard --- pkg/controllers/localbuild/argo.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index b0f82aa1..4327c137 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -82,8 +82,8 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque // Prepare the patch for the Secret's `stringData` field patchData := map[string]interface{}{ "stringData": map[string]string{ - "account.developer.password": string(hashedPassword), - "account.developer.passwordMtime": time.Now().Format(time.RFC3339), + "accounts.developer.password": string(hashedPassword), + "accounts.developer.passwordMtime": time.Now().Format(time.RFC3339), }, } // Convert patch data to JSON From 3d884da55b38b169bd1bf7145e7f4ae8815f26b5 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Tue, 12 Nov 2024 11:27:35 +0100 Subject: [PATCH 10/41] Change the gitea user from giteaAdmin to developer for a user's developer Signed-off-by: cmoulliard --- api/v1alpha1/gitrepository_types.go | 13 +++++++------ pkg/controllers/localbuild/gitea.go | 8 ++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/api/v1alpha1/gitrepository_types.go b/api/v1alpha1/gitrepository_types.go index d3ac32af..978087c4 100644 --- a/api/v1alpha1/gitrepository_types.go +++ b/api/v1alpha1/gitrepository_types.go @@ -5,12 +5,13 @@ import ( ) const ( - GitProviderGitea = "gitea" - GitProviderGitHub = "github" - GiteaAdminUserName = "giteaAdmin" - SourceTypeLocal = "local" - SourceTypeRemote = "remote" - SourceTypeEmbedded = "embedded" + GitProviderGitea = "gitea" + GitProviderGitHub = "github" + GiteaAdminUserName = "giteaAdmin" + GiteaDeveloperUserName = "developer" + SourceTypeLocal = "local" + SourceTypeRemote = "remote" + SourceTypeEmbedded = "embedded" ) type GitRepositorySpec struct { diff --git a/pkg/controllers/localbuild/gitea.go b/pkg/controllers/localbuild/gitea.go index 0afbd19a..9fb39211 100644 --- a/pkg/controllers/localbuild/gitea.go +++ b/pkg/controllers/localbuild/gitea.go @@ -25,6 +25,7 @@ import ( const ( giteaDevModePassword = "developer" + // hardcoded values from what we have in the yaml installation file. giteaNamespace = "gitea" giteaAdminSecret = "gitea-credential" @@ -58,19 +59,22 @@ func giteaAdminSecretObject() corev1.Secret { } func newGiteaAdminSecret(devMode bool) (corev1.Secret, error) { - // Use a default password when dev mode is enabled to avoid to recreate a new one each time pass := giteaDevModePassword + userName := v1alpha1.GiteaDeveloperUserName + if !devMode { var err error pass, err = util.GeneratePassword() if err != nil { return corev1.Secret{}, err } + + userName = v1alpha1.GiteaAdminUserName } obj := giteaAdminSecretObject() obj.StringData = map[string]string{ - "username": v1alpha1.GiteaAdminUserName, + "username": userName, "password": pass, } return obj, nil From f31a08e5d8f023afaeca08a9db8e88884af755e1 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Tue, 12 Nov 2024 11:58:12 +0100 Subject: [PATCH 11/41] Reverting to giteaAdmin till we know why a different user - developer fails Signed-off-by: cmoulliard --- pkg/controllers/localbuild/gitea.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/controllers/localbuild/gitea.go b/pkg/controllers/localbuild/gitea.go index 9fb39211..38064ca3 100644 --- a/pkg/controllers/localbuild/gitea.go +++ b/pkg/controllers/localbuild/gitea.go @@ -60,7 +60,8 @@ func giteaAdminSecretObject() corev1.Secret { func newGiteaAdminSecret(devMode bool) (corev1.Secret, error) { pass := giteaDevModePassword - userName := v1alpha1.GiteaDeveloperUserName + // TODO: Reverting to giteaAdmin till we know why a different user - developer fails + userName := v1alpha1.GiteaAdminUserName if !devMode { var err error From c355ba13525432733be0d2d0d863d79d45899c40 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Tue, 12 Nov 2024 14:53:54 +0100 Subject: [PATCH 12/41] Change the number from 58 to 59 as we install a new ConfigMap - RBAC for argocd Signed-off-by: cmoulliard --- pkg/controllers/localbuild/argo_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/controllers/localbuild/argo_test.go b/pkg/controllers/localbuild/argo_test.go index e35ec4c6..abad74b6 100644 --- a/pkg/controllers/localbuild/argo_test.go +++ b/pkg/controllers/localbuild/argo_test.go @@ -80,8 +80,8 @@ func TestGetK8sInstallResources(t *testing.T) { t.Fatalf("GetK8sInstallResources() error: %v", err) } - if len(objs) != 58 { - t.Fatalf("Expected 58 Argo Install Resources, got: %d", len(objs)) + if len(objs) != 59 { + t.Fatalf("Expected 59 Argo Install Resources, got: %d", len(objs)) } } From 8158551f0763dadf715c0aed3108068119f5bdaa Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 21 Nov 2024 15:22:52 +0100 Subject: [PATCH 13/41] Remove from the util go file the setupLog and replace it with fmt.Errorf() Signed-off-by: cmoulliard --- pkg/k8s/util.go | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/pkg/k8s/util.go b/pkg/k8s/util.go index 7b01a8c1..9c3ec13c 100644 --- a/pkg/k8s/util.go +++ b/pkg/k8s/util.go @@ -2,22 +2,17 @@ package k8s import ( "embed" + "fmt" + "github.com/cnoe-io/idpbuilder/pkg/util" + "k8s.io/apimachinery/pkg/runtime" "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 { @@ -78,8 +73,7 @@ func GetKubeConfig(kubeConfigPath ...string) (*rest.Config, error) { kubeConfig, err := clientcmd.BuildConfigFromFlags("", path) if err != nil { - setupLog.Error(err, "Error building kubeconfig from kind cluster") - return nil, err + return nil, fmt.Errorf("Error building kubeconfig from kind cluster: %w", err) } return kubeConfig, nil } @@ -87,13 +81,11 @@ func GetKubeConfig(kubeConfigPath ...string) (*rest.Config, error) { func GetKubeClient(kubeConfigPath ...string) (client.Client, error) { kubeCfg, err := GetKubeConfig(kubeConfigPath...) if err != nil { - setupLog.Error(err, "Error getting kubeconfig") - return nil, err + return nil, fmt.Errorf("Error getting kubeconfig: %w", err) } kubeClient, err := client.New(kubeCfg, client.Options{Scheme: GetScheme()}) if err != nil { - setupLog.Error(err, "Error creating kubernetes client") - return nil, err + return nil, fmt.Errorf("Error creating kubernetes client: %w", err) } return kubeClient, nil } From 78e1e4066662843bc14754c939506014e6afc316 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 21 Nov 2024 15:26:50 +0100 Subject: [PATCH 14/41] Removed non used argocd constants Signed-off-by: cmoulliard --- pkg/controllers/localbuild/argo.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index 4327c137..1a42a3d4 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -23,11 +23,9 @@ import ( var installArgoFS embed.FS const ( - argocdDevModePassword = "developer" - argocdAdminSecretName = "argocd-secret" - argocdInitialAdminSecretName = "argocd-initial-admin-secret" - argocdInitialAdminPasswordKey = "argocd-initial-admin-secret" - argocdNamespace = "argocd" + argocdDevModePassword = "developer" + argocdAdminSecretName = "argocd-secret" + argocdNamespace = "argocd" ) func RawArgocdInstallResources(templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) { From 7d81b27a9e67facbe3bdb0efc16106ebdabee668 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 21 Nov 2024 15:42:04 +0100 Subject: [PATCH 15/41] Use r.client instead of k8s.GetKubeClient() Signed-off-by: cmoulliard --- pkg/controllers/localbuild/argo.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index 1a42a3d4..86c37e68 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -90,20 +90,15 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque return ctrl.Result{}, fmt.Errorf("Error marshalling patch data: %w", err) } - kubeClient, err := k8s.GetKubeClient() - if err != nil { - return ctrl.Result{}, fmt.Errorf("getting kube client: %w", err) - } - // Getting the argocd-secret s := v1.Secret{} - err = kubeClient.Get(ctx, client.ObjectKey{Name: argocdAdminSecretName, Namespace: argocdNamespace}, &s) + err = r.Client.Get(ctx, client.ObjectKey{Name: argocdAdminSecretName, Namespace: argocdNamespace}, &s) if err != nil { return ctrl.Result{}, fmt.Errorf("getting argocd secret: %w", err) } // Patching the argocd-secret with the user's hashed password - err = kubeClient.Patch(ctx, &s, client.RawPatch(types.StrategicMergePatchType, patchBytes)) + err = r.Client.Patch(ctx, &s, client.RawPatch(types.StrategicMergePatchType, patchBytes)) if err != nil { return ctrl.Result{}, fmt.Errorf("Error patching the Secret: %w", err) } From a8c301606b1a62e54e7b200c5fe76e4843f5c480 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 21 Nov 2024 17:48:05 +0100 Subject: [PATCH 16/41] Rename the flag from dev to dev-mode Signed-off-by: cmoulliard --- pkg/cmd/create/root.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/create/root.go b/pkg/cmd/create/root.go index ace971a2..abad45c8 100644 --- a/pkg/cmd/create/root.go +++ b/pkg/cmd/create/root.go @@ -69,7 +69,7 @@ func init() { CreateCmd.PersistentFlags().StringVar(&buildName, "build-name", "localdev", buildNameUsage) CreateCmd.PersistentFlags().MarkDeprecated("build-name", "use --name instead.") CreateCmd.PersistentFlags().StringVar(&buildName, "name", "localdev", buildNameUsage) - CreateCmd.PersistentFlags().BoolVar(&devMode, "dev", false, devModeUsage) + CreateCmd.PersistentFlags().BoolVar(&devMode, "dev-mode", false, devModeUsage) CreateCmd.PersistentFlags().StringVar(&kubeVersion, "kube-version", "v1.30.3", kubeVersionUsage) CreateCmd.PersistentFlags().StringVar(&extraPortsMapping, "extra-ports", "", extraPortsMappingUsage) CreateCmd.PersistentFlags().StringVar(&kindConfigPath, "kind-config", "", kindConfigPathUsage) From 80a785ba7bce60ec4fb1608c304410c64aa38e53 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 21 Nov 2024 18:57:54 +0100 Subject: [PATCH 17/41] Use an unstructured object to avoid managing fields we do not care about. Signed-off-by: cmoulliard --- pkg/controllers/localbuild/argo.go | 32 +++++++++++++++++++----------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index 86c37e68..8dbdd9e8 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -3,11 +3,12 @@ package localbuild import ( "context" "embed" - "encoding/json" "fmt" "golang.org/x/crypto/bcrypt" v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/json" "sigs.k8s.io/controller-runtime/pkg/client" "time" @@ -74,9 +75,22 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque password := argocdDevModePassword hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), 0) if err != nil { - return ctrl.Result{}, fmt.Errorf("Error hashing password: %w", err) + return ctrl.Result{}, fmt.Errorf("error hashing password: %w", err) } + // Getting the argocd-secret + obj := v1.Secret{} + err = r.Client.Get(ctx, client.ObjectKey{Name: argocdAdminSecretName, Namespace: argocdNamespace}, &obj) + if err != nil { + return ctrl.Result{}, fmt.Errorf("getting argocd secret: %w", err) + } + + // Using an unstructured object to avoid managing fields we do not care about. + u := unstructured.Unstructured{} + u.SetName(obj.GetName()) + u.SetNamespace(obj.GetNamespace()) + u.SetGroupVersionKind(obj.GetObjectKind().GroupVersionKind()) + // Prepare the patch for the Secret's `stringData` field patchData := map[string]interface{}{ "stringData": map[string]string{ @@ -85,23 +99,17 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque }, } // Convert patch data to JSON - patchBytes, err := json.Marshal(patchData) + patch, err := json.Marshal(patchData) if err != nil { return ctrl.Result{}, fmt.Errorf("Error marshalling patch data: %w", err) } - // Getting the argocd-secret - s := v1.Secret{} - err = r.Client.Get(ctx, client.ObjectKey{Name: argocdAdminSecretName, Namespace: argocdNamespace}, &s) - if err != nil { - return ctrl.Result{}, fmt.Errorf("getting argocd secret: %w", err) - } - // Patching the argocd-secret with the user's hashed password - err = r.Client.Patch(ctx, &s, client.RawPatch(types.StrategicMergePatchType, patchBytes)) + err = r.Client.Patch(ctx, &u, client.RawPatch(types.MergePatchType, patch)) if err != nil { - return ctrl.Result{}, fmt.Errorf("Error patching the Secret: %w", err) + return ctrl.Result{}, fmt.Errorf("error patching the Secret: %w", err) } + return ctrl.Result{}, nil /* This is not needed as we will not generate a new admin password From 3c3511da445016a8e52da2ebc5b8d75c323306b4 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 22 Nov 2024 12:01:47 +0100 Subject: [PATCH 18/41] Include the developer username and password to the command get secret Signed-off-by: cmoulliard --- pkg/cmd/get/secrets.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index 5cad39c3..01ad2757 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -8,6 +8,7 @@ import ( "io" "os" "path/filepath" + "strings" "text/template" "github.com/cnoe-io/idpbuilder/api/v1alpha1" @@ -206,6 +207,18 @@ func secretToTemplateData(s v1.Secret) TemplateData { for k, v := range s.Data { data.Data[k] = string(v) } + + // TODO: The following code should be reviewed and improved as the secret containing the developer username/password is argocd-secret + // where the password has been bcrypted and by consequence we cannot get and decode it from the secret + // This is why we are going to add it here BUT it will be displayed every time no matter if --dev-mode has been used or not + if strings.Contains(s.Name, "gitea") { + data.Data["username-developer"] = "giteAdmin" + data.Data["password-developer"] = "developer" + } else if strings.Contains(s.Name, "argocd") { + data.Data["username-developer"] = "developer" + data.Data["password-developer"] = "developer" + } + return data } From bf8e2cc2f02dc4ecd2425abc59358a16496a9634 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Mon, 9 Dec 2024 18:34:21 +0100 Subject: [PATCH 19/41] Refactor the code to update the argocd password post reconciliation. #441 Signed-off-by: cmoulliard --- pkg/controllers/localbuild/argo.go | 101 ++++---------- pkg/controllers/localbuild/controller.go | 159 +++++++++++++++++++++++ 2 files changed, 181 insertions(+), 79 deletions(-) diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index 8dbdd9e8..b4347981 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -4,17 +4,11 @@ import ( "context" "embed" "fmt" - "golang.org/x/crypto/bcrypt" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/json" - "sigs.k8s.io/controller-runtime/pkg/client" - "time" - "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/globals" "github.com/cnoe-io/idpbuilder/pkg/k8s" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ctrl "sigs.k8s.io/controller-runtime" @@ -24,9 +18,10 @@ import ( var installArgoFS embed.FS const ( - argocdDevModePassword = "developer" - argocdAdminSecretName = "argocd-secret" - argocdNamespace = "argocd" + argocdDevModePassword = "developer" + argocdInitialAdminSecretName = "argocd-initial-admin-secret" + argocdNamespace = "argocd" + argocdIngressURL = "%s://argocd.cnoe.localtest.me:%s" ) func RawArgocdInstallResources(templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) { @@ -67,76 +62,24 @@ 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 { - // Hash password using bcrypt - password := argocdDevModePassword - hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), 0) - if err != nil { - return ctrl.Result{}, fmt.Errorf("error hashing password: %w", err) - } - - // Getting the argocd-secret - obj := v1.Secret{} - err = r.Client.Get(ctx, client.ObjectKey{Name: argocdAdminSecretName, Namespace: argocdNamespace}, &obj) - if err != nil { - return ctrl.Result{}, fmt.Errorf("getting argocd secret: %w", err) - } - - // Using an unstructured object to avoid managing fields we do not care about. - u := unstructured.Unstructured{} - u.SetName(obj.GetName()) - u.SetNamespace(obj.GetNamespace()) - u.SetGroupVersionKind(obj.GetObjectKind().GroupVersionKind()) - - // Prepare the patch for the Secret's `stringData` field - patchData := map[string]interface{}{ - "stringData": map[string]string{ - "accounts.developer.password": string(hashedPassword), - "accounts.developer.passwordMtime": time.Now().Format(time.RFC3339), - }, - } - // Convert patch data to JSON - patch, err := json.Marshal(patchData) - if err != nil { - return ctrl.Result{}, fmt.Errorf("Error marshalling patch data: %w", err) - } - - // Patching the argocd-secret with the user's hashed password - err = r.Client.Patch(ctx, &u, client.RawPatch(types.MergePatchType, patch)) - if err != nil { - return ctrl.Result{}, fmt.Errorf("error patching the Secret: %w", err) - } - return ctrl.Result{}, nil - - /* - This is not needed as we will not generate a new admin password - adminSecret := v1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: argocdInitialAdminSecretName, - Namespace: argocdNamespace, - }, - StringData: map[string]string{ - argocdInitialAdminPasswordKey: argocdDevModePassword, - }, - } - - // Re-creating the initial admin password secret: argocd-initial-admin-secret as used with "idpbuilder get secrets -p argocd" - err = kubeClient.Create(ctx, &adminSecret) - if err != nil { - return ctrl.Result{}, fmt.Errorf("Error creating the initial admin secret: %w", err) - } else { - return ctrl.Result{}, nil - }*/ + resource.Status.ArgoCD.Available = true + return ctrl.Result{}, nil +} +func (r *LocalbuildReconciler) ArgocdInitialAdminSecretObject() corev1.Secret { + return corev1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "Secret", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: argocdInitialAdminSecretName, + Namespace: argocdNamespace, + }, } +} - return ctrl.Result{}, nil +func (r *LocalbuildReconciler) ArgocdBaseUrl(config v1alpha1.BuildCustomizationSpec) string { + return fmt.Sprintf(argocdIngressURL, config.Protocol, config.Port) } diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index 20a513ed..96c0f9a8 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -1,8 +1,13 @@ package localbuild import ( + "bytes" "context" + "encoding/json" "fmt" + "io" + "k8s.io/apimachinery/pkg/types" + "net/http" "os" "path/filepath" "strings" @@ -39,6 +44,14 @@ const ( argoCDApplicationSetAnnotationKeyRefreshTrue = "true" ) +var ( + status = "failed" +) + +type ArgocdSession struct { + Token string `json:"token"` +} + type LocalbuildReconciler struct { client.Client Scheme *runtime.Scheme @@ -89,6 +102,28 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) } } + if r.Config.DevMode { + logger.Info("DevMode is enabled") + initialPassword, err := r.extractArgocdInitialAdminSecret(ctx) + if err != nil { + // Argocd initial admin secret is not yet available ... + return ctrl.Result{RequeueAfter: defaultRequeueTime}, nil + } + + logger.Info("Initial argocd admin secret found ...") + + // Secret containing the initial argocd password exists + // Lets try to update the password + if initialPassword != "" && status == "failed" { + err, status = r.updateDevPassword(ctx, initialPassword) + if err != nil { + return ctrl.Result{}, err + } else { + logger.Info(fmt.Sprintf("Argocd admin password change %s !", status)) + } + } + } + logger.V(1).Info("done installing core packages. passing control to argocd") _, err = r.ReconcileArgoAppsWithGitea(ctx, req, &localBuild) if err != nil { @@ -581,6 +616,130 @@ func (r *LocalbuildReconciler) requestArgoCDAppSetRefresh(ctx context.Context) e return nil } +func (r *LocalbuildReconciler) extractArgocdInitialAdminSecret(ctx context.Context) (string, error) { + sec := r.ArgocdInitialAdminSecretObject() + err := r.Client.Get(ctx, types.NamespacedName{ + Namespace: sec.GetNamespace(), + Name: sec.GetName(), + }, &sec) + + if err != nil { + if k8serrors.IsNotFound(err) { + return "", fmt.Errorf("initial admin secret not found") + } + } + return string(sec.Data["password"]), nil +} + +func (r *LocalbuildReconciler) updateDevPassword(ctx context.Context, adminPassword string) (error, string) { + argocdEndpoint := r.ArgocdBaseUrl(r.Config) + "/api/v1" + + payload := map[string]string{ + "username": "admin", + "password": adminPassword, + } + payloadBytes, err := json.Marshal(payload) + if err != nil { + return fmt.Errorf("Error creating JSON payload: %v\n", err), "failed" + } + + // Create an HTTP POST request to get the Session token + req, err := http.NewRequest("POST", argocdEndpoint+"/session", bytes.NewBuffer(payloadBytes)) + if err != nil { + return fmt.Errorf("Error creating HTTP request: %v\n", err), "failed" + } + req.Header.Set("Content-Type", "application/json") + + // Create an HTTP client and disable TLS verification + client := &http.Client{} + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.TLSClientConfig.InsecureSkipVerify = true + client.Transport = transport + + // Send the request + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("Error sending request: %v\n", err), "failed" + } + defer resp.Body.Close() + + // Read the response body + body, err := io.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("Error reading response body: %v\n", err), "failed" + } + + if resp.StatusCode == 200 { + var argocdSession ArgocdSession + + err := json.Unmarshal([]byte(body), &argocdSession) + if err != nil { + fmt.Errorf("Error unmarshalling JSON: %v", err) + } + + payload := map[string]string{ + "name": "admin", + "currentPassword": adminPassword, + "newPassword": argocdDevModePassword, + } + + payloadBytes, err := json.Marshal(payload) + if err != nil { + return fmt.Errorf("Error creating JSON payload: %v\n", err), "failed" + } + + req, err := http.NewRequest("PUT", argocdEndpoint+"/account/password", bytes.NewBuffer(payloadBytes)) + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", argocdSession.Token)) + req.Header.Set("Content-Type", "application/json") + + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("Error sending request: %v\n", err), "failed" + } + defer resp.Body.Close() + + // Lets checking the new admin password + payload = map[string]string{ + "username": "admin", + "password": argocdDevModePassword, + } + payloadBytes, err = json.Marshal(payload) + if err != nil { + return fmt.Errorf("Error creating JSON payload: %v\n", err), "failed" + } + + req, err = http.NewRequest("POST", argocdEndpoint+"/session", bytes.NewBuffer(payloadBytes)) + if err != nil { + return fmt.Errorf("Error creating HTTP request: %v\n", err), "failed" + } + req.Header.Set("Content-Type", "application/json") + + // Create an HTTP client and disable TLS verification + client := &http.Client{} + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.TLSClientConfig.InsecureSkipVerify = true + client.Transport = transport + + // Send the request + resp, err = client.Do(req) + if err != nil { + return fmt.Errorf("Error sending request: %v\n", err), "failed" + } + defer resp.Body.Close() + + if resp.StatusCode == 200 { + // Password verification succeeded ! + return nil, "succeeded" + } else { + return fmt.Errorf("### New password verification failed: %s", body), "failed" + } + + } else { + return fmt.Errorf("HTTP Error: %d", resp.StatusCode), "failed" + } + return nil, "failed" +} + func (r *LocalbuildReconciler) applyArgoCDAnnotation(ctx context.Context, obj client.Object, argoCDType, annotationKey, annotationValue string) error { annotations := obj.GetAnnotations() if annotations != nil { From f76db506e379cf4f3722ccd85ec20c471d114be1 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Tue, 10 Dec 2024 12:39:51 +0100 Subject: [PATCH 20/41] Refactor the code to update the gitea password post reconciliation. #441 Signed-off-by: cmoulliard --- pkg/controllers/gitrepository/controller.go | 4 ++ pkg/controllers/gitrepository/gitea.go | 1 + pkg/controllers/localbuild/controller.go | 69 +++++++++++++++++++-- pkg/controllers/localbuild/gitea.go | 39 +++++------- 4 files changed, 83 insertions(+), 30 deletions(-) diff --git a/pkg/controllers/gitrepository/controller.go b/pkg/controllers/gitrepository/controller.go index 6a303494..f9a08ff2 100644 --- a/pkg/controllers/gitrepository/controller.go +++ b/pkg/controllers/gitrepository/controller.go @@ -143,6 +143,10 @@ func (r *RepositoryReconciler) reconcileGitRepo(ctx context.Context, repo *v1alp return ctrl.Result{}, fmt.Errorf("getting git provider credentials: %w", err) } + if r.Config.DevMode { + creds.password = "developer" + } + err = provider.setProviderCredentials(ctx, repo, creds) if err != nil { return ctrl.Result{}, fmt.Errorf("setting git provider credentials: %w", err) diff --git a/pkg/controllers/gitrepository/gitea.go b/pkg/controllers/gitrepository/gitea.go index de82970f..a19a433f 100644 --- a/pkg/controllers/gitrepository/gitea.go +++ b/pkg/controllers/gitrepository/gitea.go @@ -69,6 +69,7 @@ func (g *giteaProvider) getProviderCredentials(ctx context.Context, repo *v1alph if !ok { return gitProviderCredentials{}, fmt.Errorf("%s key not found in secret %s in %s ns", giteaAdminPasswordKey, repo.Spec.SecretRef.Name, repo.Spec.SecretRef.Namespace) } + return gitProviderCredentials{ username: string(username), password: string(password), diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index 96c0f9a8..10f0df30 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -2,6 +2,7 @@ package localbuild import ( "bytes" + "code.gitea.io/sdk/gitea" "context" "encoding/json" "fmt" @@ -45,7 +46,8 @@ const ( ) var ( - status = "failed" + argocdPasswordChangeStatus = "failed" + giteaPasswordChangeStatus = "failed" ) type ArgocdSession struct { @@ -104,7 +106,9 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) if r.Config.DevMode { logger.Info("DevMode is enabled") - initialPassword, err := r.extractArgocdInitialAdminSecret(ctx) + + // Check if the Argocd Initial admin secret exists + argocdInitialAdminPassword, err := r.extractArgocdInitialAdminSecret(ctx) if err != nil { // Argocd initial admin secret is not yet available ... return ctrl.Result{RequeueAfter: defaultRequeueTime}, nil @@ -114,12 +118,30 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) // Secret containing the initial argocd password exists // Lets try to update the password - if initialPassword != "" && status == "failed" { - err, status = r.updateDevPassword(ctx, initialPassword) + if argocdInitialAdminPassword != "" && argocdPasswordChangeStatus == "failed" { + err, argocdPasswordChangeStatus = r.updateArgocdDevPassword(ctx, argocdInitialAdminPassword) if err != nil { return ctrl.Result{}, err } else { - logger.Info(fmt.Sprintf("Argocd admin password change %s !", status)) + logger.Info(fmt.Sprintf("Argocd admin password change %s !", argocdPasswordChangeStatus)) + } + } + + // Check if the Gitea credentials secret exists + giteaAdminPassword, err := r.extractGiteaAdminSecret(ctx) + if err != nil { + // Gitea admin secret is not yet available ... + return ctrl.Result{RequeueAfter: defaultRequeueTime}, nil + } + logger.Info("Gitea admin secret found ...") + // Secret containing the gitea password exists + // Lets try to update the password + if giteaAdminPassword != "" && giteaPasswordChangeStatus == "failed" { + err, giteaPasswordChangeStatus = r.updateGiteaDevPassword(ctx, giteaAdminPassword) + if err != nil { + return ctrl.Result{}, err + } else { + logger.Info(fmt.Sprintf("Gitea admin password change %s !", giteaPasswordChangeStatus)) } } } @@ -631,7 +653,42 @@ func (r *LocalbuildReconciler) extractArgocdInitialAdminSecret(ctx context.Conte return string(sec.Data["password"]), nil } -func (r *LocalbuildReconciler) updateDevPassword(ctx context.Context, adminPassword string) (error, string) { +func (r *LocalbuildReconciler) extractGiteaAdminSecret(ctx context.Context) (string, error) { + sec := r.GiteaAdminSecretObject() + err := r.Client.Get(ctx, types.NamespacedName{ + Namespace: sec.GetNamespace(), + Name: sec.GetName(), + }, &sec) + + if err != nil { + if k8serrors.IsNotFound(err) { + return "", fmt.Errorf("gitea admin secret not found") + } + } + return string(sec.Data["password"]), nil +} + +func (r *LocalbuildReconciler) updateGiteaDevPassword(ctx context.Context, adminPassword string) (error, string) { + client, err := gitea.NewClient(r.GiteaBaseUrl(r.Config), gitea.SetHTTPClient(util.GetHttpClient()), + gitea.SetBasicAuth("giteaAdmin", adminPassword), gitea.SetContext(ctx), + ) + if err != nil { + return fmt.Errorf("cannot create gitea client: %w", err), "failed" + } + + opts := gitea.EditUserOption{ + LoginName: "giteaAdmin", + Password: "developer", + } + + resp, err := client.AdminEditUser("giteaAdmin", opts) + if err != nil { + return fmt.Errorf("cannot update gitea admin user: %w", resp.StatusCode, err), "failed" + } + return nil, "succeeded" +} + +func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, adminPassword string) (error, string) { argocdEndpoint := r.ArgocdBaseUrl(r.Config) + "/api/v1" payload := map[string]string{ diff --git a/pkg/controllers/localbuild/gitea.go b/pkg/controllers/localbuild/gitea.go index 38064ca3..292d5ec3 100644 --- a/pkg/controllers/localbuild/gitea.go +++ b/pkg/controllers/localbuild/gitea.go @@ -45,7 +45,7 @@ func RawGiteaInstallResources(templateData any, config v1alpha1.PackageCustomiza return k8s.BuildCustomizedManifests(config.FilePath, "resources/gitea/k8s", installGiteaFS, scheme, templateData) } -func giteaAdminSecretObject() corev1.Secret { +func (r *LocalbuildReconciler) GiteaAdminSecretObject() corev1.Secret { return corev1.Secret{ TypeMeta: metav1.TypeMeta{ Kind: "Secret", @@ -58,27 +58,13 @@ func giteaAdminSecretObject() corev1.Secret { } } -func newGiteaAdminSecret(devMode bool) (corev1.Secret, error) { - pass := giteaDevModePassword - // TODO: Reverting to giteaAdmin till we know why a different user - developer fails - userName := v1alpha1.GiteaAdminUserName - - if !devMode { - var err error - pass, err = util.GeneratePassword() - if err != nil { - return corev1.Secret{}, err - } - - userName = v1alpha1.GiteaAdminUserName - } - - obj := giteaAdminSecretObject() +func (r *LocalbuildReconciler) newGiteaAdminSecret(password string) corev1.Secret { + obj := r.GiteaAdminSecretObject() obj.StringData = map[string]string{ - "username": userName, - "password": pass, + "username": v1alpha1.GiteaAdminUserName, + "password": password, } - return obj, nil + return obj } func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) { @@ -97,7 +83,7 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ }, } - sec := giteaAdminSecretObject() + sec := r.GiteaAdminSecretObject() err := r.Client.Get(ctx, types.NamespacedName{ Namespace: sec.GetNamespace(), Name: sec.GetName(), @@ -105,7 +91,12 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ if err != nil { if k8serrors.IsNotFound(err) { - giteaCreds, err := newGiteaAdminSecret(r.Config.DevMode) + genPassword, err := util.GeneratePassword() + if err != nil { + return ctrl.Result{}, fmt.Errorf("generating gitea password: %w", err) + } + + giteaCreds := r.newGiteaAdminSecret(genPassword) if err != nil { return ctrl.Result{}, fmt.Errorf("generating gitea admin secret: %w", err) } @@ -125,7 +116,7 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ return result, err } - baseUrl := giteaBaseUrl(r.Config) + baseUrl := r.GiteaBaseUrl(r.Config) // need this to ensure gitrepository controller can reach the api endpoint. logger.V(1).Info("checking gitea api endpoint", "url", baseUrl) c := util.GetHttpClient() @@ -224,7 +215,7 @@ func getGiteaToken(ctx context.Context, baseUrl, username, password string) (str return token.Token, nil } -func giteaBaseUrl(config v1alpha1.BuildCustomizationSpec) string { +func (r *LocalbuildReconciler) GiteaBaseUrl(config v1alpha1.BuildCustomizationSpec) string { return fmt.Sprintf(giteaIngressURL, config.Protocol, config.Port) } From 86b26a2a1ad00dbf407b7afb700485b399152d2f Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 15:31:22 +0100 Subject: [PATCH 21/41] Change the logging level from info to debug Signed-off-by: cmoulliard --- pkg/controllers/localbuild/controller.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index 10f0df30..98b0111a 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -105,7 +105,7 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) } if r.Config.DevMode { - logger.Info("DevMode is enabled") + logger.V(1).Info("DevMode is enabled") // Check if the Argocd Initial admin secret exists argocdInitialAdminPassword, err := r.extractArgocdInitialAdminSecret(ctx) @@ -114,7 +114,7 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) return ctrl.Result{RequeueAfter: defaultRequeueTime}, nil } - logger.Info("Initial argocd admin secret found ...") + logger.V(1).Info("Initial argocd admin secret found ...") // Secret containing the initial argocd password exists // Lets try to update the password From 35fc902a2b82febf22e966175438375f963b3191 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 15:44:46 +0100 Subject: [PATCH 22/41] Rename devMode, dev-mode to staticPasswords and static-passwords. Fix issues with log format of the messages Signed-off-by: cmoulliard --- api/v1alpha1/localbuild_types.go | 14 +++++++------- pkg/build/build.go | 2 +- pkg/cmd/create/root.go | 18 +++++++++--------- pkg/cmd/get/secrets.go | 4 ++-- pkg/controllers/gitrepository/controller.go | 2 +- pkg/controllers/localbuild/controller.go | 9 ++++----- .../idpbuilder.cnoe.io_localbuilds.yaml | 4 ++-- 7 files changed, 26 insertions(+), 27 deletions(-) diff --git a/api/v1alpha1/localbuild_types.go b/api/v1alpha1/localbuild_types.go index 0cc114f9..cb27b30d 100644 --- a/api/v1alpha1/localbuild_types.go +++ b/api/v1alpha1/localbuild_types.go @@ -47,13 +47,13 @@ type PackageConfigsSpec struct { // BuildCustomizationSpec fields cannot change once a cluster is created type BuildCustomizationSpec struct { - Protocol string `json:"protocol,omitempty"` - Host string `json:"host,omitempty"` - IngressHost string `json:"ingressHost,omitempty"` - Port string `json:"port,omitempty"` - UsePathRouting bool `json:"usePathRouting,omitempty"` - SelfSignedCert string `json:"selfSignedCert,omitempty"` - DevMode bool `json:"devMode,omitempty"` + Protocol string `json:"protocol,omitempty"` + Host string `json:"host,omitempty"` + IngressHost string `json:"ingressHost,omitempty"` + Port string `json:"port,omitempty"` + UsePathRouting bool `json:"usePathRouting,omitempty"` + SelfSignedCert string `json:"selfSignedCert,omitempty"` + StaticPasswords bool `json:"staticPasswords,omitempty"` } type LocalbuildSpec struct { diff --git a/pkg/build/build.go b/pkg/build/build.go index f30a82db..2a49f8dd 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -280,5 +280,5 @@ func isBuildCustomizationSpecEqual(s1, s2 v1alpha1.BuildCustomizationSpec) bool s1.Port == s2.Port && s1.UsePathRouting == s2.UsePathRouting && s1.SelfSignedCert == s2.SelfSignedCert && - s1.DevMode == s2.DevMode + s1.StaticPasswords == s2.StaticPasswords } diff --git a/pkg/cmd/create/root.go b/pkg/cmd/create/root.go index abad45c8..05f0d806 100644 --- a/pkg/cmd/create/root.go +++ b/pkg/cmd/create/root.go @@ -20,7 +20,7 @@ import ( const ( recreateClusterUsage = "Delete cluster first if it already exists." buildNameUsage = "Name for build (Prefix for kind cluster name, pod names, etc)." - devModeUsage = "When enabled, the platform will run the core packages with developer password." + staticPasswordsUsage = "Set a static password: developer to the applications: argocd and gitea." kubeVersionUsage = "Version of the kind kubernetes cluster to create." extraPortsMappingUsage = "List of extra ports to expose on the docker container and kubernetes cluster as nodePort " + "(e.g. \"22:32222,9090:39090,etc\")." @@ -41,7 +41,7 @@ var ( // Flags recreateCluster bool buildName string - devMode bool + staticPasswords bool kubeVersion string extraPortsMapping string kindConfigPath string @@ -69,7 +69,7 @@ func init() { CreateCmd.PersistentFlags().StringVar(&buildName, "build-name", "localdev", buildNameUsage) CreateCmd.PersistentFlags().MarkDeprecated("build-name", "use --name instead.") CreateCmd.PersistentFlags().StringVar(&buildName, "name", "localdev", buildNameUsage) - CreateCmd.PersistentFlags().BoolVar(&devMode, "dev-mode", false, devModeUsage) + CreateCmd.PersistentFlags().BoolVar(&staticPasswords, "static-passwords", false, staticPasswordsUsage) CreateCmd.PersistentFlags().StringVar(&kubeVersion, "kube-version", "v1.30.3", kubeVersionUsage) CreateCmd.PersistentFlags().StringVar(&extraPortsMapping, "extra-ports", "", extraPortsMappingUsage) CreateCmd.PersistentFlags().StringVar(&kindConfigPath, "kind-config", "", kindConfigPathUsage) @@ -141,12 +141,12 @@ func create(cmd *cobra.Command, args []string) error { ExtraPortsMapping: extraPortsMapping, TemplateData: v1alpha1.BuildCustomizationSpec{ - Protocol: protocol, - Host: host, - IngressHost: ingressHost, - Port: port, - UsePathRouting: pathRouting, - DevMode: devMode, + Protocol: protocol, + Host: host, + IngressHost: ingressHost, + Port: port, + UsePathRouting: pathRouting, + StaticPasswords: staticPasswords, }, CustomPackageDirs: absDirPaths, diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index 01ad2757..8a646d57 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -210,12 +210,12 @@ func secretToTemplateData(s v1.Secret) TemplateData { // TODO: The following code should be reviewed and improved as the secret containing the developer username/password is argocd-secret // where the password has been bcrypted and by consequence we cannot get and decode it from the secret - // This is why we are going to add it here BUT it will be displayed every time no matter if --dev-mode has been used or not + // This is why we are going to add it here BUT it will be displayed every time no matter if --static-passwords has been used or not if strings.Contains(s.Name, "gitea") { data.Data["username-developer"] = "giteAdmin" data.Data["password-developer"] = "developer" } else if strings.Contains(s.Name, "argocd") { - data.Data["username-developer"] = "developer" + data.Data["username-developer"] = "admin" data.Data["password-developer"] = "developer" } diff --git a/pkg/controllers/gitrepository/controller.go b/pkg/controllers/gitrepository/controller.go index f9a08ff2..829ec657 100644 --- a/pkg/controllers/gitrepository/controller.go +++ b/pkg/controllers/gitrepository/controller.go @@ -143,7 +143,7 @@ func (r *RepositoryReconciler) reconcileGitRepo(ctx context.Context, repo *v1alp return ctrl.Result{}, fmt.Errorf("getting git provider credentials: %w", err) } - if r.Config.DevMode { + if r.Config.StaticPasswords { creds.password = "developer" } diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index 98b0111a..8c3b1ca8 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -104,8 +104,8 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) } } - if r.Config.DevMode { - logger.V(1).Info("DevMode is enabled") + if r.Config.StaticPasswords { + logger.V(1).Info("StaticPasswords is enabled") // Check if the Argocd Initial admin secret exists argocdInitialAdminPassword, err := r.extractArgocdInitialAdminSecret(ctx) @@ -683,7 +683,7 @@ func (r *LocalbuildReconciler) updateGiteaDevPassword(ctx context.Context, admin resp, err := client.AdminEditUser("giteaAdmin", opts) if err != nil { - return fmt.Errorf("cannot update gitea admin user: %w", resp.StatusCode, err), "failed" + return fmt.Errorf("cannot update gitea admin user. status: %d error : %w", resp.StatusCode, err), "failed" } return nil, "succeeded" } @@ -731,7 +731,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi err := json.Unmarshal([]byte(body), &argocdSession) if err != nil { - fmt.Errorf("Error unmarshalling JSON: %v", err) + return fmt.Errorf("Error unmarshalling JSON: %v", err), "failed" } payload := map[string]string{ @@ -794,7 +794,6 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi } else { return fmt.Errorf("HTTP Error: %d", resp.StatusCode), "failed" } - return nil, "failed" } func (r *LocalbuildReconciler) applyArgoCDAnnotation(ctx context.Context, obj client.Object, argoCDType, annotationKey, annotationValue string) error { diff --git a/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml b/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml index ba9e7ab1..98c37c03 100644 --- a/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml +++ b/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml @@ -41,8 +41,6 @@ spec: description: BuildCustomizationSpec fields cannot change once a cluster is created properties: - devMode: - type: boolean host: type: string ingressHost: @@ -53,6 +51,8 @@ spec: type: string selfSignedCert: type: string + staticPasswords: + type: boolean usePathRouting: type: boolean type: object From e4c78de25a942def9e094c0b8a4d7911f4c075a8 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 15:46:20 +0100 Subject: [PATCH 23/41] Remove else block not needed when we verify if the password changed Signed-off-by: cmoulliard --- pkg/controllers/localbuild/controller.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index 8c3b1ca8..a4eaaee3 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -787,8 +787,6 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi if resp.StatusCode == 200 { // Password verification succeeded ! return nil, "succeeded" - } else { - return fmt.Errorf("### New password verification failed: %s", body), "failed" } } else { From 700a84181a9e663928ebea400129d5718b30b28a Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 15:51:44 +0100 Subject: [PATCH 24/41] Improve the code and remove the non needed return statement Signed-off-by: cmoulliard --- pkg/controllers/localbuild/controller.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index a4eaaee3..d2dd0cf0 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -726,6 +726,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi return fmt.Errorf("Error reading response body: %v\n", err), "failed" } + // We got a session Token, so we can update the Argocd admin password if resp.StatusCode == 200 { var argocdSession ArgocdSession @@ -765,18 +766,13 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi return fmt.Errorf("Error creating JSON payload: %v\n", err), "failed" } + // Define the request able to verify if the username and password changed works req, err = http.NewRequest("POST", argocdEndpoint+"/session", bytes.NewBuffer(payloadBytes)) if err != nil { return fmt.Errorf("Error creating HTTP request: %v\n", err), "failed" } req.Header.Set("Content-Type", "application/json") - // Create an HTTP client and disable TLS verification - client := &http.Client{} - transport := http.DefaultTransport.(*http.Transport).Clone() - transport.TLSClientConfig.InsecureSkipVerify = true - client.Transport = transport - // Send the request resp, err = client.Do(req) if err != nil { @@ -788,10 +784,9 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi // Password verification succeeded ! return nil, "succeeded" } - - } else { - return fmt.Errorf("HTTP Error: %d", resp.StatusCode), "failed" } + // No session token has been received and by consequence the admin password has not been changed + return nil, "failed" } func (r *LocalbuildReconciler) applyArgoCDAnnotation(ctx context.Context, obj client.Object, argoCDType, annotationKey, annotationValue string) error { From 5830b22420ac55e85ee633f504038fdbcbf05105 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 15:59:30 +0100 Subject: [PATCH 25/41] Improve code and variables Signed-off-by: cmoulliard --- pkg/controllers/localbuild/controller.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index d2dd0cf0..c4989093 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -707,14 +707,14 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi } req.Header.Set("Content-Type", "application/json") - // Create an HTTP client and disable TLS verification - client := &http.Client{} + // Create an HTTP httpClient and disable TLS verification + httpClient := &http.Client{} transport := http.DefaultTransport.(*http.Transport).Clone() transport.TLSClientConfig.InsecureSkipVerify = true - client.Transport = transport + httpClient.Transport = transport // Send the request - resp, err := client.Do(req) + resp, err := httpClient.Do(req) if err != nil { return fmt.Errorf("Error sending request: %v\n", err), "failed" } @@ -747,10 +747,12 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi } req, err := http.NewRequest("PUT", argocdEndpoint+"/account/password", bytes.NewBuffer(payloadBytes)) - req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", argocdSession.Token)) - req.Header.Set("Content-Type", "application/json") + if req != nil { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", argocdSession.Token)) + req.Header.Set("Content-Type", "application/json") + } - resp, err := client.Do(req) + resp, err := httpClient.Do(req) if err != nil { return fmt.Errorf("Error sending request: %v\n", err), "failed" } @@ -774,7 +776,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi req.Header.Set("Content-Type", "application/json") // Send the request - resp, err = client.Do(req) + resp, err = httpClient.Do(req) if err != nil { return fmt.Errorf("Error sending request: %v\n", err), "failed" } From d1ed81a1fedb651ff38426827d39a988cb17b7fd Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 16:04:27 +0100 Subject: [PATCH 26/41] Remove non used functions Signed-off-by: cmoulliard --- pkg/k8s/util.go | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/pkg/k8s/util.go b/pkg/k8s/util.go index 9c3ec13c..68b5366d 100644 --- a/pkg/k8s/util.go +++ b/pkg/k8s/util.go @@ -2,14 +2,9 @@ package k8s import ( "embed" - "fmt" "github.com/cnoe-io/idpbuilder/pkg/util" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" - "k8s.io/client-go/util/homedir" "os" - "path/filepath" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -62,30 +57,3 @@ 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 { - return nil, fmt.Errorf("Error building kubeconfig from kind cluster: %w", err) - } - return kubeConfig, nil -} - -func GetKubeClient(kubeConfigPath ...string) (client.Client, error) { - kubeCfg, err := GetKubeConfig(kubeConfigPath...) - if err != nil { - return nil, fmt.Errorf("Error getting kubeconfig: %w", err) - } - kubeClient, err := client.New(kubeCfg, client.Options{Scheme: GetScheme()}) - if err != nil { - return nil, fmt.Errorf("Error creating kubernetes client: %w", err) - } - return kubeClient, nil -} From f0754f75ca719243f1023c0050b53c8340a26d6a Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 16:14:04 +0100 Subject: [PATCH 27/41] Created a new util package for gitea and moved there: const and function(s) Signed-off-by: cmoulliard --- pkg/controllers/localbuild/controller.go | 2 +- pkg/controllers/localbuild/gitea.go | 57 ++++++------------------ pkg/util/gitea.go | 32 +++++++++++++ 3 files changed, 47 insertions(+), 44 deletions(-) create mode 100644 pkg/util/gitea.go diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index c4989093..bcc691e1 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -654,7 +654,7 @@ func (r *LocalbuildReconciler) extractArgocdInitialAdminSecret(ctx context.Conte } func (r *LocalbuildReconciler) extractGiteaAdminSecret(ctx context.Context) (string, error) { - sec := r.GiteaAdminSecretObject() + sec := util.GiteaAdminSecretObject() err := r.Client.Get(ctx, types.NamespacedName{ Namespace: sec.GetNamespace(), Name: sec.GetName(), diff --git a/pkg/controllers/localbuild/gitea.go b/pkg/controllers/localbuild/gitea.go index 292d5ec3..c290f99f 100644 --- a/pkg/controllers/localbuild/gitea.go +++ b/pkg/controllers/localbuild/gitea.go @@ -13,7 +13,6 @@ import ( "github.com/cnoe-io/idpbuilder/pkg/util" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -23,21 +22,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" ) -const ( - giteaDevModePassword = "developer" - - // hardcoded values from what we have in the yaml installation file. - giteaNamespace = "gitea" - giteaAdminSecret = "gitea-credential" - giteaAdminTokenName = "admin" - giteaAdminTokenFieldName = "token" - // this is the URL accessible outside cluster. resolves to localhost - giteaIngressURL = "%s://gitea.cnoe.localtest.me:%s" - // this is the URL accessible within cluster for ArgoCD to fetch resources. - // resolves to cluster ip - giteaSvcURL = "%s://%s%s:%s%s" -) - //go:embed resources/gitea/k8s/* var installGiteaFS embed.FS @@ -45,21 +29,8 @@ func RawGiteaInstallResources(templateData any, config v1alpha1.PackageCustomiza return k8s.BuildCustomizedManifests(config.FilePath, "resources/gitea/k8s", installGiteaFS, scheme, templateData) } -func (r *LocalbuildReconciler) GiteaAdminSecretObject() corev1.Secret { - return corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: giteaAdminSecret, - Namespace: giteaNamespace, - }, - } -} - func (r *LocalbuildReconciler) newGiteaAdminSecret(password string) corev1.Secret { - obj := r.GiteaAdminSecretObject() + obj := util.GiteaAdminSecretObject() obj.StringData = map[string]string{ "username": v1alpha1.GiteaAdminUserName, "password": password, @@ -73,7 +44,7 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ name: "Gitea", resourcePath: "resources/gitea/k8s", resourceFS: installGiteaFS, - namespace: giteaNamespace, + namespace: util.GiteaNamespace, monitoredResources: map[string]schema.GroupVersionKind{ "my-gitea": { Group: "apps", @@ -83,7 +54,7 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ }, } - sec := r.GiteaAdminSecretObject() + sec := util.GiteaAdminSecretObject() err := r.Client.Get(ctx, types.NamespacedName{ Namespace: sec.GetNamespace(), Name: sec.GetName(), @@ -139,21 +110,21 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ resource.Status.Gitea.ExternalURL = baseUrl resource.Status.Gitea.InternalURL = giteaInternalBaseUrl(r.Config) - resource.Status.Gitea.AdminUserSecretName = giteaAdminSecret - resource.Status.Gitea.AdminUserSecretNamespace = giteaNamespace + resource.Status.Gitea.AdminUserSecretName = util.GiteaAdminSecret + resource.Status.Gitea.AdminUserSecretNamespace = util.GiteaNamespace resource.Status.Gitea.Available = true return ctrl.Result{}, nil } func (r *LocalbuildReconciler) setGiteaToken(ctx context.Context, secret corev1.Secret, baseUrl string) error { - _, ok := secret.Data[giteaAdminTokenFieldName] + _, ok := secret.Data[util.GiteaAdminTokenFieldName] if ok { return nil } u := unstructured.Unstructured{} - u.SetName(giteaAdminSecret) - u.SetNamespace(giteaNamespace) + u.SetName(util.GiteaAdminSecret) + u.SetNamespace(util.GiteaNamespace) u.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Secret")) user, ok := secret.Data["username"] @@ -172,7 +143,7 @@ func (r *LocalbuildReconciler) setGiteaToken(ctx context.Context, secret corev1. } token := base64.StdEncoding.EncodeToString([]byte(t)) - err = unstructured.SetNestedField(u.Object, token, "data", giteaAdminTokenFieldName) + err = unstructured.SetNestedField(u.Object, token, "data", util.GiteaAdminTokenFieldName) if err != nil { return fmt.Errorf("setting gitea token field: %w", err) } @@ -193,7 +164,7 @@ func getGiteaToken(ctx context.Context, baseUrl, username, password string) (str } for i := range tokens { - if tokens[i].Name == giteaAdminTokenName { + if tokens[i].Name == util.GiteaAdminTokenName { resp, err := giteaClient.DeleteAccessToken(tokens[i].ID) if err != nil { return "", fmt.Errorf("deleting gitea access tokens. status: %s error : %w", resp.Status, err) @@ -203,7 +174,7 @@ func getGiteaToken(ctx context.Context, baseUrl, username, password string) (str } token, resp, err := giteaClient.CreateAccessToken(gitea.CreateAccessTokenOption{ - Name: giteaAdminTokenName, + Name: util.GiteaAdminTokenName, Scopes: []gitea.AccessTokenScope{ gitea.AccessTokenScopeAll, }, @@ -216,13 +187,13 @@ func getGiteaToken(ctx context.Context, baseUrl, username, password string) (str } func (r *LocalbuildReconciler) GiteaBaseUrl(config v1alpha1.BuildCustomizationSpec) string { - return fmt.Sprintf(giteaIngressURL, config.Protocol, config.Port) + return fmt.Sprintf(util.GiteaIngressURL, config.Protocol, config.Port) } // gitea URL reachable within the cluster with proper coredns config. Mainly for argocd func giteaInternalBaseUrl(config v1alpha1.BuildCustomizationSpec) string { if config.UsePathRouting { - return fmt.Sprintf(giteaSvcURL, config.Protocol, "", config.Host, config.Port, "/gitea") + return fmt.Sprintf(util.GiteaSvcURL, config.Protocol, "", config.Host, config.Port, "/gitea") } - return fmt.Sprintf(giteaSvcURL, config.Protocol, "gitea.", config.Host, config.Port, "") + return fmt.Sprintf(util.GiteaSvcURL, config.Protocol, "gitea.", config.Host, config.Port, "") } diff --git a/pkg/util/gitea.go b/pkg/util/gitea.go new file mode 100644 index 00000000..03da4afd --- /dev/null +++ b/pkg/util/gitea.go @@ -0,0 +1,32 @@ +package util + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + // hardcoded values from what we have in the yaml installation file. + GiteaNamespace = "gitea" + GiteaAdminSecret = "gitea-credential" + GiteaAdminTokenName = "admin" + GiteaAdminTokenFieldName = "token" + // this is the URL accessible outside cluster. resolves to localhost + GiteaIngressURL = "%s://gitea.cnoe.localtest.me:%s" + // this is the URL accessible within cluster for ArgoCD to fetch resources. + // resolves to cluster ip + GiteaSvcURL = "%s://%s%s:%s%s" +) + +func GiteaAdminSecretObject() corev1.Secret { + return corev1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "Secret", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: GiteaAdminSecret, + Namespace: GiteaNamespace, + }, + } +} From 3ab4fd309d0ee400be2a1e194d51364ad7172547 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 16:25:07 +0100 Subject: [PATCH 28/41] Move GiteaBaseUrl to the util package of gitea Signed-off-by: cmoulliard --- pkg/controllers/localbuild/gitea.go | 6 +----- pkg/util/gitea.go | 6 ++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pkg/controllers/localbuild/gitea.go b/pkg/controllers/localbuild/gitea.go index c290f99f..c7b28ab8 100644 --- a/pkg/controllers/localbuild/gitea.go +++ b/pkg/controllers/localbuild/gitea.go @@ -87,7 +87,7 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ return result, err } - baseUrl := r.GiteaBaseUrl(r.Config) + baseUrl := util.GiteaBaseUrl(r.Config) // need this to ensure gitrepository controller can reach the api endpoint. logger.V(1).Info("checking gitea api endpoint", "url", baseUrl) c := util.GetHttpClient() @@ -186,10 +186,6 @@ func getGiteaToken(ctx context.Context, baseUrl, username, password string) (str return token.Token, nil } -func (r *LocalbuildReconciler) GiteaBaseUrl(config v1alpha1.BuildCustomizationSpec) string { - return fmt.Sprintf(util.GiteaIngressURL, config.Protocol, config.Port) -} - // gitea URL reachable within the cluster with proper coredns config. Mainly for argocd func giteaInternalBaseUrl(config v1alpha1.BuildCustomizationSpec) string { if config.UsePathRouting { diff --git a/pkg/util/gitea.go b/pkg/util/gitea.go index 03da4afd..9a82d30a 100644 --- a/pkg/util/gitea.go +++ b/pkg/util/gitea.go @@ -1,6 +1,8 @@ package util import ( + "fmt" + "github.com/cnoe-io/idpbuilder/api/v1alpha1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -30,3 +32,7 @@ func GiteaAdminSecretObject() corev1.Secret { }, } } + +func GiteaBaseUrl(config v1alpha1.BuildCustomizationSpec) string { + return fmt.Sprintf(GiteaIngressURL, config.Protocol, config.Port) +} From c8ac946790832e4832e542e42b1716c73da1876b Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 16:30:42 +0100 Subject: [PATCH 29/41] Fix error r.r.GiteaBaseUrl => util.r.GiteaBaseUrl Signed-off-by: cmoulliard --- pkg/controllers/localbuild/controller.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index bcc691e1..e6d9c8bb 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -669,7 +669,7 @@ func (r *LocalbuildReconciler) extractGiteaAdminSecret(ctx context.Context) (str } func (r *LocalbuildReconciler) updateGiteaDevPassword(ctx context.Context, adminPassword string) (error, string) { - client, err := gitea.NewClient(r.GiteaBaseUrl(r.Config), gitea.SetHTTPClient(util.GetHttpClient()), + client, err := gitea.NewClient(util.GiteaBaseUrl(r.Config), gitea.SetHTTPClient(util.GetHttpClient()), gitea.SetBasicAuth("giteaAdmin", adminPassword), gitea.SetContext(ctx), ) if err != nil { From e02a5d21660a4e3d5c6772233026ee05dddfa790 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 18:17:59 +0100 Subject: [PATCH 30/41] Refactor the code to also patch the secret's password of gitea and argocd Signed-off-by: cmoulliard --- pkg/cmd/get/secrets.go | 20 ++------------- pkg/controllers/localbuild/argo.go | 17 +++---------- pkg/controllers/localbuild/controller.go | 31 +++++++++++++++--------- pkg/util/argocd.go | 17 +++++++++++++ pkg/util/gitea.go | 22 +++++++++++++++++ pkg/util/secret.go | 12 +++++++++ 6 files changed, 75 insertions(+), 44 deletions(-) create mode 100644 pkg/util/argocd.go create mode 100644 pkg/util/secret.go diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index 8a646d57..6cec892b 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -5,10 +5,10 @@ import ( "embed" "encoding/json" "fmt" + "github.com/cnoe-io/idpbuilder/pkg/util" "io" "os" "path/filepath" - "strings" "text/template" "github.com/cnoe-io/idpbuilder/api/v1alpha1" @@ -208,17 +208,6 @@ func secretToTemplateData(s v1.Secret) TemplateData { data.Data[k] = string(v) } - // TODO: The following code should be reviewed and improved as the secret containing the developer username/password is argocd-secret - // where the password has been bcrypted and by consequence we cannot get and decode it from the secret - // This is why we are going to add it here BUT it will be displayed every time no matter if --static-passwords has been used or not - if strings.Contains(s.Name, "gitea") { - data.Data["username-developer"] = "giteAdmin" - data.Data["password-developer"] = "developer" - } else if strings.Contains(s.Name, "argocd") { - data.Data["username-developer"] = "admin" - data.Data["password-developer"] = "developer" - } - return data } @@ -236,13 +225,8 @@ func getSecretsByCNOELabel(ctx context.Context, kubeClient client.Client, l labe return secrets, kubeClient.List(ctx, &secrets, &opts) } -func getSecretByName(ctx context.Context, kubeClient client.Client, ns, name string) (v1.Secret, error) { - s := v1.Secret{} - return s, kubeClient.Get(ctx, client.ObjectKey{Name: name, Namespace: ns}, &s) -} - func getCorePackageSecret(ctx context.Context, kubeClient client.Client, ns, name string) (v1.Secret, error) { - s, err := getSecretByName(ctx, kubeClient, ns, name) + s, err := util.GetSecretByName(ctx, kubeClient, ns, name) if err != nil { return v1.Secret{}, err } diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index b4347981..87c20b36 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -3,10 +3,10 @@ package localbuild import ( "context" "embed" - "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/globals" "github.com/cnoe-io/idpbuilder/pkg/k8s" + "github.com/cnoe-io/idpbuilder/pkg/util" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -17,13 +17,6 @@ import ( //go:embed resources/argo/* var installArgoFS embed.FS -const ( - argocdDevModePassword = "developer" - argocdInitialAdminSecretName = "argocd-initial-admin-secret" - argocdNamespace = "argocd" - argocdIngressURL = "%s://argocd.cnoe.localtest.me:%s" -) - func RawArgocdInstallResources(templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) { return k8s.BuildCustomizedManifests(config.FilePath, "resources/argo", installArgoFS, scheme, templateData) } @@ -74,12 +67,8 @@ func (r *LocalbuildReconciler) ArgocdInitialAdminSecretObject() corev1.Secret { APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ - Name: argocdInitialAdminSecretName, - Namespace: argocdNamespace, + Name: util.ArgocdInitialAdminSecretName, + Namespace: util.ArgocdNamespace, }, } } - -func (r *LocalbuildReconciler) ArgocdBaseUrl(config v1alpha1.BuildCustomizationSpec) string { - return fmt.Sprintf(argocdIngressURL, config.Protocol, config.Port) -} diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index e6d9c8bb..4a26738f 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -685,11 +685,16 @@ func (r *LocalbuildReconciler) updateGiteaDevPassword(ctx context.Context, admin if err != nil { return fmt.Errorf("cannot update gitea admin user. status: %d error : %w", resp.StatusCode, err), "failed" } + + err = util.PatchPasswordSecret(ctx, r.Client, util.GiteaNamespace, util.GiteaAdminSecret, "developer") + if err != nil { + return fmt.Errorf("patching the gitea credentials failed : %w", err), "failed" + } return nil, "succeeded" } func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, adminPassword string) (error, string) { - argocdEndpoint := r.ArgocdBaseUrl(r.Config) + "/api/v1" + argocdEndpoint := util.ArgocdBaseUrl(r.Config) + "/api/v1" payload := map[string]string{ "username": "admin", @@ -707,14 +712,11 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi } req.Header.Set("Content-Type", "application/json") - // Create an HTTP httpClient and disable TLS verification - httpClient := &http.Client{} - transport := http.DefaultTransport.(*http.Transport).Clone() - transport.TLSClientConfig.InsecureSkipVerify = true - httpClient.Transport = transport + // Create an HTTP c and disable TLS verification + c := util.GetHttpClient() // Send the request - resp, err := httpClient.Do(req) + resp, err := c.Do(req) if err != nil { return fmt.Errorf("Error sending request: %v\n", err), "failed" } @@ -738,7 +740,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi payload := map[string]string{ "name": "admin", "currentPassword": adminPassword, - "newPassword": argocdDevModePassword, + "newPassword": util.ArgocdDevModePassword, } payloadBytes, err := json.Marshal(payload) @@ -752,7 +754,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi req.Header.Set("Content-Type", "application/json") } - resp, err := httpClient.Do(req) + resp, err := c.Do(req) if err != nil { return fmt.Errorf("Error sending request: %v\n", err), "failed" } @@ -761,7 +763,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi // Lets checking the new admin password payload = map[string]string{ "username": "admin", - "password": argocdDevModePassword, + "password": util.ArgocdDevModePassword, } payloadBytes, err = json.Marshal(payload) if err != nil { @@ -776,14 +778,19 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi req.Header.Set("Content-Type", "application/json") // Send the request - resp, err = httpClient.Do(req) + resp, err = c.Do(req) if err != nil { return fmt.Errorf("Error sending request: %v\n", err), "failed" } defer resp.Body.Close() + // Password verification succeeded ! if resp.StatusCode == 200 { - // Password verification succeeded ! + // Let's patch the existing secret now + err = util.PatchPasswordSecret(ctx, r.Client, util.ArgocdNamespace, util.ArgocdInitialAdminSecretName, "developer") + if err != nil { + return fmt.Errorf("patching the argocd initial secret failed : %w", err), "failed" + } return nil, "succeeded" } } diff --git a/pkg/util/argocd.go b/pkg/util/argocd.go new file mode 100644 index 00000000..6f5952cb --- /dev/null +++ b/pkg/util/argocd.go @@ -0,0 +1,17 @@ +package util + +import ( + "fmt" + "github.com/cnoe-io/idpbuilder/api/v1alpha1" +) + +const ( + ArgocdDevModePassword = "developer" + ArgocdInitialAdminSecretName = "argocd-initial-admin-secret" + ArgocdNamespace = "argocd" + ArgocdIngressURL = "%s://argocd.cnoe.localtest.me:%s" +) + +func ArgocdBaseUrl(config v1alpha1.BuildCustomizationSpec) string { + return fmt.Sprintf(ArgocdIngressURL, config.Protocol, config.Port) +} diff --git a/pkg/util/gitea.go b/pkg/util/gitea.go index 9a82d30a..7fad3d7d 100644 --- a/pkg/util/gitea.go +++ b/pkg/util/gitea.go @@ -1,10 +1,14 @@ package util import ( + "context" + "encoding/base64" "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "sigs.k8s.io/controller-runtime/pkg/client" ) const ( @@ -33,6 +37,24 @@ func GiteaAdminSecretObject() corev1.Secret { } } +func PatchPasswordSecret(ctx context.Context, kubeClient client.Client, ns string, secretName string, pass string) error { + sec, err := GetSecretByName(ctx, kubeClient, ns, secretName) + if err != nil { + return fmt.Errorf("getting secret to patch fails: %w", err) + } + u := unstructured.Unstructured{} + u.SetName(sec.GetName()) + u.SetNamespace(sec.GetNamespace()) + u.SetGroupVersionKind(sec.GetObjectKind().GroupVersionKind()) + + err = unstructured.SetNestedField(u.Object, base64.StdEncoding.EncodeToString([]byte(pass)), "data", "password") + if err != nil { + return fmt.Errorf("setting password field: %w", err) + } + + return kubeClient.Patch(ctx, &u, client.Apply, client.ForceOwnership, client.FieldOwner(v1alpha1.FieldManager)) +} + func GiteaBaseUrl(config v1alpha1.BuildCustomizationSpec) string { return fmt.Sprintf(GiteaIngressURL, config.Protocol, config.Port) } diff --git a/pkg/util/secret.go b/pkg/util/secret.go new file mode 100644 index 00000000..207d0b09 --- /dev/null +++ b/pkg/util/secret.go @@ -0,0 +1,12 @@ +package util + +import ( + "context" + v1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func GetSecretByName(ctx context.Context, kubeClient client.Client, ns, name string) (v1.Secret, error) { + s := v1.Secret{} + return s, kubeClient.Get(ctx, client.ObjectKey{Name: name, Namespace: ns}, &s) +} From f67a91c0423316ed668b1915e1e201d2f4cad516 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 18:46:53 +0100 Subject: [PATCH 31/41] Regenerate the token for gitea Signed-off-by: cmoulliard --- pkg/controllers/localbuild/controller.go | 4 +- pkg/controllers/localbuild/gitea.go | 38 +---------------- pkg/util/argocd.go | 1 + pkg/util/gitea.go | 54 +++++++++++++++++++++++- 4 files changed, 57 insertions(+), 40 deletions(-) diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index 4a26738f..6c1c5994 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -686,7 +686,7 @@ func (r *LocalbuildReconciler) updateGiteaDevPassword(ctx context.Context, admin return fmt.Errorf("cannot update gitea admin user. status: %d error : %w", resp.StatusCode, err), "failed" } - err = util.PatchPasswordSecret(ctx, r.Client, util.GiteaNamespace, util.GiteaAdminSecret, "developer") + err = util.PatchPasswordSecret(ctx, r.Client, r.Config, util.GiteaNamespace, util.GiteaAdminSecret, util.GiteaAdminName, "developer") if err != nil { return fmt.Errorf("patching the gitea credentials failed : %w", err), "failed" } @@ -787,7 +787,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi // Password verification succeeded ! if resp.StatusCode == 200 { // Let's patch the existing secret now - err = util.PatchPasswordSecret(ctx, r.Client, util.ArgocdNamespace, util.ArgocdInitialAdminSecretName, "developer") + err = util.PatchPasswordSecret(ctx, r.Client, r.Config, util.ArgocdNamespace, util.ArgocdInitialAdminSecretName, util.ArgocdAdminName, "developer") if err != nil { return fmt.Errorf("patching the argocd initial secret failed : %w", err), "failed" } diff --git a/pkg/controllers/localbuild/gitea.go b/pkg/controllers/localbuild/gitea.go index c7b28ab8..83c75f30 100644 --- a/pkg/controllers/localbuild/gitea.go +++ b/pkg/controllers/localbuild/gitea.go @@ -7,7 +7,6 @@ import ( "fmt" "net/http" - "code.gitea.io/sdk/gitea" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/k8s" "github.com/cnoe-io/idpbuilder/pkg/util" @@ -137,7 +136,7 @@ func (r *LocalbuildReconciler) setGiteaToken(ctx context.Context, secret corev1. return fmt.Errorf("password field not found in gitea secret") } - t, err := getGiteaToken(ctx, baseUrl, string(user), string(pass)) + t, err := util.GetGiteaToken(ctx, baseUrl, string(user), string(pass)) if err != nil { return fmt.Errorf("getting gitea token: %w", err) } @@ -151,41 +150,6 @@ func (r *LocalbuildReconciler) setGiteaToken(ctx context.Context, secret corev1. return r.Client.Patch(ctx, &u, client.Apply, client.ForceOwnership, client.FieldOwner(v1alpha1.FieldManager)) } -func getGiteaToken(ctx context.Context, baseUrl, username, password string) (string, error) { - giteaClient, err := gitea.NewClient(baseUrl, gitea.SetHTTPClient(util.GetHttpClient()), - gitea.SetBasicAuth(username, password), gitea.SetContext(ctx), - ) - if err != nil { - return "", fmt.Errorf("creating gitea client: %w", err) - } - tokens, resp, err := giteaClient.ListAccessTokens(gitea.ListAccessTokensOptions{}) - if err != nil { - return "", fmt.Errorf("listing gitea access tokens. status: %s error : %w", resp.Status, err) - } - - for i := range tokens { - if tokens[i].Name == util.GiteaAdminTokenName { - resp, err := giteaClient.DeleteAccessToken(tokens[i].ID) - if err != nil { - return "", fmt.Errorf("deleting gitea access tokens. status: %s error : %w", resp.Status, err) - } - break - } - } - - token, resp, err := giteaClient.CreateAccessToken(gitea.CreateAccessTokenOption{ - Name: util.GiteaAdminTokenName, - Scopes: []gitea.AccessTokenScope{ - gitea.AccessTokenScopeAll, - }, - }) - if err != nil { - return "", fmt.Errorf("deleting gitea access tokens. status: %s error : %w", resp.Status, err) - } - - return token.Token, nil -} - // gitea URL reachable within the cluster with proper coredns config. Mainly for argocd func giteaInternalBaseUrl(config v1alpha1.BuildCustomizationSpec) string { if config.UsePathRouting { diff --git a/pkg/util/argocd.go b/pkg/util/argocd.go index 6f5952cb..1ef8a13e 100644 --- a/pkg/util/argocd.go +++ b/pkg/util/argocd.go @@ -8,6 +8,7 @@ import ( const ( ArgocdDevModePassword = "developer" ArgocdInitialAdminSecretName = "argocd-initial-admin-secret" + ArgocdAdminName = "admin" ArgocdNamespace = "argocd" ArgocdIngressURL = "%s://argocd.cnoe.localtest.me:%s" ) diff --git a/pkg/util/gitea.go b/pkg/util/gitea.go index 7fad3d7d..43dda037 100644 --- a/pkg/util/gitea.go +++ b/pkg/util/gitea.go @@ -1,6 +1,7 @@ package util import ( + "code.gitea.io/sdk/gitea" "context" "encoding/base64" "fmt" @@ -9,12 +10,14 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" + "strings" ) const ( // hardcoded values from what we have in the yaml installation file. GiteaNamespace = "gitea" GiteaAdminSecret = "gitea-credential" + GiteaAdminName = "giteaAdmin" GiteaAdminTokenName = "admin" GiteaAdminTokenFieldName = "token" // this is the URL accessible outside cluster. resolves to localhost @@ -37,7 +40,7 @@ func GiteaAdminSecretObject() corev1.Secret { } } -func PatchPasswordSecret(ctx context.Context, kubeClient client.Client, ns string, secretName string, pass string) error { +func PatchPasswordSecret(ctx context.Context, kubeClient client.Client, config v1alpha1.BuildCustomizationSpec, ns string, secretName string, username string, pass string) error { sec, err := GetSecretByName(ctx, kubeClient, ns, secretName) if err != nil { return fmt.Errorf("getting secret to patch fails: %w", err) @@ -52,9 +55,58 @@ func PatchPasswordSecret(ctx context.Context, kubeClient client.Client, ns strin return fmt.Errorf("setting password field: %w", err) } + if strings.Contains(secretName, "gitea") { + // We should recreate a token as user/password changed + t, err := GetGiteaToken(ctx, GiteaBaseUrl(config), string(username), string(pass)) + if err != nil { + return fmt.Errorf("getting gitea token: %w", err) + } + + token := base64.StdEncoding.EncodeToString([]byte(t)) + err = unstructured.SetNestedField(u.Object, token, "data", GiteaAdminTokenFieldName) + if err != nil { + return fmt.Errorf("setting gitea token field: %w", err) + } + } + return kubeClient.Patch(ctx, &u, client.Apply, client.ForceOwnership, client.FieldOwner(v1alpha1.FieldManager)) } +func GetGiteaToken(ctx context.Context, baseUrl, username, password string) (string, error) { + giteaClient, err := gitea.NewClient(baseUrl, gitea.SetHTTPClient(GetHttpClient()), + gitea.SetBasicAuth(username, password), gitea.SetContext(ctx), + ) + if err != nil { + return "", fmt.Errorf("creating gitea client: %w", err) + } + tokens, resp, err := giteaClient.ListAccessTokens(gitea.ListAccessTokensOptions{}) + if err != nil { + return "", fmt.Errorf("listing gitea access tokens. status: %s error : %w", resp.Status, err) + } + + for i := range tokens { + if tokens[i].Name == GiteaAdminTokenName { + resp, err := giteaClient.DeleteAccessToken(tokens[i].ID) + if err != nil { + return "", fmt.Errorf("deleting gitea access tokens. status: %s error : %w", resp.Status, err) + } + break + } + } + + token, resp, err := giteaClient.CreateAccessToken(gitea.CreateAccessTokenOption{ + Name: GiteaAdminTokenName, + Scopes: []gitea.AccessTokenScope{ + gitea.AccessTokenScopeAll, + }, + }) + if err != nil { + return "", fmt.Errorf("deleting gitea access tokens. status: %s error : %w", resp.Status, err) + } + + return token.Token, nil +} + func GiteaBaseUrl(config v1alpha1.BuildCustomizationSpec) string { return fmt.Sprintf(GiteaIngressURL, config.Protocol, config.Port) } From dbf56c25d009d5b8411aae6215b1c61ee2317f30 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Wed, 11 Dec 2024 18:47:47 +0100 Subject: [PATCH 32/41] Fix wrong call to the function: GetGiteaToken Signed-off-by: cmoulliard --- pkg/controllers/localbuild/gitea_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/controllers/localbuild/gitea_test.go b/pkg/controllers/localbuild/gitea_test.go index b4d0c761..bfda00fa 100644 --- a/pkg/controllers/localbuild/gitea_test.go +++ b/pkg/controllers/localbuild/gitea_test.go @@ -2,6 +2,7 @@ package localbuild import ( "context" + "github.com/cnoe-io/idpbuilder/pkg/util" "net/http" "net/http/httptest" "testing" @@ -33,6 +34,6 @@ func TestGetGiteaToken(t *testing.T) { })) defer ts.Close() ctx := context.Background() - _, err := getGiteaToken(ctx, ts.URL, "", "") + _, err := util.GetGiteaToken(ctx, ts.URL, "", "") require.Error(t, err) } From d029f62f8955f4f522f6757ebad76bd73183ab41 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 12 Dec 2024 10:18:49 +0100 Subject: [PATCH 33/41] Reverting the change to use as user arg: dev-mode instead of staticPassword which is only used internally Signed-off-by: cmoulliard --- api/v1alpha1/localbuild_types.go | 14 +++++++------- pkg/build/build.go | 2 +- pkg/cmd/create/root.go | 18 +++++++++--------- pkg/controllers/gitrepository/controller.go | 2 +- pkg/controllers/localbuild/controller.go | 8 ++++---- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/api/v1alpha1/localbuild_types.go b/api/v1alpha1/localbuild_types.go index cb27b30d..074e9afb 100644 --- a/api/v1alpha1/localbuild_types.go +++ b/api/v1alpha1/localbuild_types.go @@ -47,13 +47,13 @@ type PackageConfigsSpec struct { // BuildCustomizationSpec fields cannot change once a cluster is created type BuildCustomizationSpec struct { - Protocol string `json:"protocol,omitempty"` - Host string `json:"host,omitempty"` - IngressHost string `json:"ingressHost,omitempty"` - Port string `json:"port,omitempty"` - UsePathRouting bool `json:"usePathRouting,omitempty"` - SelfSignedCert string `json:"selfSignedCert,omitempty"` - StaticPasswords bool `json:"staticPasswords,omitempty"` + Protocol string `json:"protocol,omitempty"` + Host string `json:"host,omitempty"` + IngressHost string `json:"ingressHost,omitempty"` + Port string `json:"port,omitempty"` + UsePathRouting bool `json:"usePathRouting,omitempty"` + SelfSignedCert string `json:"selfSignedCert,omitempty"` + StaticPassword bool `json:"staticPasswords,omitempty"` } type LocalbuildSpec struct { diff --git a/pkg/build/build.go b/pkg/build/build.go index 2a49f8dd..c4e7026d 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -280,5 +280,5 @@ func isBuildCustomizationSpecEqual(s1, s2 v1alpha1.BuildCustomizationSpec) bool s1.Port == s2.Port && s1.UsePathRouting == s2.UsePathRouting && s1.SelfSignedCert == s2.SelfSignedCert && - s1.StaticPasswords == s2.StaticPasswords + s1.StaticPassword == s2.StaticPassword } diff --git a/pkg/cmd/create/root.go b/pkg/cmd/create/root.go index 05f0d806..06d75995 100644 --- a/pkg/cmd/create/root.go +++ b/pkg/cmd/create/root.go @@ -20,7 +20,7 @@ import ( const ( recreateClusterUsage = "Delete cluster first if it already exists." buildNameUsage = "Name for build (Prefix for kind cluster name, pod names, etc)." - staticPasswordsUsage = "Set a static password: developer to the applications: argocd and gitea." + devModeUsage = "Set the password \"developer\" for the admin user of the applications: argocd & gitea." kubeVersionUsage = "Version of the kind kubernetes cluster to create." extraPortsMappingUsage = "List of extra ports to expose on the docker container and kubernetes cluster as nodePort " + "(e.g. \"22:32222,9090:39090,etc\")." @@ -41,7 +41,7 @@ var ( // Flags recreateCluster bool buildName string - staticPasswords bool + devMode bool kubeVersion string extraPortsMapping string kindConfigPath string @@ -69,7 +69,7 @@ func init() { CreateCmd.PersistentFlags().StringVar(&buildName, "build-name", "localdev", buildNameUsage) CreateCmd.PersistentFlags().MarkDeprecated("build-name", "use --name instead.") CreateCmd.PersistentFlags().StringVar(&buildName, "name", "localdev", buildNameUsage) - CreateCmd.PersistentFlags().BoolVar(&staticPasswords, "static-passwords", false, staticPasswordsUsage) + CreateCmd.PersistentFlags().BoolVar(&devMode, "dev-mode", false, devModeUsage) CreateCmd.PersistentFlags().StringVar(&kubeVersion, "kube-version", "v1.30.3", kubeVersionUsage) CreateCmd.PersistentFlags().StringVar(&extraPortsMapping, "extra-ports", "", extraPortsMappingUsage) CreateCmd.PersistentFlags().StringVar(&kindConfigPath, "kind-config", "", kindConfigPathUsage) @@ -141,12 +141,12 @@ func create(cmd *cobra.Command, args []string) error { ExtraPortsMapping: extraPortsMapping, TemplateData: v1alpha1.BuildCustomizationSpec{ - Protocol: protocol, - Host: host, - IngressHost: ingressHost, - Port: port, - UsePathRouting: pathRouting, - StaticPasswords: staticPasswords, + Protocol: protocol, + Host: host, + IngressHost: ingressHost, + Port: port, + UsePathRouting: pathRouting, + StaticPassword: devMode, }, CustomPackageDirs: absDirPaths, diff --git a/pkg/controllers/gitrepository/controller.go b/pkg/controllers/gitrepository/controller.go index 829ec657..45ef84d2 100644 --- a/pkg/controllers/gitrepository/controller.go +++ b/pkg/controllers/gitrepository/controller.go @@ -143,7 +143,7 @@ func (r *RepositoryReconciler) reconcileGitRepo(ctx context.Context, repo *v1alp return ctrl.Result{}, fmt.Errorf("getting git provider credentials: %w", err) } - if r.Config.StaticPasswords { + if r.Config.StaticPassword { creds.password = "developer" } diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index 6c1c5994..a30faa31 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -104,8 +104,8 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) } } - if r.Config.StaticPasswords { - logger.V(1).Info("StaticPasswords is enabled") + if r.Config.StaticPassword { + logger.V(1).Info("Dev mode is enabled") // Check if the Argocd Initial admin secret exists argocdInitialAdminPassword, err := r.extractArgocdInitialAdminSecret(ctx) @@ -123,7 +123,7 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) if err != nil { return ctrl.Result{}, err } else { - logger.Info(fmt.Sprintf("Argocd admin password change %s !", argocdPasswordChangeStatus)) + logger.V(1).Info(fmt.Sprintf("Argocd admin password change %s !", argocdPasswordChangeStatus)) } } @@ -141,7 +141,7 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) if err != nil { return ctrl.Result{}, err } else { - logger.Info(fmt.Sprintf("Gitea admin password change %s !", giteaPasswordChangeStatus)) + logger.V(1).Info(fmt.Sprintf("Gitea admin password change %s !", giteaPasswordChangeStatus)) } } } From 570ca30d1f4b40cc85dc6f56c26352c9367d7a98 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 13 Dec 2024 11:58:09 +0100 Subject: [PATCH 34/41] Define an util const: StaticPassword Signed-off-by: cmoulliard --- api/v1alpha1/gitrepository_types.go | 13 ++++++------- pkg/controllers/gitrepository/controller.go | 2 +- pkg/controllers/localbuild/controller.go | 10 +++++----- pkg/util/argocd.go | 1 - pkg/util/util.go | 1 + 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/api/v1alpha1/gitrepository_types.go b/api/v1alpha1/gitrepository_types.go index 978087c4..d3ac32af 100644 --- a/api/v1alpha1/gitrepository_types.go +++ b/api/v1alpha1/gitrepository_types.go @@ -5,13 +5,12 @@ import ( ) const ( - GitProviderGitea = "gitea" - GitProviderGitHub = "github" - GiteaAdminUserName = "giteaAdmin" - GiteaDeveloperUserName = "developer" - SourceTypeLocal = "local" - SourceTypeRemote = "remote" - SourceTypeEmbedded = "embedded" + GitProviderGitea = "gitea" + GitProviderGitHub = "github" + GiteaAdminUserName = "giteaAdmin" + SourceTypeLocal = "local" + SourceTypeRemote = "remote" + SourceTypeEmbedded = "embedded" ) type GitRepositorySpec struct { diff --git a/pkg/controllers/gitrepository/controller.go b/pkg/controllers/gitrepository/controller.go index 45ef84d2..93baedef 100644 --- a/pkg/controllers/gitrepository/controller.go +++ b/pkg/controllers/gitrepository/controller.go @@ -144,7 +144,7 @@ func (r *RepositoryReconciler) reconcileGitRepo(ctx context.Context, repo *v1alp } if r.Config.StaticPassword { - creds.password = "developer" + creds.password = util.StaticPassword } err = provider.setProviderCredentials(ctx, repo, creds) diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index a30faa31..f74a5b04 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -678,7 +678,7 @@ func (r *LocalbuildReconciler) updateGiteaDevPassword(ctx context.Context, admin opts := gitea.EditUserOption{ LoginName: "giteaAdmin", - Password: "developer", + Password: util.StaticPassword, } resp, err := client.AdminEditUser("giteaAdmin", opts) @@ -686,7 +686,7 @@ func (r *LocalbuildReconciler) updateGiteaDevPassword(ctx context.Context, admin return fmt.Errorf("cannot update gitea admin user. status: %d error : %w", resp.StatusCode, err), "failed" } - err = util.PatchPasswordSecret(ctx, r.Client, r.Config, util.GiteaNamespace, util.GiteaAdminSecret, util.GiteaAdminName, "developer") + err = util.PatchPasswordSecret(ctx, r.Client, r.Config, util.GiteaNamespace, util.GiteaAdminSecret, util.GiteaAdminName, util.StaticPassword) if err != nil { return fmt.Errorf("patching the gitea credentials failed : %w", err), "failed" } @@ -740,7 +740,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi payload := map[string]string{ "name": "admin", "currentPassword": adminPassword, - "newPassword": util.ArgocdDevModePassword, + "newPassword": util.StaticPassword, } payloadBytes, err := json.Marshal(payload) @@ -763,7 +763,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi // Lets checking the new admin password payload = map[string]string{ "username": "admin", - "password": util.ArgocdDevModePassword, + "password": util.StaticPassword, } payloadBytes, err = json.Marshal(payload) if err != nil { @@ -787,7 +787,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi // Password verification succeeded ! if resp.StatusCode == 200 { // Let's patch the existing secret now - err = util.PatchPasswordSecret(ctx, r.Client, r.Config, util.ArgocdNamespace, util.ArgocdInitialAdminSecretName, util.ArgocdAdminName, "developer") + err = util.PatchPasswordSecret(ctx, r.Client, r.Config, util.ArgocdNamespace, util.ArgocdInitialAdminSecretName, util.ArgocdAdminName, util.StaticPassword) if err != nil { return fmt.Errorf("patching the argocd initial secret failed : %w", err), "failed" } diff --git a/pkg/util/argocd.go b/pkg/util/argocd.go index 1ef8a13e..eb0e9dd2 100644 --- a/pkg/util/argocd.go +++ b/pkg/util/argocd.go @@ -6,7 +6,6 @@ import ( ) const ( - ArgocdDevModePassword = "developer" ArgocdInitialAdminSecretName = "argocd-initial-admin-secret" ArgocdAdminName = "admin" ArgocdNamespace = "argocd" diff --git a/pkg/util/util.go b/pkg/util/util.go index 86f4fad3..99b15cb0 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -28,6 +28,7 @@ const ( passwordLength = 40 numSpecialChars = 3 numDigits = 3 + StaticPassword = "developer" ) func GetCLIStartTimeAnnotationValue(annotations map[string]string) (string, error) { From 2fe31a3ccc829b0aa600658ee646c98a181b414b Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 13 Dec 2024 12:00:01 +0100 Subject: [PATCH 35/41] Move the function ArgocdInitialAdminSecretObject() to the argocd.go file of the util package Signed-off-by: cmoulliard --- pkg/controllers/localbuild/argo.go | 16 ---------------- pkg/controllers/localbuild/controller.go | 2 +- pkg/util/argocd.go | 15 +++++++++++++++ 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/pkg/controllers/localbuild/argo.go b/pkg/controllers/localbuild/argo.go index 87c20b36..d55073c4 100644 --- a/pkg/controllers/localbuild/argo.go +++ b/pkg/controllers/localbuild/argo.go @@ -6,9 +6,6 @@ import ( "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/globals" "github.com/cnoe-io/idpbuilder/pkg/k8s" - "github.com/cnoe-io/idpbuilder/pkg/util" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ctrl "sigs.k8s.io/controller-runtime" @@ -59,16 +56,3 @@ func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Reque resource.Status.ArgoCD.Available = true return ctrl.Result{}, nil } - -func (r *LocalbuildReconciler) ArgocdInitialAdminSecretObject() corev1.Secret { - return corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: util.ArgocdInitialAdminSecretName, - Namespace: util.ArgocdNamespace, - }, - } -} diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index f74a5b04..e56120c5 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -639,7 +639,7 @@ func (r *LocalbuildReconciler) requestArgoCDAppSetRefresh(ctx context.Context) e } func (r *LocalbuildReconciler) extractArgocdInitialAdminSecret(ctx context.Context) (string, error) { - sec := r.ArgocdInitialAdminSecretObject() + sec := util.ArgocdInitialAdminSecretObject() err := r.Client.Get(ctx, types.NamespacedName{ Namespace: sec.GetNamespace(), Name: sec.GetName(), diff --git a/pkg/util/argocd.go b/pkg/util/argocd.go index eb0e9dd2..91700d8f 100644 --- a/pkg/util/argocd.go +++ b/pkg/util/argocd.go @@ -3,6 +3,8 @@ package util import ( "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( @@ -15,3 +17,16 @@ const ( func ArgocdBaseUrl(config v1alpha1.BuildCustomizationSpec) string { return fmt.Sprintf(ArgocdIngressURL, config.Protocol, config.Port) } + +func ArgocdInitialAdminSecretObject() corev1.Secret { + return corev1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "Secret", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: ArgocdInitialAdminSecretName, + Namespace: ArgocdNamespace, + }, + } +} From e4831cd640ca7bd5d8ec688e634d9a6eb3bc5bf8 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 13 Dec 2024 12:15:26 +0100 Subject: [PATCH 36/41] Rename functions. Remove the var about status and change the signature of the functions using it. Convert some messages to log debug messages Signed-off-by: cmoulliard --- pkg/controllers/localbuild/controller.go | 59 +++++++++++------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index e56120c5..11327286 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -45,11 +45,6 @@ const ( argoCDApplicationSetAnnotationKeyRefreshTrue = "true" ) -var ( - argocdPasswordChangeStatus = "failed" - giteaPasswordChangeStatus = "failed" -) - type ArgocdSession struct { Token string `json:"token"` } @@ -105,7 +100,7 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) } if r.Config.StaticPassword { - logger.V(1).Info("Dev mode is enabled") + logger.V(1).Info("static password is enabled") // Check if the Argocd Initial admin secret exists argocdInitialAdminPassword, err := r.extractArgocdInitialAdminSecret(ctx) @@ -118,12 +113,12 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) // Secret containing the initial argocd password exists // Lets try to update the password - if argocdInitialAdminPassword != "" && argocdPasswordChangeStatus == "failed" { - err, argocdPasswordChangeStatus = r.updateArgocdDevPassword(ctx, argocdInitialAdminPassword) + if argocdInitialAdminPassword != "" { + err = r.updateArgocdPassword(ctx, argocdInitialAdminPassword) if err != nil { return ctrl.Result{}, err } else { - logger.V(1).Info(fmt.Sprintf("Argocd admin password change %s !", argocdPasswordChangeStatus)) + logger.V(1).Info(fmt.Sprintf("Argocd admin password change succeeded !")) } } @@ -133,15 +128,15 @@ func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) // Gitea admin secret is not yet available ... return ctrl.Result{RequeueAfter: defaultRequeueTime}, nil } - logger.Info("Gitea admin secret found ...") + logger.V(1).Info("Gitea admin secret found ...") // Secret containing the gitea password exists // Lets try to update the password - if giteaAdminPassword != "" && giteaPasswordChangeStatus == "failed" { - err, giteaPasswordChangeStatus = r.updateGiteaDevPassword(ctx, giteaAdminPassword) + if giteaAdminPassword != "" { + err = r.updateGiteaPassword(ctx, giteaAdminPassword) if err != nil { return ctrl.Result{}, err } else { - logger.V(1).Info(fmt.Sprintf("Gitea admin password change %s !", giteaPasswordChangeStatus)) + logger.V(1).Info(fmt.Sprintf("Gitea admin password change succeeded !")) } } } @@ -668,12 +663,12 @@ func (r *LocalbuildReconciler) extractGiteaAdminSecret(ctx context.Context) (str return string(sec.Data["password"]), nil } -func (r *LocalbuildReconciler) updateGiteaDevPassword(ctx context.Context, adminPassword string) (error, string) { +func (r *LocalbuildReconciler) updateGiteaPassword(ctx context.Context, adminPassword string) error { client, err := gitea.NewClient(util.GiteaBaseUrl(r.Config), gitea.SetHTTPClient(util.GetHttpClient()), gitea.SetBasicAuth("giteaAdmin", adminPassword), gitea.SetContext(ctx), ) if err != nil { - return fmt.Errorf("cannot create gitea client: %w", err), "failed" + return fmt.Errorf("cannot create gitea client: %w", err) } opts := gitea.EditUserOption{ @@ -683,17 +678,17 @@ func (r *LocalbuildReconciler) updateGiteaDevPassword(ctx context.Context, admin resp, err := client.AdminEditUser("giteaAdmin", opts) if err != nil { - return fmt.Errorf("cannot update gitea admin user. status: %d error : %w", resp.StatusCode, err), "failed" + return fmt.Errorf("cannot update gitea admin user. status: %d error : %w", resp.StatusCode, err) } err = util.PatchPasswordSecret(ctx, r.Client, r.Config, util.GiteaNamespace, util.GiteaAdminSecret, util.GiteaAdminName, util.StaticPassword) if err != nil { - return fmt.Errorf("patching the gitea credentials failed : %w", err), "failed" + return fmt.Errorf("patching the gitea credentials failed : %w", err) } - return nil, "succeeded" + return nil } -func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, adminPassword string) (error, string) { +func (r *LocalbuildReconciler) updateArgocdPassword(ctx context.Context, adminPassword string) error { argocdEndpoint := util.ArgocdBaseUrl(r.Config) + "/api/v1" payload := map[string]string{ @@ -702,13 +697,13 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi } payloadBytes, err := json.Marshal(payload) if err != nil { - return fmt.Errorf("Error creating JSON payload: %v\n", err), "failed" + return fmt.Errorf("Error creating JSON payload: %v\n", err) } // Create an HTTP POST request to get the Session token req, err := http.NewRequest("POST", argocdEndpoint+"/session", bytes.NewBuffer(payloadBytes)) if err != nil { - return fmt.Errorf("Error creating HTTP request: %v\n", err), "failed" + return fmt.Errorf("Error creating HTTP request: %v\n", err) } req.Header.Set("Content-Type", "application/json") @@ -718,14 +713,14 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi // Send the request resp, err := c.Do(req) if err != nil { - return fmt.Errorf("Error sending request: %v\n", err), "failed" + return fmt.Errorf("Error sending request: %v\n", err) } defer resp.Body.Close() // Read the response body body, err := io.ReadAll(resp.Body) if err != nil { - return fmt.Errorf("Error reading response body: %v\n", err), "failed" + return fmt.Errorf("Error reading response body: %v\n", err) } // We got a session Token, so we can update the Argocd admin password @@ -734,7 +729,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi err := json.Unmarshal([]byte(body), &argocdSession) if err != nil { - return fmt.Errorf("Error unmarshalling JSON: %v", err), "failed" + return fmt.Errorf("Error unmarshalling JSON: %v", err) } payload := map[string]string{ @@ -745,7 +740,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi payloadBytes, err := json.Marshal(payload) if err != nil { - return fmt.Errorf("Error creating JSON payload: %v\n", err), "failed" + return fmt.Errorf("Error creating JSON payload: %v\n", err) } req, err := http.NewRequest("PUT", argocdEndpoint+"/account/password", bytes.NewBuffer(payloadBytes)) @@ -756,7 +751,7 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi resp, err := c.Do(req) if err != nil { - return fmt.Errorf("Error sending request: %v\n", err), "failed" + return fmt.Errorf("Error sending request: %v\n", err) } defer resp.Body.Close() @@ -767,20 +762,20 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi } payloadBytes, err = json.Marshal(payload) if err != nil { - return fmt.Errorf("Error creating JSON payload: %v\n", err), "failed" + return fmt.Errorf("Error creating JSON payload: %v\n", err) } // Define the request able to verify if the username and password changed works req, err = http.NewRequest("POST", argocdEndpoint+"/session", bytes.NewBuffer(payloadBytes)) if err != nil { - return fmt.Errorf("Error creating HTTP request: %v\n", err), "failed" + return fmt.Errorf("Error creating HTTP request: %v\n", err) } req.Header.Set("Content-Type", "application/json") // Send the request resp, err = c.Do(req) if err != nil { - return fmt.Errorf("Error sending request: %v\n", err), "failed" + return fmt.Errorf("Error sending request: %v\n", err) } defer resp.Body.Close() @@ -789,13 +784,13 @@ func (r *LocalbuildReconciler) updateArgocdDevPassword(ctx context.Context, admi // Let's patch the existing secret now err = util.PatchPasswordSecret(ctx, r.Client, r.Config, util.ArgocdNamespace, util.ArgocdInitialAdminSecretName, util.ArgocdAdminName, util.StaticPassword) if err != nil { - return fmt.Errorf("patching the argocd initial secret failed : %w", err), "failed" + return fmt.Errorf("patching the argocd initial secret failed : %w", err) } - return nil, "succeeded" + return nil } } // No session token has been received and by consequence the admin password has not been changed - return nil, "failed" + return nil } func (r *LocalbuildReconciler) applyArgoCDAnnotation(ctx context.Context, obj client.Object, argoCDType, annotationKey, annotationValue string) error { From 1cd1773ddd293c8366aa7ebb0671b5c0675d4405 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 13 Dec 2024 12:27:15 +0100 Subject: [PATCH 37/41] Remove devMode as not used Signed-off-by: cmoulliard --- pkg/build/build.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/build/build.go b/pkg/build/build.go index c4e7026d..33555efb 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -28,7 +28,6 @@ var ( type Build struct { name string - devMode bool cfg v1alpha1.BuildCustomizationSpec kindConfigPath string kubeConfigPath string From 70e3d3739067a49eb7497b6f55df9890063f4247 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 13 Dec 2024 15:14:56 +0100 Subject: [PATCH 38/41] Rename dev-mode to dev-password Signed-off-by: cmoulliard --- api/v1alpha1/localbuild_types.go | 2 +- pkg/cmd/create/root.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/v1alpha1/localbuild_types.go b/api/v1alpha1/localbuild_types.go index 074e9afb..1f9035f2 100644 --- a/api/v1alpha1/localbuild_types.go +++ b/api/v1alpha1/localbuild_types.go @@ -53,7 +53,7 @@ type BuildCustomizationSpec struct { Port string `json:"port,omitempty"` UsePathRouting bool `json:"usePathRouting,omitempty"` SelfSignedCert string `json:"selfSignedCert,omitempty"` - StaticPassword bool `json:"staticPasswords,omitempty"` + StaticPassword bool `json:"staticPassword,omitempty"` } type LocalbuildSpec struct { diff --git a/pkg/cmd/create/root.go b/pkg/cmd/create/root.go index 06d75995..08f05cef 100644 --- a/pkg/cmd/create/root.go +++ b/pkg/cmd/create/root.go @@ -20,7 +20,7 @@ import ( const ( recreateClusterUsage = "Delete cluster first if it already exists." buildNameUsage = "Name for build (Prefix for kind cluster name, pod names, etc)." - devModeUsage = "Set the password \"developer\" for the admin user of the applications: argocd & gitea." + devPasswordUsage = "Set the password \"developer\" for the admin user of the applications: argocd & gitea." kubeVersionUsage = "Version of the kind kubernetes cluster to create." extraPortsMappingUsage = "List of extra ports to expose on the docker container and kubernetes cluster as nodePort " + "(e.g. \"22:32222,9090:39090,etc\")." @@ -41,7 +41,7 @@ var ( // Flags recreateCluster bool buildName string - devMode bool + devPassword bool kubeVersion string extraPortsMapping string kindConfigPath string @@ -69,7 +69,7 @@ func init() { CreateCmd.PersistentFlags().StringVar(&buildName, "build-name", "localdev", buildNameUsage) CreateCmd.PersistentFlags().MarkDeprecated("build-name", "use --name instead.") CreateCmd.PersistentFlags().StringVar(&buildName, "name", "localdev", buildNameUsage) - CreateCmd.PersistentFlags().BoolVar(&devMode, "dev-mode", false, devModeUsage) + CreateCmd.PersistentFlags().BoolVar(&devPassword, "dev-password", false, devPasswordUsage) CreateCmd.PersistentFlags().StringVar(&kubeVersion, "kube-version", "v1.30.3", kubeVersionUsage) CreateCmd.PersistentFlags().StringVar(&extraPortsMapping, "extra-ports", "", extraPortsMappingUsage) CreateCmd.PersistentFlags().StringVar(&kindConfigPath, "kind-config", "", kindConfigPathUsage) @@ -146,7 +146,7 @@ func create(cmd *cobra.Command, args []string) error { IngressHost: ingressHost, Port: port, UsePathRouting: pathRouting, - StaticPassword: devMode, + StaticPassword: devPassword, }, CustomPackageDirs: absDirPaths, From 6c183d146bbed3f4150defbf773d5bbe6994322b Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 2 Jan 2025 12:49:44 +0100 Subject: [PATCH 39/41] Import missing package needed: util Signed-off-by: cmoulliard --- pkg/cmd/get/secrets.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index 7317637e..c69475cc 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/cnoe-io/idpbuilder/pkg/entity" "github.com/cnoe-io/idpbuilder/pkg/printer" + "github.com/cnoe-io/idpbuilder/pkg/util" "io" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "os" From 06fd82390eb2adc62b2b2e927c976e6825eafc93 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 2 Jan 2025 12:50:19 +0100 Subject: [PATCH 40/41] Use singular instead of plural Signed-off-by: cmoulliard --- pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml b/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml index 98c37c03..91d310ee 100644 --- a/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml +++ b/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml @@ -51,7 +51,7 @@ spec: type: string selfSignedCert: type: string - staticPasswords: + staticPassword: type: boolean usePathRouting: type: boolean From bc2aa2ec243ed82a058a5e057d68023f93116089 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Mon, 6 Jan 2025 09:57:43 +0100 Subject: [PATCH 41/41] Fix wrong import indentation Signed-off-by: cmoulliard --- pkg/cmd/get/secrets.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index 7142c278..1f15bc06 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -10,7 +10,7 @@ import ( "github.com/cnoe-io/idpbuilder/pkg/entity" "github.com/cnoe-io/idpbuilder/pkg/printer" - "github.com/cnoe-io/idpbuilder/pkg/util" + "github.com/cnoe-io/idpbuilder/pkg/util" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/cnoe-io/idpbuilder/api/v1alpha1"