From 27ce939c69004a5a15209a421fa24c5efb941176 Mon Sep 17 00:00:00 2001 From: Alain Takoudjou <alain.takoudjou@nexedi.com> Date: Fri, 10 Dec 2021 15:18:38 +0100 Subject: [PATCH] repman: Use caucase for repman and mariadb ssl certificate --- software/repman/buildout.hash.cfg | 6 +- .../repman/instance-mariadb.cfg.jinja2.in | 67 ++++++++-- software/repman/instance-repman.cfg.jinja2.in | 121 ++++++++++++++---- software/repman/instance.cfg.in | 4 + software/repman/software.cfg | 8 +- 5 files changed, 168 insertions(+), 38 deletions(-) diff --git a/software/repman/buildout.hash.cfg b/software/repman/buildout.hash.cfg index ae994d308d..96c9c5d99d 100644 --- a/software/repman/buildout.hash.cfg +++ b/software/repman/buildout.hash.cfg @@ -14,11 +14,11 @@ # not need these here). [instance.cfg] filename = instance.cfg.in -md5sum = 9aeb37bd4590aa7fa746ef70d78cc0d0 +md5sum = af2fc4a7a0f782fed2cb1112ef3cb397 [instance-repman.cfg] _update_hash_filename_ = instance-repman.cfg.jinja2.in -md5sum = e5b2d17e6ef5448e851521fee612f0c4 +md5sum = d9151fe9f86fb1700c6c33d30a750837 [config-toml.in] _update_hash_filename_ = templates/config.toml.in @@ -34,7 +34,7 @@ md5sum = 0eeb24c6aa0760f0d33c4cc2828ddf30 [template-mariadb.cfg] _update_hash_filename_ = instance-mariadb.cfg.jinja2.in -md5sum = 284cf030eeba4bdcc884908b2d730e47 +md5sum = cfbbf574c1f755855022b1bcd6e6ff64 [template-my-cnf] _update_hash_filename_ = templates/my.cnf.in diff --git a/software/repman/instance-mariadb.cfg.jinja2.in b/software/repman/instance-mariadb.cfg.jinja2.in index 9619d45a63..d5822d0e29 100644 --- a/software/repman/instance-mariadb.cfg.jinja2.in +++ b/software/repman/instance-mariadb.cfg.jinja2.in @@ -21,6 +21,7 @@ database-host = {{ host }}:{{ port }} monitor-base-url = ${monitor-publish-parameters:monitor-base-url} partition-path = ${buildout:directory} receiver-port = ${dbjob-parameter:socat-port} +csr-id = ${caucase-csr-id:csr-id} [jinja2-template-base] recipe = slapos.recipe.template:jinja2 @@ -62,6 +63,50 @@ context = key content {{content_section_name}}:content mode = {{ mode }} {%- endmacro %} +{% import "caucase" as caucase with context %} +{{ caucase.updater( + prefix='caucase-updater', + buildout_bin_directory=buildout_bin_directory, + updater_path='${directory:services}/caucase-updater', + url=slapparameter_dict['caucase-url'], + data_dir='${directory:srv}/caucase-updater', + crt_path='${directory:ssl}/mariadb-cert.crt', + ca_path='${directory:srv}/caucase-updater/ca.crt', + crl_path='${directory:srv}/caucase-updater/crl.pem', + key_path='${directory:ssl}/mariadb-cert.key', + on_renew=None, + max_sleep=None, + template_csr_pem=None, + openssl=openssl_bin, +)}} +{% do part_list.append('caucase-updater') -%} +{% do part_list.append('caucase-updater-promise') -%} + +[get-csr-id] +recipe = plone.recipe.command +output = ${directory:tmp}/csr_id +command = + if [ -s "${directory:ssl}/mariadb-cert.crt" ]; then + RESULT="None"; + else + if [ -f "${caucase-updater-csr:csr}" ]; then + RESULT=$({{ caucase_bin_client }} --ca-url {{ slapparameter_dict['caucase-url'] }} --send-csr ${caucase-updater-csr:csr} | cut -d ' ' -f1) + if [ ! $? -eq 0 ]; then + RESULT="None"; + fi + fi + fi + cat <<EOF > ${:output} + [caucase] + csr-id = $(echo $RESULT) + EOF +update-command = ${:command} + +[caucase-csr-id] +recipe = slapos.cookbook:zero-knowledge.read +file-path = ${get-csr-id:output} +csr-id = + [my-cnf-parameters] socket = ${directory:run}/mariadb.sock ip = {{ ip }} @@ -75,9 +120,9 @@ innodb-log-file-size = {{ dumps(slapparameter_dict.get('innodb-log-file-size', 0 innodb-file-per-table = {{ dumps(slapparameter_dict.get('innodb-file-per-table', 0)) }} innodb-log-buffer-size = {{ dumps(slapparameter_dict.get('innodb-log-buffer-size', 0)) }} relaxed-writes = {{ dumps(slapparameter_dict.get('relaxed-writes', False)) }} -ssl-crt = ${directory:mariadb-ssl}/crt.pem -ssl-key = ${directory:mariadb-ssl}/key.pem -ssl-ca-crt = ${certificate-authority:ca-dir}/cacert.pem +ssl-crt = ${directory:ssl}/mariadb-cert.crt +ssl-key = ${directory:ssl}/mariadb-cert.key +ssl-ca-crt = ${directory:srv}/caucase-updater/ca.crt [my-cnf] < = jinja2-template-base @@ -152,18 +197,17 @@ environ = {{ variable }} {%- endfor %} -[ca-mysqld] -<= certificate-authority -recipe = slapos.cookbook:certificate_authority.request -key-file = ${my-cnf-parameters:ssl-key} -cert-file = ${my-cnf-parameters:ssl-crt} -executable = ${mysqld:rendered} -wrapper = ${directory:controller}/mariadb +[mysqld-launcher] +recipe = slapos.cookbook:wrapper +command-line = ${mysqld:rendered} +wrapper-path = ${directory:controller}/mariadb +wait-for-files = + ${directory:ssl}/mariadb-cert.crt {% import "supervisord_lib" as supervisord_lib with context %} {{ supervisord_lib.supervisord("mariadb-ctl", buildout_bin_directory, supervisord_conf, use_service_hash=False) }} {% do part_list.append("supervisord-mariadb-ctl") -%} -{% set maradb_program_dict = {"name": "mariadb", "command": "${ca-mysqld:wrapper}", +{% set maradb_program_dict = {"name": "mariadb", "command": "${mysqld-launcher:wrapper-path}", "stopwaitsecs": 86400, "environment": [], "stdout_logfile": "${directory:log}/mariadb_stdout.log", "stderr_logfile": "${directory:log}/mariadb_stdout.log" } %} @@ -262,6 +306,7 @@ log = ${:var}/log run = ${:var}/run config-tmp = ${:tmp}/config custom = ${directory:etc}/mysql/custom +ssl = ${:etc}/ssl [dbjob-parameter] bash-bin = {{ bash_bin }} diff --git a/software/repman/instance-repman.cfg.jinja2.in b/software/repman/instance-repman.cfg.jinja2.in index cf3c6b1077..2ec72419c8 100644 --- a/software/repman/instance-repman.cfg.jinja2.in +++ b/software/repman/instance-repman.cfg.jinja2.in @@ -12,6 +12,10 @@ {% set frontend_parameter_dict = slapparameter_dict.get('slave-frontend', {}) -%} {% set database_slave_list = [] -%} {% set db_name_list = [] -%} +{% set count = namespace(value=1) %} +{% set caucase_bind = '[' ~ ip ~ ']:8890' -%} +{% set caucase_url = 'http://' ~ caucase_bind -%} +{% set csrid_list = [] -%} {% macro password(name) -%} [{{ name }}-password] @@ -34,6 +38,9 @@ log = ${:var}/log data = ${:var}/lib nginx-prefix = ${:var}/nginx tmp = ${:home}/tmp +backup-caucased = ${:srv}/backup-caucased +caucased = ${:srv}/caucased +ssl = ${:etc}/ssl {% import "supervisord_lib" as supervisord_lib with context %} {% set proxysql_controller = "proxysql-ctl" -%} @@ -48,6 +55,7 @@ key-file = ${slap-connection:key-file} cert-file = ${slap-connection:cert-file} computer-id = ${slap-connection:computer-id} partition-id = ${slap-connection:partition-id} +config-caucase-url = {{ caucase_url }} [download-proxy-config] recipe = slapos.recipe.template:jinja2 @@ -100,6 +108,7 @@ mode = 755 {% set db_amount = 2 -%} {% endif -%} +{% set count.value = count.value + db_amount %} {% for i in range(0, db_amount) -%} {% do mariadb_dict.__setitem__('tcp-port', 2099 + (i * 100)) -%} {% set section = 'request-mariadb-' ~ i -%} @@ -125,17 +134,19 @@ config-cluster = {{ name }} config-name = {{ dbname }} config-database-list = !py!{{ database_slave_list }} config-database-name = {{ dumps(db_list) }} -return = +return = database-host receiver-port monitor-base-url partition-path + csr-id {% do part_list.append(section) -%} {% do mariadb_server_list.append('${' ~ section ~ ':connection-database-host}') -%} {% do receiver_port_list.append('${' ~ section ~ ':connection-receiver-port}') -%} {% do mariadb_path_list.append('${' ~ section ~ ':connection-partition-path}') -%} {% do monitor_base_url_dict.__setitem__('mariadb' ~ i, '${' ~ section ~ ':connection-monitor-base-url}') -%} +{% do csrid_list.append('${' ~ section ~ ':connection-csr-id}') -%} {% endfor -%} @@ -299,6 +310,84 @@ context = {% do part_list.append(name ~ '-publish-slave-information') -%} {% endfor -%} +# deploy caucase +{% import "caucase" as caucase with context %} +{{ caucase.caucased( + prefix='caucased', + buildout_bin_directory=buildout_bin_directory, + caucased_path='${directory:service}/caucased', + backup_dir='${directory:backup-caucased}', + data_dir='${directory:caucased}', + netloc=caucase_bind, + tmp='${directory:tmp}', + service_auto_approve_count=count.value, + user_auto_approve_count=1, + key_len=2048, +)}} +{% do part_list.append('caucased') -%} +{% do part_list.append('caucased-promise') -%} +{% do publish_dict.__setitem__('caucase-http-url', caucase_url) -%} +{{ caucase.updater( + prefix='caucase-updater', + buildout_bin_directory=buildout_bin_directory, + updater_path='${directory:services}/caucase-updater', + url=caucase_url, + data_dir='${directory:srv}/caucase-updater', + crt_path='${directory:ssl}/repman-cert.crt', + ca_path='${directory:srv}/caucase-updater/ca.crt', + crl_path='${directory:srv}/caucase-updater/crl.pem', + key_path='${directory:ssl}/repman-cert.key', + on_renew=None, + max_sleep=None, + template_csr_pem=None, + openssl=openssl_bin, +)}} +{% do part_list.append('caucase-updater') -%} +{% do part_list.append('caucase-updater-promise') -%} + +#caucase user certificate +{{ caucase.updater( + prefix='caucase-user-updater', + buildout_bin_directory=buildout_bin_directory, + updater_path='${directory:services}/caucase-user-updater', + url=caucase_url, + data_dir='${directory:srv}/caucase-user-updater', + crt_path='${directory:ssl}/caucase.user.crt', + ca_path='${directory:srv}/caucase-user-updater/ca.crt', + crl_path='${directory:srv}/caucase-user-updater/crl.pem', + key_path='${directory:ssl}/caucase.user.key', + on_renew=None, + max_sleep=None, + template_csr_pem=None, + openssl=openssl_bin, + mode='user', +)}} +{% do part_list.append('caucase-user-updater') -%} +{% do part_list.append('caucase-user-updater-promise') -%} + +[caucase-sign-csr] +recipe = slapos.recipe.template:jinja2 +mode = 755 +rendered = ${directory:bin}/caucase-sign +template = + inline:#!/bin/sh + cp ${directory:ssl}/caucase.user.key ${directory:ssl}/caucase-full.key + cat ${directory:ssl}/caucase.user.crt >> ${directory:ssl}/caucase-full.key + for csr_id in {{ csrid_list | join(' ') }}; do + if [ "$csr_id" = "None" ] || [ -z "$csr_id"]; then + continue + fi + {{ buildout_bin_directory }}/caucase --ca-url {{ caucase_url }} --user-key ${directory:ssl}/caucase-full.key --sign-csr $csr_id + done + +[cron-caucase-sign-csr] +recipe = slapos.cookbook:cron.d +cron-entries = ${cron:cron-entries} +name = caucase-sign-csr +frequency = * * * * * +command = ${caucase-sign-csr:rendered} +{% do part_list.append('cron-caucase-sign-csr') -%} + [slap-configuration] recipe = slapos.cookbook:slapconfiguration computer = ${slap-connection:computer-id} @@ -332,8 +421,9 @@ proxies-log = ${directory:log}/proxy ipv6 = ${instance-parameter:ipv6-random} port = ${instance-parameter:nginx-port} ssl-port = ${instance-parameter:nginx-ssl-port} -ssl-certificate = ${ca-nginx:cert-file} -ssl-key = ${ca-nginx:key-file} +ssl-certificate = ${directory:ssl}/repman-cert.crt +ca-certificate = ${directory:srv}/caucase-updater/ca.crt +ssl-key = ${directory:ssl}/repman-cert.key pid-file = ${directory:run}/nginx.pid access-log = ${directory:log}/nginx_access.log error-log = ${directory:log}/nginx_error.log @@ -464,11 +554,12 @@ command-line = {{ nginx_bin }} -p ${directory:nginx-prefix} -c ${nginx-conf:rendered} -wrapper-path = ${directory:bin}/nginx-start +wrapper-path = ${directory:services}/nginx wait-for-files = - ${ca-directory:certs}/nginx.key - ${ca-directory:certs}/nginx.crt - ${nginx-graceful-wrapper:rendered} + ${directory:ssl}/repman-cert.crt + ${directory:srv}/caucase-updater/ca.crt + ${directory:ssl}/repman-cert.key + [nginx-graceful-wrapper] recipe = slapos.recipe.template:jinja2 @@ -478,20 +569,6 @@ rendered = ${directory:scripts}/nginx-graceful context = mode = 755 -[ca-nginx] -<= certificate-authority -recipe = slapos.cookbook:certificate_authority.request -cert-file = ${ca-directory:certs}/nginx.crt -key-file = ${ca-directory:certs}/nginx.key -executable = ${nginx-launcher:wrapper-path} -wrapper = ${directory:bin}/ca-nginx - -[ca-nginx-service] -recipe = slapos.cookbook:wrapper -command-line = ${ca-nginx:wrapper} -wrapper-path = ${directory:services}/nginx -hash-existing-files = ${buildout:directory}/software_release/buildout.cfg - [logrotate-entry-nginx] <= logrotate-entry-base name = nginx @@ -599,7 +676,7 @@ parts = replication-manager monitor-base logrotate-entry-nginx - ca-nginx-service + nginx-launcher publish-connection-parameter repman-frontend-promise repman-backend-promise diff --git a/software/repman/instance.cfg.in b/software/repman/instance.cfg.in index e9de69b172..0b3963024f 100644 --- a/software/repman/instance.cfg.in +++ b/software/repman/instance.cfg.in @@ -28,8 +28,10 @@ mode = 0644 extensions = jinja2.ext.do rendered= ${buildout:directory}/${:_buildout_section_name_} supervisord-lib = {{ supervisord_lib }} +causace-lib = {{ caucase_library }} import-list = file supervisord_lib :supervisord-lib + file caucase :causace-lib context = key slapparameter_dict slap-configuration:configuration key computer_id slap-configuration:computer @@ -48,6 +50,8 @@ context = raw bash_bin {{ bash_location }}/bin/bash raw jq_bin {{ jq_location }}/bin/jq raw curl_bin {{ curl_location }}/bin/curl + raw openssl_bin {{ openssl_location }}/bin/openssl + raw caucase_bin_client {{ caucase_bin_client }} ${:extra-context} extra-context = diff --git a/software/repman/software.cfg b/software/repman/software.cfg index 59b50b104d..e19b840a28 100644 --- a/software/repman/software.cfg +++ b/software/repman/software.cfg @@ -18,8 +18,10 @@ extends = ../../component/socat/buildout.cfg ../../component/rsync/buildout.cfg ../../component/jq/buildout.cfg + ../../component/openssl/buildout.cfg ../../stack/supervisord/buildout.cfg ../../stack/monitor/buildout.cfg + ../../stack/caucase/buildout.cfg parts = slapos-cookbook @@ -27,6 +29,7 @@ parts = instance.cfg template-mariadb.cfg template-mysqld-wrapper + caucase-eggs gowork [mariadb] @@ -39,7 +42,6 @@ part = python3 # replication-manager does not build on golang 1.17 golang = ${golang1.16:location} - [template-mysqld-wrapper] recipe = slapos.recipe.template:jinja2 rendered = ${buildout:parts-directory}/${:_buildout_section_name_}/mysqld.in @@ -76,6 +78,7 @@ mode = 0644 context = key bash_location bash:location key bin_directory buildout:bin-directory + key caucase_library caucase-jinja2-library:target key config_toml_in config-toml.in:target key config_cluster_toml_in config-cluster-toml.in:target key coreutils_location coreutils:location @@ -101,6 +104,7 @@ context = key groonga_mysql_normalizer_plugin_dir groonga-normalizer-mysql:groonga-plugin-dir key nginx_conf_in nginx.conf.in:target key nginx_location nginx:location + key openssl_location openssl:location key percona_toolkit_location percona-toolkit:location key proxy_need_stop_start_template proxy-need-start-stop.sh.in:target key repman_src_location git.signal18.io_signal18_repman:location @@ -123,7 +127,7 @@ context = key unixodbc_location unixodbc:location key sysbench_location sysbench:location key proxysql_location proxysql:location - + raw caucase_bin_client ${buildout:bin-directory}/caucase [download-file] recipe = slapos.recipe.build:download -- 2.30.9