TLS
MariaDB Enterprise Operator supports issuing, configuring and rotating TLS certiticates for both your MariaDB
and MaxScale
resources. It aims to be secure by default, for this reason, TLS certificates are issued and configured by the operator as a default behaviour.
Table of contents
MariaDB
configurationMaxScale
configurationMariaDB
certificate specificationMaxScale
certificate specification- CA bundle
- Issue certificates with the operator
- Issue certificates with cert-manager
- Provide your own certificates
- Bring your own CA
- Intermediate CAs
- Custom trust
- Distributing trust
- TLS version configuration
- Certificate lifetime configuration
- Private key configuration
- CA renewal
- Certificate renewal
- Certificate status
- TLS requirements for
Users
- Galera Enterprise SSL modes
- Secure application connections with TLS
- Test TLS certificates with
Connections
- Limitations
MariaDB
configuration
IMPORTANT
This section covers TLS configuration in new instances. If you are looking to migrate an existing instance to use TLS, please refer to Enabling TLS in existing instances instead.
TLS can be configured in MariaDB
resources by setting tls.enabled=true
:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: ... tls: enabled: true
As a result, the operator will generate a Certificate Authority (CA) and use it to issue the leaf certificates mounted by the instance. It is important to note that the TLS connections are not enforced in this case i.e. both TLS and non-TLS connections will be accepted. This is the default behaviour when no tls
field is specified.
If you want to enforce TLS connections, you can set tls.required=true
:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: ... tls: enabled: true required: true
This approach ensures that any unencrypted connection will fail, effectively enforcing security best practices.
If you want to fully opt-out from TLS, you can set tls.enabled=false
:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: ... tls: enabled: false
This will disable certificate issuance, resulting in all connections being unencrypted.
Refer to further sections for a more advanced TLS configuration.
MaxScale
configuration
IMPORTANT
This section covers TLS configuration in new instances. If you are looking to migrate an existing instance to use TLS, please refer to Enabling TLS in existing instances instead.
TLS will be automatically enabled in MaxScale
when the referred MariaDB
(via mariaDbRef
) has TLS enabled and enforced. Alternatively, you can explicitly enable TLS by setting tls.enabled=true
:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale-galera spec: ... mariaDbRef: name: mariadb-galera tls: enabled: true
As a result, the operator will generate a Certificate Authority (CA) and use it to issue the leaf certificates mounted by the instance. It is important to note that, unlike MariaDB
, MaxScale
does not support TLS and non-TLS connections simultaneously (see limitations). Therefore, TLS connections will be enforced in this case i.e. unencrypted connections will fail, ensuring security best practises.
If you want to fully opt-out from TLS, you can set tls.enabled=false
. This should only be done when MariaDB
TLS is not enforced or disabled:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale-galera spec: ... mariaDbRef: name: mariadb-galera tls: enabled: false
This will disable certificate issuance, resulting in all connections being unencrypted.
Refer to further sections for a more advanced TLS configuration.
MariaDB
certificate specification
The MariaDB
TLS setup consists of the following certificates:
- Certificate Authority (CA) keypair to issue the server certificate.
- Server leaf certificate used to encrypt server connections.
- Certificate Authority (CA) keypair to issue the client certificate.
- Client leaf certificate used to encrypt and authenticate client connections.
As a default behaviour, the operator generates a single CA to be used for issuing both the server and client certificates, but the user can decide to use dedicated CAs for each case. Root CAs, and intermedicate CAs in some cases, are supported, see limitations for further detail.
The server certificate contains the following Subject Alternative Names (SANs):
<mariadb-name>.<namespace>.svc.<cluster-name>
<mariadb-name>.<namespace>.svc
<mariadb-name>.<namespace>
<mariadb-name>
*.<mariadb-name>-internal.<namespace>.svc.<cluster-name>
*.<mariadb-name>-internal.<namespace>.svc
*.<mariadb-name>-internal.<namespace>
*.<mariadb-name>-internal
<mariadb-name>-primary.<namespace>.svc.<cluster-name>
<mariadb-name>-primary.<namespace>.svc
<mariadb-name>-primary.<namespace>
<mariadb-name>-primary
<mariadb-name>-secondary.<namespace>.svc.<cluster-name>
<mariadb-name>-secondary.<namespace>.svc
<mariadb-name>-secondary.<namespace>
<mariadb-name>-secondary
localhost
Whereas the client certificate is only valid for the <mariadb-name>-client
SAN.
MaxScale
certificate specification
The MaxScale
TLS setup consists of the following certificates:
- Certificate Authority (CA) keypair to issue the admin certificate.
- Admin leaf certificate used to encrypt the administrative REST API and GUI.
- Certificate Authority (CA) keypair to issue the listener certificate.
- Listener leaf certificate used to encrypt database connections to the listener.
- Server CA bundle used to establish trust with the MariaDB server.
- Server leaf certificate used to connect to the MariaDB server.
As a default behaviour, the operator generates a single CA to be used for issuing both the admin and the listener certificates, but the user can decide to use dedicated CAs for each case. Client certificate and CA bundle configured in the referred MariaDB are used as server certificates by default, but the user is able to provide its own certificates. Root CAs, and intermedicate CAs in some cases, are supported, see limitations for further detail.
Both the admin and listener certificates contain the following Subject Alternative Names (SANs):
<maxscale-name>.<namespace>.svc.<clusername>
<maxscale-name>.<namespace>.svc
<maxscale-name>.<namespace>
<maxscale-name>
<maxscale-name>-gui.<namespace>.svc.<clusername>
<maxscale-name>-gui.<namespace>.svc
<maxscale-name>-gui.<namespace>
<maxscale-name>-gui
*.<maxscale-name>-internal.<namespace>.svc.<clusername>
*.<maxscale-name>-internal.<namespace>.svc
*.<maxscale-name>-internal.<namespace>
*.<maxscale-name>-internal
For details about the server certificate, see MariaDB
certificate specification.
CA bundle
As you could appreciate in MariaDB
certificate specification and MaxScale
certificate specification, the TLS setup involves multiple CAs. In order to establish trust in a more convenient way, the operator groups the CAs together in a CA bundle that will need to be specified when securely connecting from your applications. Every MariaDB
and MaxScale
resources have a dedicated bundle of its own available in a Secret
named <instance-name>-ca-bundle
.
These trust bundles contain non expired CAs needed to connect to the instances. New CAs are automatically added to the bundle after renewal, whilst old CAs are removed after they expire. It is important to note that both the new and old CAs remain in the bundle for a while to ensure a smooth update when the new certificates are issued by the new CA.
Issue certificates with the operator
By setting tls.enabled=true
, the operator will generate a root CA for each instance, which will be used to issue the certificates described in the MariaDB
cert spec and MaxScale
cert spec sections:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb spec: ... tls: enabled: true
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale spec: ... tls: enabled: true
To establish trust with the instances, the CA's public key will be added to the CA bundle. If you need a different trust chain, please refer to the custom trust section.
The advantage of this approach is that the operator fully manages the Secrets
that contain the certificates without depending on any third party dependency. Also, since the operator fully controls the renewal process, it is able to pause a leaf certificate renewal if the CA is being updated at that moment, as described in the cert renewal section.
Issue certificates with cert-manager
IMPORTANT cert-manager must be previously installed in the cluster in order to use this feature.
cert-manager is the de-facto standard for managing certificates in Kubernetes. It is a Kubernetes native certificate management controller that allows you to automatically provision, manage and renew certificates. It supports multiple certificate backends (in-cluster, Hashicorp Vault...) which are configured as Issuer
or ClusterIssuer
resources.
As an example, we are going to setup an in-cluster root CA ClusterIssuer
:
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: selfsigned spec: selfSigned: {} --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: root-ca namespace: default spec: duration: 52596h # 6 years commonName: root-ca usages: - digital signature - key encipherment - cert sign issuerRef: name: selfsigned kind: ClusterIssuer isCA: true privateKey: encoding: PKCS1 algorithm: ECDSA size: 256 secretTemplate: labels: enterprise.mariadb.com/watch: "" secretName: root-ca revisionHistoryLimit: 10 --- apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: root-ca spec: ca: secretName: root-ca
Then, you can reference the ClusterIssuer
in the MariaDB
and MaxScale
resources:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: ... tls: enabled: true serverCertIssuerRef: name: root-ca kind: ClusterIssuer clientCertIssuerRef: name: root-ca kind: ClusterIssuer
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale-galera spec: ... tls: enabled: true adminCertIssuerRef: name: root-ca kind: ClusterIssuer listenerCertIssuerRef: name: root-ca kind: ClusterIssuer
The operator will create cert-manager's Certificate
resources for each certificate, and will mount the resulting TLS Secrets
in the instances. These Secrets
containing the certificates will be managed by cert-manager as well as its renewal process.
To establish trust with the instances, the ca.crt
field provided by cert-managed in the Secret
will be added to the CA bundle. If you need a different trust chain, please refer to the custom trust section.
The advantage of this approach is that you can use any of the cert-manager's certificate backends, such as the in-cluster CA or HashiCorp Vault, and potentially reuse the same Issuer
/ClusterIssuer
with multiple instances.
Provide your own certificates
Providing your own certificates is as simple as creating the Secrets
with the appropriate structure and referencing them in the MariaDB
and MaxScale
resources. The certificates must be compliant with the MariaDB
cert spec and MaxScale
cert spec.
The CA certificate must be provided as a Secret
with the following structure:
apiVersion: v1 kind: Secret type: Opaque metadata: name: mariadb-galera-server-ca labels: enterprise.mariadb.com/watch: "" data: ca.crt: -----BEGIN CERTIFICATE----- <public-key> -----END CERTIFICATE----- ca.key: -----BEGIN EC PRIVATE KEY----- <private-key> -----END EC PRIVATE KEY-----
The ca.key
field is only required if you want to the operator to automatically re-issue certificates with this CA, see bring your own CA for further detail. In other words, if only ca.crt
is provided, the operator will trust this CA by adding it to the CA bundle, but no certificates will be issued with it, the user will responsible for upating the certificate Secret
manually with renewed certificates.
The enterprise.mariadb.com/watch
label is required only if you want the operator to automatically trigger an update when the CA is renewed, see CA renewal for more detail.
The leaf certificate must match the previous CA's public key, and it should provided as a TLS Secret
with the following structure:
apiVersion: v1 kind: Secret type: kubernetes.io/tls metadata: name: mariadb-galera-server-tls labels: enterprise.mariadb.com/watch: "" data: tls.crt: -----BEGIN CERTIFICATE----- <public-key> -----END CERTIFICATE----- tls.key: -----BEGIN EC PRIVATE KEY----- <private-key> -----END EC PRIVATE KEY-----
The enterprise.mariadb.com/watch
label is required only if you want the operator to automatically trigger an update when the certificate is renewed, see cert renewal for more detail.
Once the certificate Secrets
are available in the cluster, you can create the MariaDB
and MaxScale
resources referencing them:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: ... tls: enabled: true serverCASecretRef: name: mariadb-server-ca serverCertSecretRef: name: mariadb-galera-server-tls clientCASecretRef: name: mariadb-client-ca clientCertSecretRef: name: mariadb-galera-client-tls
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale-galera spec: ... tls: enabled: true adminCASecretRef: name: maxscale-admin-ca adminCertSecretRef: name: maxscale-galera-admin-tls listenerCASecretRef: name: maxscale-listener-ca listenerCertSecretRef: name: maxscale-galera-listener-tls serverCASecretRef: name: mariadb-galera-ca-bundle serverCertSecretRef: name: mariadb-galera-client-tls
Bring your own CA
If you already have a CA setup outside of Kubernetes, you can use it with the operator by providing the CA certificate as a Secret
with the following structure:
apiVersion: v1 kind: Secret type: Opaque metadata: name: mariadb-ca labels: enterprise.mariadb.com/watch: "" data: ca.crt: -----BEGIN CERTIFICATE----- <public-key> -----END CERTIFICATE----- ca.key: -----BEGIN EC PRIVATE KEY----- <private-key> -----END EC PRIVATE KEY-----
Just by providing a reference to this Secret
, the operator will use it to issue leaf certificates instead of generating a new CA:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: ... tls: enabled: true serverCASecretRef: name: mariadb-server-ca clientCASecretRef: name: mariadb-client-ca
Intermediate CAs
Intermediate CAs are supported by the operator with some limitations. Leaf certificates issued by the intermediate CAs are slightly different, and include the intermediate CA public key as part of the certificate, in the following order: Leaf certificate -> Intermediate CA
. This is a common practise to easily establish trust in complex PKI setups, where multiple CA are involved.
Many applications support this Leaf certificate -> Intermediate CA
structure as a valid leaf certificate, and are able to establish trust with the intermediate CA. Normally, the intermediate CA will not be directly trusted, but used as a path to the root CA, which should be trusted by the application. If not trusted already, you can add the root CA to the CA bundle by using a custom trust.
Custom trust
You are able to provide a set of CA public keys to be added to the CA bundle by creating a Secret
with the following structure:
apiVersion: v1 kind: Secret type: Opaque metadata: name: custom-trust labels: enterprise.mariadb.com/watch: "" data: ca.crt: -----BEGIN CERTIFICATE----- <my-org-root-ca> -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- <root-ca> -----END CERTIFICATE-----
And referencing it in the MariaDB
and MaxScale
resources, for instance:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale-galera spec: ... tls: enabled: true adminCASecretRef: name: custom-trust adminCertIssuerRef: name: my-org-intermediate-ca kind: ClusterIssuer listenerCASecretRef: name: custom-trust listenerCertIssuerRef: name: intermediate-ca kind: ClusterIssuer
This is specially useful when issuing certificates with an intermediate CA, see intermediate CAs section for further detail.
Distributing trust
Distributing the CA bundle to your application namespace is out of the scope of this operator, the bundles will remain in the same namespace as the MariaDB
and MaxScale
instances.
If your application is in a different namespace, you can copy the CA bundle to the application namespace. Projects like trust-manager can help you to automate this process and continously reconcile bundle changes.
TLS version configuration
You may configure the supported TLS versions in MariaDB
by setting:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: tls: versions: - TLSv1.3 - TLSv1.2 - TLSv1.1 - TLSv1.0
If not specified, the MariaDB's default TLS versions will be used. See MariaDB docs.
Regarding MaxScale
, you can also configure the supported TLS versions, both for the Admin REST API and MariaDB servers:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale-galera spec: ... tls: adminVersions: - TLSv13 - TLSv12 - TLSv11 - TLSv10 serverVersions: - TLSv13 - TLSv12 - TLSv11 - TLSv10
If not specified, the MaxScale's default TLS versions will be used. See MaxScale docs:
Certificate lifetime configuration
By default, CA certificates are valid for 3 years, while leaf certificates have a validity of 3 months. This lifetime can be customized in both MariaDB
and MaxScale
resources through the certificate configuration fields. For example:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: tls: enabled: true required: true serverCertConfig: caLifetime: 8766h # 1 year certLifetime: 720h # 1 month clientCertConfig: caLifetime: 8766h # 1 year certLifetime: 720h # 1 month
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale-galera spec: tls: enabled: true adminCertConfig: caLifetime: 8766h # 1 year certLifetime: 1h # 1 month listenerCertConfig: caLifetime: 8766h # 1 year certLifetime: 720h # 1 month
When issuing certificates with cert-manager, you can specify the certificate configuration field alongside the issuer reference:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: tls: enabled: true required: true serverCertIssuerRef: name: root-ca kind: ClusterIssuer serverCertConfig: caLifetime: 8766h # 1 year certLifetime: 720h # 1 month clientCertIssuerRef: name: root-ca kind: ClusterIssuer clientCertConfig: caLifetime: 8766h # 1 year certLifetime: 720h # 1 month
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale-galera spec: tls: enabled: true adminCertIssuerRef: name: root-ca kind: ClusterIssuer adminCertConfig: caLifetime: 8766h # 1 year certLifetime: 1h # 1 month listenerCertIssuerRef: name: root-ca kind: ClusterIssuer listenerCertConfig: caLifetime: 8766h # 1 year certLifetime: 720h # 1 month
Private key configuration
By default, private keys are generated with the ECDSA
algorithm and a size of 256
. You can customize the private key configuration in both MariaDB
and MaxScale
resources through the certificate configuration fields. For example:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: tls: enabled: true required: true serverCertConfig: privateKeyAlgorithm: RSA privateKeySize: 2048 clientCertConfig: privateKeyAlgorithm: RSA privateKeySize: 2048
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale-galera spec: tls: enabled: true adminCertConfig: privateKeyAlgorithm: RSA privateKeySize: 2048 listenerCertConfig: privateKeyAlgorithm: RSA privateKeySize: 2048
When issuing certificates with cert-manager, you can specify the private key configuration field alongside the issuer reference:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: tls: enabled: true required: true serverCertIssuerRef: name: root-ca kind: ClusterIssuer serverCertConfig: privateKeyAlgorithm: ECDSA privateKeySize: 256 clientCertIssuerRef: name: root-ca kind: ClusterIssuer clientCertConfig: privateKeyAlgorithm: ECDSA privateKeySize: 256
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale-galera spec: tls: enabled: true adminCertIssuerRef: name: root-ca kind: ClusterIssuer adminCertConfig: privateKeyAlgorithm: ECDSA privateKeySize: 256 listenerCertIssuerRef: name: root-ca kind: ClusterIssuer listenerCertConfig: privateKeyAlgorithm: ECDSA privateKeySize: 256
The following set of algorithms and sizes are supported:
Algorithm | Key Sizes |
---|---|
RSA | 2048, 3072, 4096 |
ECDSA | 256, 384, 521 |
CA renewal
Depending on the setup, CAs can be managed and renewed by either MariaDB Enterprise Operator or cert-manager.
When managed by the operator, CAs have a lifetime of 3 years by default, and are marked for renewal after 66% of its lifetime has passed i.e. ~2 years. After being renewed, the operator will trigger an update of the instances to include the new CA in the bundle.
When managed by cert-manager, the renewal process is fully controlled by cert-manager, but the operator will also update the CA bundle after the CA is renewed.
You may choose any of the available update strategies to control the instance update process.
Certificate renewal
Depending on the setup, certificates can be managed and renewed by the operator or cert-manager. In either case, certificates have a lifetime of 90 days by default, and marked for renewal after 66% of its lifetime has passed i.e. ~60 days.
When the certificates are issued by the operator, the operator is able to pause a leaf certificate renewal if the CA is being updated at that same moment. This approach ensures a smooth update by avoiding the simultaneous rollout of the new CA and its associated certificates. Rolling them out together could be problematic, as all Pods need to trust the new CA before its issued certificates can be utilized.
When the certificates are issued by cert-manager, the renewal process is fully managed by cert-manager, and the operator will not interfere with it. The operator will only update the instances whenever the CA or the certificates get renewed.
You may choose any of the available update strategies to control the instance update process.
Certificate status
To have a high level picture of the certificates status, you can check the status.tls
field of the MariaDB
and MaxScale
resources:
kubectl get mariadb mariadb-galera -o jsonpath="{.status.tls}" | jq { "caBundle": [ { "issuer": "CN=mariadb-galera-ca", "notAfter": "2028-01-20T14:26:50Z", "notBefore": "2025-01-20T13:26:50Z", "subject": "CN=mariadb-galera-ca" } ], "clientCert": { "issuer": "CN=mariadb-galera-ca", "notAfter": "2025-04-20T14:26:50Z", "notBefore": "2025-01-20T13:26:50Z", "subject": "CN=mariadb-galera-client" }, "serverCert": { "issuer": "CN=mariadb-galera-ca", "notAfter": "2025-04-20T14:26:50Z", "notBefore": "2025-01-20T13:26:50Z", "subject": "CN=mariadb-galera.default.svc.cluster.local" } }
kubectl get maxscale maxscale-galera -o jsonpath="{.status.tls}" | jq { "adminCert": { "issuer": "CN=maxscale-galera-ca", "notAfter": "2025-04-20T14:33:09Z", "notBefore": "2025-01-20T13:33:09Z", "subject": "CN=maxscale-galera.default.svc.cluster.local" }, "caBundle": [ { "issuer": "CN=maxscale-galera-ca", "notAfter": "2028-01-20T14:33:09Z", "notBefore": "2025-01-20T13:33:09Z", "subject": "CN=maxscale-galera-ca" }, { "issuer": "CN=mariadb-galera-ca", "notAfter": "2028-01-20T14:28:46Z", "notBefore": "2025-01-20T13:28:46Z", "subject": "CN=mariadb-galera-ca" } ], "listenerCert": { "issuer": "CN=maxscale-galera-ca", "notAfter": "2025-04-20T14:33:09Z", "notBefore": "2025-01-20T13:33:09Z", "subject": "CN=maxscale-galera.default.svc.cluster.local" }, "serverCert": { "issuer": "CN=mariadb-galera-ca", "notAfter": "2025-04-20T14:28:46Z", "notBefore": "2025-01-20T13:28:46Z", "subject": "CN=mariadb-galera-client" } }
TLS requirements for Users
You are able to declaratively manage access to your MariaDB
instances by creating User
SQL resources. In particular, when TLS is enabled, you can provide additional requirements for the user when connecting over TLS.
For instance, if you want to require a valid x509 certificate for the user to be able o connect:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: User metadata: name: user spec: ... require: x509: true
In order to restrict which subject the user certificate should have and/or require a particular issuer, you may set:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: User metadata: name: user spec: ... require: issuer: "/CN=mariadb-galera-ca" subject: "/CN=mariadb-galera-client"
When any of these TLS requirements are not met, the user will not be able to connect to the instance.
See MariaDB docs and the API reference for further detail.
Galera Enterprise SSL modes
MariaDB Enterprise Cluster (Galera) supports multiple SSL modes to secure the communication between the nodes. For configuring the SSL enforcement level on the server i.e. WSREP, you can set:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: tls: enabled: true galeraServerSSLMode: SERVER_X509
The following values are supported: SERVER_X509
, SERVER
and PROVIDER
. Refer to the Galera Enterprise docs for further detail about these modes.
You may also configure the SSL enforcement level used during Snapshot State Transfers(SST) by setting:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: tls: enabled: true galeraSSTEnabled: true galeraClientSSLMode: VERIFY_IDENTITY
The following values are supported: VERIFY_IDENTITY
, VERIFY
, REQUIRED
and DISABLED
. Refer to the Galera Enterprise docs for further detail about these modes.
If you are willing to increase the enforcement level in an existing instance, make sure you follow the migration guide provided in the Enabling TLS in existing instances section.
Secure application connections with TLS
In this guide, we will configure TLS for an application running in the app
namespace to connect with MariaDB
and MaxScale
instances deployed in the default
namespace. We assume that the following resources are already present in the default
namespace:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: rootPasswordSecretKeyRef: name: mariadb key: root-password storage: size: 1Gi replicas: 3 galera: enabled: true tls: enabled: true required: true --- apiVersion: enterprise.mariadb.com/v1alpha1 kind: MaxScale metadata: name: maxscale-galera spec: replicas: 2 mariaDbRef: name: mariadb-galera tls: enabled: true
The first step is to create a User
resource and grant the necessary permissions:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: User metadata: name: app namespace: app spec: mariaDbRef: name: mariadb-galera namespace: default require: issuer: "/CN=mariadb-galera-ca" subject: "/CN=mariadb-galera-client" host: "%" --- apiVersion: enterprise.mariadb.com/v1alpha1 kind: Grant metadata: name: grant-app namespace: app spec: mariaDbRef: name: mariadb-galera namespace: default privileges: - "ALL PRIVILEGES" database: "*" table: "*" username: app host: "%"
The app
user will be able to connect to the MariaDB
instance from the app
namespace by providing a certificate with subject mariadb-galera-client
and issued by the mariadb-galera-ca
CA.
With the permissions in place, the next step is to prepare the certificates required for the application to connect:
- CA Bundle: The trust bundle for
MariaDB
andMaxScale
is available as aSecret
named<instance-name>-ca-bundle
in thedefault
namespace. For more details, refer to the sections on CA bundle and distributing trust. - Client Certificate:
MariaDB
provides a default client certificate stored in aSecret
named<mariadb-name>-client-cert
in thedefault
namespace. You can either use thisSecret
or generate a new one with the subjectmariadb-galera-client
, issued by themariadb-galera-ca
CA. While issuing client certificates for applications falls outside the scope of this operator, you can test them usingConnection
resources.
In this example, we assume that the following Secrets
are available in the app
namespace:
- mariadb-bundle
: CA bundle for the MariaDB
and MaxScale
instances.
- mariadb-galera-client-cert
: Client certificate required to connect to the MariaDB
instance.
With these Secrets
in place, we can proceed to define our application:
apiVersion: batch/v1 kind: CronJob metadata: name: mariadb-client namespace: app spec: schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: mariadb-client image: mariadb:11.4.4 command: - bash args: - -c - > mariadb -u app -h mariadb-galera-primary.default.svc.cluster.local --ssl-ca=/etc/pki/ca.crt --ssl-cert=/etc/pki/tls.crt --ssl-key=/etc/pki/tls.key --ssl-verify-server-cert -e "SELECT 'MariaDB connection successful!' AS Status;" -t volumeMounts: - name: pki mountPath: /etc/pki readOnly: true volumes: - name: pki projected: sources: - secret: name: mariadb-bundle items: - key: ca.crt path: ca.crt - secret: name: mariadb-galera-client-cert items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key restartPolicy: Never
The application will connect to the MariaDB
instance using the app
user, and will execute a simple query to check the connection status. The --ssl-ca
, --ssl-cert
, --ssl-key
and --ssl-verify-server-cert
flags are used to provide the CA bundle, client certificate and key, and to verify the server certificate respectively.
If the connection is successful, the output should be:
+---------------------------------+ | Status | +---------------------------------+ | MariaDB connection successful! | +---------------------------------+
You can also point the application to the MaxScale
instance by updating the host to maxscale-galera.default.svc.cluster.local
:
apiVersion: batch/v1 kind: CronJob metadata: name: maxscale-client namespace: app spec: schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: maxscale-client image: mariadb:11.4.4 command: - bash args: - -c - > mariadb -u app -h maxscale-galera.default.svc.cluster.local --ssl-ca=/etc/pki/ca.crt --ssl-cert=/etc/pki/tls.crt --ssl-key=/etc/pki/tls.key --ssl-verify-server-cert -e "SELECT 'MaxScale connection successful!' AS Status;" -t volumeMounts: - name: pki mountPath: /etc/pki readOnly: true volumes: - name: pki projected: sources: - secret: name: mariadb-bundle items: - key: ca.crt path: ca.crt - secret: name: mariadb-galera-client-cert items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key restartPolicy: Never
If successful, the expected output is:
+---------------------------------+ | Status | +---------------------------------+ | MaxScale connection successful! | +---------------------------------+
Test TLS certificates with Connections
In order to validate your TLS setup, and to ensure that you TLS certificates are correctly issued and configured, you can use the Connection
resource to test the connection to both your MariaDB
and MaxScale
instances:
apiVersion: enterprise.mariadb.com/v1alpha1 kind: Connection metadata: name: connection spec: mariaDbRef: name: mariadb-galera username: mariadb passwordSecretKeyRef: name: mariadb key: password tlsClientCertSecretRef: name: mariadb-galera-client-cert database: mariadb healthCheck: interval: 30s
apiVersion: enterprise.mariadb.com/v1alpha1 kind: Connection metadata: name: connection-maxscale spec: maxScaleRef: name: maxscale-galera username: mariadb passwordSecretKeyRef: name: mariadb key: password tlsClientCertSecretRef: name: mariadb-galera-client-cert database: mariadb healthCheck: interval: 30s
If successful, the Connection
resource will be in a Ready
state, which means that your TLS setup is correctly configured:
kubectl get connections NAME READY STATUS SECRET AGE connection True Healthy connection 2m8s connection-maxscale True Healthy connection-maxscale 97s
This could be specially useful when providing your own certificates and issuing certificates for your applications.
Limitations
Galera and intermediate CAs
Leaf certificates issued by intermediate CAs are not supported by Galera, see MDEV-35812. This implies that a root CA must be used to issue the MariaDB
certificates.
This doesn't affect MaxScale
, as it is able to establish trust with intermediate CAs, and therefore you can still issue your application facing certificates (MaxScale listeners) with an intermediate CA, giving you more flexibility in your PKI setup.
MaxScale
- Unlike
MariaDB
, TLS and non-TLS connections on the same port are not supported simultanously. - TLS encryption must be enabled for listeners when they are created. For servers, the TLS can be enabled after creation but it cannot be disabled or altered.
Refer to the MaxScale documentation for further detail.