Adding SSL Support

This commit is contained in:
Tyler Hale 2024-08-01 14:43:13 -06:00
parent 4daa6d2d0b
commit 828a542896
Signed by: Tyler
GPG key ID: C7CC4B910D88EF96
10 changed files with 162 additions and 6 deletions

View file

@ -4,12 +4,16 @@ Ansible playbook that provisions a group of servers to run mariadb as a Galera C
## Requirements
If you are using HaProxy as a front end to the cluster, you will need to create a user for the health checks to work properly. The user does not need to be able to access any databases, it just needs to be able to authenticate against the server.
If you are using HaProxy as a front end to the cluster **without SSL**, you will need to create a user for the health checks to work properly. The user does not need to be able to access any databases, it just needs to be able to authenticate against the server.
```sql
CREATE USER 'haproxy_check'@'10.10.10.253' WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 0 MAX_STATEMENT_TIME 0.0000000001;
```
If you are using HaProxy as a front end to the cluster **with SSL**, use default tcp checks to validate the service is available as HaProxy does not support the SSL settings for mysql.
If this is the first install, the `mariadb_cluster_bootstrap` variable will need to be set to true to bootstrap the cluster.
## Variables
| Variable | Required | Default | Description |
@ -43,6 +47,9 @@ You can view the status of the cluster by running the following command.
```sql
SHOW GLOBAL STATUS LIKE 'wsrep_%';
SHOW GLOBAL VARIABLES LIKE 'have_ssl';
SHOW SESSION STATUS LIKE 'Ssl_cipher';
SHOW GLOBAL VARIABLES LIKE 'require_secure_transport';
```
## License

View file

@ -0,0 +1,4 @@
---
collections:
- community.general
- community.crypto

View file

@ -3,3 +3,7 @@
mariadb_cluster_wsrep_cluster_name: "my_wsrep_cluster"
mariadb_cluster_access_ip: ""
mariadb_cluster_master: "{{ groups['mariadb_cluster'][0] }}"
mariadb_cluster_ssl: true
mariadb_cluster_bootstrap: false
mariadb_cluster_cert_length: "+7300d"

View file

@ -17,3 +17,4 @@
- name: Bootstrap Galera
include_tasks: tasks/bootstrap-galera.yml
when: mariadb_cluster_bootstrap == true

View file

@ -3,12 +3,12 @@
- name: Stop MariaDB on first MariaDB Galera cluster node
service: name=mariadb state=stopped
when: inventory_hostname == groups['mariadb_cluster'][0]
when: inventory_hostname == mariadb_cluster_master
- name: Bootstrap first MariaDB Galera cluster node
command: galera_new_cluster
when: inventory_hostname == groups['mariadb_cluster'][0]
when: inventory_hostname == mariadb_cluster_master
- name: Restart the other MariaDB Galera cluster nodes
service: name=mariadb state=restarted
when: inventory_hostname != groups['mariadb_cluster'][0]
when: inventory_hostname != mariadb_cluster_master

View file

@ -0,0 +1,39 @@
---
# file: roles/mariadb_cluster/tasks/certificates-server.yml
- name: "{{ hostvars[item]['ansible_hostname'] }} - Create private key"
community.crypto.openssl_privatekey:
path: /etc/ssl/galera/server.key
- name: "{{ hostvars[item]['ansible_hostname'] }} - Check if server certificate exists"
stat:
path: "/etc/ssl/galera/server.pem"
register: serverCertCheck
- name: "{{ hostvars[item]['ansible_hostname'] }} - CSR"
block:
- name: "{{ hostvars[item]['ansible_hostname'] }} - Create CSR for new certificate"
community.crypto.openssl_csr_pipe:
privatekey_path: /etc/ssl/galera/server.key
common_name: "{{ hostvars[item]['ansible_hostname'] }}"
subject_alt_name:
- "DNS:{{ mariadb_cluster_wsrep_cluster_name }}"
register: csr
- name: "{{ hostvars[item]['ansible_hostname'] }} - Sign certificate with CA"
community.crypto.x509_certificate_pipe:
csr_content: "{{ csr.csr }}"
provider: ownca
ownca_path: /etc/ssl/galera/ca-certificate.pem
ownca_privatekey_path: /etc/ssl/galera/ca-certificate.key
ownca_not_after: "{{ mariadb_cluster_cert_length }}"
ownca_not_before: "-1d"
delegate_to: "{{ mariadb_cluster_master }}"
register: certificate
- name: "{{ hostvars[item]['ansible_hostname'] }} - Write certificate file"
copy:
dest: /etc/ssl/galera/server.pem
content: "{{ certificate.certificate }}"
when: not serverCertCheck.stat.exists

