diff --git a/docs/api-reference.md b/docs/api-reference.md index 0c1dd435..52b4dbb8 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -61645,6 +61645,13 @@ Certificate provisioner configuration. + acme + object + + ACME certificate provisioner configuration.
+ + false + selfSigned object @@ -61655,6 +61662,662 @@ Certificate provisioner configuration. +### PulsarCluster.spec.global.tls.certProvisioner.acme + + + +ACME certificate provisioner configuration. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
brokerobject + Broker self signed certificate config.
+
false
enabledboolean + Generate self signed certificates for broker, proxy and functions worker.
+
false
externalmap[string]object + External services self signed certificate config (e.g., admin console, grafana). The key is the service name, and the value contains generation config
+
false
issuerobject + ACME issuer configuration.
+
false
privateKeyobject + Cert-manager options for generating the private key.
+
false
proxyobject + Proxy self signed certificate config.
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.broker + + + +Broker self signed certificate config. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
dnsNames[]string + A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension.
+
false
generateboolean + Generate certificate for the component.
+
false
privateKeyobject + Cert-manager options for generating the private key.
+
false
secretNamestring + The name of the Kubernetes Secret where the generated certificate and key will be stored whe perComponent is enabled. Required for external services. Internal services pick up the secret name from the tls config if not specified
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.broker.privateKey + + + +Cert-manager options for generating the private key. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
algorithmstring +
+
false
encodingstring +
+
false
rotationPolicystring +
+
false
sizeinteger +
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.external[key] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
dnsNames[]string + A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension.
+
false
generateboolean + Generate certificate for the component.
+
false
privateKeyobject + Cert-manager options for generating the private key.
+
false
secretNamestring + The name of the Kubernetes Secret where the generated certificate and key will be stored whe perComponent is enabled. Required for external services. Internal services pick up the secret name from the tls config if not specified
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.external[key].privateKey + + + +Cert-manager options for generating the private key. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
algorithmstring +
+
false
encodingstring +
+
false
rotationPolicystring +
+
false
sizeinteger +
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.issuer + + + +ACME issuer configuration. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
emailstring + Email used for ACME registration.
+
false
namestring + Name of the Issuer resource.
+
false
privateKeySecretNamestring + Secret storing the ACME account private key.
+
false
serverstring + ACME server URL.
+
false
solvers[]object + ACME challenge solvers. Solvers are evaluated in order; no domain-based routing
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.issuer.solvers[index] + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
dns01object + DNS01 solver configuration.
+
false
http01object + HTTP01 solver configuration.
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.issuer.solvers[index].dns01 + + + +DNS01 solver configuration. + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
cloudDNSobject +
+
false
cloudflareobject +
+
false
route53object +
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.issuer.solvers[index].dns01.cloudDNS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
projectstring +
+
false
serviceAccountSecretKeystring +
+
false
serviceAccountSecretNamestring +
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.issuer.solvers[index].dns01.cloudflare + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
apiTokenSecretKeystring +
+
false
apiTokenSecretNamestring +
+
false
emailstring +
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.issuer.solvers[index].dns01.route53 + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
hostedZoneIdstring +
+
false
regionstring +
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.issuer.solvers[index].http01 + + + +HTTP01 solver configuration. + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
ingressClassstring + Ingress class used for HTTP01 challenge.
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.privateKey + + + +Cert-manager options for generating the private key. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
algorithmstring +
+
false
encodingstring +
+
false
rotationPolicystring +
+
false
sizeinteger +
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.proxy + + + +Proxy self signed certificate config. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
dnsNames[]string + A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension.
+
false
generateboolean + Generate certificate for the component.
+
false
privateKeyobject + Cert-manager options for generating the private key.
+
false
secretNamestring + The name of the Kubernetes Secret where the generated certificate and key will be stored whe perComponent is enabled. Required for external services. Internal services pick up the secret name from the tls config if not specified
+
false
+ + +### PulsarCluster.spec.global.tls.certProvisioner.acme.proxy.privateKey + + + +Cert-manager options for generating the private key. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
algorithmstring +
+
false
encodingstring +
+
false
rotationPolicystring +
+
false
sizeinteger +
+
false
+ + ### PulsarCluster.spec.global.tls.certProvisioner.selfSigned @@ -61777,14 +62440,14 @@ Autorecovery self signed certificate config. dnsNames []string - A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension along with the default K8s service DNS.
+ A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension.
false generate boolean - Generate self signed certificates for the component.
+ Generate certificate for the component.
false @@ -61871,14 +62534,14 @@ Bookkeeper self signed certificate config. dnsNames []string - A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension along with the default K8s service DNS.
+ A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension.
false generate boolean - Generate self signed certificates for the component.
+ Generate certificate for the component.
false @@ -61965,14 +62628,14 @@ Broker self signed certificate config. dnsNames []string - A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension along with the default K8s service DNS.
+ A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension.
false generate boolean - Generate self signed certificates for the component.
+ Generate certificate for the component.
false @@ -62059,14 +62722,14 @@ Cert-manager options for generating the private key. dnsNames []string - A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension along with the default K8s service DNS.
+ A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension.
false generate boolean - Generate self signed certificates for the component.
+ Generate certificate for the component.
false @@ -62153,14 +62816,14 @@ Functions worker self signed certificate config. dnsNames []string - A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension along with the default K8s service DNS.
+ A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension.
false generate boolean - Generate self signed certificates for the component.
+ Generate certificate for the component.
false @@ -62294,14 +62957,14 @@ Proxy self signed certificate config. dnsNames []string - A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension along with the default K8s service DNS.
+ A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension.
false generate boolean - Generate self signed certificates for the component.
+ Generate certificate for the component.
false @@ -62388,14 +63051,14 @@ Zookeeper self signed certificate config. dnsNames []string - A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension along with the default K8s service DNS.
+ A list of DNS names (and IP addresses) to include in the certificate's Subject Alternative Names (SANs) extension.
false generate boolean - Generate self signed certificates for the component.
+ Generate certificate for the component.
false diff --git a/helm/kaap/crds/autorecoveries.kaap.oss.datastax.com-v1.yml b/helm/kaap/crds/autorecoveries.kaap.oss.datastax.com-v1.yml index 332ac1e8..1fc6fd9f 100644 --- a/helm/kaap/crds/autorecoveries.kaap.oss.datastax.com-v1.yml +++ b/helm/kaap/crds/autorecoveries.kaap.oss.datastax.com-v1.yml @@ -1682,6 +1682,198 @@ spec: certProvisioner: description: "Certificate provisioner configuration." properties: + acme: + description: "ACME certificate provisioner configuration." + properties: + broker: + description: "Broker self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + enabled: + description: "Generate self signed certificates for\ + \ broker, proxy and functions worker." + type: "boolean" + external: + additionalProperties: + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject\ + \ Alternative Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key\ + \ will be stored whe perComponent is enabled.\ + \ Required for external services. Internal\ + \ services pick up the secret name from the\ + \ tls config if not specified" + type: "string" + type: "object" + description: "External services self signed certificate\ + \ config (e.g., admin console, grafana). The key\ + \ is the service name, and the value contains generation\ + \ config" + type: "object" + issuer: + description: "ACME issuer configuration." + properties: + email: + description: "Email used for ACME registration." + type: "string" + name: + description: "Name of the Issuer resource." + type: "string" + privateKeySecretName: + description: "Secret storing the ACME account\ + \ private key." + type: "string" + server: + description: "ACME server URL." + type: "string" + solvers: + description: "ACME challenge solvers. Solvers\ + \ are evaluated in order; no domain-based routing" + items: + properties: + dns01: + description: "DNS01 solver configuration." + properties: + cloudDNS: + properties: + project: + type: "string" + serviceAccountSecretKey: + type: "string" + serviceAccountSecretName: + type: "string" + type: "object" + cloudflare: + properties: + apiTokenSecretKey: + type: "string" + apiTokenSecretName: + type: "string" + email: + type: "string" + type: "object" + route53: + properties: + hostedZoneId: + type: "string" + region: + type: "string" + type: "object" + type: "object" + http01: + description: "HTTP01 solver configuration." + properties: + ingressClass: + description: "Ingress class used for\ + \ HTTP01 challenge." + type: "string" + type: "object" + type: "object" + type: "array" + type: "object" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + proxy: + description: "Proxy self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + type: "object" selfSigned: description: "Self signed certificate provisioner configuration." properties: @@ -1692,14 +1884,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1729,14 +1919,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1766,14 +1954,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1810,14 +1996,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject\ - \ Alternative Names (SANs) extension along\ - \ with the default K8s service DNS." + \ Alternative Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1853,14 +2037,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1911,14 +2093,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1948,14 +2128,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ diff --git a/helm/kaap/crds/bastions.kaap.oss.datastax.com-v1.yml b/helm/kaap/crds/bastions.kaap.oss.datastax.com-v1.yml index 98790279..24d98245 100644 --- a/helm/kaap/crds/bastions.kaap.oss.datastax.com-v1.yml +++ b/helm/kaap/crds/bastions.kaap.oss.datastax.com-v1.yml @@ -1686,6 +1686,198 @@ spec: certProvisioner: description: "Certificate provisioner configuration." properties: + acme: + description: "ACME certificate provisioner configuration." + properties: + broker: + description: "Broker self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + enabled: + description: "Generate self signed certificates for\ + \ broker, proxy and functions worker." + type: "boolean" + external: + additionalProperties: + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject\ + \ Alternative Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key\ + \ will be stored whe perComponent is enabled.\ + \ Required for external services. Internal\ + \ services pick up the secret name from the\ + \ tls config if not specified" + type: "string" + type: "object" + description: "External services self signed certificate\ + \ config (e.g., admin console, grafana). The key\ + \ is the service name, and the value contains generation\ + \ config" + type: "object" + issuer: + description: "ACME issuer configuration." + properties: + email: + description: "Email used for ACME registration." + type: "string" + name: + description: "Name of the Issuer resource." + type: "string" + privateKeySecretName: + description: "Secret storing the ACME account\ + \ private key." + type: "string" + server: + description: "ACME server URL." + type: "string" + solvers: + description: "ACME challenge solvers. Solvers\ + \ are evaluated in order; no domain-based routing" + items: + properties: + dns01: + description: "DNS01 solver configuration." + properties: + cloudDNS: + properties: + project: + type: "string" + serviceAccountSecretKey: + type: "string" + serviceAccountSecretName: + type: "string" + type: "object" + cloudflare: + properties: + apiTokenSecretKey: + type: "string" + apiTokenSecretName: + type: "string" + email: + type: "string" + type: "object" + route53: + properties: + hostedZoneId: + type: "string" + region: + type: "string" + type: "object" + type: "object" + http01: + description: "HTTP01 solver configuration." + properties: + ingressClass: + description: "Ingress class used for\ + \ HTTP01 challenge." + type: "string" + type: "object" + type: "object" + type: "array" + type: "object" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + proxy: + description: "Proxy self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + type: "object" selfSigned: description: "Self signed certificate provisioner configuration." properties: @@ -1696,14 +1888,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1733,14 +1923,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1770,14 +1958,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1814,14 +2000,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject\ - \ Alternative Names (SANs) extension along\ - \ with the default K8s service DNS." + \ Alternative Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1857,14 +2041,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1915,14 +2097,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -1952,14 +2132,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ diff --git a/helm/kaap/crds/bookkeepers.kaap.oss.datastax.com-v1.yml b/helm/kaap/crds/bookkeepers.kaap.oss.datastax.com-v1.yml index 9efe0ae1..b733eab6 100644 --- a/helm/kaap/crds/bookkeepers.kaap.oss.datastax.com-v1.yml +++ b/helm/kaap/crds/bookkeepers.kaap.oss.datastax.com-v1.yml @@ -5029,6 +5029,198 @@ spec: certProvisioner: description: "Certificate provisioner configuration." properties: + acme: + description: "ACME certificate provisioner configuration." + properties: + broker: + description: "Broker self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + enabled: + description: "Generate self signed certificates for\ + \ broker, proxy and functions worker." + type: "boolean" + external: + additionalProperties: + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject\ + \ Alternative Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key\ + \ will be stored whe perComponent is enabled.\ + \ Required for external services. Internal\ + \ services pick up the secret name from the\ + \ tls config if not specified" + type: "string" + type: "object" + description: "External services self signed certificate\ + \ config (e.g., admin console, grafana). The key\ + \ is the service name, and the value contains generation\ + \ config" + type: "object" + issuer: + description: "ACME issuer configuration." + properties: + email: + description: "Email used for ACME registration." + type: "string" + name: + description: "Name of the Issuer resource." + type: "string" + privateKeySecretName: + description: "Secret storing the ACME account\ + \ private key." + type: "string" + server: + description: "ACME server URL." + type: "string" + solvers: + description: "ACME challenge solvers. Solvers\ + \ are evaluated in order; no domain-based routing" + items: + properties: + dns01: + description: "DNS01 solver configuration." + properties: + cloudDNS: + properties: + project: + type: "string" + serviceAccountSecretKey: + type: "string" + serviceAccountSecretName: + type: "string" + type: "object" + cloudflare: + properties: + apiTokenSecretKey: + type: "string" + apiTokenSecretName: + type: "string" + email: + type: "string" + type: "object" + route53: + properties: + hostedZoneId: + type: "string" + region: + type: "string" + type: "object" + type: "object" + http01: + description: "HTTP01 solver configuration." + properties: + ingressClass: + description: "Ingress class used for\ + \ HTTP01 challenge." + type: "string" + type: "object" + type: "object" + type: "array" + type: "object" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + proxy: + description: "Proxy self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + type: "object" selfSigned: description: "Self signed certificate provisioner configuration." properties: @@ -5039,14 +5231,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5076,14 +5266,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5113,14 +5301,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5157,14 +5343,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject\ - \ Alternative Names (SANs) extension along\ - \ with the default K8s service DNS." + \ Alternative Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5200,14 +5384,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5258,14 +5440,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5295,14 +5475,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ diff --git a/helm/kaap/crds/brokers.kaap.oss.datastax.com-v1.yml b/helm/kaap/crds/brokers.kaap.oss.datastax.com-v1.yml index b654aa1c..86e1eeb1 100644 --- a/helm/kaap/crds/brokers.kaap.oss.datastax.com-v1.yml +++ b/helm/kaap/crds/brokers.kaap.oss.datastax.com-v1.yml @@ -4961,6 +4961,198 @@ spec: certProvisioner: description: "Certificate provisioner configuration." properties: + acme: + description: "ACME certificate provisioner configuration." + properties: + broker: + description: "Broker self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + enabled: + description: "Generate self signed certificates for\ + \ broker, proxy and functions worker." + type: "boolean" + external: + additionalProperties: + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject\ + \ Alternative Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key\ + \ will be stored whe perComponent is enabled.\ + \ Required for external services. Internal\ + \ services pick up the secret name from the\ + \ tls config if not specified" + type: "string" + type: "object" + description: "External services self signed certificate\ + \ config (e.g., admin console, grafana). The key\ + \ is the service name, and the value contains generation\ + \ config" + type: "object" + issuer: + description: "ACME issuer configuration." + properties: + email: + description: "Email used for ACME registration." + type: "string" + name: + description: "Name of the Issuer resource." + type: "string" + privateKeySecretName: + description: "Secret storing the ACME account\ + \ private key." + type: "string" + server: + description: "ACME server URL." + type: "string" + solvers: + description: "ACME challenge solvers. Solvers\ + \ are evaluated in order; no domain-based routing" + items: + properties: + dns01: + description: "DNS01 solver configuration." + properties: + cloudDNS: + properties: + project: + type: "string" + serviceAccountSecretKey: + type: "string" + serviceAccountSecretName: + type: "string" + type: "object" + cloudflare: + properties: + apiTokenSecretKey: + type: "string" + apiTokenSecretName: + type: "string" + email: + type: "string" + type: "object" + route53: + properties: + hostedZoneId: + type: "string" + region: + type: "string" + type: "object" + type: "object" + http01: + description: "HTTP01 solver configuration." + properties: + ingressClass: + description: "Ingress class used for\ + \ HTTP01 challenge." + type: "string" + type: "object" + type: "object" + type: "array" + type: "object" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + proxy: + description: "Proxy self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + type: "object" selfSigned: description: "Self signed certificate provisioner configuration." properties: @@ -4971,14 +5163,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5008,14 +5198,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5045,14 +5233,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5089,14 +5275,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject\ - \ Alternative Names (SANs) extension along\ - \ with the default K8s service DNS." + \ Alternative Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5132,14 +5316,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5190,14 +5372,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -5227,14 +5407,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ diff --git a/helm/kaap/crds/functionsworkers.kaap.oss.datastax.com-v1.yml b/helm/kaap/crds/functionsworkers.kaap.oss.datastax.com-v1.yml index e75c68c0..425977f3 100644 --- a/helm/kaap/crds/functionsworkers.kaap.oss.datastax.com-v1.yml +++ b/helm/kaap/crds/functionsworkers.kaap.oss.datastax.com-v1.yml @@ -2572,6 +2572,198 @@ spec: certProvisioner: description: "Certificate provisioner configuration." properties: + acme: + description: "ACME certificate provisioner configuration." + properties: + broker: + description: "Broker self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + enabled: + description: "Generate self signed certificates for\ + \ broker, proxy and functions worker." + type: "boolean" + external: + additionalProperties: + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject\ + \ Alternative Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key\ + \ will be stored whe perComponent is enabled.\ + \ Required for external services. Internal\ + \ services pick up the secret name from the\ + \ tls config if not specified" + type: "string" + type: "object" + description: "External services self signed certificate\ + \ config (e.g., admin console, grafana). The key\ + \ is the service name, and the value contains generation\ + \ config" + type: "object" + issuer: + description: "ACME issuer configuration." + properties: + email: + description: "Email used for ACME registration." + type: "string" + name: + description: "Name of the Issuer resource." + type: "string" + privateKeySecretName: + description: "Secret storing the ACME account\ + \ private key." + type: "string" + server: + description: "ACME server URL." + type: "string" + solvers: + description: "ACME challenge solvers. Solvers\ + \ are evaluated in order; no domain-based routing" + items: + properties: + dns01: + description: "DNS01 solver configuration." + properties: + cloudDNS: + properties: + project: + type: "string" + serviceAccountSecretKey: + type: "string" + serviceAccountSecretName: + type: "string" + type: "object" + cloudflare: + properties: + apiTokenSecretKey: + type: "string" + apiTokenSecretName: + type: "string" + email: + type: "string" + type: "object" + route53: + properties: + hostedZoneId: + type: "string" + region: + type: "string" + type: "object" + type: "object" + http01: + description: "HTTP01 solver configuration." + properties: + ingressClass: + description: "Ingress class used for\ + \ HTTP01 challenge." + type: "string" + type: "object" + type: "object" + type: "array" + type: "object" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + proxy: + description: "Proxy self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + type: "object" selfSigned: description: "Self signed certificate provisioner configuration." properties: @@ -2582,14 +2774,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -2619,14 +2809,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -2656,14 +2844,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -2700,14 +2886,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject\ - \ Alternative Names (SANs) extension along\ - \ with the default K8s service DNS." + \ Alternative Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -2743,14 +2927,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -2801,14 +2983,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -2838,14 +3018,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ diff --git a/helm/kaap/crds/proxies.kaap.oss.datastax.com-v1.yml b/helm/kaap/crds/proxies.kaap.oss.datastax.com-v1.yml index b245542f..74c2a820 100644 --- a/helm/kaap/crds/proxies.kaap.oss.datastax.com-v1.yml +++ b/helm/kaap/crds/proxies.kaap.oss.datastax.com-v1.yml @@ -339,6 +339,198 @@ spec: certProvisioner: description: "Certificate provisioner configuration." properties: + acme: + description: "ACME certificate provisioner configuration." + properties: + broker: + description: "Broker self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + enabled: + description: "Generate self signed certificates for\ + \ broker, proxy and functions worker." + type: "boolean" + external: + additionalProperties: + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject\ + \ Alternative Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key\ + \ will be stored whe perComponent is enabled.\ + \ Required for external services. Internal\ + \ services pick up the secret name from the\ + \ tls config if not specified" + type: "string" + type: "object" + description: "External services self signed certificate\ + \ config (e.g., admin console, grafana). The key\ + \ is the service name, and the value contains generation\ + \ config" + type: "object" + issuer: + description: "ACME issuer configuration." + properties: + email: + description: "Email used for ACME registration." + type: "string" + name: + description: "Name of the Issuer resource." + type: "string" + privateKeySecretName: + description: "Secret storing the ACME account\ + \ private key." + type: "string" + server: + description: "ACME server URL." + type: "string" + solvers: + description: "ACME challenge solvers. Solvers\ + \ are evaluated in order; no domain-based routing" + items: + properties: + dns01: + description: "DNS01 solver configuration." + properties: + cloudDNS: + properties: + project: + type: "string" + serviceAccountSecretKey: + type: "string" + serviceAccountSecretName: + type: "string" + type: "object" + cloudflare: + properties: + apiTokenSecretKey: + type: "string" + apiTokenSecretName: + type: "string" + email: + type: "string" + type: "object" + route53: + properties: + hostedZoneId: + type: "string" + region: + type: "string" + type: "object" + type: "object" + http01: + description: "HTTP01 solver configuration." + properties: + ingressClass: + description: "Ingress class used for\ + \ HTTP01 challenge." + type: "string" + type: "object" + type: "object" + type: "array" + type: "object" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + proxy: + description: "Proxy self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + type: "object" selfSigned: description: "Self signed certificate provisioner configuration." properties: @@ -349,14 +541,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -386,14 +576,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -423,14 +611,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -467,14 +653,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject\ - \ Alternative Names (SANs) extension along\ - \ with the default K8s service DNS." + \ Alternative Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -510,14 +694,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -568,14 +750,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -605,14 +785,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ diff --git a/helm/kaap/crds/pulsarclusters.kaap.oss.datastax.com-v1.yml b/helm/kaap/crds/pulsarclusters.kaap.oss.datastax.com-v1.yml index 073ada27..958a2896 100644 --- a/helm/kaap/crds/pulsarclusters.kaap.oss.datastax.com-v1.yml +++ b/helm/kaap/crds/pulsarclusters.kaap.oss.datastax.com-v1.yml @@ -14570,6 +14570,198 @@ spec: certProvisioner: description: "Certificate provisioner configuration." properties: + acme: + description: "ACME certificate provisioner configuration." + properties: + broker: + description: "Broker self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + enabled: + description: "Generate self signed certificates for\ + \ broker, proxy and functions worker." + type: "boolean" + external: + additionalProperties: + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject\ + \ Alternative Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key\ + \ will be stored whe perComponent is enabled.\ + \ Required for external services. Internal\ + \ services pick up the secret name from the\ + \ tls config if not specified" + type: "string" + type: "object" + description: "External services self signed certificate\ + \ config (e.g., admin console, grafana). The key\ + \ is the service name, and the value contains generation\ + \ config" + type: "object" + issuer: + description: "ACME issuer configuration." + properties: + email: + description: "Email used for ACME registration." + type: "string" + name: + description: "Name of the Issuer resource." + type: "string" + privateKeySecretName: + description: "Secret storing the ACME account\ + \ private key." + type: "string" + server: + description: "ACME server URL." + type: "string" + solvers: + description: "ACME challenge solvers. Solvers\ + \ are evaluated in order; no domain-based routing" + items: + properties: + dns01: + description: "DNS01 solver configuration." + properties: + cloudDNS: + properties: + project: + type: "string" + serviceAccountSecretKey: + type: "string" + serviceAccountSecretName: + type: "string" + type: "object" + cloudflare: + properties: + apiTokenSecretKey: + type: "string" + apiTokenSecretName: + type: "string" + email: + type: "string" + type: "object" + route53: + properties: + hostedZoneId: + type: "string" + region: + type: "string" + type: "object" + type: "object" + http01: + description: "HTTP01 solver configuration." + properties: + ingressClass: + description: "Ingress class used for\ + \ HTTP01 challenge." + type: "string" + type: "object" + type: "object" + type: "array" + type: "object" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + proxy: + description: "Proxy self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + type: "object" selfSigned: description: "Self signed certificate provisioner configuration." properties: @@ -14580,14 +14772,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -14617,14 +14807,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -14654,14 +14842,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -14698,14 +14884,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject\ - \ Alternative Names (SANs) extension along\ - \ with the default K8s service DNS." + \ Alternative Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -14741,14 +14925,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -14799,14 +14981,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -14836,14 +15016,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ diff --git a/helm/kaap/crds/zookeepers.kaap.oss.datastax.com-v1.yml b/helm/kaap/crds/zookeepers.kaap.oss.datastax.com-v1.yml index a3d7b677..fa3396e9 100644 --- a/helm/kaap/crds/zookeepers.kaap.oss.datastax.com-v1.yml +++ b/helm/kaap/crds/zookeepers.kaap.oss.datastax.com-v1.yml @@ -339,6 +339,198 @@ spec: certProvisioner: description: "Certificate provisioner configuration." properties: + acme: + description: "ACME certificate provisioner configuration." + properties: + broker: + description: "Broker self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + enabled: + description: "Generate self signed certificates for\ + \ broker, proxy and functions worker." + type: "boolean" + external: + additionalProperties: + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject\ + \ Alternative Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key\ + \ will be stored whe perComponent is enabled.\ + \ Required for external services. Internal\ + \ services pick up the secret name from the\ + \ tls config if not specified" + type: "string" + type: "object" + description: "External services self signed certificate\ + \ config (e.g., admin console, grafana). The key\ + \ is the service name, and the value contains generation\ + \ config" + type: "object" + issuer: + description: "ACME issuer configuration." + properties: + email: + description: "Email used for ACME registration." + type: "string" + name: + description: "Name of the Issuer resource." + type: "string" + privateKeySecretName: + description: "Secret storing the ACME account\ + \ private key." + type: "string" + server: + description: "ACME server URL." + type: "string" + solvers: + description: "ACME challenge solvers. Solvers\ + \ are evaluated in order; no domain-based routing" + items: + properties: + dns01: + description: "DNS01 solver configuration." + properties: + cloudDNS: + properties: + project: + type: "string" + serviceAccountSecretKey: + type: "string" + serviceAccountSecretName: + type: "string" + type: "object" + cloudflare: + properties: + apiTokenSecretKey: + type: "string" + apiTokenSecretName: + type: "string" + email: + type: "string" + type: "object" + route53: + properties: + hostedZoneId: + type: "string" + region: + type: "string" + type: "object" + type: "object" + http01: + description: "HTTP01 solver configuration." + properties: + ingressClass: + description: "Ingress class used for\ + \ HTTP01 challenge." + type: "string" + type: "object" + type: "object" + type: "array" + type: "object" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + proxy: + description: "Proxy self signed certificate config." + properties: + dnsNames: + description: "A list of DNS names (and IP addresses)\ + \ to include in the certificate's Subject Alternative\ + \ Names (SANs) extension." + items: + type: "string" + type: "array" + generate: + description: "Generate certificate for the component." + type: "boolean" + privateKey: + description: "Cert-manager options for generating\ + \ the private key." + properties: + algorithm: + type: "string" + encoding: + type: "string" + rotationPolicy: + type: "string" + size: + type: "integer" + type: "object" + secretName: + description: "The name of the Kubernetes Secret\ + \ where the generated certificate and key will\ + \ be stored whe perComponent is enabled. Required\ + \ for external services. Internal services pick\ + \ up the secret name from the tls config if\ + \ not specified" + type: "string" + type: "object" + type: "object" selfSigned: description: "Self signed certificate provisioner configuration." properties: @@ -349,14 +541,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -386,14 +576,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -423,14 +611,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -467,14 +653,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject\ - \ Alternative Names (SANs) extension along\ - \ with the default K8s service DNS." + \ Alternative Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -510,14 +694,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -568,14 +750,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ @@ -605,14 +785,12 @@ spec: dnsNames: description: "A list of DNS names (and IP addresses)\ \ to include in the certificate's Subject Alternative\ - \ Names (SANs) extension along with the default\ - \ K8s service DNS." + \ Names (SANs) extension." items: type: "string" type: "array" generate: - description: "Generate self signed certificates\ - \ for the component." + description: "Generate certificate for the component." type: "boolean" privateKey: description: "Cert-manager options for generating\ diff --git a/helm/kaap/templates/rbac/cluster-scoped.yaml b/helm/kaap/templates/rbac/cluster-scoped.yaml index 7d4a677f..f9ef9f3b 100644 --- a/helm/kaap/templates/rbac/cluster-scoped.yaml +++ b/helm/kaap/templates/rbac/cluster-scoped.yaml @@ -140,6 +140,7 @@ rules: - get - update - list + - patch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding diff --git a/helm/kaap/templates/rbac/namespace-scoped.yaml b/helm/kaap/templates/rbac/namespace-scoped.yaml index cbe4fc6f..033bb26c 100644 --- a/helm/kaap/templates/rbac/namespace-scoped.yaml +++ b/helm/kaap/templates/rbac/namespace-scoped.yaml @@ -160,6 +160,7 @@ rules: - get - update - list + - patch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding diff --git a/operator-common/src/test/java/com/datastax/oss/kaap/mocks/MockKubernetesClient.java b/operator-common/src/test/java/com/datastax/oss/kaap/mocks/MockKubernetesClient.java index 79e789dc..6c413a1e 100644 --- a/operator-common/src/test/java/com/datastax/oss/kaap/mocks/MockKubernetesClient.java +++ b/operator-common/src/test/java/com/datastax/oss/kaap/mocks/MockKubernetesClient.java @@ -195,6 +195,7 @@ private void mockAndInterceptResourceCreation(String namespace) { final NamespaceableResource interaction = Mockito.mock(NamespaceableResource.class); when(interaction.inNamespace(eq(namespace))).thenReturn(interaction); + when(interaction.forceConflicts()).thenReturn(interaction); when(interaction.create()).thenAnswer(ic1 -> { addCreatedResource(ic); return null; @@ -217,6 +218,7 @@ private void mockAndInterceptResourceCreation(String namespace) { final Resource resourceMock = Mockito.mock(Resource.class); when(interaction.resource(any(HasMetadata.class))).thenAnswer(ic2 -> { final Resource mockedResource = resourceMock; + when(mockedResource.forceConflicts()).thenReturn(mockedResource); when(mockedResource.create()).thenAnswer(ic3 -> { addCreatedResource(ic2); return null; diff --git a/operator/src/main/java/com/datastax/oss/kaap/controllers/utils/CertManagerCertificatesProvisioner.java b/operator/src/main/java/com/datastax/oss/kaap/controllers/utils/CertManagerCertificatesProvisioner.java index 24350688..c66af227 100644 --- a/operator/src/main/java/com/datastax/oss/kaap/controllers/utils/CertManagerCertificatesProvisioner.java +++ b/operator/src/main/java/com/datastax/oss/kaap/controllers/utils/CertManagerCertificatesProvisioner.java @@ -27,7 +27,13 @@ import com.datastax.oss.kaap.crds.GlobalSpec; import com.datastax.oss.kaap.crds.cluster.PulsarClusterSpec; import com.datastax.oss.kaap.crds.configs.tls.TlsConfig; -import com.datastax.oss.kaap.crds.configs.tls.TlsConfig.SelfSignedCertificatePerComponentConfig; +import com.datastax.oss.kaap.crds.configs.tls.TlsConfig.ComponentCertificateConfig; +import io.fabric8.certmanager.api.model.acme.v1.ACMEChallengeSolver; +import io.fabric8.certmanager.api.model.acme.v1.ACMEChallengeSolverBuilder; +import io.fabric8.certmanager.api.model.acme.v1.ACMEChallengeSolverDNS01Builder; +import io.fabric8.certmanager.api.model.acme.v1.ACMEChallengeSolverHTTP01Builder; +import io.fabric8.certmanager.api.model.acme.v1.ACMEChallengeSolverHTTP01IngressBuilder; +import io.fabric8.certmanager.api.model.acme.v1.ACMEIssuerBuilder; import io.fabric8.certmanager.api.model.v1.Certificate; import io.fabric8.certmanager.api.model.v1.CertificateBuilder; import io.fabric8.certmanager.api.model.v1.CertificatePrivateKey; @@ -37,6 +43,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; import lombok.extern.jbosslog.JBossLog; import org.apache.commons.lang3.ObjectUtils; @@ -48,6 +55,7 @@ public class CertManagerCertificatesProvisioner { private final PulsarClusterSpec pulsarClusterSpec; private final GlobalSpec globalSpec; private final TlsConfig.SelfSignedCertProvisionerConfig selfSigned; + private final TlsConfig.AcmeCertProvisionerConfig acme; private final String clusterSpecName; private final String ssCaSecretName; private final String caIssuerName; @@ -59,30 +67,36 @@ public CertManagerCertificatesProvisioner(KubernetesClient client, String namesp this.namespace = namespace; this.pulsarClusterSpec = pulsarClusterSpec; this.globalSpec = pulsarClusterSpec.getGlobalSpec(); - if (globalSpec.getTls() == null - || !globalSpec.getTls().getEnabled() - || globalSpec.getTls().getCertProvisioner() == null - || globalSpec.getTls().getCertProvisioner().getSelfSigned() == null) { + TlsConfig tls = globalSpec != null ? globalSpec.getTls() : null; + TlsConfig.CertProvisionerConfig provisioner = tls != null ? tls.getCertProvisioner() : null; + if (tls == null || !Boolean.TRUE.equals(tls.getEnabled()) || provisioner == null) { this.selfSigned = null; + this.acme = null; this.clusterSpecName = null; this.caIssuerName = null; this.ssCaSecretName = null; this.serviceDnsSuffix = null; - } else { - this.selfSigned = globalSpec.getTls().getCertProvisioner().getSelfSigned(); - this.clusterSpecName = globalSpec.getName(); - this.caIssuerName = "%s-ca-issuer".formatted(clusterSpecName); - this.ssCaSecretName = BaseResourcesFactory.getTlsSsCaSecretName(globalSpec); - this.serviceDnsSuffix = "%s.svc.%s".formatted(namespace, globalSpec.getKubernetesClusterDomain()); + return; } - + this.selfSigned = provisioner.getSelfSigned(); + this.acme = provisioner.getAcme(); + this.clusterSpecName = globalSpec.getName(); + this.caIssuerName = "%s-ca-issuer".formatted(clusterSpecName); + this.ssCaSecretName = BaseResourcesFactory.getTlsSsCaSecretName(globalSpec); + this.serviceDnsSuffix = "%s.svc.%s".formatted(namespace, globalSpec.getKubernetesClusterDomain()); } public void generateCertificates() { - if (selfSigned == null) { - return; + validateProvisionersConfig(); + if (selfSigned != null && Boolean.TRUE.equals(selfSigned.getEnabled())) { + generateSelfSignedCertificates(); + } + if (acme != null && Boolean.TRUE.equals(acme.getEnabled())) { + generateAcmeCertificates(); } + } + private void generateSelfSignedCertificates() { createRootCACertificate(); if (selfSigned.getPerComponent() == null || !selfSigned.getPerComponent()) { List dnsNames = new ArrayList<>(); @@ -112,7 +126,8 @@ public void generateCertificates() { certName, globalSpec.getTls().getDefaultSecretName(), selfSigned.getPrivateKey(), - dnsNames + dnsNames, + caIssuerName ); } else { if (TlsConfig.TlsEntryConfig.isEnabled(globalSpec.getTls().getBroker())) { @@ -120,14 +135,18 @@ public void generateCertificates() { globalSpec.getComponents().getBrokerBaseName(), ObjectUtils.firstNonNull(selfSigned.getBroker().getSecretName(), globalSpec.getTls().getBroker().getSecretName()), - getBrokerDNSNames(selfSigned.getBroker())); + getBrokerDNSNames(selfSigned.getBroker()), + caIssuerName, + selfSigned.getPrivateKey()); } if (TlsConfig.TlsEntryConfig.isEnabled(globalSpec.getTls().getBookkeeper())) { createCertificatePerComponent(selfSigned.getBookkeeper(), globalSpec.getComponents().getBookkeeperBaseName(), ObjectUtils.firstNonNull(selfSigned.getBookkeeper().getSecretName(), globalSpec.getTls().getBookkeeper().getSecretName()), - getBookKeeperDNSNames(selfSigned.getBookkeeper())); + getBookKeeperDNSNames(selfSigned.getBookkeeper()), + caIssuerName, + selfSigned.getPrivateKey()); } if (TlsConfig.TlsEntryConfig.isEnabled(globalSpec.getTls().getAutorecovery())) { createAutorecoveryCertificate(); @@ -137,14 +156,18 @@ public void generateCertificates() { globalSpec.getComponents().getProxyBaseName(), ObjectUtils.firstNonNull(selfSigned.getProxy().getSecretName(), globalSpec.getTls().getProxy().getSecretName()), - getProxyDNSNames(selfSigned.getProxy())); + getProxyDNSNames(selfSigned.getProxy()), + caIssuerName, + selfSigned.getPrivateKey()); } if (TlsConfig.TlsEntryConfig.isEnabled(globalSpec.getTls().getZookeeper())) { createCertificatePerComponent(selfSigned.getZookeeper(), globalSpec.getComponents().getZookeeperBaseName(), ObjectUtils.firstNonNull(selfSigned.getZookeeper().getSecretName(), globalSpec.getTls().getZookeeper().getSecretName()), - getZookeeperDNSNames(selfSigned.getZookeeper())); + getZookeeperDNSNames(selfSigned.getZookeeper()), + caIssuerName, + selfSigned.getPrivateKey()); } if (TlsConfig.FunctionsWorkerTlsEntryConfig.isEnabled(globalSpec.getTls().getFunctionsWorker())) { @@ -152,20 +175,24 @@ public void generateCertificates() { globalSpec.getComponents().getFunctionsWorkerBaseName(), ObjectUtils.firstNonNull(selfSigned.getFunctionsWorker().getSecretName(), globalSpec.getTls().getFunctionsWorker().getSecretName()), - getFunctionsWorkerDNSNames(selfSigned.getFunctionsWorker())); + getFunctionsWorkerDNSNames(selfSigned.getFunctionsWorker()), + caIssuerName, + selfSigned.getPrivateKey()); } if (selfSigned.getExternal() != null) { - for (Map.Entry entry + for (Map.Entry entry : selfSigned.getExternal().entrySet()) { final String serviceName = entry.getKey(); - final SelfSignedCertificatePerComponentConfig config = entry.getValue(); + final ComponentCertificateConfig config = entry.getValue(); if (config.getGenerate() != null && config.getGenerate()) { createCertificatePerComponent( config, serviceName, config.getSecretName(), - getBaseK8sDnsNames(config, serviceName) + getBaseK8sDnsNames(config, serviceName), + caIssuerName, + selfSigned.getPrivateKey() ); } } @@ -173,9 +200,161 @@ public void generateCertificates() { } } + private void generateAcmeCertificates() { + createAcmeIssuer(); + String issuerName = acme.getIssuer().getName(); + if (TlsConfig.TlsEntryConfig.isEnabled(globalSpec.getTls().getBroker())) { + createCertificatePerComponent( + acme.getBroker(), + globalSpec.getComponents().getBrokerBaseName(), + ObjectUtils.firstNonNull(acme.getBroker().getSecretName(), + globalSpec.getTls().getBroker().getSecretName()), + mergeDnsNames(null, acme.getBroker()), + issuerName, + acme.getPrivateKey() + ); + } + if (TlsConfig.ProxyTlsEntryConfig.isEnabled(globalSpec.getTls().getProxy())) { + createCertificatePerComponent( + acme.getProxy(), + globalSpec.getComponents().getProxyBaseName(), + ObjectUtils.firstNonNull(acme.getProxy().getSecretName(), + globalSpec.getTls().getProxy().getSecretName()), + mergeDnsNames(null, acme.getProxy()), + issuerName, + acme.getPrivateKey() + ); + } + if (acme.getExternal() != null) { + for (Map.Entry entry : acme.getExternal().entrySet()) { + final String serviceName = entry.getKey(); + final ComponentCertificateConfig config = entry.getValue(); + + if (Boolean.TRUE.equals(config.getGenerate())) { + createCertificatePerComponent( + config, + serviceName, + config.getSecretName(), + mergeDnsNames(null, config), + issuerName, + acme.getPrivateKey() + ); + } + } + } + } + + public static void validateAcmeIssuerConfig(TlsConfig.AcmeIssuerConfig config) { + if (config.getSolvers() == null || config.getSolvers().isEmpty()) { + throw new IllegalArgumentException("At least one ACME solver must be configured"); + } + for (TlsConfig.SolverConfig solver : config.getSolvers()) { + int count = 0; + if (solver.getHttp01() != null) { + count++; + } + if (solver.getDns01() != null) { + count++; + } + if (count != 1) { + throw new IllegalArgumentException( + "Exactly one of http01 or dns01 must be configured per solver"); + } + if (solver.getDns01() != null) { + TlsConfig.Dns01Config dns = solver.getDns01(); + int providers = 0; + if (dns.getRoute53() != null) { + providers++; + } + if (dns.getCloudflare() != null) { + providers++; + } + if (dns.getCloudDNS() != null) { + providers++; + } + if (providers != 1) { + throw new IllegalArgumentException( + "Exactly one DNS provider must be configured per solver"); + } + } + } + } + + private void createAcmeIssuer() { + TlsConfig.AcmeIssuerConfig issuerConfig = acme.getIssuer(); + validateAcmeIssuerConfig(issuerConfig); + List solvers = new ArrayList<>(); + + for (TlsConfig.SolverConfig solver : issuerConfig.getSolvers()) { + ACMEChallengeSolverBuilder solverBuilder = new ACMEChallengeSolverBuilder(); + if (solver.getHttp01() != null) { + TlsConfig.Http01Config http = solver.getHttp01(); + solverBuilder.withHttp01( + new ACMEChallengeSolverHTTP01Builder() + .withIngress( + new ACMEChallengeSolverHTTP01IngressBuilder() + .withIngressClassName(http.getIngressClass()) + .build() + ) + .build() + ); + } + + if (solver.getDns01() != null) { + TlsConfig.Dns01Config dns = solver.getDns01(); + ACMEChallengeSolverDNS01Builder dnsBuilder = new ACMEChallengeSolverDNS01Builder(); + if (dns.getRoute53() != null) { + TlsConfig.Route53Config r = dns.getRoute53(); + dnsBuilder + .withNewRoute53() + .withRegion(r.getRegion()) + .withHostedZoneID(r.getHostedZoneId()) + .endRoute53(); + } else if (dns.getCloudflare() != null) { + TlsConfig.CloudflareConfig cf = dns.getCloudflare(); + dnsBuilder + .withNewCloudflare() + .withEmail(cf.getEmail()) + .withNewApiTokenSecretRef(cf.getApiTokenSecretKey(), cf.getApiTokenSecretName()) + .endCloudflare(); + } else if (dns.getCloudDNS() != null) { + TlsConfig.GoogleCloudDnsConfig g = dns.getCloudDNS(); + dnsBuilder + .withNewCloudDNS() + .withProject(g.getProject()) + .withNewServiceAccountSecretRef(g.getServiceAccountSecretKey(), + g.getServiceAccountSecretName()) + .endCloudDNS(); + } + solverBuilder.withDns01(dnsBuilder.build()); + } + solvers.add(solverBuilder.build()); + } + + Issuer issuer = new IssuerBuilder() + .withNewMetadata() + .withName(issuerConfig.getName()) + .withNamespace(namespace) + .endMetadata() + .withNewSpec() + .withAcme( + new ACMEIssuerBuilder() + .withServer(issuerConfig.getServer()) + .withEmail(issuerConfig.getEmail()) + .withNewPrivateKeySecretRef() + .withName(issuerConfig.getPrivateKeySecretName()) + .endPrivateKeySecretRef() + .withSolvers(solvers) + .build() + ) + .endSpec() + .build(); + client.resource(issuer).inNamespace(namespace).forceConflicts().serverSideApply(); + } + private void createAutorecoveryCertificate() { // autorecovery only need to be accessed via the client tls auth, no dns names needed - final TlsConfig.SelfSignedCertificatePerComponentConfig autorecoveryConfig = selfSigned.getAutorecovery(); + final ComponentCertificateConfig autorecoveryConfig = selfSigned.getAutorecovery(); final CertificatePrivateKey privateKey = ObjectUtils .firstNonNull(autorecoveryConfig == null ? null : autorecoveryConfig.getPrivateKey(), @@ -200,26 +379,30 @@ private void createAutorecoveryCertificate() { client.resource(caCertificate) .inNamespace(namespace) - .createOrReplace(); + .forceConflicts() + .serverSideApply(); } - private void createCertificatePerComponent(final TlsConfig.SelfSignedCertificatePerComponentConfig componentConfig, + private void createCertificatePerComponent(final ComponentCertificateConfig componentConfig, final String baseName, final String secretName, - List dnsNames) { - if (componentConfig == null || !componentConfig.getGenerate()) { + List dnsNames, + String issuerName, + CertificatePrivateKey provisionerPrivateKey) { + if (componentConfig == null || !Boolean.TRUE.equals(componentConfig.getGenerate())) { return; } createCertificate( "%s-%s-tls".formatted(clusterSpecName, baseName), secretName, - ObjectUtils.firstNonNull(componentConfig.getPrivateKey(), selfSigned.getPrivateKey()), - dnsNames + ObjectUtils.firstNonNull(componentConfig.getPrivateKey(), provisionerPrivateKey), + dnsNames, + issuerName ); } - private List mergeDnsNames(List k8sDnsNames, SelfSignedCertificatePerComponentConfig config) { + private List mergeDnsNames(List k8sDnsNames, ComponentCertificateConfig config) { final List finalDnsNames = new ArrayList<>(ObjectUtils.firstNonNull(k8sDnsNames, new ArrayList<>())); if (config != null && config.getDnsNames() != null) { finalDnsNames.addAll(config.getDnsNames()); @@ -230,21 +413,23 @@ private List mergeDnsNames(List k8sDnsNames, SelfSignedCertifica private List getDnsNamesForExternalServicesForGlobalCert() { final List dnsNames = new ArrayList<>(); if (selfSigned.getExternal() != null) { - for (Map.Entry entry + for (Map.Entry entry : selfSigned.getExternal().entrySet()) { - final SelfSignedCertificatePerComponentConfig config = entry.getValue(); - dnsNames.addAll(getBaseK8sDnsNames(config, entry.getKey())); + final ComponentCertificateConfig config = entry.getValue(); + if (Boolean.TRUE.equals(config.getGenerate())) { + dnsNames.addAll(getBaseK8sDnsNames(config, entry.getKey())); + } } } return dnsNames; } - private List getBaseK8sDnsNames(SelfSignedCertificatePerComponentConfig config, String serviceName) { + private List getBaseK8sDnsNames(ComponentCertificateConfig config, String serviceName) { List k8sDnsNames = enumerateDnsNames(serviceName, true); return mergeDnsNames(k8sDnsNames, config); } - private List getBookKeeperDNSNames(SelfSignedCertificatePerComponentConfig config) { + private List getBookKeeperDNSNames(ComponentCertificateConfig config) { final String componentBaseName = BookKeeperResourcesFactory.getComponentBaseName(globalSpec); List k8sDnsNames = BookKeeperController .enumerateBookKeeperSets(clusterSpecName, componentBaseName, pulsarClusterSpec.getBookkeeper()).stream() @@ -253,7 +438,7 @@ private List getBookKeeperDNSNames(SelfSignedCertificatePerComponentConf return mergeDnsNames(k8sDnsNames, config); } - private List getFunctionsWorkerDNSNames(SelfSignedCertificatePerComponentConfig config) { + private List getFunctionsWorkerDNSNames(ComponentCertificateConfig config) { final String functionsWorkerBase = FunctionsWorkerResourcesFactory.getResourceName(clusterSpecName, FunctionsWorkerResourcesFactory.getComponentBaseName(globalSpec)); @@ -265,7 +450,7 @@ private List getFunctionsWorkerDNSNames(SelfSignedCertificatePerComponen return mergeDnsNames(k8sDnsNames, config); } - private List getZookeeperDNSNames(SelfSignedCertificatePerComponentConfig config) { + private List getZookeeperDNSNames(ComponentCertificateConfig config) { final String zookeeperDNSNames = ZooKeeperResourcesFactory.getResourceName(clusterSpecName, ZooKeeperResourcesFactory.getComponentBaseName(globalSpec)); @@ -277,7 +462,7 @@ private List getZookeeperDNSNames(SelfSignedCertificatePerComponentConfi return mergeDnsNames(k8sDnsNames, config); } - private List getProxyDNSNames(SelfSignedCertificatePerComponentConfig config) { + private List getProxyDNSNames(ComponentCertificateConfig config) { final String componentBaseName = ProxyResourcesFactory.getComponentBaseName(globalSpec); List k8sDnsNames = ProxyController .enumerateProxySets(clusterSpecName, componentBaseName, pulsarClusterSpec.getProxy()).stream() @@ -286,7 +471,7 @@ private List getProxyDNSNames(SelfSignedCertificatePerComponentConfig co return mergeDnsNames(k8sDnsNames, config); } - private List getBrokerDNSNames(SelfSignedCertificatePerComponentConfig config) { + private List getBrokerDNSNames(ComponentCertificateConfig config) { final String componentBaseName = BrokerResourcesFactory.getComponentBaseName(globalSpec); List k8sDnsNames = BrokerController .enumerateBrokerSets(clusterSpecName, componentBaseName, pulsarClusterSpec.getBroker()).stream() @@ -311,8 +496,9 @@ private List enumerateDnsNames(final String serviceName, boolean wildcar private void createCertificate(String name, String secretName, CertificatePrivateKey privateKey, - List dnsNames) { - final Certificate ssCertificate = new CertificateBuilder() + List dnsNames, + String issuerName) { + final Certificate certificate = new CertificateBuilder() .withNewMetadata() .withName(name) .withNamespace(namespace) @@ -321,16 +507,16 @@ private void createCertificate(String name, .withPrivateKey(privateKey) .withSecretName(secretName) .withNewIssuerRef() - .withName(caIssuerName) + .withName(issuerName) .endIssuerRef() .withDnsNames(dnsNames) .endSpec() .build(); - - client.resource(ssCertificate) + client.resource(certificate) .inNamespace(namespace) - .createOrReplace(); - log.debugf("Created self-signed certificate %s mapped to secret %s", name, secretName); + .forceConflicts() + .serverSideApply(); + log.debugf("Created certificate %s mapped to secret %s", name, secretName); } private void createRootCACertificate() { @@ -349,7 +535,8 @@ private void createRootCACertificate() { client.resource(ssIssuer) .inNamespace(namespace) - .createOrReplace(); + .forceConflicts() + .serverSideApply(); final Certificate caCertificate = new CertificateBuilder() .withNewMetadata() @@ -370,7 +557,8 @@ private void createRootCACertificate() { client.resource(caCertificate) .inNamespace(namespace) - .createOrReplace(); + .forceConflicts() + .serverSideApply(); final Issuer caIssuer = new IssuerBuilder() .withNewMetadata() @@ -386,9 +574,92 @@ private void createRootCACertificate() { client.resource(caIssuer) .inNamespace(namespace) - .createOrReplace(); + .forceConflicts() + .serverSideApply(); log.debug("Created self-signed root CA certificate"); } + private void validateProvisionersConfig() { + if (selfSigned == null || acme == null) { + return; + } + validateComponent( + "broker", + selfSigned.getBroker(), + acme.getBroker(), + globalSpec.getTls().getBroker() + ); + validateComponent( + "proxy", + selfSigned.getProxy(), + acme.getProxy(), + globalSpec.getTls().getProxy() + ); + validateExternal(selfSigned.getExternal(), acme.getExternal()); + } + + private void validateComponent( + String componentName, + ComponentCertificateConfig selfSignedConfig, + ComponentCertificateConfig acmeConfig, + TlsConfig.TlsEntryConfig tlsEntryConfig) { + if (selfSignedConfig == null || acmeConfig == null) { + return; + } + + if (Boolean.TRUE.equals(selfSignedConfig.getGenerate()) + && Boolean.TRUE.equals(acmeConfig.getGenerate())) { + + String ssSecret = ObjectUtils.firstNonNull( + selfSignedConfig.getSecretName(), + tlsEntryConfig.getSecretName() + ); + String acmeSecret = ObjectUtils.firstNonNull( + acmeConfig.getSecretName(), + tlsEntryConfig.getSecretName() + ); + + if (Objects.equals(ssSecret, acmeSecret)) { + throw new IllegalArgumentException( + String.format( + "Invalid TLS configuration: both selfSigned and ACME provisioners generate a %s " + + "certificate using the same secret '%s'. This would cause certificates to " + + "override each other.", componentName, ssSecret + ) + ); + } + } + } + + private void validateExternal(Map selfSignedExternal, + Map acmeExternal) { + if (selfSignedExternal == null || acmeExternal == null) { + return; + } + for (Map.Entry entry : selfSignedExternal.entrySet()) { + String serviceName = entry.getKey(); + ComponentCertificateConfig ssConfig = entry.getValue(); + ComponentCertificateConfig acmeConfig = acmeExternal.get(serviceName); + if (acmeConfig == null) { + continue; + } + if (Boolean.TRUE.equals(ssConfig.getGenerate()) + && Boolean.TRUE.equals(acmeConfig.getGenerate())) { + + String ssSecret = ssConfig.getSecretName(); + String acmeSecret = acmeConfig.getSecretName(); + + if (Objects.equals(ssSecret, acmeSecret)) { + throw new IllegalArgumentException( + String.format("Invalid TLS configuration: both selfSigned and ACME provisioners generate an" + + " external certificate for service '%s' using the same secret '%s'. " + + "This would cause certificates to override each other.", serviceName, + ssSecret + ) + ); + } + } + } + } } \ No newline at end of file diff --git a/operator/src/main/java/com/datastax/oss/kaap/crds/configs/tls/TlsConfig.java b/operator/src/main/java/com/datastax/oss/kaap/crds/configs/tls/TlsConfig.java index 4e76751e..0fec85d7 100644 --- a/operator/src/main/java/com/datastax/oss/kaap/crds/configs/tls/TlsConfig.java +++ b/operator/src/main/java/com/datastax/oss/kaap/crds/configs/tls/TlsConfig.java @@ -25,6 +25,7 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.ToString; +import lombok.experimental.SuperBuilder; @Data @NoArgsConstructor @@ -119,53 +120,149 @@ public FunctionsWorkerTlsEntryConfig(Boolean enabled, String secretName, Boolean public static class CertProvisionerConfig { @JsonPropertyDescription("Self signed certificate provisioner configuration.") SelfSignedCertProvisionerConfig selfSigned; - + @JsonPropertyDescription("ACME certificate provisioner configuration.") + AcmeCertProvisionerConfig acme; } @Data @NoArgsConstructor @AllArgsConstructor - @Builder - public static class SelfSignedCertProvisionerConfig { + @SuperBuilder + public static class BaseCertProvisionerConfig { @JsonPropertyDescription("Generate self signed certificates for broker, proxy and functions worker.") Boolean enabled; - @JsonPropertyDescription("Include dns name in the DNS names covered by the certificate.") - Boolean includeDns; @JsonPropertyDescription("Cert-manager options for generating the private key.") CertificatePrivateKey privateKey; + @JsonPropertyDescription("Broker self signed certificate config.") + ComponentCertificateConfig broker; + @JsonPropertyDescription("Proxy self signed certificate config.") + ComponentCertificateConfig proxy; + @JsonPropertyDescription("External services self signed certificate config (e.g., admin console, grafana). " + + "The key is the service name, and the value contains generation config") + Map external; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @SuperBuilder + @EqualsAndHashCode(callSuper = true) + @ToString(callSuper = true) + public static class SelfSignedCertProvisionerConfig extends BaseCertProvisionerConfig { + @JsonPropertyDescription("Include dns name in the DNS names covered by the certificate.") + Boolean includeDns; @JsonPropertyDescription("Generate a different certificate for each component.") Boolean perComponent; @JsonPropertyDescription("Secret where to store the root CA certificate.") String caSecretName; - @JsonPropertyDescription("Zookeeper self signed certificate config.") - SelfSignedCertificatePerComponentConfig zookeeper; + ComponentCertificateConfig zookeeper; @JsonPropertyDescription("Bookkeeper self signed certificate config.") - SelfSignedCertificatePerComponentConfig bookkeeper; - @JsonPropertyDescription("Broker self signed certificate config.") - SelfSignedCertificatePerComponentConfig broker; - @JsonPropertyDescription("Proxy self signed certificate config.") - SelfSignedCertificatePerComponentConfig proxy; + ComponentCertificateConfig bookkeeper; @JsonPropertyDescription("Functions worker self signed certificate config.") - SelfSignedCertificatePerComponentConfig functionsWorker; + ComponentCertificateConfig functionsWorker; @JsonPropertyDescription("Autorecovery self signed certificate config.") - SelfSignedCertificatePerComponentConfig autorecovery; - @JsonPropertyDescription("External services self signed certificate config (e.g., admin console, grafana). " - + "The key is the service name, and the value contains generation config") - Map external; + ComponentCertificateConfig autorecovery; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @SuperBuilder + @EqualsAndHashCode(callSuper = true) + @ToString(callSuper = true) + public static class AcmeCertProvisionerConfig extends BaseCertProvisionerConfig { + @JsonPropertyDescription("ACME issuer configuration.") + AcmeIssuerConfig issuer; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class AcmeIssuerConfig { + @JsonPropertyDescription("Name of the Issuer resource.") + String name; + @JsonPropertyDescription("ACME server URL.") + String server; + @JsonPropertyDescription("Email used for ACME registration.") + String email; + @JsonPropertyDescription("Secret storing the ACME account private key.") + String privateKeySecretName; + @JsonPropertyDescription("ACME challenge solvers. Solvers are evaluated in order; no domain-based routing") + List solvers; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class SolverConfig { + @JsonPropertyDescription("HTTP01 solver configuration.") + Http01Config http01; + @JsonPropertyDescription("DNS01 solver configuration.") + Dns01Config dns01; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class Http01Config { + @JsonPropertyDescription("Ingress class used for HTTP01 challenge.") + String ingressClass; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class Dns01Config { + Route53Config route53; + CloudflareConfig cloudflare; + GoogleCloudDnsConfig cloudDNS; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class Route53Config { + String region; + String hostedZoneId; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class CloudflareConfig { + String email; + String apiTokenSecretName; + String apiTokenSecretKey; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class GoogleCloudDnsConfig { + String project; + String serviceAccountSecretName; + String serviceAccountSecretKey; } @Data @NoArgsConstructor @AllArgsConstructor @Builder - public static class SelfSignedCertificatePerComponentConfig { - @JsonPropertyDescription("Generate self signed certificates for the component.") + public static class ComponentCertificateConfig { + @JsonPropertyDescription("Generate certificate for the component.") Boolean generate; @JsonPropertyDescription("Cert-manager options for generating the private key.") CertificatePrivateKey privateKey; @JsonPropertyDescription("A list of DNS names (and IP addresses) to include in the certificate's Subject " - + "Alternative Names (SANs) extension along with the default K8s service DNS.") + + "Alternative Names (SANs) extension.") List dnsNames; @JsonPropertyDescription("The name of the Kubernetes Secret where the generated certificate " + "and key will be stored whe perComponent is enabled. Required for external services. " diff --git a/operator/src/test/java/com/datastax/oss/kaap/controllers/utils/CertManagerCertificatesProvisionerTest.java b/operator/src/test/java/com/datastax/oss/kaap/controllers/utils/CertManagerCertificatesProvisionerTest.java index 50bb6da1..ce28f14d 100644 --- a/operator/src/test/java/com/datastax/oss/kaap/controllers/utils/CertManagerCertificatesProvisionerTest.java +++ b/operator/src/test/java/com/datastax/oss/kaap/controllers/utils/CertManagerCertificatesProvisionerTest.java @@ -18,10 +18,11 @@ import com.datastax.oss.kaap.common.SerializationUtil; import com.datastax.oss.kaap.crds.cluster.PulsarClusterSpec; import com.datastax.oss.kaap.mocks.MockKubernetesClient; +import io.fabric8.certmanager.api.model.acme.v1.ACMEChallengeSolver; import io.fabric8.certmanager.api.model.v1.Certificate; import io.fabric8.certmanager.api.model.v1.Issuer; +import org.junit.jupiter.api.Test; import org.testng.Assert; -import org.testng.annotations.Test; public class CertManagerCertificatesProvisionerTest { @@ -451,6 +452,243 @@ public void testGeneratePerComponent() throws Exception { } + @Test + public void testAcmeIssuerHttp01() { + final MockKubernetesClient mockKubernetesClient = generateCertificates(""" + global: + name: pul + tls: + enabled: true + broker: + enabled: true + secretName: pul-broker-tls + certProvisioner: + acme: + enabled: true + broker: + generate: true + secretName: pul-broker-tls + issuer: + name: pul-acme-issuer + server: https://acme-v02.api.letsencrypt.org/directory + email: admin@example.com + privateKeySecretName: pul-acme-account-key + solvers: + - http01: + ingressClass: nginx + """); + + final Issuer issuer = mockKubernetesClient + .getCreatedResource(Issuer.class, "pul-acme-issuer") + .getResource(); + assertAcmeIssuerBase(issuer); + Assert.assertEquals(issuer.getSpec().getAcme().getSolvers().size(), 1); + + final ACMEChallengeSolver solver = issuer.getSpec().getAcme().getSolvers().getFirst(); + Assert.assertNotNull(solver.getHttp01()); + Assert.assertNotNull(solver.getHttp01().getIngress()); + Assert.assertEquals(solver.getHttp01().getIngress().getIngressClassName(), "nginx"); + Assert.assertNull(solver.getDns01()); + } + + @Test + public void testAcmeIssuerRoute53() { + final MockKubernetesClient mockKubernetesClient = generateCertificates(""" + global: + name: pul + tls: + enabled: true + broker: + enabled: true + secretName: pul-broker-tls + certProvisioner: + acme: + enabled: true + broker: + generate: true + secretName: pul-broker-tls + issuer: + name: pul-acme-issuer + server: https://acme-v02.api.letsencrypt.org/directory + email: admin@example.com + privateKeySecretName: pul-acme-account-key + solvers: + - dns01: + route53: + region: us-east-1 + hostedZoneId: Z123456789 + """); + + final Issuer issuer = mockKubernetesClient + .getCreatedResource(Issuer.class, "pul-acme-issuer") + .getResource(); + assertAcmeIssuerBase(issuer); + Assert.assertEquals(issuer.getSpec().getAcme().getSolvers().size(), 1); + + final ACMEChallengeSolver solver = issuer.getSpec().getAcme().getSolvers().getFirst(); + Assert.assertNull(solver.getHttp01()); + Assert.assertNotNull(solver.getDns01()); + Assert.assertNotNull(solver.getDns01().getRoute53()); + Assert.assertEquals(solver.getDns01().getRoute53().getRegion(), "us-east-1"); + Assert.assertEquals(solver.getDns01().getRoute53().getHostedZoneID(), "Z123456789"); + Assert.assertNull(solver.getDns01().getCloudflare()); + Assert.assertNull(solver.getDns01().getCloudDNS()); + } + + @Test + public void testAcmeIssuerCloudflare() { + final MockKubernetesClient mockKubernetesClient = generateCertificates(""" + global: + name: pul + tls: + enabled: true + broker: + enabled: true + secretName: pul-broker-tls + certProvisioner: + acme: + enabled: true + broker: + generate: true + secretName: pul-broker-tls + issuer: + name: pul-acme-issuer + server: https://acme-v02.api.letsencrypt.org/directory + email: admin@example.com + privateKeySecretName: pul-acme-account-key + solvers: + - dns01: + cloudflare: + email: cf-admin@example.com + apiTokenSecretName: cf-api-token + apiTokenSecretKey: token + """); + + final Issuer issuer = mockKubernetesClient + .getCreatedResource(Issuer.class, "pul-acme-issuer") + .getResource(); + assertAcmeIssuerBase(issuer); + Assert.assertEquals(issuer.getSpec().getAcme().getSolvers().size(), 1); + + final ACMEChallengeSolver solver = issuer.getSpec().getAcme().getSolvers().getFirst(); + Assert.assertNull(solver.getHttp01()); + Assert.assertNotNull(solver.getDns01()); + Assert.assertNotNull(solver.getDns01().getCloudflare()); + Assert.assertEquals(solver.getDns01().getCloudflare().getEmail(), "cf-admin@example.com"); + Assert.assertEquals(solver.getDns01().getCloudflare().getApiTokenSecretRef().getName(), + "cf-api-token"); + Assert.assertEquals(solver.getDns01().getCloudflare().getApiTokenSecretRef().getKey(), "token"); + Assert.assertNull(solver.getDns01().getRoute53()); + Assert.assertNull(solver.getDns01().getCloudDNS()); + } + + @Test + public void testAcmeIssuerCloudDns() { + final MockKubernetesClient mockKubernetesClient = generateCertificates(""" + global: + name: pul + tls: + enabled: true + broker: + enabled: true + secretName: pul-broker-tls + certProvisioner: + acme: + enabled: true + broker: + generate: true + secretName: pul-broker-tls + issuer: + name: pul-acme-issuer + server: https://acme-v02.api.letsencrypt.org/directory + email: admin@example.com + privateKeySecretName: pul-acme-account-key + solvers: + - dns01: + cloudDNS: + project: my-gcp-project + serviceAccountSecretName: gcp-sa-secret + serviceAccountSecretKey: service-account.json + """); + + final Issuer issuer = mockKubernetesClient + .getCreatedResource(Issuer.class, "pul-acme-issuer") + .getResource(); + assertAcmeIssuerBase(issuer); + Assert.assertEquals(issuer.getSpec().getAcme().getSolvers().size(), 1); + + final ACMEChallengeSolver solver = issuer.getSpec().getAcme().getSolvers().getFirst(); + Assert.assertNull(solver.getHttp01()); + Assert.assertNotNull(solver.getDns01()); + Assert.assertNotNull(solver.getDns01().getCloudDNS()); + Assert.assertEquals(solver.getDns01().getCloudDNS().getProject(), "my-gcp-project"); + Assert.assertEquals( + solver.getDns01().getCloudDNS().getServiceAccountSecretRef().getName(), + "gcp-sa-secret" + ); + Assert.assertEquals( + solver.getDns01().getCloudDNS().getServiceAccountSecretRef().getKey(), + "service-account.json" + ); + Assert.assertNull(solver.getDns01().getRoute53()); + Assert.assertNull(solver.getDns01().getCloudflare()); + } + + @Test + public void testAcmeCertificateGeneration() { + final MockKubernetesClient mockKubernetesClient = generateCertificates(""" + global: + name: pul + tls: + enabled: true + broker: + enabled: true + secretName: pul-broker-tls + certProvisioner: + acme: + enabled: true + broker: + generate: true + secretName: pul-broker-tls + issuer: + name: pul-acme-issuer + server: https://acme-v02.api.letsencrypt.org/directory + email: admin@example.com + privateKeySecretName: pul-acme-account-key + solvers: + - http01: + ingressClass: nginx + """); + + final Certificate brokerCertificate = + mockKubernetesClient.getCreatedResource(Certificate.class, "pul-broker-tls").getResource(); + Assert.assertNotNull(brokerCertificate); + Assert.assertEquals(brokerCertificate.getSpec().getIssuerRef().getName(), "pul-acme-issuer"); + Assert.assertEquals(brokerCertificate.getSpec().getSecretName(), "pul-broker-tls"); + + final Issuer issuer = mockKubernetesClient + .getCreatedResource(Issuer.class, "pul-acme-issuer") + .getResource(); + Assert.assertNotNull(issuer); + Assert.assertEquals(issuer.getSpec().getAcme().getSolvers().size(), 1); + } + + private static void assertAcmeIssuerBase(Issuer issuer) { + Assert.assertNotNull(issuer); + Assert.assertEquals(issuer.getMetadata().getName(), "pul-acme-issuer"); + Assert.assertEquals(issuer.getMetadata().getNamespace(), NAMESPACE); + + Assert.assertNotNull(issuer.getSpec()); + Assert.assertNotNull(issuer.getSpec().getAcme()); + Assert.assertEquals( + issuer.getSpec().getAcme().getServer(), + "https://acme-v02.api.letsencrypt.org/directory" + ); + Assert.assertEquals(issuer.getSpec().getAcme().getEmail(), "admin@example.com"); + Assert.assertEquals(issuer.getSpec().getAcme().getPrivateKeySecretRef().getName(), + "pul-acme-account-key"); + } + private MockKubernetesClient generateCertificates(String spec) { final PulsarClusterSpec pulsarClusterSpec = SerializationUtil.readYaml(spec, PulsarClusterSpec.class); diff --git a/tests/src/test/java/com/datastax/oss/kaap/tests/helm/TlsTest.java b/tests/src/test/java/com/datastax/oss/kaap/tests/helm/TlsTest.java index 4198b205..af8e6d9e 100644 --- a/tests/src/test/java/com/datastax/oss/kaap/tests/helm/TlsTest.java +++ b/tests/src/test/java/com/datastax/oss/kaap/tests/helm/TlsTest.java @@ -48,27 +48,27 @@ protected void test(boolean perComponentCerts, boolean pulsar3) throws Exception .selfSigned(TlsConfig.SelfSignedCertProvisionerConfig.builder() .enabled(true) .perComponent(true) - .zookeeper(TlsConfig.SelfSignedCertificatePerComponentConfig + .zookeeper(TlsConfig.ComponentCertificateConfig .builder() .generate(true) .build()) - .functionsWorker(TlsConfig.SelfSignedCertificatePerComponentConfig + .functionsWorker(TlsConfig.ComponentCertificateConfig .builder() .generate(true) .build()) - .proxy(TlsConfig.SelfSignedCertificatePerComponentConfig + .proxy(TlsConfig.ComponentCertificateConfig .builder() .generate(true) .build()) - .broker(TlsConfig.SelfSignedCertificatePerComponentConfig + .broker(TlsConfig.ComponentCertificateConfig .builder() .generate(true) .build()) - .bookkeeper(TlsConfig.SelfSignedCertificatePerComponentConfig + .bookkeeper(TlsConfig.ComponentCertificateConfig .builder() .generate(true) .build()) - .autorecovery(TlsConfig.SelfSignedCertificatePerComponentConfig + .autorecovery(TlsConfig.ComponentCertificateConfig .builder() .generate(true) .build())