diff --git a/api/apps/v1alpha1/redis/types.go b/api/apps/v1alpha1/redis/types.go index 3e12687a..e9a02c72 100644 --- a/api/apps/v1alpha1/redis/types.go +++ b/api/apps/v1alpha1/redis/types.go @@ -41,9 +41,6 @@ type ConfigSpec struct { // Enable password generation. // +kubebuilder:default:=true AuthEnabled bool `json:"authEnabled"` - // TLS configuration for client-facing connections. When enabled, an nginx stream sidecar terminates TLS on port 6380. Intra-cluster traffic on 6379 (operator probes, sentinel, replication) remains plaintext. - // +kubebuilder:default:={} - Tls TLS `json:"tls"` } type Resources struct { @@ -53,27 +50,6 @@ type Resources struct { Memory resource.Quantity `json:"memory,omitempty"` } -type TLS struct { - // Enable TLS termination via nginx stream sidecar. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // cert-manager Issuer reference. Used only when secretName is empty. - // +kubebuilder:default:={} - IssuerRef TLSIssuerRef `json:"issuerRef"` - // Name of an existing kubernetes.io/tls secret. When non-empty, cert-manager Certificate is NOT rendered and the user manages the secret. - // +kubebuilder:default:="" - SecretName string `json:"secretName"` -} - -type TLSIssuerRef struct { - // Either "Issuer" or "ClusterIssuer". - // +kubebuilder:default:="ClusterIssuer" - Kind string `json:"kind"` - // Issuer/ClusterIssuer resource name. - // +kubebuilder:default:="selfsigned-cluster-issuer" - Name string `json:"name"` -} - // +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" type ResourcesPreset string diff --git a/api/apps/v1alpha1/redis/zz_generated.deepcopy.go b/api/apps/v1alpha1/redis/zz_generated.deepcopy.go index 4e5f844b..6390200c 100644 --- a/api/apps/v1alpha1/redis/zz_generated.deepcopy.go +++ b/api/apps/v1alpha1/redis/zz_generated.deepcopy.go @@ -55,7 +55,6 @@ func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { *out = *in in.Resources.DeepCopyInto(&out.Resources) out.Size = in.Size.DeepCopy() - out.Tls = in.Tls } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. @@ -84,34 +83,3 @@ func (in *Resources) DeepCopy() *Resources { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TLS) DeepCopyInto(out *TLS) { - *out = *in - out.IssuerRef = in.IssuerRef -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLS. -func (in *TLS) DeepCopy() *TLS { - if in == nil { - return nil - } - out := new(TLS) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TLSIssuerRef) DeepCopyInto(out *TLSIssuerRef) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSIssuerRef. -func (in *TLSIssuerRef) DeepCopy() *TLSIssuerRef { - if in == nil { - return nil - } - out := new(TLSIssuerRef) - in.DeepCopyInto(out) - return out -} diff --git a/packages/apps/redis/README.md b/packages/apps/redis/README.md index 454ff91a..7f82d229 100644 --- a/packages/apps/redis/README.md +++ b/packages/apps/redis/README.md @@ -28,15 +28,9 @@ Service utilizes the Spotahome Redis Operator for efficient management and orche ### Application-specific parameters -| Name | Description | Type | Value | -| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------------------------- | -| `authEnabled` | Enable password generation. | `bool` | `true` | -| `tls` | TLS configuration for client-facing connections. When enabled, an nginx stream sidecar terminates TLS on port 6380. Intra-cluster traffic on 6379 (operator probes, sentinel, replication) remains plaintext. | `object` | `{}` | -| `tls.enabled` | Enable TLS termination via nginx stream sidecar. | `bool` | `false` | -| `tls.secretName` | Name of an existing kubernetes.io/tls secret. When non-empty, cert-manager Certificate is NOT rendered and the user manages the secret. | `string` | `""` | -| `tls.issuerRef` | cert-manager Issuer reference. Used only when secretName is empty. | `object` | `{}` | -| `tls.issuerRef.name` | Issuer/ClusterIssuer resource name. | `string` | `selfsigned-cluster-issuer` | -| `tls.issuerRef.kind` | Either "Issuer" or "ClusterIssuer". | `string` | `ClusterIssuer` | +| Name | Description | Type | Value | +| ------------- | --------------------------- | ------ | ------ | +| `authEnabled` | Enable password generation. | `bool` | `true` | ## Parameter examples and reference diff --git a/packages/apps/redis/templates/_tls.tpl b/packages/apps/redis/templates/_tls.tpl deleted file mode 100644 index a5cbc5a7..00000000 --- a/packages/apps/redis/templates/_tls.tpl +++ /dev/null @@ -1,35 +0,0 @@ -{{/* -redis.tls.secretName — wraps cozy-lib.tls.secretName with redis-specific suffix. -Returns either the user-provided tls.secretName or "-redis-tls". -*/}} -{{- define "redis.tls.secretName" -}} -{{- include "cozy-lib.tls.secretName" (dict - "Release" .Release - "suffix" "redis-tls" - "secretName" .Values.tls.secretName -) -}} -{{- end -}} - -{{/* -redis.tls.dnsNames — DNS SANs for the Redis TLS certificate. -Covers the chart's TLS-only ClusterIP services (-master for writes, --replicas for reads) and the external LoadBalancer service across -short, namespaced, and FQDN forms. The operator-managed rfs-* service is -intentionally excluded because it serves plaintext on 6379 only. -The external-lb variants are always included so toggling .Values.external -later does not require certificate reissue. -*/}} -{{- define "redis.tls.dnsNames" -}} -- {{ .Release.Name }}-master -- {{ .Release.Name }}-master.{{ .Release.Namespace }} -- {{ .Release.Name }}-master.{{ .Release.Namespace }}.svc -- {{ .Release.Name }}-master.{{ .Release.Namespace }}.svc.cluster.local -- {{ .Release.Name }}-replicas -- {{ .Release.Name }}-replicas.{{ .Release.Namespace }} -- {{ .Release.Name }}-replicas.{{ .Release.Namespace }}.svc -- {{ .Release.Name }}-replicas.{{ .Release.Namespace }}.svc.cluster.local -- {{ .Release.Name }}-external-lb -- {{ .Release.Name }}-external-lb.{{ .Release.Namespace }} -- {{ .Release.Name }}-external-lb.{{ .Release.Namespace }}.svc -- {{ .Release.Name }}-external-lb.{{ .Release.Namespace }}.svc.cluster.local -{{- end -}} diff --git a/packages/apps/redis/templates/dashboard-resourcemap.yaml b/packages/apps/redis/templates/dashboard-resourcemap.yaml index d427cf37..63f82a7d 100644 --- a/packages/apps/redis/templates/dashboard-resourcemap.yaml +++ b/packages/apps/redis/templates/dashboard-resourcemap.yaml @@ -19,9 +19,6 @@ rules: - secrets resourceNames: - "{{ .Release.Name }}-auth" - {{- if .Values.tls.enabled }} - - "{{ include "redis.tls.secretName" . }}" - {{- end }} verbs: ["get", "list", "watch"] - apiGroups: - cozystack.io diff --git a/packages/apps/redis/templates/redisfailover.yaml b/packages/apps/redis/templates/redisfailover.yaml index b05d76a7..160e030d 100644 --- a/packages/apps/redis/templates/redisfailover.yaml +++ b/packages/apps/redis/templates/redisfailover.yaml @@ -64,48 +64,6 @@ spec: - appendonly no - save "" {{- end }} - {{- if .Values.tls.enabled }} - extraContainers: - - name: tls-proxy - image: nginxinc/nginx-unprivileged:1.29-alpine - imagePullPolicy: IfNotPresent - ports: - - containerPort: 6380 - name: redis-tls - protocol: TCP - volumeMounts: - - name: tls-certs - mountPath: /etc/nginx/tls - readOnly: true - - name: nginx-tls-config - mountPath: /etc/nginx/nginx.conf - subPath: nginx.conf - readOnly: true - resources: - requests: - cpu: 10m - memory: 16Mi - limits: - cpu: 100m - memory: 64Mi - livenessProbe: - tcpSocket: - port: 6380 - initialDelaySeconds: 5 - periodSeconds: 10 - readinessProbe: - tcpSocket: - port: 6380 - initialDelaySeconds: 2 - periodSeconds: 5 - extraVolumes: - - name: tls-certs - secret: - secretName: {{ include "redis.tls.secretName" . }} - - name: nginx-tls-config - configMap: - name: {{ .Release.Name }}-redis-tls-nginx - {{- end }} {{- if .Values.authEnabled }} auth: secretPath: {{ .Release.Name }}-auth diff --git a/packages/apps/redis/templates/service.yaml b/packages/apps/redis/templates/service.yaml index 321bf204..81a73761 100644 --- a/packages/apps/redis/templates/service.yaml +++ b/packages/apps/redis/templates/service.yaml @@ -1,47 +1,3 @@ -{{- if .Values.tls.enabled }} ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ .Release.Name }}-master - labels: - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/component: redis -spec: - type: ClusterIP - selector: - app.kubernetes.io/component: redis - app.kubernetes.io/name: {{ .Release.Name }} - app.kubernetes.io/part-of: redis-failover - redisfailovers-role: master - ports: - - name: redis-tls - port: 6380 - targetPort: redis-tls - protocol: TCP ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ .Release.Name }}-replicas - labels: - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/component: redis -spec: - type: ClusterIP - selector: - app.kubernetes.io/component: redis - app.kubernetes.io/name: {{ .Release.Name }} - app.kubernetes.io/part-of: redis-failover - redisfailovers-role: slave - ports: - - name: redis-tls - port: 6380 - targetPort: redis-tls - protocol: TCP -{{- end }} {{- if .Values.external }} --- apiVersion: v1 @@ -65,15 +21,7 @@ spec: app.kubernetes.io/part-of: redis-failover redisfailovers-role: master ports: - {{- if .Values.tls.enabled }} - - name: redis-tls - port: 6380 - targetPort: redis-tls - protocol: TCP - {{- else }} - name: redis port: 6379 targetPort: redis - protocol: TCP - {{- end }} {{- end }} diff --git a/packages/apps/redis/templates/tls-certificate.yaml b/packages/apps/redis/templates/tls-certificate.yaml deleted file mode 100644 index 2c091acf..00000000 --- a/packages/apps/redis/templates/tls-certificate.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if and .Values.tls.enabled (not .Values.tls.secretName) }} -{{- $dnsNames := list -}} -{{- $dnsNames = append $dnsNames (printf "%s-master" .Release.Name) -}} -{{- $dnsNames = append $dnsNames (printf "%s-master.%s" .Release.Name .Release.Namespace) -}} -{{- $dnsNames = append $dnsNames (printf "%s-master.%s.svc" .Release.Name .Release.Namespace) -}} -{{- $dnsNames = append $dnsNames (printf "%s-master.%s.svc.cluster.local" .Release.Name .Release.Namespace) -}} -{{- $dnsNames = append $dnsNames (printf "%s-replicas" .Release.Name) -}} -{{- $dnsNames = append $dnsNames (printf "%s-replicas.%s" .Release.Name .Release.Namespace) -}} -{{- $dnsNames = append $dnsNames (printf "%s-replicas.%s.svc" .Release.Name .Release.Namespace) -}} -{{- $dnsNames = append $dnsNames (printf "%s-replicas.%s.svc.cluster.local" .Release.Name .Release.Namespace) -}} -{{- $dnsNames = append $dnsNames (printf "%s-external-lb" .Release.Name) -}} -{{- $dnsNames = append $dnsNames (printf "%s-external-lb.%s" .Release.Name .Release.Namespace) -}} -{{- $dnsNames = append $dnsNames (printf "%s-external-lb.%s.svc" .Release.Name .Release.Namespace) -}} -{{- $dnsNames = append $dnsNames (printf "%s-external-lb.%s.svc.cluster.local" .Release.Name .Release.Namespace) -}} -{{- include "cozy-lib.tls.certificate" (dict - "Release" .Release - "name" (printf "%s-redis-tls" .Release.Name) - "secretName" (include "redis.tls.secretName" .) - "dnsNames" $dnsNames - "issuerRef" .Values.tls.issuerRef -) }} -{{- end }} diff --git a/packages/apps/redis/templates/tls-nginx-config.yaml b/packages/apps/redis/templates/tls-nginx-config.yaml deleted file mode 100644 index cf08f1ea..00000000 --- a/packages/apps/redis/templates/tls-nginx-config.yaml +++ /dev/null @@ -1,34 +0,0 @@ -{{- if .Values.tls.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ .Release.Name }}-redis-tls-nginx - labels: - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/component: redis-tls-proxy -data: - nginx.conf: | - worker_processes 1; - error_log /dev/stderr notice; - pid /tmp/nginx.pid; - events { - worker_connections 1024; - } - stream { - upstream redis_backend { - server 127.0.0.1:6379; - } - server { - listen 6380 ssl; - ssl_certificate /etc/nginx/tls/tls.crt; - ssl_certificate_key /etc/nginx/tls/tls.key; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; - ssl_prefer_server_ciphers off; - proxy_pass redis_backend; - proxy_timeout 1h; - proxy_connect_timeout 5s; - } - } -{{- end }} diff --git a/packages/apps/redis/tests/dashboard-resourcemap-tls_test.yaml b/packages/apps/redis/tests/dashboard-resourcemap-tls_test.yaml deleted file mode 100644 index f984b051..00000000 --- a/packages/apps/redis/tests/dashboard-resourcemap-tls_test.yaml +++ /dev/null @@ -1,29 +0,0 @@ -suite: Dashboard RBAC includes TLS secret -templates: - - templates/dashboard-resourcemap.yaml -release: - namespace: tenant-test -tests: - - it: TLS secret not in RBAC when tls.enabled is false - set: - tls: - enabled: false - documentSelector: - path: kind - value: Role - asserts: - - notContains: - path: rules[?(@.resources[0]=='secrets')].resourceNames - content: RELEASE-NAME-redis-tls - - - it: TLS secret added to RBAC when tls.enabled is true - set: - tls: - enabled: true - documentSelector: - path: kind - value: Role - asserts: - - contains: - path: rules[?(@.resources[0]=='secrets')].resourceNames - content: RELEASE-NAME-redis-tls diff --git a/packages/apps/redis/tests/redisfailover-tls_test.yaml b/packages/apps/redis/tests/redisfailover-tls_test.yaml deleted file mode 100644 index 52b279e6..00000000 --- a/packages/apps/redis/tests/redisfailover-tls_test.yaml +++ /dev/null @@ -1,84 +0,0 @@ -suite: RedisFailover TLS sidecar injection -templates: - - templates/redisfailover.yaml -tests: - - it: does not inject extraContainers when tls.enabled is false - set: - tls: - enabled: false - documentSelector: - path: kind - value: RedisFailover - asserts: - - notExists: - path: spec.redis.extraContainers - - notExists: - path: spec.redis.extraVolumes - - - it: injects nginx tls-proxy sidecar when tls.enabled is true - set: - tls: - enabled: true - documentSelector: - path: kind - value: RedisFailover - asserts: - - equal: - path: spec.redis.extraContainers[0].name - value: tls-proxy - - matchRegex: - path: spec.redis.extraContainers[0].image - pattern: "nginx" - - equal: - path: spec.redis.extraContainers[0].ports[0].containerPort - value: 6380 - - equal: - path: spec.redis.extraContainers[0].ports[0].name - value: redis-tls - - - it: extraVolumes reference auto-generated TLS secret when secretName empty - set: - tls: - enabled: true - secretName: "" - documentSelector: - path: kind - value: RedisFailover - asserts: - - contains: - path: spec.redis.extraVolumes - content: - name: tls-certs - secret: - secretName: RELEASE-NAME-redis-tls - - - it: extraVolumes reference user-provided secret when secretName is set - set: - tls: - enabled: true - secretName: my-custom-secret - documentSelector: - path: kind - value: RedisFailover - asserts: - - contains: - path: spec.redis.extraVolumes - content: - name: tls-certs - secret: - secretName: my-custom-secret - - - it: extraVolumes include nginx config ConfigMap - set: - tls: - enabled: true - documentSelector: - path: kind - value: RedisFailover - asserts: - - contains: - path: spec.redis.extraVolumes - content: - name: nginx-tls-config - configMap: - name: RELEASE-NAME-redis-tls-nginx diff --git a/packages/apps/redis/tests/service-tls_test.yaml b/packages/apps/redis/tests/service-tls_test.yaml deleted file mode 100644 index 86d5ef9d..00000000 --- a/packages/apps/redis/tests/service-tls_test.yaml +++ /dev/null @@ -1,179 +0,0 @@ -suite: TLS service architecture -templates: - - templates/service.yaml -tests: - ################################################################### - # External LoadBalancer service (existing behavior, port switches) # - ################################################################### - - - it: no service when external is false and TLS is false - set: - external: false - tls: - enabled: false - asserts: - - hasDocuments: - count: 0 - - - it: external true and TLS false renders LB on port 6379 plaintext - set: - external: true - tls: - enabled: false - asserts: - - hasDocuments: - count: 1 - - documentIndex: 0 - equal: - path: metadata.name - value: RELEASE-NAME-external-lb - - documentIndex: 0 - equal: - path: spec.type - value: LoadBalancer - - documentIndex: 0 - equal: - path: spec.ports[0].port - value: 6379 - - documentIndex: 0 - equal: - path: spec.ports[0].name - value: redis - - documentIndex: 0 - equal: - path: spec.ports[0].targetPort - value: redis - - - it: external true and TLS true renders LB on port 6380 TLS - set: - external: true - tls: - enabled: true - documentSelector: - path: metadata.name - value: RELEASE-NAME-external-lb - asserts: - - equal: - path: spec.type - value: LoadBalancer - - equal: - path: spec.ports[0].port - value: 6380 - - equal: - path: spec.ports[0].name - value: redis-tls - - equal: - path: spec.ports[0].targetPort - value: redis-tls - - ################################################################### - # Internal ClusterIP services (only when TLS enabled) # - ################################################################### - - - it: no master or replicas service when TLS disabled (external true) - set: - external: true - tls: - enabled: false - asserts: - - hasDocuments: - count: 1 - - documentIndex: 0 - equal: - path: metadata.name - value: RELEASE-NAME-external-lb - - - it: no services when TLS disabled and external false - set: - external: false - tls: - enabled: false - asserts: - - hasDocuments: - count: 0 - - - it: TLS enabled external false renders two ClusterIP services and no LB - set: - external: false - tls: - enabled: true - asserts: - - hasDocuments: - count: 2 - - - it: TLS enabled external true renders three services (master + replicas + LB) - set: - external: true - tls: - enabled: true - asserts: - - hasDocuments: - count: 3 - - ################### - # Master service # - ################### - - - it: master service is a TLS ClusterIP on port 6380 targeting redis-tls - set: - external: false - tls: - enabled: true - documentSelector: - path: metadata.name - value: RELEASE-NAME-master - asserts: - - isKind: - of: Service - - equal: - path: spec.type - value: ClusterIP - - equal: - path: spec.ports[0].port - value: 6380 - - equal: - path: spec.ports[0].name - value: redis-tls - - equal: - path: spec.ports[0].targetPort - value: redis-tls - - equal: - path: spec.selector["redisfailovers-role"] - value: master - - equal: - path: spec.selector["app.kubernetes.io/component"] - value: redis - - #################### - # Replicas service # - #################### - - - it: replicas service is a TLS ClusterIP on port 6380 selecting slave role - set: - external: false - tls: - enabled: true - documentSelector: - path: metadata.name - value: RELEASE-NAME-replicas - asserts: - - isKind: - of: Service - - equal: - path: spec.type - value: ClusterIP - - equal: - path: spec.ports[0].port - value: 6380 - - equal: - path: spec.ports[0].name - value: redis-tls - - equal: - path: spec.ports[0].targetPort - value: redis-tls - - equal: - path: spec.selector["redisfailovers-role"] - value: slave - - equal: - path: spec.selector["app.kubernetes.io/component"] - value: redis diff --git a/packages/apps/redis/tests/tls-certificate_test.yaml b/packages/apps/redis/tests/tls-certificate_test.yaml deleted file mode 100644 index 0fc7bd3f..00000000 --- a/packages/apps/redis/tests/tls-certificate_test.yaml +++ /dev/null @@ -1,76 +0,0 @@ -suite: TLS Certificate -templates: - - templates/tls-certificate.yaml -tests: - - it: does not render when tls.enabled is false - set: - tls: - enabled: false - asserts: - - hasDocuments: { count: 0 } - - - it: does not render when tls.secretName is provided (user owns secret) - set: - tls: - enabled: true - secretName: my-existing-secret - asserts: - - hasDocuments: { count: 0 } - - - it: renders Certificate when tls.enabled and secretName empty - set: - tls: - enabled: true - secretName: "" - asserts: - - hasDocuments: { count: 1 } - - isKind: { of: Certificate } - - equal: { path: apiVersion, value: cert-manager.io/v1 } - - equal: { path: spec.secretName, value: RELEASE-NAME-redis-tls } - - - it: uses default issuerRef - set: - tls: - enabled: true - asserts: - - equal: { path: spec.issuerRef.name, value: selfsigned-cluster-issuer } - - equal: { path: spec.issuerRef.kind, value: ClusterIssuer } - - - it: respects custom issuerRef - set: - tls: - enabled: true - issuerRef: - name: letsencrypt-prod - kind: ClusterIssuer - asserts: - - equal: { path: spec.issuerRef.name, value: letsencrypt-prod } - - - it: dnsNames include master, replicas and external-lb service variants - set: - tls: - enabled: true - asserts: - - contains: { path: spec.dnsNames, content: RELEASE-NAME-master } - - contains: { path: spec.dnsNames, content: RELEASE-NAME-master.NAMESPACE.svc.cluster.local } - - contains: { path: spec.dnsNames, content: RELEASE-NAME-replicas } - - contains: { path: spec.dnsNames, content: RELEASE-NAME-replicas.NAMESPACE.svc.cluster.local } - - contains: { path: spec.dnsNames, content: RELEASE-NAME-external-lb } - - contains: { path: spec.dnsNames, content: RELEASE-NAME-external-lb.NAMESPACE.svc.cluster.local } - - - it: dnsNames do not contain rfs- operator plaintext service - set: - tls: - enabled: true - asserts: - - notContains: { path: spec.dnsNames, content: rfs-RELEASE-NAME } - - notContains: { path: spec.dnsNames, content: rfs-RELEASE-NAME.NAMESPACE.svc.cluster.local } - - - it: dnsNames include external-lb variants even when external is false - set: - external: false - tls: - enabled: true - asserts: - - contains: { path: spec.dnsNames, content: RELEASE-NAME-external-lb } - - contains: { path: spec.dnsNames, content: RELEASE-NAME-external-lb.NAMESPACE.svc.cluster.local } diff --git a/packages/apps/redis/tests/tls-nginx-config_test.yaml b/packages/apps/redis/tests/tls-nginx-config_test.yaml deleted file mode 100644 index c7d57b01..00000000 --- a/packages/apps/redis/tests/tls-nginx-config_test.yaml +++ /dev/null @@ -1,44 +0,0 @@ -suite: TLS nginx ConfigMap -templates: - - templates/tls-nginx-config.yaml -tests: - - it: does not render when tls.enabled is false - set: - tls: - enabled: false - asserts: - - hasDocuments: { count: 0 } - - - it: renders ConfigMap when tls.enabled is true - set: - tls: - enabled: true - asserts: - - hasDocuments: { count: 1 } - - isKind: { of: ConfigMap } - - equal: - path: metadata.name - value: RELEASE-NAME-redis-tls-nginx - - exists: - path: data["nginx.conf"] - - - it: nginx config contains required directives - set: - tls: - enabled: true - asserts: - - matchRegex: - path: data["nginx.conf"] - pattern: "listen 6380 ssl" - - matchRegex: - path: data["nginx.conf"] - pattern: "127\\.0\\.0\\.1:6379" - - matchRegex: - path: data["nginx.conf"] - pattern: "ssl_certificate /etc/nginx/tls/tls\\.crt" - - matchRegex: - path: data["nginx.conf"] - pattern: "ssl_certificate_key /etc/nginx/tls/tls\\.key" - - matchRegex: - path: data["nginx.conf"] - pattern: "ssl_protocols TLSv1\\.2 TLSv1\\.3" diff --git a/packages/apps/redis/values.schema.json b/packages/apps/redis/values.schema.json index ad678339..a93d92ac 100644 --- a/packages/apps/redis/values.schema.json +++ b/packages/apps/redis/values.schema.json @@ -91,49 +91,6 @@ "description": "Enable password generation.", "type": "boolean", "default": true - }, - "tls": { - "description": "TLS configuration for client-facing connections. When enabled, an nginx stream sidecar terminates TLS on port 6380. Intra-cluster traffic on 6379 (operator probes, sentinel, replication) remains plaintext.", - "type": "object", - "default": {}, - "required": [ - "enabled", - "issuerRef", - "secretName" - ], - "properties": { - "enabled": { - "description": "Enable TLS termination via nginx stream sidecar.", - "type": "boolean", - "default": false - }, - "issuerRef": { - "description": "cert-manager Issuer reference. Used only when secretName is empty.", - "type": "object", - "default": {}, - "required": [ - "kind", - "name" - ], - "properties": { - "kind": { - "description": "Either \"Issuer\" or \"ClusterIssuer\".", - "type": "string", - "default": "ClusterIssuer" - }, - "name": { - "description": "Issuer/ClusterIssuer resource name.", - "type": "string", - "default": "selfsigned-cluster-issuer" - } - } - }, - "secretName": { - "description": "Name of an existing kubernetes.io/tls secret. When non-empty, cert-manager Certificate is NOT rendered and the user manages the secret.", - "type": "string", - "default": "" - } - } } } } diff --git a/packages/apps/redis/values.yaml b/packages/apps/redis/values.yaml index 736c3c75..efe80d07 100644 --- a/packages/apps/redis/values.yaml +++ b/packages/apps/redis/values.yaml @@ -46,25 +46,3 @@ version: v8 ## @param {bool} authEnabled - Enable password generation. authEnabled: true - -## @typedef {struct} TLSIssuerRef - cert-manager Issuer reference. -## @field {string} name - Issuer/ClusterIssuer resource name. -## @field {string} kind - Either "Issuer" or "ClusterIssuer". - -## @typedef {struct} TLS - TLS configuration for client-facing connections. -## @field {bool} enabled - Enable TLS termination via nginx stream sidecar. -## @field {string} secretName - Name of an existing kubernetes.io/tls secret. When non-empty, cert-manager Certificate is NOT rendered and the user manages the secret. -## @field {TLSIssuerRef} issuerRef - cert-manager Issuer reference. Used only when secretName is empty. - -## TLS limitations: -## - Internal connections must use -master:6380 (writes) or -replicas:6380 (reads). Direct connection only — no Sentinel-aware service discovery over TLS. -## - Sentinel HA clients (rfs-*:26379) operate on plaintext and resolve master IP as :6379 (the operator hardcodes the plaintext port). To use Sentinel-aware clients with TLS, the operator would need patching — out of scope. -## - For applications that need automatic master failover with TLS: use -master:6380 (the K8s Service's selector follows the master role label, so it auto-routes to the new master after failover). - -## @param {TLS} tls - TLS configuration for client-facing connections. When enabled, an nginx stream sidecar terminates TLS on port 6380. Intra-cluster traffic on 6379 (operator probes, sentinel, replication) remains plaintext. -tls: - enabled: false - secretName: "" - issuerRef: - name: "selfsigned-cluster-issuer" - kind: "ClusterIssuer" diff --git a/packages/library/cozy-lib/templates/_tls.tpl b/packages/library/cozy-lib/templates/_tls.tpl deleted file mode 100644 index 310ccfbb..00000000 --- a/packages/library/cozy-lib/templates/_tls.tpl +++ /dev/null @@ -1,110 +0,0 @@ -{{/* -TLS certificate helpers for cert-manager integration. -These helpers render cert-manager Certificate CRs for services that need TLS. -*/}} - -{{/* -Render a cert-manager Certificate CR. - -Usage: - {{- include "cozy-lib.tls.certificate" (dict - "Release" .Release - "name" "my-redis-tls" - "secretName" "my-redis-tls-secret" - "dnsNames" (list "redis-svc" "redis-svc.ns.svc") - "issuerRef" (dict "name" "selfsigned-cluster-issuer" "kind" "ClusterIssuer") - ) }} - -Parameters: - - Release (required) - Helm release object, used for labels - - name (required) - Certificate CR metadata.name - - secretName (required) - TLS secret name to create (can be same as name). Required when calling directly. When using through tls.yaml, defaults to name. - - dnsNames (required) - list of DNS SANs - - issuerRef (required) - dict with "name" and "kind" (e.g. ClusterIssuer, Issuer) - - duration (optional) - certificate duration, defaults to 8760h (1 year); empty strings are treated as unset - - renewBefore (optional) - renewal window, defaults to 720h (30 days) - - usages (optional) - list of key usages, defaults to ["server auth"] (not cert-manager's default of "digital signature, key encipherment"; this is a deliberate choice for TLS server certificates) -*/}} -{{- define "cozy-lib.tls.certificate" -}} -{{- if not .Release -}} -{{- fail "ERROR: \"Release\" is required for cozy-lib.tls.certificate. Pass the Helm release object via the context dict." -}} -{{- end -}} -{{- if not .name -}} -{{- fail "ERROR: \"name\" is required for cozy-lib.tls.certificate. It sets the Certificate CR metadata.name." -}} -{{- end -}} -{{- if not .secretName -}} -{{- fail "ERROR: \"secretName\" is required for cozy-lib.tls.certificate. Specify the TLS secret name to create." -}} -{{- end -}} -{{- if not .dnsNames -}} -{{- fail "ERROR: \"dnsNames\" is required for cozy-lib.tls.certificate. Provide at least one DNS name as a list." -}} -{{- end -}} -{{- if not .issuerRef -}} -{{- fail "ERROR: \"issuerRef\" is required for cozy-lib.tls.certificate. Provide a dict with \"name\" and \"kind\"." -}} -{{- end -}} -{{- if not .issuerRef.name -}} -{{- fail "ERROR: \"issuerRef.name\" is required for cozy-lib.tls.certificate. Specify the ClusterIssuer or Issuer name." -}} -{{- end -}} -{{- if not .issuerRef.kind -}} -{{- fail "ERROR: \"issuerRef.kind\" is required for cozy-lib.tls.certificate. Specify \"ClusterIssuer\" or \"Issuer\"." -}} -{{- end -}} -{{- if not (or (eq .issuerRef.kind "Issuer") (eq .issuerRef.kind "ClusterIssuer")) -}} -{{- fail "ERROR: issuerRef.kind must be \"Issuer\" or \"ClusterIssuer\"" -}} -{{- end -}} -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: {{ .name }} - labels: - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} -spec: - secretName: {{ .secretName }} - duration: {{ ternary "8760h" .duration (empty .duration) }} - renewBefore: {{ ternary "720h" .renewBefore (empty .renewBefore) }} - privateKey: - algorithm: RSA - size: 2048 - usages: - {{- if .usages }} - {{- range .usages }} - - {{ . }} - {{- end }} - {{- else }} - - server auth - {{- end }} - dnsNames: - {{- range .dnsNames }} - - {{ . }} - {{- end }} - issuerRef: - name: {{ .issuerRef.name }} - kind: {{ .issuerRef.kind }} - group: cert-manager.io -{{- end }} - -{{/* -Convenience helper for chart consumers. -Return a TLS secret name — either the user-provided value or a generated default. -Useful in conditionals to decide whether to mount a TLS secret or render a Certificate CR. - -Usage: - {{- $tlsSecret := include "cozy-lib.tls.secretName" (dict "Release" .Release "suffix" "tls" "secretName" .Values.tls.secretName) }} - -Parameters: - - Release (required) - Helm release object - - suffix (required) - suffix for generated name (e.g. "tls", "server-tls") - - secretName (optional) - user-provided secret name; if set, returned as-is -*/}} -{{- define "cozy-lib.tls.secretName" -}} -{{- if not .Release -}} -{{- fail "ERROR: \"Release\" is required for cozy-lib.tls.secretName. Pass the Helm release object via the context dict." -}} -{{- end -}} -{{- if not .suffix -}} -{{- fail "ERROR: \"suffix\" is required for cozy-lib.tls.secretName. Provide a suffix for the generated secret name (e.g. \"tls\", \"server-tls\")." -}} -{{- end -}} -{{- if not (empty .secretName) -}} -{{- .secretName -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name .suffix -}} -{{- end -}} -{{- end }} diff --git a/packages/system/redis-rd/cozyrds/redis.yaml b/packages/system/redis-rd/cozyrds/redis.yaml index 73711517..e5191aa4 100644 --- a/packages/system/redis-rd/cozyrds/redis.yaml +++ b/packages/system/redis-rd/cozyrds/redis.yaml @@ -8,7 +8,7 @@ spec: plural: redises singular: redis openAPISchema: |- - {"title":"Chart Values","type":"object","properties":{"replicas":{"description":"Number of Redis replicas.","type":"integer","default":2},"resources":{"description":"Explicit CPU and memory configuration for each Redis replica. When omitted, the preset defined in `resourcesPreset` is applied.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Default sizing preset used when `resources` is omitted.","type":"string","default":"nano","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]},"size":{"description":"Persistent Volume Claim size available for application data.","default":"1Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":""},"external":{"description":"Enable external access from outside the cluster.","type":"boolean","default":false},"version":{"description":"Redis major version to deploy","type":"string","default":"v8","enum":["v8","v7"]},"authEnabled":{"description":"Enable password generation.","type":"boolean","default":true},"tls":{"description":"TLS configuration for client-facing connections. When enabled, an nginx stream sidecar terminates TLS on port 6380. Intra-cluster traffic on 6379 (operator probes, sentinel, replication) remains plaintext.","type":"object","default":{},"required":["enabled","issuerRef","secretName"],"properties":{"enabled":{"description":"Enable TLS termination via nginx stream sidecar.","type":"boolean","default":false},"issuerRef":{"description":"cert-manager Issuer reference. Used only when secretName is empty.","type":"object","default":{},"required":["kind","name"],"properties":{"kind":{"description":"Either \"Issuer\" or \"ClusterIssuer\".","type":"string","default":"ClusterIssuer"},"name":{"description":"Issuer/ClusterIssuer resource name.","type":"string","default":"selfsigned-cluster-issuer"}}},"secretName":{"description":"Name of an existing kubernetes.io/tls secret. When non-empty, cert-manager Certificate is NOT rendered and the user manages the secret.","type":"string","default":""}}}}} + {"title":"Chart Values","type":"object","properties":{"replicas":{"description":"Number of Redis replicas.","type":"integer","default":2},"resources":{"description":"Explicit CPU and memory configuration for each Redis replica. When omitted, the preset defined in `resourcesPreset` is applied.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Default sizing preset used when `resources` is omitted.","type":"string","default":"nano","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]},"size":{"description":"Persistent Volume Claim size available for application data.","default":"1Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":""},"external":{"description":"Enable external access from outside the cluster.","type":"boolean","default":false},"version":{"description":"Redis major version to deploy","type":"string","default":"v8","enum":["v8","v7"]},"authEnabled":{"description":"Enable password generation.","type":"boolean","default":true}}} release: prefix: redis- labels: @@ -25,13 +25,12 @@ spec: tags: - cache icon: PHN2ZyB3aWR0aD0iMTQ0IiBoZWlnaHQ9IjE0NCIgdmlld0JveD0iMCAwIDE0NCAxNDQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxNDQiIGhlaWdodD0iMTQ0IiByeD0iMjQiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl82ODNfMzIxMykiLz4KPHBhdGggZD0iTTEyMC4xNDkgOTUuNTQ5MUMxMTQuNTg2IDk4LjQ0ODUgODUuNzcwOSAxMTAuMjk2IDc5LjYzNjMgMTEzLjQ5NUM3My41MDE2IDExNi42OTMgNzAuMDkzNyAxMTYuNjYyIDY1LjI0NzIgMTE0LjM0NkM2MC40MDEyIDExMi4wMjkgMjkuNzM2NCA5OS42NDIzIDI0LjIxMjUgOTcuMDAxOUMyMS40NTE5IDk1LjY4MjcgMjAgOTQuNTY4NyAyMCA5My41MTY2VjgyLjk4MDlDMjAgODIuOTgwOSA1OS45MjIgNzQuMjkwMSA2Ni4zNjY5IDcxLjk3NzhDNzIuODExNSA2OS42NjU2IDc1LjA0NzYgNjkuNTgyMSA4MC41MzIgNzEuNTkxQzg2LjAxNzMgNzMuNjAwOCAxMTguODEyIDc5LjUxNzYgMTI0LjIzMyA4MS41MDI5TDEyNC4yMyA5MS44ODk2QzEyNC4yMzEgOTIuOTMxMSAxMjIuOTggOTQuMDczNiAxMjAuMTQ5IDk1LjU0OTFaIiBmaWxsPSIjOTEyNjI2Ii8+CjxwYXRoIGQ9Ik0xMjAuMTQ3IDg1LjA3NTJDMTE0LjU4NSA4Ny45NzM0IDg1Ljc3IDk5LjgyMTggNzkuNjM1NCAxMDMuMDJDNzMuNTAxMSAxMDYuMjE5IDcwLjA5MzIgMTA2LjE4NyA2NS4yNDcyIDEwMy44NzFDNjAuNDAwNyAxMDEuNTU1IDI5LjczNzEgODkuMTY2OCAyNC4yMTM2IDg2LjUyOEMxOC42OTAxIDgzLjg4NzYgMTguNTc0NCA4Mi4wNzA0IDI0LjAwMDMgNzkuOTQ1OEMyOS40MjYxIDc3LjgyMDUgNTkuOTIxNSA2NS44NTYxIDY2LjM2NzIgNjMuNTQzOEM3Mi44MTE4IDYxLjIzMjQgNzUuMDQ3NSA2MS4xNDgxIDgwLjUzMTkgNjMuMTU3OEM4Ni4wMTY4IDY1LjE2NjggMTE0LjY2IDc2LjU2NzYgMTIwLjA3OSA3OC41NTI1QzEyNS41MDEgODAuNTM5OSAxMjUuNzA5IDgyLjE3NjMgMTIwLjE0NyA4NS4wNzUyWiIgZmlsbD0iI0M2MzAyQiIvPgo8cGF0aCBkPSJNMTIwLjE0OSA3OC41MDJDMTE0LjU4NiA4MS40MDE4IDg1Ljc3MDkgOTMuMjQ5MyA3OS42MzYzIDk2LjQ0ODhDNzMuNTAxNiA5OS42NDYyIDcwLjA5MzcgOTkuNjE1MiA2NS4yNDcyIDk3LjI5ODVDNjAuNDAwOCA5NC45ODMgMjkuNzM2NCA4Mi41OTUyIDI0LjIxMjUgNzkuOTU0N0MyMS40NTE5IDc4LjYzNTUgMjAgNzcuNTIzMiAyMCA3Ni40NzA3VjY1LjkzMzhDMjAgNjUuOTMzOCA1OS45MjIgNTcuMjQzNCA2Ni4zNjY5IDU0LjkzMTFDNzIuODExNSA1Mi42MTg5IDc1LjA0NzYgNTIuNTM1IDgwLjUzMiA1NC41NDQzQzg2LjAxNzcgNTYuNTUzNiAxMTguODEzIDYyLjQ2OTMgMTI0LjIzMyA2NC40NTVMMTI0LjIzIDc0Ljg0MjhDMTI0LjIzMSA3NS44ODQgMTIyLjk4IDc3LjAyNjQgMTIwLjE0OSA3OC41MDJaIiBmaWxsPSIjOTEyNjI2Ii8+CjxwYXRoIGQ9Ik0xMjAuMTQ3IDY4LjAyODJDMTE0LjU4NSA3MC45MjcxIDg1Ljc3IDgyLjc3NDcgNzkuNjM1NCA4NS45NzM3QzczLjUwMTEgODkuMTcxNiA3MC4wOTMyIDg5LjE0MDIgNjUuMjQ3MiA4Ni44MjM1QzYwLjQwMDcgODQuNTA4NCAyOS43MzcxIDcyLjEyMDEgMjQuMjEzNiA2OS40ODA5QzE4LjY5MDEgNjYuODQxMyAxOC41NzQ0IDY1LjAyMzcgMjQuMDAwMyA2Mi44OTg0QzI5LjQyNjEgNjAuNzc0MiA1OS45MjE5IDQ4LjgwOSA2Ni4zNjcyIDQ2LjQ5NzJDNzIuODExOCA0NC4xODUzIDc1LjA0NzUgNDQuMTAxNCA4MC41MzE5IDQ2LjExMDhDODYuMDE2OCA0OC4xMTk3IDExNC42NiA1OS41MTk3IDEyMC4wNzkgNjEuNTA1NUMxMjUuNTAxIDYzLjQ5MjQgMTI1LjcwOSA2NS4xMjkyIDEyMC4xNDcgNjguMDI4MloiIGZpbGw9IiNDNjMwMkIiLz4KPHBhdGggZD0iTTEyMC4xNDkgNjAuODIyNEMxMTQuNTg2IDYzLjcyMTQgODUuNzcwOSA3NS41Njk4IDc5LjYzNjMgNzguNzY5MkM3My41MDE2IDgxLjk2NzEgNzAuMDkzNyA4MS45MzU3IDY1LjI0NzIgNzkuNjE5QzYwLjQwMDggNzcuMzAzNSAyOS43MzY0IDY0LjkxNTIgMjQuMjEyNSA2Mi4yNzZDMjEuNDUxOSA2MC45NTU2IDIwIDU5Ljg0MjggMjAgNTguNzkxNVY0OC4yNTQyQzIwIDQ4LjI1NDIgNTkuOTIyIDM5LjU2NDIgNjYuMzY2OSAzNy4yNTI0QzcyLjgxMTUgMzQuOTM5NyA3NS4wNDc2IDM0Ljg1NjcgODAuNTMyIDM2Ljg2NTZDODYuMDE3NyAzOC44NzQ5IDExOC44MTMgNDQuNzkwNSAxMjQuMjMzIDQ2Ljc3NjNMMTI0LjIzIDU3LjE2MzdDMTI0LjIzMSA1OC4yMDQgMTIyLjk4IDU5LjM0NjUgMTIwLjE0OSA2MC44MjI0WiIgZmlsbD0iIzkxMjYyNiIvPgo8cGF0aCBkPSJNMTIwLjE0NyA1MC4zNDlDMTE0LjU4NSA1My4yNDc5IDg1Ljc2OTggNjUuMDk2MyA3OS42MzUyIDY4LjI5NDFDNzMuNTAwOSA3MS40OTIgNzAuMDkzIDcxLjQ2MDYgNjUuMjQ2OSA2OS4xNDUxQzYwLjQwMDkgNjYuODI4MyAyOS43MzY5IDU0LjQ0MDkgMjQuMjEzOCA1MS44MDEzQzE4LjY4OTkgNDkuMTYyMSAxOC41NzQ2IDQ3LjM0NDEgMjQgNDUuMjE5MkMyOS40MjU5IDQzLjA5NDYgNTkuOTIxNyAzMS4xMzEgNjYuMzY3IDI4LjgxODRDNzIuODExNiAyNi41MDYxIDc1LjA0NzMgMjYuNDIzIDgwLjUzMTcgMjguNDMyNEM4Ni4wMTY2IDMwLjQ0MTcgMTE0LjY1OSA0MS44NDE4IDEyMC4wNzkgNDMuODI3NUMxMjUuNTAxIDQ1LjgxMjggMTI1LjcwOSA0Ny40NSAxMjAuMTQ3IDUwLjM0OVoiIGZpbGw9IiNDNjMwMkIiLz4KPHBhdGggZD0iTTg0Ljg1NDEgNDAuMDk5NEw3NS44OTI2IDQxLjAyOThMNzMuODg2NSA0NS44NTdMNzAuNjQ2MyA0MC40NzAzTDYwLjI5ODMgMzkuNTQwNEw2OC4wMTk3IDM2Ljc1NThMNjUuNzAzIDMyLjQ4MTRMNzIuOTMyMSAzNS4zMDg4TDc5Ljc0NzEgMzMuMDc3NUw3Ny45MDUyIDM3LjQ5NzJMODQuODU0MSA0MC4wOTk0Wk03My4zNTE1IDYzLjUxODRMNTYuNjI2NiA1Ni41ODE2TDgwLjU5MiA1Mi45MDI5TDczLjM1MTUgNjMuNTE4NFpNNTAuMTYzNyA0Mi43ODI2QzU3LjIzODEgNDIuNzgyNiA2Mi45NzMgNDUuMDA1NyA2Mi45NzMgNDcuNzQ3NUM2Mi45NzMgNTAuNDkwMSA1Ny4yMzgxIDUyLjcxMjggNTAuMTYzNyA1Mi43MTI4QzQzLjA4OTMgNTIuNzEyOCAzNy4zNTQ1IDUwLjQ4OTcgMzcuMzU0NSA0Ny43NDc1QzM3LjM1NDUgNDUuMDA1NyA0My4wODkzIDQyLjc4MjYgNTAuMTYzNyA0Mi43ODI2WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTk1LjQ0MzQgNDEuNDE3NEwxMDkuNjI3IDQ3LjAyMjRMOTUuNDU1NiA1Mi42MjJMOTUuNDQzNCA0MS40MTc0WiIgZmlsbD0iIzYyMUIxQyIvPgo8cGF0aCBkPSJNNzkuNzUyOSA0Ny42MjYxTDk1LjQ0NDkgNDEuNDE4OUw5NS40NTcxIDUyLjYyMzZMOTMuOTE4NCA1My4yMjU0TDc5Ljc1MjkgNDcuNjI2MVoiIGZpbGw9IiM5QTI5MjgiLz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl82ODNfMzIxMyIgeDE9IjE4OSIgeTE9IjIxMC41IiB4Mj0iMCIgeTI9IjAiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0E4MDAwMCIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkNGQ0YiLz4KPC9saW5lYXJHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K - keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "replicas"], ["spec", "resources"], ["spec", "resourcesPreset"], ["spec", "size"], ["spec", "storageClass"], ["spec", "external"], ["spec", "version"], ["spec", "authEnabled"], ["spec", "tls"], ["spec", "tls", "enabled"], ["spec", "tls", "secretName"], ["spec", "tls", "issuerRef"], ["spec", "tls", "issuerRef", "name"], ["spec", "tls", "issuerRef", "kind"]] + keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "replicas"], ["spec", "resources"], ["spec", "resourcesPreset"], ["spec", "size"], ["spec", "storageClass"], ["spec", "external"], ["spec", "version"], ["spec", "authEnabled"]] secrets: exclude: [] include: - resourceNames: - redis-{{ .name }}-auth - - redis-{{ .name }}-redis-tls services: exclude: [] include: diff --git a/packages/tests/cozy-lib-tests/templates/tests/tls-missing-release.yaml b/packages/tests/cozy-lib-tests/templates/tests/tls-missing-release.yaml deleted file mode 100644 index ad51a301..00000000 --- a/packages/tests/cozy-lib-tests/templates/tests/tls-missing-release.yaml +++ /dev/null @@ -1,6 +0,0 @@ -{{/* -Test-only template: calls cozy-lib.tls.certificate without Release -to verify the validation guard triggers. -*/}} -{{- $certArgs := dict "name" .Values.tls.name "secretName" .Values.tls.secretName "dnsNames" .Values.tls.dnsNames "issuerRef" .Values.tls.issuerRef -}} -{{- include "cozy-lib.tls.certificate" $certArgs -}} diff --git a/packages/tests/cozy-lib-tests/templates/tests/tls-missing-secretname.yaml b/packages/tests/cozy-lib-tests/templates/tests/tls-missing-secretname.yaml deleted file mode 100644 index 92e28bcc..00000000 --- a/packages/tests/cozy-lib-tests/templates/tests/tls-missing-secretname.yaml +++ /dev/null @@ -1,6 +0,0 @@ -{{/* -Test-only template: calls cozy-lib.tls.certificate without secretName -to verify the validation guard triggers. -*/}} -{{- $certArgs := dict "Release" .Release "name" .Values.tls.name "dnsNames" .Values.tls.dnsNames "issuerRef" .Values.tls.issuerRef -}} -{{- include "cozy-lib.tls.certificate" $certArgs -}} diff --git a/packages/tests/cozy-lib-tests/templates/tests/tls-secretname-missing-release.yaml b/packages/tests/cozy-lib-tests/templates/tests/tls-secretname-missing-release.yaml deleted file mode 100644 index b361c611..00000000 --- a/packages/tests/cozy-lib-tests/templates/tests/tls-secretname-missing-release.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{{/* -Test-only template: calls cozy-lib.tls.secretName without Release -to verify the validation guard triggers. -*/}} -{{- $secretName := include "cozy-lib.tls.secretName" (dict "suffix" "tls" "secretName" .Values.tlsSecretName) -}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: test-secretname-missing-release -data: - secretName: {{ $secretName | quote }} diff --git a/packages/tests/cozy-lib-tests/templates/tests/tls-secretname-missing-suffix.yaml b/packages/tests/cozy-lib-tests/templates/tests/tls-secretname-missing-suffix.yaml deleted file mode 100644 index 199d7d6d..00000000 --- a/packages/tests/cozy-lib-tests/templates/tests/tls-secretname-missing-suffix.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{{/* -Test-only template: calls cozy-lib.tls.secretName without suffix -to verify the validation guard triggers. -*/}} -{{- $secretName := include "cozy-lib.tls.secretName" (dict "Release" .Release "secretName" .Values.tlsSecretName) -}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: test-secretname-missing-suffix -data: - secretName: {{ $secretName | quote }} diff --git a/packages/tests/cozy-lib-tests/templates/tests/tls-secretname.yaml b/packages/tests/cozy-lib-tests/templates/tests/tls-secretname.yaml deleted file mode 100644 index dc63eee9..00000000 --- a/packages/tests/cozy-lib-tests/templates/tests/tls-secretname.yaml +++ /dev/null @@ -1,7 +0,0 @@ -{{- $secretName := include "cozy-lib.tls.secretName" (dict "Release" .Release "suffix" .Values.tlsSuffix "secretName" .Values.tlsSecretName) -}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: test-secretname -data: - secretName: {{ $secretName | quote }} diff --git a/packages/tests/cozy-lib-tests/templates/tests/tls.yaml b/packages/tests/cozy-lib-tests/templates/tests/tls.yaml deleted file mode 100644 index 3d38d7dc..00000000 --- a/packages/tests/cozy-lib-tests/templates/tests/tls.yaml +++ /dev/null @@ -1,6 +0,0 @@ -{{- if .Values.tls }} -{{- $certArgs := dict "Release" .Release "name" .Values.tls.name "secretName" (default .Values.tls.name .Values.tls.secretName) "dnsNames" .Values.tls.dnsNames "issuerRef" .Values.tls.issuerRef "usages" (.Values.tls.usages | default list) -}} -{{- if and .Values.tls.duration (ne .Values.tls.duration "") }}{{- $_ := set $certArgs "duration" .Values.tls.duration }}{{- end -}} -{{- if and .Values.tls.renewBefore (ne .Values.tls.renewBefore "") }}{{- $_ := set $certArgs "renewBefore" .Values.tls.renewBefore }}{{- end -}} -{{- include "cozy-lib.tls.certificate" $certArgs -}} -{{- end }} diff --git a/packages/tests/cozy-lib-tests/tests/tls_missing_release_test.yaml b/packages/tests/cozy-lib-tests/tests/tls_missing_release_test.yaml deleted file mode 100644 index 5cfe9f5c..00000000 --- a/packages/tests/cozy-lib-tests/tests/tls_missing_release_test.yaml +++ /dev/null @@ -1,25 +0,0 @@ -suite: TLS certificate helper - Release validation - -templates: - - templates/tests/tls-missing-release.yaml - -tests: - # Missing Release triggers a validation error - - it: errors when Release is not provided - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: missing-release-tls - secretName: missing-release-tls-secret - dnsNames: - - svc.example - issuerRef: - name: selfsigned-cluster-issuer - kind: ClusterIssuer - asserts: - - failedTemplate: - errorMessage: 'ERROR: "Release" is required for cozy-lib.tls.certificate. Pass the Helm release object via the context dict.' diff --git a/packages/tests/cozy-lib-tests/tests/tls_missing_secretname_test.yaml b/packages/tests/cozy-lib-tests/tests/tls_missing_secretname_test.yaml deleted file mode 100644 index 14cee109..00000000 --- a/packages/tests/cozy-lib-tests/tests/tls_missing_secretname_test.yaml +++ /dev/null @@ -1,24 +0,0 @@ -suite: TLS certificate helper - secretName validation - -templates: - - templates/tests/tls-missing-secretname.yaml - -tests: - # Missing secretName triggers a validation error - - it: errors when secretName is not provided - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: missing-secret-tls - dnsNames: - - svc.example - issuerRef: - name: selfsigned-cluster-issuer - kind: ClusterIssuer - asserts: - - failedTemplate: - errorMessage: 'ERROR: "secretName" is required for cozy-lib.tls.certificate. Specify the TLS secret name to create.' diff --git a/packages/tests/cozy-lib-tests/tests/tls_secretname_missing_release_test.yaml b/packages/tests/cozy-lib-tests/tests/tls_secretname_missing_release_test.yaml deleted file mode 100644 index ecfcb9ea..00000000 --- a/packages/tests/cozy-lib-tests/tests/tls_secretname_missing_release_test.yaml +++ /dev/null @@ -1,17 +0,0 @@ -suite: TLS secretName helper - Release validation - -templates: - - templates/tests/tls-secretname-missing-release.yaml - -tests: - - it: errors when Release is not provided - release: - name: my-app - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tlsSecretName: my-custom-tls-secret - asserts: - - failedTemplate: - errorMessage: 'ERROR: "Release" is required for cozy-lib.tls.secretName. Pass the Helm release object via the context dict.' diff --git a/packages/tests/cozy-lib-tests/tests/tls_secretname_missing_suffix_test.yaml b/packages/tests/cozy-lib-tests/tests/tls_secretname_missing_suffix_test.yaml deleted file mode 100644 index 586d0cee..00000000 --- a/packages/tests/cozy-lib-tests/tests/tls_secretname_missing_suffix_test.yaml +++ /dev/null @@ -1,17 +0,0 @@ -suite: TLS secretName helper - suffix validation - -templates: - - templates/tests/tls-secretname-missing-suffix.yaml - -tests: - - it: errors when suffix is not provided - release: - name: my-app - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tlsSecretName: "" - asserts: - - failedTemplate: - errorMessage: 'ERROR: "suffix" is required for cozy-lib.tls.secretName. Provide a suffix for the generated secret name (e.g. "tls", "server-tls").' diff --git a/packages/tests/cozy-lib-tests/tests/tls_secretname_test.yaml b/packages/tests/cozy-lib-tests/tests/tls_secretname_test.yaml deleted file mode 100644 index 94386838..00000000 --- a/packages/tests/cozy-lib-tests/tests/tls_secretname_test.yaml +++ /dev/null @@ -1,46 +0,0 @@ -suite: TLS secretName helper - -templates: - - templates/tests/tls-secretname.yaml - -tests: - - it: returns user-provided secretName when set - release: - name: my-app - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tlsSecretName: my-custom-tls-secret - tlsSuffix: tls - asserts: - - equal: - path: data.secretName - value: my-custom-tls-secret - - - it: generates default secretName from release name and suffix when secretName is omitted - release: - name: my-app - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tlsSuffix: tls - asserts: - - equal: - path: data.secretName - value: my-app-tls - - - it: generates default secretName when secretName is an empty string - release: - name: my-app - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tlsSecretName: "" - tlsSuffix: tls - asserts: - - equal: - path: data.secretName - value: my-app-tls diff --git a/packages/tests/cozy-lib-tests/tests/tls_test.yaml b/packages/tests/cozy-lib-tests/tests/tls_test.yaml deleted file mode 100644 index a1b33587..00000000 --- a/packages/tests/cozy-lib-tests/tests/tls_test.yaml +++ /dev/null @@ -1,350 +0,0 @@ -suite: TLS certificate helper - -templates: - - templates/tests/tls.yaml - -tests: - # Certificate CR renders with all required fields - - it: renders a Certificate CR with all required fields - values: - - tls_values.yaml - release: - name: test-release - namespace: tenant-test - asserts: - - hasDocuments: - count: 1 - - isKind: - of: Certificate - - isAPIVersion: - of: cert-manager.io/v1 - - equal: - path: metadata.name - value: my-redis-tls - - equal: - path: spec.secretName - value: my-redis-tls-secret - - equal: - path: spec.privateKey.algorithm - value: RSA - - equal: - path: spec.privateKey.size - value: 2048 - - # dnsNames are correctly set - - it: sets dnsNames correctly - values: - - tls_values.yaml - release: - name: test-release - namespace: tenant-test - asserts: - - equal: - path: spec.dnsNames - value: - - redis-svc - - redis-svc.tenant-test.svc - - # issuerRef is correctly set - - it: sets issuerRef correctly - values: - - tls_values.yaml - release: - name: test-release - namespace: tenant-test - asserts: - - equal: - path: spec.issuerRef.name - value: selfsigned-cluster-issuer - - equal: - path: spec.issuerRef.kind - value: ClusterIssuer - - equal: - path: spec.issuerRef.group - value: cert-manager.io - - # Labels include release info - - it: includes standard labels - values: - - tls_values.yaml - release: - name: test-release - namespace: tenant-test - asserts: - - equal: - path: metadata.labels["app.kubernetes.io/instance"] - value: test-release - - equal: - path: metadata.labels["app.kubernetes.io/managed-by"] - value: Helm - - # Default duration and renewBefore are used when not provided - - it: uses default duration and renewBefore - values: - - tls_values.yaml - release: - name: test-release - namespace: tenant-test - asserts: - - equal: - path: spec.duration - value: 8760h - - equal: - path: spec.renewBefore - value: 720h - - # Custom duration and renewBefore work when provided - - it: uses custom duration and renewBefore when provided - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: custom-tls - secretName: custom-tls-secret - dnsNames: - - svc.example - issuerRef: - name: my-issuer - kind: Issuer - duration: 43800h - renewBefore: 360h - asserts: - - equal: - path: spec.duration - value: 43800h - - equal: - path: spec.renewBefore - value: 360h - - # Default usages is server auth - - it: uses server auth as default usage - values: - - tls_values.yaml - release: - name: test-release - namespace: tenant-test - asserts: - - equal: - path: spec.usages - value: - - server auth - - # Custom usages work when provided - - it: uses custom usages when provided - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: client-tls - secretName: client-tls-secret - dnsNames: - - svc.example - issuerRef: - name: my-issuer - kind: ClusterIssuer - usages: - - server auth - - client auth - asserts: - - equal: - path: spec.usages - value: - - server auth - - client auth - - # secretName defaults to name when not provided - - it: uses name as secretName when secretName not provided - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: my-tls-cert - dnsNames: - - svc.example - issuerRef: - name: selfsigned-cluster-issuer - kind: ClusterIssuer - asserts: - - equal: - path: metadata.name - value: my-tls-cert - - equal: - path: spec.secretName - value: my-tls-cert - - # Issuer kind is passed through to Certificate CR - - it: passes issuerRef kind to Certificate CR - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: test-tls - dnsNames: - - svc.example - issuerRef: - name: selfsigned-cluster-issuer - kind: ClusterIssuer - asserts: - - equal: - path: spec.issuerRef.kind - value: ClusterIssuer - - # Namespace-scoped Issuer also works - - it: supports namespace-scoped Issuer - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: test-tls - dnsNames: - - svc.example - issuerRef: - name: my-namespace-issuer - kind: Issuer - asserts: - - equal: - path: spec.issuerRef.kind - value: Issuer - - equal: - path: spec.issuerRef.name - value: my-namespace-issuer - - # TLS disabled produces zero documents - - it: produces zero documents when tls is not set - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - asserts: - - hasDocuments: - count: 0 - - # TLS disabled when tls is explicitly null - - it: produces zero documents when tls is null - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: null - asserts: - - hasDocuments: - count: 0 - - # Empty dnsNames triggers a validation error - - it: errors when dnsNames is empty - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: empty-dns-tls - dnsNames: [] - issuerRef: - name: selfsigned-cluster-issuer - kind: ClusterIssuer - asserts: - - failedTemplate: - errorMessage: 'ERROR: "dnsNames" is required for cozy-lib.tls.certificate. Provide at least one DNS name as a list.' - - # Missing issuerRef name triggers a validation error - - it: errors when issuerRef name is not provided - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: missing-issuer-tls - dnsNames: - - svc.example - issuerRef: - kind: ClusterIssuer - asserts: - - failedTemplate: - errorMessage: 'ERROR: "issuerRef.name" is required for cozy-lib.tls.certificate. Specify the ClusterIssuer or Issuer name.' - - # Missing issuerRef kind triggers a validation error - - it: errors when issuerRef kind is not provided - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: missing-kind-tls - dnsNames: - - svc.example - issuerRef: - name: my-issuer - asserts: - - failedTemplate: - errorMessage: 'ERROR: "issuerRef.kind" is required for cozy-lib.tls.certificate. Specify "ClusterIssuer" or "Issuer".' - - # Invalid issuerRef kind triggers a validation error - - it: errors when issuerRef kind is not Issuer or ClusterIssuer - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: invalid-kind-tls - dnsNames: - - svc.example - issuerRef: - name: my-issuer - kind: InvalidKind - asserts: - - failedTemplate: - errorMessage: 'ERROR: issuerRef.kind must be "Issuer" or "ClusterIssuer"' - - # Empty string duration should fall back to default 8760h - - it: uses default duration when duration is an empty string - release: - name: test-release - namespace: tenant-test - set: - _cluster: {} - _namespace: {} - tls: - name: empty-duration-tls - dnsNames: - - svc.example - issuerRef: - name: selfsigned-cluster-issuer - kind: ClusterIssuer - duration: "" - renewBefore: "" - asserts: - - hasDocuments: - count: 1 - - equal: - path: spec.duration - value: 8760h - - equal: - path: spec.renewBefore - value: 720h diff --git a/packages/tests/cozy-lib-tests/tests/tls_values.yaml b/packages/tests/cozy-lib-tests/tests/tls_values.yaml deleted file mode 100644 index 6673dda1..00000000 --- a/packages/tests/cozy-lib-tests/tests/tls_values.yaml +++ /dev/null @@ -1,12 +0,0 @@ -tls: - name: my-redis-tls - secretName: my-redis-tls-secret - dnsNames: - - redis-svc - - redis-svc.tenant-test.svc - issuerRef: - name: selfsigned-cluster-issuer - kind: ClusterIssuer - -_cluster: {} -_namespace: {}