From af96ec53ce11e59cb52bb59047dccd1c433713f7 Mon Sep 17 00:00:00 2001 From: Razvan-Daniel Mihai <84674+razvan@users.noreply.github.com> Date: Thu, 18 Sep 2025 14:35:32 +0200 Subject: [PATCH 1/6] secret op with crd versioning --- .../25.11.0/README.txt | 24 ++ .../manifests/secret-operator-manifests.yaml | 250 +++++++++++++ ...erator.v25.11.0.clusterserviceversion.yaml | 341 ++++++++++++++++++ .../25.11.0/metadata/annotations.yaml | 10 + 4 files changed, 625 insertions(+) create mode 100644 operators/stackable-secret-operator/25.11.0/README.txt create mode 100644 operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml create mode 100644 operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml create mode 100644 operators/stackable-secret-operator/25.11.0/metadata/annotations.yaml diff --git a/operators/stackable-secret-operator/25.11.0/README.txt b/operators/stackable-secret-operator/25.11.0/README.txt new file mode 100644 index 00000000000..622599082bc --- /dev/null +++ b/operators/stackable-secret-operator/25.11.0/README.txt @@ -0,0 +1,24 @@ + +As of today, (Sep 19), you need to install this manually after the operator is installed. + +See: https://github.com/stackabletech/secret-operator/pull/634#issuecomment-3312563238 + +--- +# Source: secret-operator/templates/secretclasses.yaml +apiVersion: secrets.stackable.tech/v1alpha1 +kind: SecretClass +metadata: + name: tls + labels: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + app.kubernetes.io/version: "0.0.0-pr640" +spec: + backend: + autoTls: + ca: + secret: + name: secret-provisioner-tls-ca + namespace: default + autoGenerate: true diff --git a/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml b/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml new file mode 100644 index 00000000000..7d50708552c --- /dev/null +++ b/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml @@ -0,0 +1,250 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: secret-operator-deployer-manifests +data: + stackable-secret-operator-scc.yaml: | + --- + apiVersion: security.openshift.io/v1 + kind: SecurityContextConstraints + metadata: + name: stackable-secret-operator-scc + annotations: + kubernetes.io/description: SCC for Stackable secret operator + allowHostDirVolumePlugin: true + allowHostIPC: false + allowHostNetwork: false + allowHostPID: false + allowHostPorts: false + allowPrivilegeEscalation: true + allowPrivilegedContainer: true # Needed because otherwise we get spec.template.spec.containers[0].volumeMounts.mountPropagation: Forbidden: Bidirectional mount propagation is available only to privileged containers + allowedCapabilities: null + defaultAddCapabilities: null + fsGroup: + type: RunAsAny + groups: [] + priority: null + readOnlyRootFilesystem: false + requiredDropCapabilities: + - MKNOD + runAsUser: + type: RunAsAny + seLinuxContext: + type: MustRunAs + supplementalGroups: + type: RunAsAny + users: [] + volumes: + - downwardAPI + - projected + - hostPath + - emptyDir + + tls.yaml: | + --- + # Source: secret-operator/templates/secretclasses.yaml + apiVersion: secrets.stackable.tech/v1alpha1 + kind: SecretClass + metadata: + name: tls + labels: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + app.kubernetes.io/version: "0.0.0-pr640" + spec: + backend: + autoTls: + ca: + secret: + name: secret-provisioner-tls-ca + namespace: default + autoGenerate: true + + csidriver.yaml: | + --- + # Source: secret-operator/templates/csidriver.yaml + apiVersion: storage.k8s.io/v1 + kind: CSIDriver + metadata: + name: secrets.stackable.tech + labels: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + app.kubernetes.io/version: "0.0.0-pr640" + spec: + attachRequired: false + podInfoOnMount: true + fsGroupPolicy: File + volumeLifecycleModes: + - Ephemeral + - Persistent + + storageclass.yaml: | + --- + apiVersion: storage.k8s.io/v1 + kind: StorageClass + metadata: + name: secrets.stackable.tech + labels: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + app.kubernetes.io/version: "25.7.0" + provisioner: secrets.stackable.tech + + service.yaml: | + --- + # Source: secret-operator/templates/service.yaml + apiVersion: v1 + kind: Service + metadata: + name: secret-operator + labels: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + app.kubernetes.io/version: "0.0.0-pr640" + spec: + selector: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + ports: + - name: conversion-webhook + protocol: TCP + port: 8443 + targetPort: 8443 + + daemonset.yaml: | + --- + # Source: secret-operator/templates/daemonset.yaml + apiVersion: apps/v1 + kind: DaemonSet + metadata: + name: secret-operator-daemonset + labels: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + app.kubernetes.io/version: "0.0.0-pr640" + spec: + selector: + matchLabels: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + template: + metadata: + labels: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + spec: + serviceAccountName: secret-operator-serviceaccount + securityContext: {} + containers: + - name: secret-operator + securityContext: + privileged: true + runAsUser: 0 + image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr640" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + env: + # The following env vars are passed as clap (think CLI) arguments to the operator. + # They are picked up by clap using the structs defied in the operator. + # (which is turn pulls in https://github.com/stackabletech/operator-rs/blob/main/crates/stackable-operator/src/cli.rs) + # You can read there about the expected values and purposes. + - name: CSI_ENDPOINT + value: /csi/csi.sock + - name: PRIVILEGED + value: "true" + # Sometimes products need to know the operator image, e.g. the opa-bundle-builder OPA + # sidecar uses the operator image. + - name: OPERATOR_IMAGE + # Tilt can use annotations as image paths, but not env variables + valueFrom: + fieldRef: + fieldPath: metadata.annotations['internal.stackable.tech/image'] + # Namespace the operator Pod is running in, e.g. used to construct the conversion + # webhook endpoint. + - name: OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + # The name of the Kubernetes Service that point to the operator Pod, e.g. used to + # construct the conversion webhook endpoint. + - name: OPERATOR_SERVICE_NAME + value: secret-operator + # Operators need to know the node name they are running on, to e.g. discover the + # Kubernetes domain name from the kubelet API. + - name: KUBERNETES_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - name: csi + mountPath: /csi + - name: mountpoint + mountPath: /var/lib/kubelet/pods + mountPropagation: Bidirectional + - name: tmp + mountPath: /tmp + - name: external-provisioner + image: "oci.stackable.tech/sdp/sig-storage/csi-provisioner:v5.2.0" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + args: + - --csi-address=/csi/csi.sock + - --feature-gates=Topology=true + - --extra-create-metadata + volumeMounts: + - name: csi + mountPath: /csi + - name: node-driver-registrar + image: "oci.stackable.tech/sdp/sig-storage/csi-node-driver-registrar:v2.13.0" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + args: + - --csi-address=/csi/csi.sock + - --kubelet-registration-path=/var/lib/kubelet/plugins/secrets.stackable.tech/csi.sock + volumeMounts: + - name: registration-sock + mountPath: /registration + - name: csi + mountPath: /csi + volumes: + - name: registration-sock + hostPath: + # node-driver-registrar appends a driver-unique filename to this path to avoid conflicts + # see https://github.com/stackabletech/secret-operator/issues/229 for why this path should not be too long + path: /var/lib/kubelet/plugins_registry + - name: csi + hostPath: + path: /var/lib/kubelet/plugins/secrets.stackable.tech/ + - name: mountpoint + hostPath: + path: /var/lib/kubelet/pods/ + - name: tmp + emptyDir: {} diff --git a/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml b/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml new file mode 100644 index 00000000000..fc325b9bbb8 --- /dev/null +++ b/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml @@ -0,0 +1,341 @@ +--- +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + name: secret-operator.v25.11.0 + labels: + operatorframework.io/arch.amd64: supported + operatorframework.io/arch.arm64: supported + operatorframework.io/os.linux: supported + annotations: + operatorframework.io/suggested-namespace: stackable-operators + features.operators.openshift.io/cnf: "false" + features.operators.openshift.io/cni: "false" + features.operators.openshift.io/csi: "false" + features.operators.openshift.io/disconnected: "false" + features.operators.openshift.io/fips-compliant: "false" + features.operators.openshift.io/proxy-aware: "false" + features.operators.openshift.io/tls-profiles: "false" + features.operators.openshift.io/token-auth-aws: "false" + features.operators.openshift.io/token-auth-azure: "false" + features.operators.openshift.io/token-auth-gcp: "false" + support: Stackable GmbH + categories: Storage + capabilities: Full Lifecycle + description: Stackable Secret Operator + repository: https://github.com/stackabletech/secret-operator + containerImage: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr640" + +spec: + displayName: Stackable Secret Operator + description: |- + This is a Kubernetes operator to provide secret functionality to other Stackable operators. The Stackable Secret Operator + is part of the Stackable Data Platform, a curated selection of the best open source data apps like Kafka, Druid, Trino or Spark, all + working together seamlessly. Based on Kubernetes, it runs everywhere - on prem or in the cloud. + + You can install the operator using [stackablectl or helm](https://docs.stackable.tech/home/stable/secret-operator/installation.html). + + NOTE: Make sure you install this operator in a namespace called "stackable-operators". Failing to do so will result in a broken installation. + + icon: + - base64data: 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nSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEB0ggQAAAAQnSABAAAARCdIAAAAANEJEgAAAEBcSZL8f1HQsc8tcXUVAAAAAElFTkSuQmCC + mediatype: image/png + keywords: + - secret + maintainers: + - email: info@stackable.tech + name: Stackable GmbH + maturity: stable + provider: + name: Stackable GmbH + url: https://stackable.tech + version: "25.11.0" + minKubeVersion: "1.23.0" + skips: + - secret-operator.v25.3.0 + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: true + type: MultiNamespace + # OLM requires that AllNamespaces is supported in order to install webhooks. + - supported: true + type: AllNamespaces + #customresourcedefinitions: + # owned: + # # a list of CRDs that this operator owns + # # name is the metadata.name of the CRD (which is of the form .) + # - name: secretclasses.secrets.stackable.tech + # # version is the spec.versions[].name value defined in the CRD + # version: v1alpha1 + # # kind is the CamelCased singular value defined in spec.names.kind of the CRD. + # kind: SecretClass + # # human-friendly display name of the CRD for rendering in graphical consoles (optional) + # displayName: Secret classes managed by the operator. + # # a short description of the CRDs purpose for rendering in graphical consoles (optional) + # description: Secret classes managed by the operator. + # - name: secretclasses.secrets.stackable.tech + # # version is the spec.versions[].name value defined in the CRD + # version: v1alpha2 + # # kind is the CamelCased singular value defined in spec.names.kind of the CRD. + # kind: SecretClass + # # human-friendly display name of the CRD for rendering in graphical consoles (optional) + # displayName: Secret classes managed by the operator. + # # a short description of the CRDs purpose for rendering in graphical consoles (optional) + # description: Secret classes managed by the operator. Renames experimentalGenerateSamAccountName. + # - name: truststores.secrets.stackable.tech + # # version is the spec.versions[].name value defined in the CRD + # version: v1alpha1 + # # kind is the CamelCased singular value defined in spec.names.kind of the CRD. + # kind: TrustStore + # # human-friendly display name of the CRD for rendering in graphical consoles (optional) + # displayName: Trust stores managed by the operator. + # # a short description of the CRDs purpose for rendering in graphical consoles (optional) + # description: Trust stores managed by the operator. + relatedImages: + - name: secret-operator + image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr640" + - name: csi-provisioner + image: "oci.stackable.tech/sdp/sig-storage/csi-provisioner:v5.2.0" + - name: csi-node-driver-registrar + image: "oci.stackable.tech/sdp/sig-storage/csi-node-driver-registrar:v2.13.0" + install: + # strategy indicates what type of deployment artifacts are used + strategy: deployment + # spec for the deployment strategy is a list of deployment specs and required permissions - similar to a pod template used in a deployment + spec: + permissions: [] + # permissions required at the cluster scope + clusterPermissions: + - serviceAccountName: secret-operator-serviceaccount + rules: + # Required to maintain the CRD. The operator needs to do this, as it needs to enter e.g. it's + # generated certificate in the conversion webhook. + - apiGroups: [apiextensions.k8s.io] + resources: [customresourcedefinitions] + verbs: + - create + - patch + - apiGroups: + - "" + resources: + - secrets + - events + verbs: + - get + - list + - watch + - create + - patch + - update + - apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - patch + - get + - watch + - list + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - patch + - create + - delete + - apiGroups: + - "" + resources: + - configmaps + - nodes + - persistentvolumeclaims + verbs: + - get + - list + - watch + # For automatic cluster domain detection + - apiGroups: + - "" + resources: + - nodes/proxy + verbs: + - get + - apiGroups: + - storage.k8s.io + resources: + - csinodes + - storageclasses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - patch + - apiGroups: + - secrets.stackable.tech + resources: + - secretclasses + - truststores + verbs: + - get + - watch + - list + - apiGroups: + - listeners.stackable.tech + resources: + - listenerclasses + - listeners + - podlisteners + verbs: + - get + - apiGroups: + - cert-manager.io + resources: + - certificates + verbs: + - get + - patch + - create + - apiGroups: + - events.k8s.io + resources: + - events + verbs: + - create + - patch + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - stackable-secret-operator-scc + verbs: + - use + + - serviceAccountName: secret-operator-deployer + rules: + - apiGroups: + - batch + resources: + - jobs + verbs: + - get + - create + - patch + - apiGroups: + - apps + resources: + - deployments + verbs: + - get + - list + - patch + - apiGroups: + - apps + resources: + - daemonsets + verbs: + - get + - list + - watch + - create + - patch + - apiGroups: + - storage.k8s.io + resources: + - csidrivers + - storageclasses + verbs: + - get + - list + - watch + - create + - patch + - apiGroups: + - secrets.stackable.tech + resources: + - secretclasses + - truststores + verbs: + - get + - list + - watch + - create + - patch + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - get + - list + - watch + - create + - patch + - apiGroups: + - "" + resources: + - services + verbs: + - get + - create + - patch + deployments: + - name: secret-operator-deployer-25.11.0 + spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app.kubernetes.io/name: secret-operator-deployer + app.kubernetes.io/instance: secret-operator-deployer + template: + metadata: + labels: + app.kubernetes.io/name: secret-operator-deployer + app.kubernetes.io/instance: secret-operator-deployer + spec: + serviceAccountName: secret-operator-deployer + securityContext: {} + containers: + - name: secret-operator-deployer + securityContext: {} + image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr640" + imagePullPolicy: Always + command: ["/usr/bin/bash"] + args: + - "-c" + - "/usr/local/bin/stackable-secret-operator-olm-deployer run --dir /manifests --namespace $NAMESPACE --csv secret-operator.v25.11.0 --keep-alive" + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + resources: + limits: + cpu: 100m + memory: 512Mi + requests: + cpu: 100m + memory: 512Mi + volumeMounts: + - name: manifests + mountPath: /manifests + volumes: + - name: manifests + configMap: + name: secret-operator-deployer-manifests diff --git a/operators/stackable-secret-operator/25.11.0/metadata/annotations.yaml b/operators/stackable-secret-operator/25.11.0/metadata/annotations.yaml new file mode 100644 index 00000000000..7b8e0504a53 --- /dev/null +++ b/operators/stackable-secret-operator/25.11.0/metadata/annotations.yaml @@ -0,0 +1,10 @@ +--- +annotations: + operators.operatorframework.io.bundle.channel.default.v1: "25.11" + operators.operatorframework.io.bundle.channels.v1: "stable,25.11" + operators.operatorframework.io.bundle.manifests.v1: manifests/ + operators.operatorframework.io.bundle.mediatype.v1: registry+v1 + operators.operatorframework.io.bundle.metadata.v1: metadata/ + operators.operatorframework.io.bundle.package.v1: stackable-secret-operator + + com.redhat.openshift.versions: v4.11-v4.19 From d53059c914f76f422d0eb67ccf6ab6157dfbf41c Mon Sep 17 00:00:00 2001 From: Razvan-Daniel Mihai <84674+razvan@users.noreply.github.com> Date: Fri, 19 Sep 2025 17:19:48 +0200 Subject: [PATCH 2/6] delete tls from manifests --- .../manifests/secret-operator-manifests.yaml | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml b/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml index 7d50708552c..7ad133c3deb 100644 --- a/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml +++ b/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml @@ -41,27 +41,6 @@ data: - hostPath - emptyDir - tls.yaml: | - --- - # Source: secret-operator/templates/secretclasses.yaml - apiVersion: secrets.stackable.tech/v1alpha1 - kind: SecretClass - metadata: - name: tls - labels: - app.kubernetes.io/name: secret-operator - app.kubernetes.io/instance: secret-operator - stackable.tech/vendor: Stackable - app.kubernetes.io/version: "0.0.0-pr640" - spec: - backend: - autoTls: - ca: - secret: - name: secret-provisioner-tls-ca - namespace: default - autoGenerate: true - csidriver.yaml: | --- # Source: secret-operator/templates/csidriver.yaml From 89b67cea1d35dab3ace1a40f90a92a7b4d8290ba Mon Sep 17 00:00:00 2001 From: Razvan-Daniel Mihai <84674+razvan@users.noreply.github.com> Date: Thu, 23 Oct 2025 10:48:41 +0200 Subject: [PATCH 3/6] update to latest version of the helm chart --- .../25.11.0/manifests/SecretClass.yml | 825 ++++++++++++++++++ .../25.11.0/manifests/TrustStore.yml | 64 ++ .../manifests/secret-operator-manifests.yaml | 32 +- ...erator.v25.11.0.clusterserviceversion.yaml | 143 ++- 4 files changed, 1018 insertions(+), 46 deletions(-) create mode 100644 operators/stackable-secret-operator/25.11.0/manifests/SecretClass.yml create mode 100644 operators/stackable-secret-operator/25.11.0/manifests/TrustStore.yml diff --git a/operators/stackable-secret-operator/25.11.0/manifests/SecretClass.yml b/operators/stackable-secret-operator/25.11.0/manifests/SecretClass.yml new file mode 100644 index 00000000000..4a644b109db --- /dev/null +++ b/operators/stackable-secret-operator/25.11.0/manifests/SecretClass.yml @@ -0,0 +1,825 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: secretclasses.secrets.stackable.tech +spec: + group: secrets.stackable.tech + names: + categories: [] + kind: SecretClass + plural: secretclasses + shortNames: [] + singular: secretclass + scope: Cluster + versions: + - additionalPrinterColumns: [] + name: v1alpha2 + schema: + openAPIV3Schema: + description: Auto-generated derived type for SecretClassSpec via `CustomResource` + properties: + spec: + description: |- + A [SecretClass](https://docs.stackable.tech/home/nightly/secret-operator/secretclass) is a cluster-global Kubernetes resource + that defines a category of secrets that the Secret Operator knows how to provision. + properties: + backend: + description: |- + Each SecretClass is associated with a single + [backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend), + which dictates the mechanism for issuing that kind of Secret. + oneOf: + - required: + - k8sSearch + - required: + - autoTls + - required: + - experimentalCertManager + - required: + - kerberosKeytab + properties: + autoTls: + description: |- + The [`autoTls` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-autotls) + issues a TLS certificate signed by the Secret Operator. + The certificate authority can be provided by the administrator, or managed automatically by the Secret Operator. + + A new certificate and key pair will be generated and signed for each Pod, keys or certificates are never reused. + properties: + additionalTrustRoots: + default: [] + description: Additional trust roots which are added to the provided `ca.crt` file. + items: + oneOf: + - required: + - configMap + - required: + - secret + properties: + configMap: + description: |- + Reference (name and namespace) to a Kubernetes ConfigMap object where additional + certificates are stored. + The extensions of the keys denote its contents: A key suffixed with `.crt` contains a stack + of base64 encoded DER certificates, a key suffixed with `.der` contains a binary DER + certificate. + properties: + name: + description: Name of the ConfigMap being referred to. + type: string + namespace: + description: Namespace of the ConfigMap being referred to. + type: string + required: + - name + - namespace + type: object + secret: + description: |- + Reference (name and namespace) to a Kubernetes Secret object where additional certificates + are stored. + The extensions of the keys denote its contents: A key suffixed with `.crt` contains a stack + of base64 encoded DER certificates, a key suffixed with `.der` contains a binary DER + certificate. + properties: + name: + description: Name of the Secret being referred to. + type: string + namespace: + description: Namespace of the Secret being referred to. + type: string + required: + - name + - namespace + type: object + type: object + type: array + ca: + description: Configures the certificate authority used to issue Pod certificates. + properties: + autoGenerate: + default: false + description: |- + Whether the certificate authority should be managed by Secret Operator, including being generated + if it does not already exist. + type: boolean + caCertificateLifetime: + default: 365d + description: |- + The lifetime of each generated certificate authority. + + Should always be more than double `maxCertificateLifetime`. + + If `autoGenerate: true` then the Secret Operator will prepare a new CA certificate the old CA approaches expiration. + If `autoGenerate: false` then the Secret Operator will log a warning instead. + type: string + keyGeneration: + default: + rsa: + length: 2048 + description: |- + The algorithm used to generate a key pair and required configuration settings. + Currently only RSA and a key length of 2048, 3072 or 4096 bits can be configured. + oneOf: + - required: + - rsa + properties: + rsa: + properties: + length: + description: |- + The amount of bits used for generating the RSA keypair. + Currently, `2048`, `3072` and `4096` are supported. Defaults to `2048` bits. + enum: + - 2048 + - 3072 + - 4096 + type: integer + required: + - length + type: object + type: object + secret: + description: |- + Reference (name and namespace) to a Kubernetes Secret object where the CA certificate + and key is stored in the keys `ca.crt` and `ca.key` respectively. + properties: + name: + description: Name of the Secret being referred to. + type: string + namespace: + description: Namespace of the Secret being referred to. + type: string + required: + - name + - namespace + type: object + required: + - secret + type: object + maxCertificateLifetime: + default: 15d + description: |- + Maximum lifetime the created certificates are allowed to have. + In case consumers request a longer lifetime than allowed by this setting, + the lifetime will be the minimum of both, so this setting takes precedence. + The default value is 15 days. + type: string + required: + - ca + type: object + experimentalCertManager: + description: |- + The [`experimentalCertManager` backend][1] injects a TLS certificate issued + by [cert-manager](https://cert-manager.io/). + + A new certificate will be requested the first time it is used by a Pod, it + will be reused after that (subject to cert-manager renewal rules). + + [1]: https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-certmanager + properties: + defaultCertificateLifetime: + default: 1d + description: |- + The default lifetime of certificates. + + Defaults to 1 day. This may need to be increased for external issuers that impose rate limits (such as Let's Encrypt). + type: string + issuer: + description: A reference to the cert-manager issuer that the certificates should be requested from. + properties: + kind: + description: |- + The kind of the issuer, Issuer or ClusterIssuer. + + If Issuer then it must be in the same namespace as the Pods using it. + enum: + - Issuer + - ClusterIssuer + type: string + name: + description: The name of the issuer. + type: string + required: + - kind + - name + type: object + keyGeneration: + default: + rsa: + length: 2048 + description: |- + The algorithm used to generate a key pair and required configuration settings. + Currently only RSA and a key length of 2048, 3072 or 4096 bits can be configured. + oneOf: + - required: + - rsa + properties: + rsa: + properties: + length: + description: |- + The amount of bits used for generating the RSA keypair. + Currently, `2048`, `3072` and `4096` are supported. Defaults to `2048` bits. + enum: + - 2048 + - 3072 + - 4096 + type: integer + required: + - length + type: object + type: object + required: + - issuer + type: object + k8sSearch: + description: |- + The [`k8sSearch` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-k8ssearch) + can be used to mount Secrets across namespaces into Pods. + properties: + searchNamespace: + description: Configures the namespace searched for Secret objects. + oneOf: + - required: + - pod + - required: + - name + properties: + name: + description: |- + The Secret objects are located in a single global namespace. + Should be used for secrets that are provisioned by the cluster administrator. + type: string + pod: + description: |- + The Secret objects are located in the same namespace as the Pod object. + Should be used for Secrets that are provisioned by the application administrator. + type: object + type: object + trustStoreConfigMapName: + description: |- + Name of a ConfigMap that contains the information required to validate against this SecretClass. + + Resolved relative to `search_namespace`. + + Required to request a TrustStore for this SecretClass. + nullable: true + type: string + required: + - searchNamespace + type: object + kerberosKeytab: + description: |- + The [`kerberosKeytab` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-kerberoskeytab) + creates a Kerberos keytab file for a selected realm. + The Kerberos KDC and administrator credentials must be provided by the administrator. + properties: + admin: + description: Kerberos admin configuration settings. + oneOf: + - required: + - mit + - required: + - activeDirectory + properties: + activeDirectory: + description: Credentials should be provisioned in a Microsoft Active Directory domain. + properties: + generateSamAccountName: + description: |- + Allows samAccountName generation for new accounts to be customized. + Note that setting this field (even if empty) makes the Secret Operator take + over the generation duty from the domain controller. + nullable: true + properties: + prefix: + default: '' + description: A prefix to be prepended to generated samAccountNames. + type: string + totalLength: + default: 20 + description: |- + The total length of generated samAccountNames, _including_ `prefix`. + Must be larger than the length of `prefix`, but at most `20`. + + Note that this should be as large as possible, to minimize the risk of collisions. + format: uint8 + maximum: 255.0 + minimum: 0.0 + type: integer + type: object + ldapServer: + description: |- + An AD LDAP server, such as the AD Domain Controller. + This must match the server’s FQDN, or GSSAPI authentication will fail. + type: string + ldapTlsCaSecret: + description: |- + Reference (name and namespace) to a Kubernetes Secret object containing + the TLS CA (in `ca.crt`) that the LDAP server’s certificate should be authenticated against. + properties: + name: + description: Name of the Secret being referred to. + type: string + namespace: + description: Namespace of the Secret being referred to. + type: string + required: + - name + - namespace + type: object + passwordCacheSecret: + description: |- + Reference (name and namespace) to a Kubernetes Secret object where workload + passwords will be stored. This must not be accessible to end users. + properties: + name: + description: Name of the Secret being referred to. + type: string + namespace: + description: Namespace of the Secret being referred to. + type: string + required: + - name + - namespace + type: object + schemaDistinguishedName: + description: |- + The root Distinguished Name (DN) for AD-managed schemas, + typically `CN=Schema,CN=Configuration,{domain_dn}`. + type: string + userDistinguishedName: + description: |- + The root Distinguished Name (DN) where service accounts should be provisioned, + typically `CN=Users,{domain_dn}`. + type: string + required: + - ldapServer + - ldapTlsCaSecret + - passwordCacheSecret + - schemaDistinguishedName + - userDistinguishedName + type: object + mit: + description: Credentials should be provisioned in a MIT Kerberos Admin Server. + properties: + kadminServer: + description: |- + The hostname of the Kerberos Admin Server. + This should be provided by the Kerberos administrator. + type: string + required: + - kadminServer + type: object + type: object + adminKeytabSecret: + description: |- + Reference (`name` and `namespace`) to a K8s Secret object where a + keytab with administrative privileges is stored in the key `keytab`. + properties: + name: + description: Name of the Secret being referred to. + type: string + namespace: + description: Namespace of the Secret being referred to. + type: string + required: + - name + - namespace + type: object + adminPrincipal: + description: The admin principal. + type: string + kdc: + description: |- + The hostname of the Kerberos Key Distribution Center (KDC). + This should be provided by the Kerberos administrator. + type: string + realmName: + description: The name of the Kerberos realm. This should be provided by the Kerberos administrator. + type: string + required: + - admin + - adminKeytabSecret + - adminPrincipal + - kdc + - realmName + type: object + type: object + required: + - backend + type: object + required: + - spec + title: SecretClass + type: object + served: true + storage: true + subresources: {} + - additionalPrinterColumns: [] + name: v1alpha1 + schema: + openAPIV3Schema: + description: Auto-generated derived type for SecretClassSpec via `CustomResource` + properties: + spec: + description: |- + A [SecretClass](https://docs.stackable.tech/home/nightly/secret-operator/secretclass) is a cluster-global Kubernetes resource + that defines a category of secrets that the Secret Operator knows how to provision. + properties: + backend: + description: |- + Each SecretClass is associated with a single + [backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend), + which dictates the mechanism for issuing that kind of Secret. + oneOf: + - required: + - k8sSearch + - required: + - autoTls + - required: + - experimentalCertManager + - required: + - kerberosKeytab + properties: + autoTls: + description: |- + The [`autoTls` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-autotls) + issues a TLS certificate signed by the Secret Operator. + The certificate authority can be provided by the administrator, or managed automatically by the Secret Operator. + + A new certificate and key pair will be generated and signed for each Pod, keys or certificates are never reused. + properties: + additionalTrustRoots: + default: [] + description: Additional trust roots which are added to the provided `ca.crt` file. + items: + oneOf: + - required: + - configMap + - required: + - secret + properties: + configMap: + description: |- + Reference (name and namespace) to a Kubernetes ConfigMap object where additional + certificates are stored. + The extensions of the keys denote its contents: A key suffixed with `.crt` contains a stack + of base64 encoded DER certificates, a key suffixed with `.der` contains a binary DER + certificate. + properties: + name: + description: Name of the ConfigMap being referred to. + type: string + namespace: + description: Namespace of the ConfigMap being referred to. + type: string + required: + - name + - namespace + type: object + secret: + description: |- + Reference (name and namespace) to a Kubernetes Secret object where additional certificates + are stored. + The extensions of the keys denote its contents: A key suffixed with `.crt` contains a stack + of base64 encoded DER certificates, a key suffixed with `.der` contains a binary DER + certificate. + properties: + name: + description: Name of the Secret being referred to. + type: string + namespace: + description: Namespace of the Secret being referred to. + type: string + required: + - name + - namespace + type: object + type: object + type: array + ca: + description: Configures the certificate authority used to issue Pod certificates. + properties: + autoGenerate: + default: false + description: |- + Whether the certificate authority should be managed by Secret Operator, including being generated + if it does not already exist. + type: boolean + caCertificateLifetime: + default: 365d + description: |- + The lifetime of each generated certificate authority. + + Should always be more than double `maxCertificateLifetime`. + + If `autoGenerate: true` then the Secret Operator will prepare a new CA certificate the old CA approaches expiration. + If `autoGenerate: false` then the Secret Operator will log a warning instead. + type: string + keyGeneration: + default: + rsa: + length: 2048 + description: |- + The algorithm used to generate a key pair and required configuration settings. + Currently only RSA and a key length of 2048, 3072 or 4096 bits can be configured. + oneOf: + - required: + - rsa + properties: + rsa: + properties: + length: + description: |- + The amount of bits used for generating the RSA keypair. + Currently, `2048`, `3072` and `4096` are supported. Defaults to `2048` bits. + enum: + - 2048 + - 3072 + - 4096 + type: integer + required: + - length + type: object + type: object + secret: + description: |- + Reference (name and namespace) to a Kubernetes Secret object where the CA certificate + and key is stored in the keys `ca.crt` and `ca.key` respectively. + properties: + name: + description: Name of the Secret being referred to. + type: string + namespace: + description: Namespace of the Secret being referred to. + type: string + required: + - name + - namespace + type: object + required: + - secret + type: object + maxCertificateLifetime: + default: 15d + description: |- + Maximum lifetime the created certificates are allowed to have. + In case consumers request a longer lifetime than allowed by this setting, + the lifetime will be the minimum of both, so this setting takes precedence. + The default value is 15 days. + type: string + required: + - ca + type: object + experimentalCertManager: + description: |- + The [`experimentalCertManager` backend][1] injects a TLS certificate issued + by [cert-manager](https://cert-manager.io/). + + A new certificate will be requested the first time it is used by a Pod, it + will be reused after that (subject to cert-manager renewal rules). + + [1]: https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-certmanager + properties: + defaultCertificateLifetime: + default: 1d + description: |- + The default lifetime of certificates. + + Defaults to 1 day. This may need to be increased for external issuers that impose rate limits (such as Let's Encrypt). + type: string + issuer: + description: A reference to the cert-manager issuer that the certificates should be requested from. + properties: + kind: + description: |- + The kind of the issuer, Issuer or ClusterIssuer. + + If Issuer then it must be in the same namespace as the Pods using it. + enum: + - Issuer + - ClusterIssuer + type: string + name: + description: The name of the issuer. + type: string + required: + - kind + - name + type: object + keyGeneration: + default: + rsa: + length: 2048 + description: |- + The algorithm used to generate a key pair and required configuration settings. + Currently only RSA and a key length of 2048, 3072 or 4096 bits can be configured. + oneOf: + - required: + - rsa + properties: + rsa: + properties: + length: + description: |- + The amount of bits used for generating the RSA keypair. + Currently, `2048`, `3072` and `4096` are supported. Defaults to `2048` bits. + enum: + - 2048 + - 3072 + - 4096 + type: integer + required: + - length + type: object + type: object + required: + - issuer + type: object + k8sSearch: + description: |- + The [`k8sSearch` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-k8ssearch) + can be used to mount Secrets across namespaces into Pods. + properties: + searchNamespace: + description: Configures the namespace searched for Secret objects. + oneOf: + - required: + - pod + - required: + - name + properties: + name: + description: |- + The Secret objects are located in a single global namespace. + Should be used for secrets that are provisioned by the cluster administrator. + type: string + pod: + description: |- + The Secret objects are located in the same namespace as the Pod object. + Should be used for Secrets that are provisioned by the application administrator. + type: object + type: object + trustStoreConfigMapName: + description: |- + Name of a ConfigMap that contains the information required to validate against this SecretClass. + + Resolved relative to `search_namespace`. + + Required to request a TrustStore for this SecretClass. + nullable: true + type: string + required: + - searchNamespace + type: object + kerberosKeytab: + description: |- + The [`kerberosKeytab` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-kerberoskeytab) + creates a Kerberos keytab file for a selected realm. + The Kerberos KDC and administrator credentials must be provided by the administrator. + properties: + admin: + description: Kerberos admin configuration settings. + oneOf: + - required: + - mit + - required: + - activeDirectory + properties: + activeDirectory: + description: Credentials should be provisioned in a Microsoft Active Directory domain. + properties: + experimentalGenerateSamAccountName: + description: |- + Allows samAccountName generation for new accounts to be customized. + Note that setting this field (even if empty) makes the Secret Operator take + over the generation duty from the domain controller. + nullable: true + properties: + prefix: + default: '' + description: A prefix to be prepended to generated samAccountNames. + type: string + totalLength: + default: 20 + description: |- + The total length of generated samAccountNames, _including_ `prefix`. + Must be larger than the length of `prefix`, but at most `20`. + + Note that this should be as large as possible, to minimize the risk of collisions. + format: uint8 + maximum: 255.0 + minimum: 0.0 + type: integer + type: object + ldapServer: + description: |- + An AD LDAP server, such as the AD Domain Controller. + This must match the server’s FQDN, or GSSAPI authentication will fail. + type: string + ldapTlsCaSecret: + description: |- + Reference (name and namespace) to a Kubernetes Secret object containing + the TLS CA (in `ca.crt`) that the LDAP server’s certificate should be authenticated against. + properties: + name: + description: Name of the Secret being referred to. + type: string + namespace: + description: Namespace of the Secret being referred to. + type: string + required: + - name + - namespace + type: object + passwordCacheSecret: + description: |- + Reference (name and namespace) to a Kubernetes Secret object where workload + passwords will be stored. This must not be accessible to end users. + properties: + name: + description: Name of the Secret being referred to. + type: string + namespace: + description: Namespace of the Secret being referred to. + type: string + required: + - name + - namespace + type: object + schemaDistinguishedName: + description: |- + The root Distinguished Name (DN) for AD-managed schemas, + typically `CN=Schema,CN=Configuration,{domain_dn}`. + type: string + userDistinguishedName: + description: |- + The root Distinguished Name (DN) where service accounts should be provisioned, + typically `CN=Users,{domain_dn}`. + type: string + required: + - ldapServer + - ldapTlsCaSecret + - passwordCacheSecret + - schemaDistinguishedName + - userDistinguishedName + type: object + mit: + description: Credentials should be provisioned in a MIT Kerberos Admin Server. + properties: + kadminServer: + description: |- + The hostname of the Kerberos Admin Server. + This should be provided by the Kerberos administrator. + type: string + required: + - kadminServer + type: object + type: object + adminKeytabSecret: + description: |- + Reference (`name` and `namespace`) to a K8s Secret object where a + keytab with administrative privileges is stored in the key `keytab`. + properties: + name: + description: Name of the Secret being referred to. + type: string + namespace: + description: Namespace of the Secret being referred to. + type: string + required: + - name + - namespace + type: object + adminPrincipal: + description: The admin principal. + type: string + kdc: + description: |- + The hostname of the Kerberos Key Distribution Center (KDC). + This should be provided by the Kerberos administrator. + type: string + realmName: + description: The name of the Kerberos realm. This should be provided by the Kerberos administrator. + type: string + required: + - admin + - adminKeytabSecret + - adminPrincipal + - kdc + - realmName + type: object + type: object + required: + - backend + type: object + required: + - spec + title: SecretClass + type: object + served: true + storage: false + subresources: {} diff --git a/operators/stackable-secret-operator/25.11.0/manifests/TrustStore.yml b/operators/stackable-secret-operator/25.11.0/manifests/TrustStore.yml new file mode 100644 index 00000000000..b6c8d610b69 --- /dev/null +++ b/operators/stackable-secret-operator/25.11.0/manifests/TrustStore.yml @@ -0,0 +1,64 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: truststores.secrets.stackable.tech +spec: + group: secrets.stackable.tech + names: + categories: [] + kind: TrustStore + plural: truststores + shortNames: [] + singular: truststore + scope: Namespaced + versions: + - additionalPrinterColumns: [] + name: v1alpha1 + schema: + openAPIV3Schema: + description: Auto-generated derived type for TrustStoreSpec via `CustomResource` + properties: + spec: + description: |- + A [TrustStore](https://docs.stackable.tech/home/nightly/secret-operator/truststore) requests information about how to + validate secrets issued by a [SecretClass](https://docs.stackable.tech/home/nightly/secret-operator/secretclass). + + The requested information is written to a ConfigMap with the same name as the TrustStore. + properties: + format: + description: The [format](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#format) that the data should be converted into. + enum: + - tls-pem + - tls-pkcs12 + - kerberos + - null + nullable: true + type: string + secretClassName: + description: The name of the SecretClass that the request concerns. + type: string + targetKind: + default: ConfigMap + description: |- + Which Kubernetes kind should be used to output the requested information to. + + The trust information (such as a `ca.crt`) can be considered public information, so we put + it in a `ConfigMap` by default. However, some tools might require it to be placed in a + `Secret`, so we also support that. + + Can be either `ConfigMap` or `Secret`, defaults to `ConfigMap`. + enum: + - Secret + - ConfigMap + type: string + required: + - secretClassName + type: object + required: + - spec + title: TrustStore + type: object + served: true + storage: true + subresources: {} diff --git a/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml b/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml index 7ad133c3deb..cf874f8425d 100644 --- a/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml +++ b/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml @@ -52,7 +52,7 @@ data: app.kubernetes.io/name: secret-operator app.kubernetes.io/instance: secret-operator stackable.tech/vendor: Stackable - app.kubernetes.io/version: "0.0.0-pr640" + app.kubernetes.io/version: "0.0.0-dev" spec: attachRequired: false podInfoOnMount: true @@ -71,7 +71,7 @@ data: app.kubernetes.io/name: secret-operator app.kubernetes.io/instance: secret-operator stackable.tech/vendor: Stackable - app.kubernetes.io/version: "25.7.0" + app.kubernetes.io/version: "0.0.0-dev" provisioner: secrets.stackable.tech service.yaml: | @@ -85,9 +85,10 @@ data: app.kubernetes.io/name: secret-operator app.kubernetes.io/instance: secret-operator stackable.tech/vendor: Stackable - app.kubernetes.io/version: "0.0.0-pr640" + app.kubernetes.io/version: "0.0.0-dev" spec: selector: + webhook.stackable.tech/conversion: enabled app.kubernetes.io/name: secret-operator app.kubernetes.io/instance: secret-operator stackable.tech/vendor: Stackable @@ -99,16 +100,16 @@ data: daemonset.yaml: | --- - # Source: secret-operator/templates/daemonset.yaml + # Source: secret-operator/templates/csi-node-driver-daemonset.yaml apiVersion: apps/v1 kind: DaemonSet metadata: - name: secret-operator-daemonset + name: secret-operator-csi-node-driver labels: app.kubernetes.io/name: secret-operator app.kubernetes.io/instance: secret-operator stackable.tech/vendor: Stackable - app.kubernetes.io/version: "0.0.0-pr640" + app.kubernetes.io/version: "0.0.0-dev" spec: selector: matchLabels: @@ -117,19 +118,22 @@ data: stackable.tech/vendor: Stackable template: metadata: + annotations: + internal.stackable.tech/image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" labels: app.kubernetes.io/name: secret-operator app.kubernetes.io/instance: secret-operator stackable.tech/vendor: Stackable spec: + # NOTE (@Techassi): Does it maybe make sense to have two different service accounts? serviceAccountName: secret-operator-serviceaccount securityContext: {} containers: - - name: secret-operator + - name: csi-node-service securityContext: privileged: true runAsUser: 0 - image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr640" + image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" imagePullPolicy: IfNotPresent resources: limits: @@ -138,6 +142,12 @@ data: requests: cpu: 100m memory: 128Mi + # The arguments passed to the command being run in the container. The final command will + # look like `secret-operator run csi-server [OPTIONS]`. The CSI server needs to run on + # every Kubernetes cluster node and as such is deployed as a DaemonSet. + args: + - run + - csi-node-service env: # The following env vars are passed as clap (think CLI) arguments to the operator. # They are picked up by clap using the structs defied in the operator. @@ -170,6 +180,8 @@ data: valueFrom: fieldRef: fieldPath: spec.nodeName + # The namespace that the TLS Certificate Authority is installed into. + # Internally defaults to the namespace where secret-operator is installed. volumeMounts: - name: csi mountPath: /csi @@ -179,7 +191,7 @@ data: - name: tmp mountPath: /tmp - name: external-provisioner - image: "oci.stackable.tech/sdp/sig-storage/csi-provisioner:v5.2.0" + image: "oci.stackable.tech/sdp/sig-storage/csi-provisioner:v5.3.0" imagePullPolicy: IfNotPresent resources: limits: @@ -196,7 +208,7 @@ data: - name: csi mountPath: /csi - name: node-driver-registrar - image: "oci.stackable.tech/sdp/sig-storage/csi-node-driver-registrar:v2.13.0" + image: "oci.stackable.tech/sdp/sig-storage/csi-node-driver-registrar:v2.15.0" imagePullPolicy: IfNotPresent resources: limits: diff --git a/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml b/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml index fc325b9bbb8..78786a2fe0c 100644 --- a/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml +++ b/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml @@ -24,7 +24,7 @@ metadata: capabilities: Full Lifecycle description: Stackable Secret Operator repository: https://github.com/stackabletech/secret-operator - containerImage: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr640" + containerImage: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" spec: displayName: Stackable Secret Operator @@ -63,44 +63,44 @@ spec: # OLM requires that AllNamespaces is supported in order to install webhooks. - supported: true type: AllNamespaces - #customresourcedefinitions: - # owned: - # # a list of CRDs that this operator owns - # # name is the metadata.name of the CRD (which is of the form .) - # - name: secretclasses.secrets.stackable.tech - # # version is the spec.versions[].name value defined in the CRD - # version: v1alpha1 - # # kind is the CamelCased singular value defined in spec.names.kind of the CRD. - # kind: SecretClass - # # human-friendly display name of the CRD for rendering in graphical consoles (optional) - # displayName: Secret classes managed by the operator. - # # a short description of the CRDs purpose for rendering in graphical consoles (optional) - # description: Secret classes managed by the operator. - # - name: secretclasses.secrets.stackable.tech - # # version is the spec.versions[].name value defined in the CRD - # version: v1alpha2 - # # kind is the CamelCased singular value defined in spec.names.kind of the CRD. - # kind: SecretClass - # # human-friendly display name of the CRD for rendering in graphical consoles (optional) - # displayName: Secret classes managed by the operator. - # # a short description of the CRDs purpose for rendering in graphical consoles (optional) - # description: Secret classes managed by the operator. Renames experimentalGenerateSamAccountName. - # - name: truststores.secrets.stackable.tech - # # version is the spec.versions[].name value defined in the CRD - # version: v1alpha1 - # # kind is the CamelCased singular value defined in spec.names.kind of the CRD. - # kind: TrustStore - # # human-friendly display name of the CRD for rendering in graphical consoles (optional) - # displayName: Trust stores managed by the operator. - # # a short description of the CRDs purpose for rendering in graphical consoles (optional) - # description: Trust stores managed by the operator. + customresourcedefinitions: + owned: + # a list of CRDs that this operator owns + # name is the metadata.name of the CRD (which is of the form .) + - name: secretclasses.secrets.stackable.tech + # version is the spec.versions[].name value defined in the CRD + version: v1alpha1 + # kind is the CamelCased singular value defined in spec.names.kind of the CRD. + kind: SecretClass + # human-friendly display name of the CRD for rendering in graphical consoles (optional) + displayName: Secret classes managed by the operator. + # a short description of the CRDs purpose for rendering in graphical consoles (optional) + description: Secret classes managed by the operator. + - name: secretclasses.secrets.stackable.tech + # version is the spec.versions[].name value defined in the CRD + version: v1alpha2 + # kind is the CamelCased singular value defined in spec.names.kind of the CRD. + kind: SecretClass + # human-friendly display name of the CRD for rendering in graphical consoles (optional) + displayName: Secret classes managed by the operator. + # a short description of the CRDs purpose for rendering in graphical consoles (optional) + description: Secret classes managed by the operator. Renames experimentalGenerateSamAccountName. + - name: truststores.secrets.stackable.tech + # version is the spec.versions[].name value defined in the CRD + version: v1alpha1 + # kind is the CamelCased singular value defined in spec.names.kind of the CRD. + kind: TrustStore + # human-friendly display name of the CRD for rendering in graphical consoles (optional) + displayName: Trust stores managed by the operator. + # a short description of the CRDs purpose for rendering in graphical consoles (optional) + description: Trust stores managed by the operator. relatedImages: - name: secret-operator - image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr640" + image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" - name: csi-provisioner - image: "oci.stackable.tech/sdp/sig-storage/csi-provisioner:v5.2.0" + image: "oci.stackable.tech/sdp/sig-storage/csi-provisioner:v5.3.0" - name: csi-node-driver-registrar - image: "oci.stackable.tech/sdp/sig-storage/csi-node-driver-registrar:v2.13.0" + image: "oci.stackable.tech/sdp/sig-storage/csi-node-driver-registrar:v2.15.0" install: # strategy indicates what type of deployment artifacts are used strategy: deployment @@ -190,6 +190,8 @@ spec: - secretclasses - truststores verbs: + - create + - patch - get - watch - list @@ -294,6 +296,75 @@ spec: - create - patch deployments: + - name: secret-operator + spec: + selector: + matchLabels: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + template: + metadata: + annotations: + internal.stackable.tech/image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" + labels: + webhook.stackable.tech/conversion: enabled + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + spec: + # NOTE (@Techassi): Does it maybe make sense to have two different service accounts? + serviceAccountName: secret-operator-serviceaccount + securityContext: {} + containers: + - name: secret-operator + securityContext: + runAsUser: 0 + image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + # The arguments passed to the command being run in the container. The final command will + # look like `secret-operator run controller [OPTIONS]`. The controller needs to only run + # once in a Kubernetes cluster and as such is deployed as a Deployment with a single + # replica. + args: + - run + - controller + env: + # The following env vars are passed as clap (think CLI) arguments to the operator. + # They are picked up by clap using the structs defied in the operator. + # (which is turn pulls in https://github.com/stackabletech/operator-rs/blob/main/crates/stackable-operator/src/cli.rs) + # You can read there about the expected values and purposes. + + # Sometimes products need to know the operator image, e.g. the opa-bundle-builder OPA + # sidecar uses the operator image. + - name: OPERATOR_IMAGE + # Tilt can use annotations as image paths, but not env variables + valueFrom: + fieldRef: + fieldPath: metadata.annotations['internal.stackable.tech/image'] + # Namespace the operator Pod is running in, e.g. used to construct the conversion + # webhook endpoint. + - name: OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + # The name of the Kubernetes Service that point to the operator Pod, e.g. used to + # construct the conversion webhook endpoint. + - name: OPERATOR_SERVICE_NAME + value: secret-operator + # Operators need to know the node name they are running on, to e.g. discover the + # Kubernetes domain name from the kubelet API. + - name: KUBERNETES_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName - name: secret-operator-deployer-25.11.0 spec: replicas: 1 @@ -314,7 +385,7 @@ spec: containers: - name: secret-operator-deployer securityContext: {} - image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr640" + image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" imagePullPolicy: Always command: ["/usr/bin/bash"] args: From 75a0a1f9894326c003fd06746c68e05346fb3662 Mon Sep 17 00:00:00 2001 From: Razvan-Daniel Mihai <84674+razvan@users.noreply.github.com> Date: Thu, 23 Oct 2025 11:56:05 +0200 Subject: [PATCH 4/6] move secret op deployment to manifests --- .../manifests/secret-operator-manifests.yaml | 91 +++++++++++++++++-- ...erator.v25.11.0.clusterserviceversion.yaml | 76 +--------------- 2 files changed, 89 insertions(+), 78 deletions(-) diff --git a/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml b/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml index cf874f8425d..892dfe5a2b5 100644 --- a/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml +++ b/operators/stackable-secret-operator/25.11.0/manifests/secret-operator-manifests.yaml @@ -52,7 +52,7 @@ data: app.kubernetes.io/name: secret-operator app.kubernetes.io/instance: secret-operator stackable.tech/vendor: Stackable - app.kubernetes.io/version: "0.0.0-dev" + app.kubernetes.io/version: "0.0.0-pr648" spec: attachRequired: false podInfoOnMount: true @@ -71,7 +71,7 @@ data: app.kubernetes.io/name: secret-operator app.kubernetes.io/instance: secret-operator stackable.tech/vendor: Stackable - app.kubernetes.io/version: "0.0.0-dev" + app.kubernetes.io/version: "0.0.0-pr648" provisioner: secrets.stackable.tech service.yaml: | @@ -85,7 +85,7 @@ data: app.kubernetes.io/name: secret-operator app.kubernetes.io/instance: secret-operator stackable.tech/vendor: Stackable - app.kubernetes.io/version: "0.0.0-dev" + app.kubernetes.io/version: "0.0.0-pr648" spec: selector: webhook.stackable.tech/conversion: enabled @@ -109,7 +109,7 @@ data: app.kubernetes.io/name: secret-operator app.kubernetes.io/instance: secret-operator stackable.tech/vendor: Stackable - app.kubernetes.io/version: "0.0.0-dev" + app.kubernetes.io/version: "0.0.0-pr648" spec: selector: matchLabels: @@ -119,7 +119,7 @@ data: template: metadata: annotations: - internal.stackable.tech/image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" + internal.stackable.tech/image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr648" labels: app.kubernetes.io/name: secret-operator app.kubernetes.io/instance: secret-operator @@ -133,7 +133,7 @@ data: securityContext: privileged: true runAsUser: 0 - image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" + image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr648" imagePullPolicy: IfNotPresent resources: limits: @@ -239,3 +239,82 @@ data: path: /var/lib/kubelet/pods/ - name: tmp emptyDir: {} + deployment.yaml: | + --- + apiVersion: apps/v1 + kind: Deployment + metadata: + name: secret-operator + labels: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + app.kubernetes.io/version: "0.0.0-pr648" + spec: + selector: + matchLabels: + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + template: + metadata: + annotations: + internal.stackable.tech/image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr648" + labels: + webhook.stackable.tech/conversion: enabled + app.kubernetes.io/name: secret-operator + app.kubernetes.io/instance: secret-operator + stackable.tech/vendor: Stackable + spec: + # NOTE (@Techassi): Does it maybe make sense to have two different service accounts? + serviceAccountName: secret-operator-serviceaccount + securityContext: {} + containers: + - name: secret-operator + securityContext: + runAsUser: 0 + image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr648" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + # The arguments passed to the command being run in the container. The final command will + # look like `secret-operator run controller [OPTIONS]`. The controller needs to only run + # once in a Kubernetes cluster and as such is deployed as a Deployment with a single + # replica. + args: + - run + - controller + env: + # The following env vars are passed as clap (think CLI) arguments to the operator. + # They are picked up by clap using the structs defied in the operator. + # (which is turn pulls in https://github.com/stackabletech/operator-rs/blob/main/crates/stackable-operator/src/cli.rs) + # You can read there about the expected values and purposes. + + # Sometimes products need to know the operator image, e.g. the opa-bundle-builder OPA + # sidecar uses the operator image. + - name: OPERATOR_IMAGE + # Tilt can use annotations as image paths, but not env variables + valueFrom: + fieldRef: + fieldPath: metadata.annotations['internal.stackable.tech/image'] + # Namespace the operator Pod is running in, e.g. used to construct the conversion + # webhook endpoint. + - name: OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + # The name of the Kubernetes Service that point to the operator Pod, e.g. used to + # construct the conversion webhook endpoint. + - name: OPERATOR_SERVICE_NAME + value: secret-operator + # Operators need to know the node name they are running on, to e.g. discover the + # Kubernetes domain name from the kubelet API. + - name: KUBERNETES_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName diff --git a/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml b/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml index 78786a2fe0c..0879344fd37 100644 --- a/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml +++ b/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml @@ -24,7 +24,7 @@ metadata: capabilities: Full Lifecycle description: Stackable Secret Operator repository: https://github.com/stackabletech/secret-operator - containerImage: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" + containerImage: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr648" spec: displayName: Stackable Secret Operator @@ -96,7 +96,7 @@ spec: description: Trust stores managed by the operator. relatedImages: - name: secret-operator - image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" + image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr648" - name: csi-provisioner image: "oci.stackable.tech/sdp/sig-storage/csi-provisioner:v5.3.0" - name: csi-node-driver-registrar @@ -244,6 +244,7 @@ spec: verbs: - get - list + - create - patch - apiGroups: - apps @@ -296,75 +297,6 @@ spec: - create - patch deployments: - - name: secret-operator - spec: - selector: - matchLabels: - app.kubernetes.io/name: secret-operator - app.kubernetes.io/instance: secret-operator - stackable.tech/vendor: Stackable - template: - metadata: - annotations: - internal.stackable.tech/image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" - labels: - webhook.stackable.tech/conversion: enabled - app.kubernetes.io/name: secret-operator - app.kubernetes.io/instance: secret-operator - stackable.tech/vendor: Stackable - spec: - # NOTE (@Techassi): Does it maybe make sense to have two different service accounts? - serviceAccountName: secret-operator-serviceaccount - securityContext: {} - containers: - - name: secret-operator - securityContext: - runAsUser: 0 - image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" - imagePullPolicy: IfNotPresent - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - # The arguments passed to the command being run in the container. The final command will - # look like `secret-operator run controller [OPTIONS]`. The controller needs to only run - # once in a Kubernetes cluster and as such is deployed as a Deployment with a single - # replica. - args: - - run - - controller - env: - # The following env vars are passed as clap (think CLI) arguments to the operator. - # They are picked up by clap using the structs defied in the operator. - # (which is turn pulls in https://github.com/stackabletech/operator-rs/blob/main/crates/stackable-operator/src/cli.rs) - # You can read there about the expected values and purposes. - - # Sometimes products need to know the operator image, e.g. the opa-bundle-builder OPA - # sidecar uses the operator image. - - name: OPERATOR_IMAGE - # Tilt can use annotations as image paths, but not env variables - valueFrom: - fieldRef: - fieldPath: metadata.annotations['internal.stackable.tech/image'] - # Namespace the operator Pod is running in, e.g. used to construct the conversion - # webhook endpoint. - - name: OPERATOR_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - # The name of the Kubernetes Service that point to the operator Pod, e.g. used to - # construct the conversion webhook endpoint. - - name: OPERATOR_SERVICE_NAME - value: secret-operator - # Operators need to know the node name they are running on, to e.g. discover the - # Kubernetes domain name from the kubelet API. - - name: KUBERNETES_NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - name: secret-operator-deployer-25.11.0 spec: replicas: 1 @@ -385,7 +317,7 @@ spec: containers: - name: secret-operator-deployer securityContext: {} - image: "oci.stackable.tech/sdp/secret-operator:0.0.0-dev" + image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr648" imagePullPolicy: Always command: ["/usr/bin/bash"] args: From 348f60cf4888bb4cb145b279a2b142dd0bd97660 Mon Sep 17 00:00:00 2001 From: Razvan-Daniel Mihai <84674+razvan@users.noreply.github.com> Date: Thu, 23 Oct 2025 15:19:47 +0200 Subject: [PATCH 5/6] remove crd manifests --- .../25.11.0/manifests/SecretClass.yml | 825 ------------------ .../25.11.0/manifests/TrustStore.yml | 64 -- ...erator.v25.11.0.clusterserviceversion.yaml | 31 - 3 files changed, 920 deletions(-) delete mode 100644 operators/stackable-secret-operator/25.11.0/manifests/SecretClass.yml delete mode 100644 operators/stackable-secret-operator/25.11.0/manifests/TrustStore.yml diff --git a/operators/stackable-secret-operator/25.11.0/manifests/SecretClass.yml b/operators/stackable-secret-operator/25.11.0/manifests/SecretClass.yml deleted file mode 100644 index 4a644b109db..00000000000 --- a/operators/stackable-secret-operator/25.11.0/manifests/SecretClass.yml +++ /dev/null @@ -1,825 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: secretclasses.secrets.stackable.tech -spec: - group: secrets.stackable.tech - names: - categories: [] - kind: SecretClass - plural: secretclasses - shortNames: [] - singular: secretclass - scope: Cluster - versions: - - additionalPrinterColumns: [] - name: v1alpha2 - schema: - openAPIV3Schema: - description: Auto-generated derived type for SecretClassSpec via `CustomResource` - properties: - spec: - description: |- - A [SecretClass](https://docs.stackable.tech/home/nightly/secret-operator/secretclass) is a cluster-global Kubernetes resource - that defines a category of secrets that the Secret Operator knows how to provision. - properties: - backend: - description: |- - Each SecretClass is associated with a single - [backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend), - which dictates the mechanism for issuing that kind of Secret. - oneOf: - - required: - - k8sSearch - - required: - - autoTls - - required: - - experimentalCertManager - - required: - - kerberosKeytab - properties: - autoTls: - description: |- - The [`autoTls` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-autotls) - issues a TLS certificate signed by the Secret Operator. - The certificate authority can be provided by the administrator, or managed automatically by the Secret Operator. - - A new certificate and key pair will be generated and signed for each Pod, keys or certificates are never reused. - properties: - additionalTrustRoots: - default: [] - description: Additional trust roots which are added to the provided `ca.crt` file. - items: - oneOf: - - required: - - configMap - - required: - - secret - properties: - configMap: - description: |- - Reference (name and namespace) to a Kubernetes ConfigMap object where additional - certificates are stored. - The extensions of the keys denote its contents: A key suffixed with `.crt` contains a stack - of base64 encoded DER certificates, a key suffixed with `.der` contains a binary DER - certificate. - properties: - name: - description: Name of the ConfigMap being referred to. - type: string - namespace: - description: Namespace of the ConfigMap being referred to. - type: string - required: - - name - - namespace - type: object - secret: - description: |- - Reference (name and namespace) to a Kubernetes Secret object where additional certificates - are stored. - The extensions of the keys denote its contents: A key suffixed with `.crt` contains a stack - of base64 encoded DER certificates, a key suffixed with `.der` contains a binary DER - certificate. - properties: - name: - description: Name of the Secret being referred to. - type: string - namespace: - description: Namespace of the Secret being referred to. - type: string - required: - - name - - namespace - type: object - type: object - type: array - ca: - description: Configures the certificate authority used to issue Pod certificates. - properties: - autoGenerate: - default: false - description: |- - Whether the certificate authority should be managed by Secret Operator, including being generated - if it does not already exist. - type: boolean - caCertificateLifetime: - default: 365d - description: |- - The lifetime of each generated certificate authority. - - Should always be more than double `maxCertificateLifetime`. - - If `autoGenerate: true` then the Secret Operator will prepare a new CA certificate the old CA approaches expiration. - If `autoGenerate: false` then the Secret Operator will log a warning instead. - type: string - keyGeneration: - default: - rsa: - length: 2048 - description: |- - The algorithm used to generate a key pair and required configuration settings. - Currently only RSA and a key length of 2048, 3072 or 4096 bits can be configured. - oneOf: - - required: - - rsa - properties: - rsa: - properties: - length: - description: |- - The amount of bits used for generating the RSA keypair. - Currently, `2048`, `3072` and `4096` are supported. Defaults to `2048` bits. - enum: - - 2048 - - 3072 - - 4096 - type: integer - required: - - length - type: object - type: object - secret: - description: |- - Reference (name and namespace) to a Kubernetes Secret object where the CA certificate - and key is stored in the keys `ca.crt` and `ca.key` respectively. - properties: - name: - description: Name of the Secret being referred to. - type: string - namespace: - description: Namespace of the Secret being referred to. - type: string - required: - - name - - namespace - type: object - required: - - secret - type: object - maxCertificateLifetime: - default: 15d - description: |- - Maximum lifetime the created certificates are allowed to have. - In case consumers request a longer lifetime than allowed by this setting, - the lifetime will be the minimum of both, so this setting takes precedence. - The default value is 15 days. - type: string - required: - - ca - type: object - experimentalCertManager: - description: |- - The [`experimentalCertManager` backend][1] injects a TLS certificate issued - by [cert-manager](https://cert-manager.io/). - - A new certificate will be requested the first time it is used by a Pod, it - will be reused after that (subject to cert-manager renewal rules). - - [1]: https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-certmanager - properties: - defaultCertificateLifetime: - default: 1d - description: |- - The default lifetime of certificates. - - Defaults to 1 day. This may need to be increased for external issuers that impose rate limits (such as Let's Encrypt). - type: string - issuer: - description: A reference to the cert-manager issuer that the certificates should be requested from. - properties: - kind: - description: |- - The kind of the issuer, Issuer or ClusterIssuer. - - If Issuer then it must be in the same namespace as the Pods using it. - enum: - - Issuer - - ClusterIssuer - type: string - name: - description: The name of the issuer. - type: string - required: - - kind - - name - type: object - keyGeneration: - default: - rsa: - length: 2048 - description: |- - The algorithm used to generate a key pair and required configuration settings. - Currently only RSA and a key length of 2048, 3072 or 4096 bits can be configured. - oneOf: - - required: - - rsa - properties: - rsa: - properties: - length: - description: |- - The amount of bits used for generating the RSA keypair. - Currently, `2048`, `3072` and `4096` are supported. Defaults to `2048` bits. - enum: - - 2048 - - 3072 - - 4096 - type: integer - required: - - length - type: object - type: object - required: - - issuer - type: object - k8sSearch: - description: |- - The [`k8sSearch` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-k8ssearch) - can be used to mount Secrets across namespaces into Pods. - properties: - searchNamespace: - description: Configures the namespace searched for Secret objects. - oneOf: - - required: - - pod - - required: - - name - properties: - name: - description: |- - The Secret objects are located in a single global namespace. - Should be used for secrets that are provisioned by the cluster administrator. - type: string - pod: - description: |- - The Secret objects are located in the same namespace as the Pod object. - Should be used for Secrets that are provisioned by the application administrator. - type: object - type: object - trustStoreConfigMapName: - description: |- - Name of a ConfigMap that contains the information required to validate against this SecretClass. - - Resolved relative to `search_namespace`. - - Required to request a TrustStore for this SecretClass. - nullable: true - type: string - required: - - searchNamespace - type: object - kerberosKeytab: - description: |- - The [`kerberosKeytab` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-kerberoskeytab) - creates a Kerberos keytab file for a selected realm. - The Kerberos KDC and administrator credentials must be provided by the administrator. - properties: - admin: - description: Kerberos admin configuration settings. - oneOf: - - required: - - mit - - required: - - activeDirectory - properties: - activeDirectory: - description: Credentials should be provisioned in a Microsoft Active Directory domain. - properties: - generateSamAccountName: - description: |- - Allows samAccountName generation for new accounts to be customized. - Note that setting this field (even if empty) makes the Secret Operator take - over the generation duty from the domain controller. - nullable: true - properties: - prefix: - default: '' - description: A prefix to be prepended to generated samAccountNames. - type: string - totalLength: - default: 20 - description: |- - The total length of generated samAccountNames, _including_ `prefix`. - Must be larger than the length of `prefix`, but at most `20`. - - Note that this should be as large as possible, to minimize the risk of collisions. - format: uint8 - maximum: 255.0 - minimum: 0.0 - type: integer - type: object - ldapServer: - description: |- - An AD LDAP server, such as the AD Domain Controller. - This must match the server’s FQDN, or GSSAPI authentication will fail. - type: string - ldapTlsCaSecret: - description: |- - Reference (name and namespace) to a Kubernetes Secret object containing - the TLS CA (in `ca.crt`) that the LDAP server’s certificate should be authenticated against. - properties: - name: - description: Name of the Secret being referred to. - type: string - namespace: - description: Namespace of the Secret being referred to. - type: string - required: - - name - - namespace - type: object - passwordCacheSecret: - description: |- - Reference (name and namespace) to a Kubernetes Secret object where workload - passwords will be stored. This must not be accessible to end users. - properties: - name: - description: Name of the Secret being referred to. - type: string - namespace: - description: Namespace of the Secret being referred to. - type: string - required: - - name - - namespace - type: object - schemaDistinguishedName: - description: |- - The root Distinguished Name (DN) for AD-managed schemas, - typically `CN=Schema,CN=Configuration,{domain_dn}`. - type: string - userDistinguishedName: - description: |- - The root Distinguished Name (DN) where service accounts should be provisioned, - typically `CN=Users,{domain_dn}`. - type: string - required: - - ldapServer - - ldapTlsCaSecret - - passwordCacheSecret - - schemaDistinguishedName - - userDistinguishedName - type: object - mit: - description: Credentials should be provisioned in a MIT Kerberos Admin Server. - properties: - kadminServer: - description: |- - The hostname of the Kerberos Admin Server. - This should be provided by the Kerberos administrator. - type: string - required: - - kadminServer - type: object - type: object - adminKeytabSecret: - description: |- - Reference (`name` and `namespace`) to a K8s Secret object where a - keytab with administrative privileges is stored in the key `keytab`. - properties: - name: - description: Name of the Secret being referred to. - type: string - namespace: - description: Namespace of the Secret being referred to. - type: string - required: - - name - - namespace - type: object - adminPrincipal: - description: The admin principal. - type: string - kdc: - description: |- - The hostname of the Kerberos Key Distribution Center (KDC). - This should be provided by the Kerberos administrator. - type: string - realmName: - description: The name of the Kerberos realm. This should be provided by the Kerberos administrator. - type: string - required: - - admin - - adminKeytabSecret - - adminPrincipal - - kdc - - realmName - type: object - type: object - required: - - backend - type: object - required: - - spec - title: SecretClass - type: object - served: true - storage: true - subresources: {} - - additionalPrinterColumns: [] - name: v1alpha1 - schema: - openAPIV3Schema: - description: Auto-generated derived type for SecretClassSpec via `CustomResource` - properties: - spec: - description: |- - A [SecretClass](https://docs.stackable.tech/home/nightly/secret-operator/secretclass) is a cluster-global Kubernetes resource - that defines a category of secrets that the Secret Operator knows how to provision. - properties: - backend: - description: |- - Each SecretClass is associated with a single - [backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend), - which dictates the mechanism for issuing that kind of Secret. - oneOf: - - required: - - k8sSearch - - required: - - autoTls - - required: - - experimentalCertManager - - required: - - kerberosKeytab - properties: - autoTls: - description: |- - The [`autoTls` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-autotls) - issues a TLS certificate signed by the Secret Operator. - The certificate authority can be provided by the administrator, or managed automatically by the Secret Operator. - - A new certificate and key pair will be generated and signed for each Pod, keys or certificates are never reused. - properties: - additionalTrustRoots: - default: [] - description: Additional trust roots which are added to the provided `ca.crt` file. - items: - oneOf: - - required: - - configMap - - required: - - secret - properties: - configMap: - description: |- - Reference (name and namespace) to a Kubernetes ConfigMap object where additional - certificates are stored. - The extensions of the keys denote its contents: A key suffixed with `.crt` contains a stack - of base64 encoded DER certificates, a key suffixed with `.der` contains a binary DER - certificate. - properties: - name: - description: Name of the ConfigMap being referred to. - type: string - namespace: - description: Namespace of the ConfigMap being referred to. - type: string - required: - - name - - namespace - type: object - secret: - description: |- - Reference (name and namespace) to a Kubernetes Secret object where additional certificates - are stored. - The extensions of the keys denote its contents: A key suffixed with `.crt` contains a stack - of base64 encoded DER certificates, a key suffixed with `.der` contains a binary DER - certificate. - properties: - name: - description: Name of the Secret being referred to. - type: string - namespace: - description: Namespace of the Secret being referred to. - type: string - required: - - name - - namespace - type: object - type: object - type: array - ca: - description: Configures the certificate authority used to issue Pod certificates. - properties: - autoGenerate: - default: false - description: |- - Whether the certificate authority should be managed by Secret Operator, including being generated - if it does not already exist. - type: boolean - caCertificateLifetime: - default: 365d - description: |- - The lifetime of each generated certificate authority. - - Should always be more than double `maxCertificateLifetime`. - - If `autoGenerate: true` then the Secret Operator will prepare a new CA certificate the old CA approaches expiration. - If `autoGenerate: false` then the Secret Operator will log a warning instead. - type: string - keyGeneration: - default: - rsa: - length: 2048 - description: |- - The algorithm used to generate a key pair and required configuration settings. - Currently only RSA and a key length of 2048, 3072 or 4096 bits can be configured. - oneOf: - - required: - - rsa - properties: - rsa: - properties: - length: - description: |- - The amount of bits used for generating the RSA keypair. - Currently, `2048`, `3072` and `4096` are supported. Defaults to `2048` bits. - enum: - - 2048 - - 3072 - - 4096 - type: integer - required: - - length - type: object - type: object - secret: - description: |- - Reference (name and namespace) to a Kubernetes Secret object where the CA certificate - and key is stored in the keys `ca.crt` and `ca.key` respectively. - properties: - name: - description: Name of the Secret being referred to. - type: string - namespace: - description: Namespace of the Secret being referred to. - type: string - required: - - name - - namespace - type: object - required: - - secret - type: object - maxCertificateLifetime: - default: 15d - description: |- - Maximum lifetime the created certificates are allowed to have. - In case consumers request a longer lifetime than allowed by this setting, - the lifetime will be the minimum of both, so this setting takes precedence. - The default value is 15 days. - type: string - required: - - ca - type: object - experimentalCertManager: - description: |- - The [`experimentalCertManager` backend][1] injects a TLS certificate issued - by [cert-manager](https://cert-manager.io/). - - A new certificate will be requested the first time it is used by a Pod, it - will be reused after that (subject to cert-manager renewal rules). - - [1]: https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-certmanager - properties: - defaultCertificateLifetime: - default: 1d - description: |- - The default lifetime of certificates. - - Defaults to 1 day. This may need to be increased for external issuers that impose rate limits (such as Let's Encrypt). - type: string - issuer: - description: A reference to the cert-manager issuer that the certificates should be requested from. - properties: - kind: - description: |- - The kind of the issuer, Issuer or ClusterIssuer. - - If Issuer then it must be in the same namespace as the Pods using it. - enum: - - Issuer - - ClusterIssuer - type: string - name: - description: The name of the issuer. - type: string - required: - - kind - - name - type: object - keyGeneration: - default: - rsa: - length: 2048 - description: |- - The algorithm used to generate a key pair and required configuration settings. - Currently only RSA and a key length of 2048, 3072 or 4096 bits can be configured. - oneOf: - - required: - - rsa - properties: - rsa: - properties: - length: - description: |- - The amount of bits used for generating the RSA keypair. - Currently, `2048`, `3072` and `4096` are supported. Defaults to `2048` bits. - enum: - - 2048 - - 3072 - - 4096 - type: integer - required: - - length - type: object - type: object - required: - - issuer - type: object - k8sSearch: - description: |- - The [`k8sSearch` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-k8ssearch) - can be used to mount Secrets across namespaces into Pods. - properties: - searchNamespace: - description: Configures the namespace searched for Secret objects. - oneOf: - - required: - - pod - - required: - - name - properties: - name: - description: |- - The Secret objects are located in a single global namespace. - Should be used for secrets that are provisioned by the cluster administrator. - type: string - pod: - description: |- - The Secret objects are located in the same namespace as the Pod object. - Should be used for Secrets that are provisioned by the application administrator. - type: object - type: object - trustStoreConfigMapName: - description: |- - Name of a ConfigMap that contains the information required to validate against this SecretClass. - - Resolved relative to `search_namespace`. - - Required to request a TrustStore for this SecretClass. - nullable: true - type: string - required: - - searchNamespace - type: object - kerberosKeytab: - description: |- - The [`kerberosKeytab` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-kerberoskeytab) - creates a Kerberos keytab file for a selected realm. - The Kerberos KDC and administrator credentials must be provided by the administrator. - properties: - admin: - description: Kerberos admin configuration settings. - oneOf: - - required: - - mit - - required: - - activeDirectory - properties: - activeDirectory: - description: Credentials should be provisioned in a Microsoft Active Directory domain. - properties: - experimentalGenerateSamAccountName: - description: |- - Allows samAccountName generation for new accounts to be customized. - Note that setting this field (even if empty) makes the Secret Operator take - over the generation duty from the domain controller. - nullable: true - properties: - prefix: - default: '' - description: A prefix to be prepended to generated samAccountNames. - type: string - totalLength: - default: 20 - description: |- - The total length of generated samAccountNames, _including_ `prefix`. - Must be larger than the length of `prefix`, but at most `20`. - - Note that this should be as large as possible, to minimize the risk of collisions. - format: uint8 - maximum: 255.0 - minimum: 0.0 - type: integer - type: object - ldapServer: - description: |- - An AD LDAP server, such as the AD Domain Controller. - This must match the server’s FQDN, or GSSAPI authentication will fail. - type: string - ldapTlsCaSecret: - description: |- - Reference (name and namespace) to a Kubernetes Secret object containing - the TLS CA (in `ca.crt`) that the LDAP server’s certificate should be authenticated against. - properties: - name: - description: Name of the Secret being referred to. - type: string - namespace: - description: Namespace of the Secret being referred to. - type: string - required: - - name - - namespace - type: object - passwordCacheSecret: - description: |- - Reference (name and namespace) to a Kubernetes Secret object where workload - passwords will be stored. This must not be accessible to end users. - properties: - name: - description: Name of the Secret being referred to. - type: string - namespace: - description: Namespace of the Secret being referred to. - type: string - required: - - name - - namespace - type: object - schemaDistinguishedName: - description: |- - The root Distinguished Name (DN) for AD-managed schemas, - typically `CN=Schema,CN=Configuration,{domain_dn}`. - type: string - userDistinguishedName: - description: |- - The root Distinguished Name (DN) where service accounts should be provisioned, - typically `CN=Users,{domain_dn}`. - type: string - required: - - ldapServer - - ldapTlsCaSecret - - passwordCacheSecret - - schemaDistinguishedName - - userDistinguishedName - type: object - mit: - description: Credentials should be provisioned in a MIT Kerberos Admin Server. - properties: - kadminServer: - description: |- - The hostname of the Kerberos Admin Server. - This should be provided by the Kerberos administrator. - type: string - required: - - kadminServer - type: object - type: object - adminKeytabSecret: - description: |- - Reference (`name` and `namespace`) to a K8s Secret object where a - keytab with administrative privileges is stored in the key `keytab`. - properties: - name: - description: Name of the Secret being referred to. - type: string - namespace: - description: Namespace of the Secret being referred to. - type: string - required: - - name - - namespace - type: object - adminPrincipal: - description: The admin principal. - type: string - kdc: - description: |- - The hostname of the Kerberos Key Distribution Center (KDC). - This should be provided by the Kerberos administrator. - type: string - realmName: - description: The name of the Kerberos realm. This should be provided by the Kerberos administrator. - type: string - required: - - admin - - adminKeytabSecret - - adminPrincipal - - kdc - - realmName - type: object - type: object - required: - - backend - type: object - required: - - spec - title: SecretClass - type: object - served: true - storage: false - subresources: {} diff --git a/operators/stackable-secret-operator/25.11.0/manifests/TrustStore.yml b/operators/stackable-secret-operator/25.11.0/manifests/TrustStore.yml deleted file mode 100644 index b6c8d610b69..00000000000 --- a/operators/stackable-secret-operator/25.11.0/manifests/TrustStore.yml +++ /dev/null @@ -1,64 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: truststores.secrets.stackable.tech -spec: - group: secrets.stackable.tech - names: - categories: [] - kind: TrustStore - plural: truststores - shortNames: [] - singular: truststore - scope: Namespaced - versions: - - additionalPrinterColumns: [] - name: v1alpha1 - schema: - openAPIV3Schema: - description: Auto-generated derived type for TrustStoreSpec via `CustomResource` - properties: - spec: - description: |- - A [TrustStore](https://docs.stackable.tech/home/nightly/secret-operator/truststore) requests information about how to - validate secrets issued by a [SecretClass](https://docs.stackable.tech/home/nightly/secret-operator/secretclass). - - The requested information is written to a ConfigMap with the same name as the TrustStore. - properties: - format: - description: The [format](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#format) that the data should be converted into. - enum: - - tls-pem - - tls-pkcs12 - - kerberos - - null - nullable: true - type: string - secretClassName: - description: The name of the SecretClass that the request concerns. - type: string - targetKind: - default: ConfigMap - description: |- - Which Kubernetes kind should be used to output the requested information to. - - The trust information (such as a `ca.crt`) can be considered public information, so we put - it in a `ConfigMap` by default. However, some tools might require it to be placed in a - `Secret`, so we also support that. - - Can be either `ConfigMap` or `Secret`, defaults to `ConfigMap`. - enum: - - Secret - - ConfigMap - type: string - required: - - secretClassName - type: object - required: - - spec - title: TrustStore - type: object - served: true - storage: true - subresources: {} diff --git a/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml b/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml index 0879344fd37..9f369290f88 100644 --- a/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml +++ b/operators/stackable-secret-operator/25.11.0/manifests/stackable-secret-operator.v25.11.0.clusterserviceversion.yaml @@ -63,37 +63,6 @@ spec: # OLM requires that AllNamespaces is supported in order to install webhooks. - supported: true type: AllNamespaces - customresourcedefinitions: - owned: - # a list of CRDs that this operator owns - # name is the metadata.name of the CRD (which is of the form .) - - name: secretclasses.secrets.stackable.tech - # version is the spec.versions[].name value defined in the CRD - version: v1alpha1 - # kind is the CamelCased singular value defined in spec.names.kind of the CRD. - kind: SecretClass - # human-friendly display name of the CRD for rendering in graphical consoles (optional) - displayName: Secret classes managed by the operator. - # a short description of the CRDs purpose for rendering in graphical consoles (optional) - description: Secret classes managed by the operator. - - name: secretclasses.secrets.stackable.tech - # version is the spec.versions[].name value defined in the CRD - version: v1alpha2 - # kind is the CamelCased singular value defined in spec.names.kind of the CRD. - kind: SecretClass - # human-friendly display name of the CRD for rendering in graphical consoles (optional) - displayName: Secret classes managed by the operator. - # a short description of the CRDs purpose for rendering in graphical consoles (optional) - description: Secret classes managed by the operator. Renames experimentalGenerateSamAccountName. - - name: truststores.secrets.stackable.tech - # version is the spec.versions[].name value defined in the CRD - version: v1alpha1 - # kind is the CamelCased singular value defined in spec.names.kind of the CRD. - kind: TrustStore - # human-friendly display name of the CRD for rendering in graphical consoles (optional) - displayName: Trust stores managed by the operator. - # a short description of the CRDs purpose for rendering in graphical consoles (optional) - description: Trust stores managed by the operator. relatedImages: - name: secret-operator image: "oci.stackable.tech/sdp/secret-operator:0.0.0-pr648" From 41fc53d747fb12425370d661938c49aff1ed5289 Mon Sep 17 00:00:00 2001 From: Razvan-Daniel Mihai <84674+razvan@users.noreply.github.com> Date: Thu, 23 Oct 2025 15:33:05 +0200 Subject: [PATCH 6/6] delete readme --- .../25.11.0/README.txt | 24 ------------------- 1 file changed, 24 deletions(-) delete mode 100644 operators/stackable-secret-operator/25.11.0/README.txt diff --git a/operators/stackable-secret-operator/25.11.0/README.txt b/operators/stackable-secret-operator/25.11.0/README.txt deleted file mode 100644 index 622599082bc..00000000000 --- a/operators/stackable-secret-operator/25.11.0/README.txt +++ /dev/null @@ -1,24 +0,0 @@ - -As of today, (Sep 19), you need to install this manually after the operator is installed. - -See: https://github.com/stackabletech/secret-operator/pull/634#issuecomment-3312563238 - ---- -# Source: secret-operator/templates/secretclasses.yaml -apiVersion: secrets.stackable.tech/v1alpha1 -kind: SecretClass -metadata: - name: tls - labels: - app.kubernetes.io/name: secret-operator - app.kubernetes.io/instance: secret-operator - stackable.tech/vendor: Stackable - app.kubernetes.io/version: "0.0.0-pr640" -spec: - backend: - autoTls: - ca: - secret: - name: secret-provisioner-tls-ca - namespace: default - autoGenerate: true