mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-03 10:37:21 +09:00
fix(mariadb): use MariaDB TLS verification flags in backup script
The backup image is alpine plus mariadb-client, so the backup script is
parsed by the MariaDB client. That client implements no ssl-mode option:
it is MySQL 8 syntax, and the MariaDB client rejects it while parsing
arguments ("unknown variable", exit 7) before it ever opens a
connection. Every TLS-enabled backup run therefore failed at the first
client invocation.
Replace it with the MariaDB equivalent, --ssl-ca combined with
--ssl-verify-server-cert, which validates the chain against the CA and
checks the server hostname against the certificate SANs.
Also align the cluster-domain fallback in the certificate template with
the rest of the catalog, which defaults to cozy.local rather than the
upstream Kubernetes cluster.local. These names go into the leaf
certificate SAN list that the backup client now verifies against, so a
mismatched fallback would produce certificates that fail hostname
verification.
The previous assertions only checked that an SSL string appeared in the
rendered script, so they stayed green against a script the client
refuses to parse. They now pin the client dialect instead: the MariaDB
verification flags must be present, the MySQL-only option must never be
emitted in any TLS state, and both client invocations must carry the
options.
Signed-off-by: Aleksei Sviridkin <f@lex.la>
This commit is contained in:
3 files changed
+97
-16
No files matched your search
@@ -11,8 +11,18 @@ stringData:
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
{{- /*
|
||||
The backup image is alpine + mariadb-client, so these options are parsed
|
||||
by the MariaDB client, which implements no ssl-mode option and rejects it
|
||||
at argument parsing time before connecting. --ssl-ca combined with
|
||||
--ssl-verify-server-cert is the MariaDB equivalent of MySQL's strictest
|
||||
mode: it validates the chain against the CA and checks the server
|
||||
hostname against the certificate SANs. Keep this rationale in a template
|
||||
comment rather than a shell comment so the MySQL-only option name never
|
||||
appears in the rendered script.
|
||||
*/}}
|
||||
{{- if $tlsEnabled }}
|
||||
SSL_OPTS="--ssl-ca=/etc/mysql-ssl/ca.crt --ssl-mode=VERIFY_IDENTITY"
|
||||
SSL_OPTS="--ssl-ca=/etc/mysql-ssl/ca.crt --ssl-verify-server-cert"
|
||||
{{- else }}
|
||||
SSL_OPTS=""
|
||||
{{- end }}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{{- $tlsEnabled := (include "mariadb.tls.enabled" .) | eq "true" -}}
|
||||
{{- if $tlsEnabled }}
|
||||
{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cluster.local" }}
|
||||
{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }}
|
||||
---
|
||||
# Self-signed bootstrap Issuer — used only to sign the CA Certificate below.
|
||||
apiVersion: cert-manager.io/v1
|
||||
|
||||
@@ -851,27 +851,48 @@ tests:
|
||||
name: tls-ca
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# E: backup script contains --ssl-mode=VERIFY_IDENTITY when TLS enabled
|
||||
# VERIFY_IDENTITY is the strictest SSL mode — validates CA and hostname,
|
||||
# matching the cert SAN list that already covers the primary/secondary
|
||||
# service names used by MYSQL_HOST.
|
||||
# Cluster-domain fallback. The platform injects _cluster.cluster-domain
|
||||
# (networking.clusterDomain, "cozy.local"), but the chart-level fallback
|
||||
# must match it: these FQDNs land in the leaf certificate SAN list, and the
|
||||
# backup client verifies the server hostname against exactly that list. A
|
||||
# fallback pointing at the upstream Kubernetes default instead of the
|
||||
# Cozystack one would silently produce certificates that fail verification.
|
||||
# -------------------------------------------------------------------
|
||||
- it: "backup-script Secret contains --ssl-mode=VERIFY_IDENTITY when tls.enabled=true"
|
||||
- it: "leaf certificate SANs fall back to cozy.local when cluster-domain is unset"
|
||||
templates:
|
||||
- templates/backup-script.yaml
|
||||
- templates/certmanager.yaml
|
||||
documentIndex: 3
|
||||
set:
|
||||
tls:
|
||||
enabled: true
|
||||
backup:
|
||||
enabled: true
|
||||
s3Bucket: s3.example.org/test
|
||||
cleanupStrategy: "--keep-last=3"
|
||||
# helm-unittest deep-merges `set` over the suite defaults, so the key is
|
||||
# blanked rather than removed to exercise the fallback branch.
|
||||
_cluster:
|
||||
cluster-domain: ""
|
||||
asserts:
|
||||
- matchRegex:
|
||||
path: stringData["backup.sh"]
|
||||
pattern: "--ssl-mode=VERIFY_IDENTITY"
|
||||
- contains:
|
||||
path: spec.dnsNames
|
||||
content: "my-mariadb.tenant-test.svc.cozy.local"
|
||||
- notContains:
|
||||
path: spec.dnsNames
|
||||
content: "my-mariadb.tenant-test.svc.cluster.local"
|
||||
|
||||
- it: "backup-script Secret contains --ssl-ca=/etc/mysql-ssl/ca.crt when tls.enabled=true"
|
||||
# -------------------------------------------------------------------
|
||||
# E: backup script uses MariaDB-native TLS verification flags.
|
||||
#
|
||||
# The backup image is alpine + mariadb-client, so the script is parsed by
|
||||
# the MariaDB client, not the MySQL one. The two dialects differ:
|
||||
#
|
||||
# MySQL 8 : --ssl-mode=VERIFY_IDENTITY
|
||||
# MariaDB : --ssl-ca=<file> --ssl-verify-server-cert
|
||||
#
|
||||
# The MariaDB client has no --ssl-mode option at all and rejects it during
|
||||
# argument parsing ("unknown variable 'ssl-mode=...'", exit 7) before any
|
||||
# connection is attempted, so a single --ssl-mode occurrence fails every
|
||||
# TLS-enabled backup run. These tests therefore assert the dialect, not the
|
||||
# mere presence of some SSL string.
|
||||
# -------------------------------------------------------------------
|
||||
- it: "backup-script Secret uses MariaDB TLS verification flags when tls.enabled=true"
|
||||
templates:
|
||||
- templates/backup-script.yaml
|
||||
set:
|
||||
@@ -882,9 +903,53 @@ tests:
|
||||
s3Bucket: s3.example.org/test
|
||||
cleanupStrategy: "--keep-last=3"
|
||||
asserts:
|
||||
# --ssl-ca alone only supplies the trust anchor; without
|
||||
# --ssl-verify-server-cert the MariaDB client skips hostname
|
||||
# verification, which would silently downgrade the connection.
|
||||
- matchRegex:
|
||||
path: stringData["backup.sh"]
|
||||
pattern: "--ssl-ca=/etc/mysql-ssl/ca\\.crt"
|
||||
- matchRegex:
|
||||
path: stringData["backup.sh"]
|
||||
pattern: "--ssl-verify-server-cert"
|
||||
|
||||
# Regression guard: no MySQL-8-only option may reach the MariaDB client, in
|
||||
# any TLS state. Anchored on the option name so both --ssl-mode=VALUE and a
|
||||
# bare --ssl-mode are caught.
|
||||
- it: "backup-script Secret never emits the MySQL-only --ssl-mode option (tls.enabled=true)"
|
||||
templates:
|
||||
- templates/backup-script.yaml
|
||||
set:
|
||||
tls:
|
||||
enabled: true
|
||||
backup:
|
||||
enabled: true
|
||||
s3Bucket: s3.example.org/test
|
||||
cleanupStrategy: "--keep-last=3"
|
||||
asserts:
|
||||
- notMatchRegex:
|
||||
path: stringData["backup.sh"]
|
||||
pattern: "--ssl-mode"
|
||||
|
||||
# Both client invocations must carry $SSL_OPTS. If only one does, that leg
|
||||
# connects without TLS verification while the suite still looks green.
|
||||
- it: "backup-script Secret passes SSL_OPTS to both mysql and mysqldump"
|
||||
templates:
|
||||
- templates/backup-script.yaml
|
||||
set:
|
||||
tls:
|
||||
enabled: true
|
||||
backup:
|
||||
enabled: true
|
||||
s3Bucket: s3.example.org/test
|
||||
cleanupStrategy: "--keep-last=3"
|
||||
asserts:
|
||||
- matchRegex:
|
||||
path: stringData["backup.sh"]
|
||||
pattern: "mysql -u \"\\$MYSQL_USER\" -h \"\\$MYSQL_HOST\" \\$SSL_OPTS"
|
||||
- matchRegex:
|
||||
path: stringData["backup.sh"]
|
||||
pattern: "mysqldump -u \"\\$MYSQL_USER\" -h \"\\$MYSQL_HOST\" \\$SSL_OPTS"
|
||||
|
||||
- it: "backup-script Secret does not contain ssl flags when tls.enabled=false"
|
||||
templates:
|
||||
@@ -900,6 +965,12 @@ tests:
|
||||
- notMatchRegex:
|
||||
path: stringData["backup.sh"]
|
||||
pattern: "--ssl-mode"
|
||||
- notMatchRegex:
|
||||
path: stringData["backup.sh"]
|
||||
pattern: "--ssl-ca"
|
||||
- notMatchRegex:
|
||||
path: stringData["backup.sh"]
|
||||
pattern: "--ssl-verify-server-cert"
|
||||
|
||||
- it: "backup CronJob has tls-ca volumeMount when external=true and tls.enabled unset"
|
||||
templates:
|
||||
|
||||
Reference in new issue
Block a user