View file

@ -0,0 +1,67 @@
---
# file: roles/mariadb_cluster/tasks/certificates.yml
- name: Ensure directory exists for local self-signed TLS certs
file:
path: /etc/ssl/galera/
state: directory
owner: mysql
group: mysql
recurse: true
- name: CA Setup
block:
- name: Generate an OpenSSL private key
community.crypto.openssl_privatekey:
path: /etc/ssl/galera/ca-certificate.key
- name: Create certificate signing request (CSR) for CA certificate
community.crypto.openssl_csr_pipe:
privatekey_path: /etc/ssl/galera/ca-certificate.key
common_name: Galera-Ansible
use_common_name_for_san: false
basic_constraints:
- 'CA:TRUE'
basic_constraints_critical: true
key_usage:
- keyCertSign
key_usage_critical: true
register: ca_csr
changed_when: false
- name: Create self-signed CA certificate from CSR
community.crypto.x509_certificate:
path: /etc/ssl/galera/ca-certificate.pem
csr_content: "{{ ca_csr.csr }}"
privatekey_path: /etc/ssl/galera/ca-certificate.key
selfsigned_not_after: "{{ mariadb_cluster_cert_length }}"
provider: selfsigned
- name: Copy ca-certificate locally for transfer
fetch:
src: /etc/ssl/galera/ca-certificate.pem
dest: /tmp/galera-ca-certificate.pem
flat: yes
when: inventory_hostname == mariadb_cluster_master
- name: Transfer ca cert to other members
copy:
src: /tmp/galera-ca-certificate.pem
dest: /etc/ssl/galera/ca-certificate.pem
owner: mysql
group: mysql
mode: '0644'
- name: Server Certificates
include_tasks: certificates-server.yml
loop: "{{ groups['mariadb_cluster'] }}"
loop_control:
extended: yes
- name: Ensure mysql has permissions to access certs
file:
path: /etc/ssl/galera/
state: directory
owner: mysql
group: mysql
recurse: true

View file

@ -11,13 +11,24 @@
- mariadb-server
- galera
state: latest
tags: packages
- name: Update galera config
template:
src: "galera.cnf.j2"
dest: "/etc/my.cnf.d/galera.cnf"
dest: "/etc/my.cnf.d/z-galera.cnf"
notify: Bootstrap Galera
- name: Certificates tasks
include_tasks: certificates.yml
when: mariadb_cluster_ssl == true
- name: Update ssl config
template:
src: "ssl.cnf.j2"
dest: "/etc/my.cnf.d/z-ssl.cnf"
when: mariadb_cluster_ssl == true
- name: Enable firewall rule for MySQL access
firewalld:
port: 3306/tcp
@ -29,11 +40,12 @@
- name: "Enable firewall rule for MySQL access to Access IP"
firewalld:
rich_rule: 'rule family="ipv4" source address="{{ mariadb_cluster_access_ip }}" port port="3306" protocol="tcp" accept'
rich_rule: 'rule family="ipv4" source address="{{ item }}" port port="3306" protocol="tcp" accept'
permanent: yes
state: enabled
immediate: yes
notify: Reload firewalld
loop: "{{ mariadb_cluster_access_ip }}"
when: mariadb_cluster_access_ip != ""
- name: Setup access for other servers
@ -66,6 +78,12 @@
dest: /etc/systemd/system/mariadb.service.d/override.conf
notify: Daemon Reload
- name: Set selinux nis_enabled
seboolean:
name: nis_enabled
state: true
persistent: true
- name: Flush handlers
meta: flush_handlers

View file

@ -37,7 +37,11 @@ wsrep_on=1
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
# Provider specific configuration options
{% if mariadb_cluster_ssl == true %}
wsrep_provider_options="socket.ssl_key=/etc/ssl/galera/server.key;socket.ssl_cert=/etc/ssl/galera/server.pem;socket.ssl_ca=/etc/ssl/galera/ca-certificate.pem"
{% else %}
#wsrep_provider_options=
{% endif %}
# Logical cluster name. Should be the same for all nodes.
wsrep_cluster_name="{{ mariadb_cluster_wsrep_cluster_name }}"

View file

@ -0,0 +1,12 @@
# MySQL Server
[mysqld]
ssl-ca = /etc/ssl/galera/ca-certificate.pem
ssl-key = /etc/ssl/galera/server.key
ssl-cert = /etc/ssl/galera/server.pem
require_secure_transport = 1
# MySQL Client Configuration
[mysql]
ssl-ca = /etc/ssl/galera/ca-certificate.pem
ssl-key = /etc/ssl/galera/server.key
ssl-cert = /etc/ssl/galera/server.pem