diff --git a/.github/workflows/release_docker_k8_operator.yaml b/.github/workflows/release_docker_k8_operator.yaml index cbed4ff85..788d414b6 100644 --- a/.github/workflows/release_docker_k8_operator.yaml +++ b/.github/workflows/release_docker_k8_operator.yaml @@ -26,16 +26,4 @@ jobs: context: k8-operator push: true platforms: linux/amd64,linux/arm64 - tags: infisical/kubernetes-operator:latest - - - uses: actions/setup-go@v2 - - - name: Generate YAML for Kubectl - run: make dist charts - - - name: Upload CRD manifest - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: dist/install-secrets-operator.yaml - tag: ${{ github.ref }} \ No newline at end of file + tags: infisical/kubernetes-operator:latest \ No newline at end of file diff --git a/helm-charts/secrets-operator/templates/infisicalsecret-crd.yaml b/helm-charts/secrets-operator/templates/infisicalsecret-crd.yaml index 8628a57d9..c5b82fa14 100644 --- a/helm-charts/secrets-operator/templates/infisicalsecret-crd.yaml +++ b/helm-charts/secrets-operator/templates/infisicalsecret-crd.yaml @@ -38,19 +38,11 @@ spec: environment: description: The Infisical environment such as dev, prod, testing type: string - infisicalToken: - properties: - secretName: - description: The name of the Kubernetes Secret - type: string - secretNamespace: - description: The name space where the Kubernetes Secret is located - type: string - required: - - secretName - - secretNamespace - type: object - managedSecret: + hostAPI: + default: https://app.infisical.com/api + description: Infisical host to pull secrets from + type: string + managedSecretReference: properties: secretName: description: The name of the Kubernetes Secret @@ -65,6 +57,18 @@ spec: projectId: description: The Infisical project id type: string + tokenSecretReference: + properties: + secretName: + description: The name of the Kubernetes Secret + type: string + secretNamespace: + description: The name space where the Kubernetes Secret is located + type: string + required: + - secretName + - secretNamespace + type: object required: - environment - projectId diff --git a/k8-operator/api/v1alpha1/infisicalsecret_types.go b/k8-operator/api/v1alpha1/infisicalsecret_types.go index 74e3f9788..7940474f9 100644 --- a/k8-operator/api/v1alpha1/infisicalsecret_types.go +++ b/k8-operator/api/v1alpha1/infisicalsecret_types.go @@ -16,8 +16,8 @@ type KubeSecretReference struct { // InfisicalSecretSpec defines the desired state of InfisicalSecret type InfisicalSecretSpec struct { - InfisicalToken KubeSecretReference `json:"infisicalToken,omitempty"` - ManagedSecret KubeSecretReference `json:"managedSecret,omitempty"` + TokenSecretReference KubeSecretReference `json:"tokenSecretReference,omitempty"` + ManagedSecretReference KubeSecretReference `json:"managedSecretReference,omitempty"` // The Infisical project id // +kubebuilder:validation:Required @@ -26,6 +26,10 @@ type InfisicalSecretSpec struct { // The Infisical environment such as dev, prod, testing // +kubebuilder:validation:Required Environment string `json:"environment"` + + // Infisical host to pull secrets from + // +kubebuilder:default="https://app.infisical.com/api" + HostAPI string `json:"hostAPI,omitempty"` } // InfisicalSecretStatus defines the observed state of InfisicalSecret diff --git a/k8-operator/api/v1alpha1/zz_generated.deepcopy.go b/k8-operator/api/v1alpha1/zz_generated.deepcopy.go index e6053ba74..af9eff318 100644 --- a/k8-operator/api/v1alpha1/zz_generated.deepcopy.go +++ b/k8-operator/api/v1alpha1/zz_generated.deepcopy.go @@ -88,8 +88,8 @@ func (in *InfisicalSecretList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *InfisicalSecretSpec) DeepCopyInto(out *InfisicalSecretSpec) { *out = *in - out.InfisicalToken = in.InfisicalToken - out.ManagedSecret = in.ManagedSecret + out.TokenSecretReference = in.TokenSecretReference + out.ManagedSecretReference = in.ManagedSecretReference } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfisicalSecretSpec. diff --git a/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml b/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml index ca00676b4..c885fbdde 100644 --- a/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml +++ b/k8-operator/config/crd/bases/secrets.infisical.com_infisicalsecrets.yaml @@ -38,19 +38,11 @@ spec: environment: description: The Infisical environment such as dev, prod, testing type: string - infisicalToken: - properties: - secretName: - description: The name of the Kubernetes Secret - type: string - secretNamespace: - description: The name space where the Kubernetes Secret is located - type: string - required: - - secretName - - secretNamespace - type: object - managedSecret: + hostAPI: + default: https://app.infisical.com/api + description: Infisical host to pull secrets from + type: string + managedSecretReference: properties: secretName: description: The name of the Kubernetes Secret @@ -65,6 +57,18 @@ spec: projectId: description: The Infisical project id type: string + tokenSecretReference: + properties: + secretName: + description: The name of the Kubernetes Secret + type: string + secretNamespace: + description: The name space where the Kubernetes Secret is located + type: string + required: + - secretName + - secretNamespace + type: object required: - environment - projectId diff --git a/k8-operator/config/default/kustomization.yaml b/k8-operator/config/default/kustomization.yaml index 4cab9014c..1237b893d 100644 --- a/k8-operator/config/default/kustomization.yaml +++ b/k8-operator/config/default/kustomization.yaml @@ -1,12 +1,12 @@ # Adds namespace to all resources. -namespace: k8-operator-system +namespace: infisical-operator-system # Value of this field is prepended to the # names of all resources, e.g. a deployment named # "wordpress" becomes "alices-wordpress". # Note that it should also match with the prefix (text before '-') of the namespace # field above. -namePrefix: k8-operator- +namePrefix: infisical-operator- # Labels to add to all resources and selectors. #commonLabels: diff --git a/k8-operator/config/samples/sample.yaml b/k8-operator/config/samples/sample.yaml new file mode 100644 index 000000000..1a185b15f --- /dev/null +++ b/k8-operator/config/samples/sample.yaml @@ -0,0 +1,14 @@ +apiVersion: secrets.infisical.com/v1alpha1 +kind: InfisicalSecret +metadata: + name: infisicalsecret-sample + # namespace: first-project +spec: + projectId: 62faf98ae0b05e8529b5da46 + environment: dev + tokenSecretReference: + secretName: service-token + secretNamespace: first-project + managedSecretReference: + secretName: managed-secret + secretNamespace: first-project diff --git a/k8-operator/config/samples/secrets_v1alpha1_infisicalsecret.yaml b/k8-operator/config/samples/secrets_v1alpha1_infisicalsecret.yaml deleted file mode 100644 index 7ab08e9cd..000000000 --- a/k8-operator/config/samples/secrets_v1alpha1_infisicalsecret.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: secrets.infisical.com/v1alpha1 -kind: InfisicalSecret -metadata: - labels: - app.kubernetes.io/name: infisicalsecret - app.kubernetes.io/instance: infisicalsecret-sample - app.kubernetes.io/part-of: k8-operator - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/created-by: k8-operator - name: infisicalsecret-sample -spec: - projectId: 62faf98ae0b05e8529b5da46 - environment: dev - infisicalToken: - secretName: service-token - secretNamespace: default - managedSecret: - secretName: managed-secret - secretNamespace: default diff --git a/k8-operator/controllers/infisicalsecret_controller.go b/k8-operator/controllers/infisicalsecret_controller.go index 297e29bfb..f6422e177 100644 --- a/k8-operator/controllers/infisicalsecret_controller.go +++ b/k8-operator/controllers/infisicalsecret_controller.go @@ -36,6 +36,8 @@ func (r *InfisicalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Requ var infisicalSecretCR v1alpha1.InfisicalSecret err := r.Get(ctx, req.NamespacedName, &infisicalSecretCR) + requeueTime := time.Minute * 5 + if err != nil { if errors.IsNotFound(err) { log.Info("Infisical Secret not found") @@ -43,7 +45,7 @@ func (r *InfisicalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Requ } else { log.Error(err, "Unable to fetch Infisical Secret from cluster. Will retry") return ctrl.Result{ - RequeueAfter: time.Minute, + RequeueAfter: requeueTime, }, nil } } @@ -58,13 +60,13 @@ func (r *InfisicalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Requ if err != nil { log.Error(err, "Unable to reconcile Infisical Secret and will try again") return ctrl.Result{ - RequeueAfter: time.Minute, + RequeueAfter: requeueTime, }, nil } // Sync again after the specified time return ctrl.Result{ - RequeueAfter: time.Minute, + RequeueAfter: requeueTime, }, nil } diff --git a/k8-operator/controllers/infisicalsecret_helper.go b/k8-operator/controllers/infisicalsecret_helper.go index fbcacadea..be4e35dd5 100644 --- a/k8-operator/controllers/infisicalsecret_helper.go +++ b/k8-operator/controllers/infisicalsecret_helper.go @@ -29,12 +29,12 @@ func (r *InfisicalSecretReconciler) GetKubeSecretByNamespacedName(ctx context.Co func (r *InfisicalSecretReconciler) GetInfisicalToken(ctx context.Context, infisicalSecret v1alpha1.InfisicalSecret) (string, error) { tokenSecret, err := r.GetKubeSecretByNamespacedName(ctx, types.NamespacedName{ - Namespace: infisicalSecret.Spec.InfisicalToken.SecretNamespace, - Name: infisicalSecret.Spec.InfisicalToken.SecretName, + Namespace: infisicalSecret.Spec.TokenSecretReference.SecretNamespace, + Name: infisicalSecret.Spec.TokenSecretReference.SecretName, }) if err != nil { - return "", fmt.Errorf("failed to read Infisical token secret from secret named [%s] in namespace [%s]: with error [%w]", infisicalSecret.Spec.ManagedSecret.SecretName, infisicalSecret.Spec.ManagedSecret.SecretNamespace, err) + return "", fmt.Errorf("failed to read Infisical token secret from secret named [%s] in namespace [%s]: with error [%w]", infisicalSecret.Spec.ManagedSecretReference.SecretName, infisicalSecret.Spec.ManagedSecretReference.SecretNamespace, err) } infisicalServiceToken := tokenSecret.Data[INFISICAL_TOKEN_SECRET_KEY_NAME] @@ -54,8 +54,8 @@ func (r *InfisicalSecretReconciler) CreateInfisicalManagedKubeSecret(ctx context // create a new secret as specified by the managed secret spec of CRD newKubeSecretInstance := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: infisicalSecret.Spec.ManagedSecret.SecretName, - Namespace: infisicalSecret.Spec.ManagedSecret.SecretNamespace, + Name: infisicalSecret.Spec.ManagedSecretReference.SecretName, + Namespace: infisicalSecret.Spec.ManagedSecretReference.SecretNamespace, }, Type: "Opaque", Data: plainProcessedSecrets, @@ -94,15 +94,15 @@ func (r *InfisicalSecretReconciler) ReconcileInfisicalSecret(ctx context.Context } managedKubeSecret, err := r.GetKubeSecretByNamespacedName(ctx, types.NamespacedName{ - Name: infisicalSecret.Spec.ManagedSecret.SecretName, - Namespace: infisicalSecret.Spec.ManagedSecret.SecretNamespace, + Name: infisicalSecret.Spec.ManagedSecretReference.SecretName, + Namespace: infisicalSecret.Spec.ManagedSecretReference.SecretNamespace, }) if err != nil && !errors.IsNotFound(err) { return fmt.Errorf("something went wrong when fetching the managed Kubernetes secret [%w]", err) } - secretsFromApi, err := api.GetAllEnvironmentVariables(infisicalSecret.Spec.ProjectId, infisicalSecret.Spec.Environment, infisicalToken) + secretsFromApi, err := api.GetAllEnvironmentVariables(infisicalSecret.Spec.ProjectId, infisicalSecret.Spec.Environment, infisicalToken, infisicalSecret.Spec.HostAPI) if err != nil { return err diff --git a/k8-operator/kubectl-install/install-secrets-operator.yaml b/k8-operator/kubectl-install/install-secrets-operator.yaml index 03c747b26..6a3cb8e6d 100644 --- a/k8-operator/kubectl-install/install-secrets-operator.yaml +++ b/k8-operator/kubectl-install/install-secrets-operator.yaml @@ -9,7 +9,7 @@ metadata: app.kubernetes.io/name: namespace app.kubernetes.io/part-of: k8-operator control-plane: controller-manager - name: k8-operator-system + name: infisical-operator-system --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -46,19 +46,11 @@ spec: environment: description: The Infisical environment such as dev, prod, testing type: string - infisicalToken: - properties: - secretName: - description: The name of the Kubernetes Secret - type: string - secretNamespace: - description: The name space where the Kubernetes Secret is located - type: string - required: - - secretName - - secretNamespace - type: object - managedSecret: + hostAPI: + default: https://app.infisical.com/api + description: Infisical host to pull secrets from + type: string + managedSecretReference: properties: secretName: description: The name of the Kubernetes Secret @@ -73,6 +65,18 @@ spec: projectId: description: The Infisical project id type: string + tokenSecretReference: + properties: + secretName: + description: The name of the Kubernetes Secret + type: string + secretNamespace: + description: The name space where the Kubernetes Secret is located + type: string + required: + - secretName + - secretNamespace + type: object required: - environment - projectId @@ -142,8 +146,8 @@ metadata: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/name: serviceaccount app.kubernetes.io/part-of: k8-operator - name: k8-operator-controller-manager - namespace: k8-operator-system + name: infisical-operator-controller-manager + namespace: infisical-operator-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -155,8 +159,8 @@ metadata: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/name: role app.kubernetes.io/part-of: k8-operator - name: k8-operator-leader-election-role - namespace: k8-operator-system + name: infisical-operator-leader-election-role + namespace: infisical-operator-system rules: - apiGroups: - "" @@ -194,7 +198,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: creationTimestamp: null - name: k8-operator-manager-role + name: infisical-operator-manager-role rules: - apiGroups: - "" @@ -253,7 +257,7 @@ metadata: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/name: clusterrole app.kubernetes.io/part-of: k8-operator - name: k8-operator-metrics-reader + name: infisical-operator-metrics-reader rules: - nonResourceURLs: - /metrics @@ -270,7 +274,7 @@ metadata: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/name: clusterrole app.kubernetes.io/part-of: k8-operator - name: k8-operator-proxy-role + name: infisical-operator-proxy-role rules: - apiGroups: - authentication.k8s.io @@ -295,16 +299,16 @@ metadata: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/name: rolebinding app.kubernetes.io/part-of: k8-operator - name: k8-operator-leader-election-rolebinding - namespace: k8-operator-system + name: infisical-operator-leader-election-rolebinding + namespace: infisical-operator-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: k8-operator-leader-election-role + name: infisical-operator-leader-election-role subjects: - kind: ServiceAccount - name: k8-operator-controller-manager - namespace: k8-operator-system + name: infisical-operator-controller-manager + namespace: infisical-operator-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -316,15 +320,15 @@ metadata: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/name: clusterrolebinding app.kubernetes.io/part-of: k8-operator - name: k8-operator-manager-rolebinding + name: infisical-operator-manager-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: k8-operator-manager-role + name: infisical-operator-manager-role subjects: - kind: ServiceAccount - name: k8-operator-controller-manager - namespace: k8-operator-system + name: infisical-operator-controller-manager + namespace: infisical-operator-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -336,15 +340,15 @@ metadata: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/name: clusterrolebinding app.kubernetes.io/part-of: k8-operator - name: k8-operator-proxy-rolebinding + name: infisical-operator-proxy-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: k8-operator-proxy-role + name: infisical-operator-proxy-role subjects: - kind: ServiceAccount - name: k8-operator-controller-manager - namespace: k8-operator-system + name: infisical-operator-controller-manager + namespace: infisical-operator-system --- apiVersion: v1 kind: Service @@ -357,8 +361,8 @@ metadata: app.kubernetes.io/name: service app.kubernetes.io/part-of: k8-operator control-plane: controller-manager - name: k8-operator-controller-manager-metrics-service - namespace: k8-operator-system + name: infisical-operator-controller-manager-metrics-service + namespace: infisical-operator-system spec: ports: - name: https @@ -379,8 +383,8 @@ metadata: app.kubernetes.io/name: deployment app.kubernetes.io/part-of: k8-operator control-plane: controller-manager - name: k8-operator-controller-manager - namespace: k8-operator-system + name: infisical-operator-controller-manager + namespace: infisical-operator-system spec: replicas: 1 selector: @@ -467,5 +471,5 @@ spec: - ALL securityContext: runAsNonRoot: true - serviceAccountName: k8-operator-controller-manager + serviceAccountName: infisical-operator-controller-manager terminationGracePeriodSeconds: 10 diff --git a/k8-operator/packages/api/api.go b/k8-operator/packages/api/api.go index ac2cc5b25..64f8add46 100644 --- a/k8-operator/packages/api/api.go +++ b/k8-operator/packages/api/api.go @@ -13,10 +13,8 @@ import ( "golang.org/x/crypto/nacl/box" ) -const INFISICAL_URL = "https://app.infisical.com/api" - -func GetAllEnvironmentVariables(projectId string, envName string, infisicalToken string) ([]models.SingleEnvironmentVariable, error) { - envsFromApi, err := GetSecretsFromAPIUsingInfisicalToken(infisicalToken, envName, projectId) +func GetAllEnvironmentVariables(projectId string, envName string, infisicalToken string, hostAPI string) ([]models.SingleEnvironmentVariable, error) { + envsFromApi, err := GetSecretsFromAPIUsingInfisicalToken(infisicalToken, envName, projectId, hostAPI) if err != nil { return nil, err } @@ -24,7 +22,7 @@ func GetAllEnvironmentVariables(projectId string, envName string, infisicalToken return SubstituteSecrets(envsFromApi), nil } -func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string, projectId string) ([]models.SingleEnvironmentVariable, error) { +func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string, projectId string, hostAPI string) ([]models.SingleEnvironmentVariable, error) { if infisicalToken == "" || projectId == "" || envName == "" { return nil, errors.New("infisical token, project id and or environment name cannot be empty") } @@ -44,7 +42,7 @@ func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string, SetQueryParam("environment", envName). SetQueryParam("channel", "cli"). SetResult(&pullSecretsByInfisicalTokenResponse). - Get(fmt.Sprintf("%v/v1/secret/%v/service-token", INFISICAL_URL, projectId)) + Get(fmt.Sprintf("%v/v1/secret/%v/service-token", hostAPI, projectId)) if err != nil { return nil, err