Use a self-signed TLS certificate for PostgreSQL

This commit is contained in:
Greg Karékinian 2020-05-13 19:10:14 +02:00
parent 84cb3de4a0
commit 8d2ab785fc
4 changed files with 101 additions and 63 deletions

View File

@ -1,30 +1,51 @@
{ {
"id": "postgresql", "id": "postgresql",
"ejabberd_user_password": { "ejabberd_user_password": {
"encrypted_data": "egFuX4xov+JZUq/GUbCBEQUnxDKczzxdJiYeRDisNEIVPYLNO/piG701sw==\n", "encrypted_data": "hz0xHS2wl66X6xxqLE5/6apQb8SvIR7r8hCd9ZzEcHf7VaWoFMNLmrmwqw==\n",
"iv": "G0JpgKtcPnTQ5d6v\n", "iv": "PfEp9Jhqfp0o7Cje\n",
"auth_tag": "NoNoLmZZT+2qgIuDBEdGKQ==\n", "auth_tag": "ckEADxPfymTvSVLLXUxTWA==\n",
"version": 3, "version": 3,
"cipher": "aes-256-gcm" "cipher": "aes-256-gcm"
}, },
"server_password": { "server_password": {
"encrypted_data": "vJ3cK8vzUKI97YJVLE11I9Ti/Z3Rits+UQjIDZMZDx4cvTiGN0QX\n", "encrypted_data": "9aV4IykJB3lISayq/crmowTjrQjwSWSrh7+O9LMq0IgZaWZ6Bk6R\n",
"iv": "ENFE12MnoSta++6j\n", "iv": "XFeNPuZAh4nCX9NU\n",
"auth_tag": "JbeVb+zdrkHvj9g9end/2Q==\n", "auth_tag": "LoAIWrqSAmcuA+r3nyHu2Q==\n",
"version": 3, "version": 3,
"cipher": "aes-256-gcm" "cipher": "aes-256-gcm"
}, },
"mastodon_user_password": { "mastodon_user_password": {
"encrypted_data": "PTCEBIB+qYe+lBoFjgLxendhx2ccJJ4UbUEwnPf8MT39fsF9MFQwFiytvg==\n", "encrypted_data": "LGU8N2C9Ax17QvFCWNV9m1rbRpBT9YH1qVn/Cmz0/p+1aUcOUN8rzxb57Q==\n",
"iv": "j59Ndhijtj/YQNp5\n", "iv": "FiYQKLmfJ/CYO50H\n",
"auth_tag": "bbdA+OmJvTfjwNHzrF19tg==\n", "auth_tag": "t3NwAMqoGCJ/c/5H2KjQ+Q==\n",
"version": 3, "version": 3,
"cipher": "aes-256-gcm" "cipher": "aes-256-gcm"
}, },
"replication_password": { "replication_password": {
"encrypted_data": "OFLn4FHP8BbCgBJzlqG+Zo3wjzXtklyKgk3OBKdkcUzzgno=\n", "encrypted_data": "6UildEd3UactuYufRp+UjHFlK3zLZ8Vmggfc8URBRNVfWHs=\n",
"iv": "xHiYpKX90SF7Blqi\n", "iv": "e4SpyAt32vXuX4un\n",
"auth_tag": "VO/xnf+N+zX6F3DQ8EdSBQ==\n", "auth_tag": "AkCEvuEnb+E5jTC84tC8NA==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"ssl_cert": {
"encrypted_data": "loF7NMyOJXr8PfxsuN6zvp86hIqWYoGFiGq+ldirctWnmkeDmaROgzDW1oQp\nAubnEHZNx7IFRn/FGpGhhbX/DGjbL6EK0bSE6x6uzOEhpaFDAqmzzEfMXCMj\nDIsrM5WSmP1WBFd6g+/zk3EAXHeekOlLBEj13zzSJVj4piLFERKZRTgix0eP\nOmH+lGBoxy4hXKfa9ru7c5h4vLVQHSlHjrrsyeKdumbmXWSb3IJWtEsNQRqu\nKu6DZ+IRC8fH+DBs8/32dTbJ6uR29kbKfZrWTrpOKXWJLnT1snuiTMeRbTcO\nVbS1ZSeGcpGMFFayAui4KgPaDK8vT/mXcd2P3+c85GZtmmvIKfloIRmtb4in\nleUx3z70BxPFRg5wYfSiP/xJMpjJrh5/6P+96iMkgmU+wuXT+95yf4Agz7G5\n0gObs/sJCAV9qOoWIXSU3jyNvaYsZMPj8FHXlpnCXojHJ2WnqLCAPeVWYHbd\nvNSEOvmCN07xK1PkGZT9NGfPzRcZxqop5gJ3qP9Km33Z06SNF+28i2d4lpy+\n1oWqg5ow2CBhRrb0Bx8FplQug4EXCV7Sni4mc0jSX90rBv+e65Em+33x0A27\nPrp7lfcv+7ridU5AZXifFZSuIJF6LMXz+ji2zC2JMjS4xQ8/KXBd8E5/fRJH\nI18X+t/xx8gakmaDrz/3+4i8TVt1I8pIpN/SaAXTZqgme1QoISymf6LQzFxW\ns1kQGOwbtgx60+2BG7kF9XRRZJay8P1uxmVgjHWbqyL0KbYTlU2zTLuRs3ez\n+rPEsxB/hNfUeB9guALFLtvlkAob1Fh/Za6aukaFlaVJHbHoXehH/aXBPAVK\n0ld+3fql5Ib/OAD7prWaUCZ/tP357RWwCxz+ECjtJhFdREx8fT1aZGvmJ0yx\nESNhSjrn+b+rVc+HiD4hAytW+QP2yNqfKO9YzxXYfN5BBTxh/fvO2qVtQmSf\n+u9iatEaico44E7MX1ZOYAclTA289dwyu6R9PRa1p0zral5b+vJAOx1iH1uq\nzHUKTiRCRAcWrcciL8PH8MRXdcHSxmfyBSBbcz+dh/MURyQMx/LOQ31gYuYq\nzlgbJNsVl6V9rl9x2SargwJrD1WM863oyQumZc/M42GX0z9PilIhLQbF26MN\n2tUf5IDK7d42Z5A6ATxR+0qKh2/WvDXDbNHy+cuAjRJRX9vTgNqpR5qCOyT5\nIxA55rLvHYxbnqic124I1EdXGtoEXqsxt1YAq3ho9QCQz1t5Z/AP63oUEuLr\np4WIeo44fqZzjprRFEE3KbCGlUDx56xLg4a84JF1rMU0ce11BUtEEtRF2p4X\noecU8Z5vvhvsqXxYko6aFNcAvxO2FdZmC76lilNsHgH9VS02ctjOT7Mvi2XP\n3QEVOg==\n",
"iv": "v+wkuXO+2VZHRkOu\n",
"auth_tag": "C56+Qe/UNzR8k9HizIFyMA==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"ssl_key": {
"encrypted_data": "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\n",
"iv": "sPYjnXdqpABH9wrl\n",
"auth_tag": "F5ajYZMx+6r333stbQ0E1Q==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"ssl_root_cert": {
"encrypted_data": "hwwHOg/kuJxMEOLpDC2zCrIRoWkbcNzui849HEtootXsL8YPFMIo0wKzC4JS\nc5R5A7MOqgoijjrhymMKkWZ4nqdx0ZVjlLQoBpFd2D6OYmomID/e4Qi2fR4Q\nZ9eS1xoPi0cAcKKML83yHJ3bRkZhqcZLIauqm3N+pAwEdYjHo9HrNPs9stqL\noSyLIG5IwNvwh8DJMb9XU5tBlMOpI0eUDRptBHjecAdmSv59jxse7dSHVove\ndsooWNdsz48318QMG3e2ALRIWZHFb0t2C/01wYqk9PrazIX9upC1BHZ7f4XZ\nAOkukFD/uVa3wLrzQnGhh8bLxZmsRaKaGlY79vg6HgYqUoqmEuB6FHVRX7xb\nh4zt3CcWQMwU0r+Po1a2Qo5HT9xP40QgrHwtJwlpLgIP/9yxhTjpb2qdJzY3\n88MI/wZLvyezTZwMmZikE9+IlwfUBBmsSJVHOtKlPQ27YAHXmALczQUPrYG9\nqWLnWoqmyYFMpPF4u7QQUXNjde+z5sZb2gELRy1nBtHGPEZQY/Ji9P4AT0jW\n3tTidly4yYa0sXLGFH/ZbePRwrUX1qd7RalOLWUYkPwEUVcO5FzzWvCr58S0\n570VoHhyTrYWwaRfiEhEsOV/aSrVERa7T89NvDGpaKQmzpWCF1uGbnmRUI+a\nyYhSzgXaFiKiE8JFvev83slqRpsxF2z2bdHEBvSIce69pzC5VjWKVuHG/Lf8\nVseTapbVXNptMTgm+ToZHcbtBFdWlh3rpyaAKj5uKkKenY0n/R7s4M0GFviY\nj+zLQhHGYXNCybKTfguDfcKe6XiktguwXTCaXo8HpaZr49i2HsAYmSEHw4oE\nYKoYUfm9v1n6O6uxWXV92OIpRS0bkb4hUMWY9K6oG/hbUCupX/RWnBZW4wAS\nvh561oz1Ef1NVI85l2DDG++oCgXgiqzulIQxyNFOyofX5KLmJ8/nLSUc2R3E\nITPaqEG/5NUSyeQMPbIVRN4bsXcogWB/779QiXP6nDEuucNH6kpesiDbEmxC\n5J9i3xKI97zDL8HEmT7Tgp5Tu9FOyOA36qS14cMo8Ue4MWDGV1NrnbWf7LvE\nnx65h8tk1LzimnTE/NqhrYgodylUnNf6c76CaHUhqBDi3JUMF9O/IwRuYH7w\nTvOGphtyix7Lph3wCJJf/VVgK4jy2erq9+mr82dKBBCynEbUJVhpVlAkdKqX\n44LC+KIvJBb4UPerutEYmOOy2Ha1elQyFebSgUR6bxxG9JvZEOYY+UCdeRnz\nQTCQYEvUO7nHSI1uKDW2/BC0f6vzQxYWBT1XgWt5D+wlqz3ysW2AKCK2j4xL\nEFZEQF4ibX0Acm/dp/BVztq8ymhTtqW7pMPHbub0/Q4kgFiPq66FHxJdQU4Q\nuS9w2ciiPGbCbgdww3RfEU3c0kTieyHRcL/pU3aaO6RTA3SeGRX6DqXX3Si3\npkLiyuXBBIskbn0RiBn1SXYMJ17Vaye4BvFlDc2PywhEsXkRGn6Ad1gLOkyZ\nycLnXizhLX0kePSgyn/0N9RI067dlv2lzdaVuheQQEX7efrFCC2zMzvdgP8=\n",
"iv": "TrPuASVYx7D2onkS\n",
"auth_tag": "Gzn4kJCs87LK3ZKJxCHAnw==\n",
"version": 3, "version": 3,
"cipher": "aes-256-gcm" "cipher": "aes-256-gcm"
} }

View File

@ -6,7 +6,6 @@
Usage: Usage:
When the `tls` attribute is set to true, a TLS certificate for the FQDN
(`node['fqdn']`, for example `andromeda.kosmos.org`) is generated using Let's (`node['fqdn']`, for example `andromeda.kosmos.org`) is generated using Let's
Encrypt and copied to the PostgreSQL data directory and added to the Encrypt and copied to the PostgreSQL data directory and added to the
`postgresql.conf` file `postgresql.conf` file
@ -16,7 +15,6 @@ Encrypt and copied to the PostgreSQL data directory and added to the
```ruby ```ruby
postgresql_custom_server "12" do postgresql_custom_server "12" do
role "primary" role "primary"
tls true
end end
``` ```
@ -25,7 +23,6 @@ end
```ruby ```ruby
postgresql_custom_server "12" do postgresql_custom_server "12" do
role "replica" role "replica"
tls true
end end
``` ```
@ -47,3 +44,47 @@ about PostgreSQL client authentication, see the
The primary opens up the PostgreSQL port (5432 TCP) to replicas, and replicas The primary opens up the PostgreSQL port (5432 TCP) to replicas, and replicas
to the primary. to the primary.
## TLS self-signed certificate
A wildcard (`*.kosmos.org` certificate) was generated with the following
commands:
```
openssl req -new -nodes -text -out root.csr -keyout root.key \
-subj "/CN=root.kosmos.org"
chmod og-rwx root.key
openssl x509 -req -in root.csr -text -days 3650 \
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
-signkey root.key -out root.crt
openssl req -new -nodes -text -out server.csr \
-keyout server.key -subj "/CN=*.kosmos.org"
chmod og-rwx server.key
openssl x509 -req -in server.csr -text -days 1825 \
-CA root.crt -CAkey root.key -CAcreateserial \
-out server.crt
```
It is valid until May 12 2025.
The content of `server.crt`, `server.key` and `root.crt` an stored in the
`postgresql` encrypted data bag. The root key is stored in LastPass
("Self-signed TLS root certificate"). `server.crt` & `server.key` are used by
the PostgreSQL server.
The root certificate needs to be deployed to clients so they verify the cert
can be trusted.
For example:
```ruby
postgresql_data_bag_item = data_bag_item('credentials', 'postgresql')
root_cert_path = "/etc/ssl/certs/root.kosmos.org.crt"
file root_cert_path do
content postgresql_data_bag_item['ssl_root_cert']
mode "0644"
end
```
`/etc/ssl/certs/root.kosmos.org.crt` can be used as the CA root cert path in
the client's configuration

View File

@ -2,7 +2,6 @@ resource_name :postgresql_custom_server
property :postgresql_version, String, required: true, name_property: true property :postgresql_version, String, required: true, name_property: true
property :role, String, required: true # Can be primary or replica property :role, String, required: true # Can be primary or replica
property :tls, [TrueClass, FalseClass], default: false
action :create do action :create do
postgresql_version = new_resource.postgresql_version postgresql_version = new_resource.postgresql_version
@ -63,56 +62,33 @@ action :create do
additional_config[:promote_trigger_file] = "#{postgresql_data_dir}/failover.trigger" additional_config[:promote_trigger_file] = "#{postgresql_data_dir}/failover.trigger"
end end
if new_resource.tls ssl_cert = postgresql_data_bag_item['ssl_cert']
include_recipe "kosmos-nginx" ssl_cert_path = "#{postgresql_data_dir}/server.crt"
include_recipe "kosmos-base::letsencrypt" ssl_key = postgresql_data_bag_item['ssl_key']
ssl_key_path = "#{postgresql_data_dir}/server.key"
domain = node[:fqdn] file ssl_cert_path do
content ssl_cert
postgresql_post_hook = <<-EOF owner "postgres"
#!/usr/bin/env bash group "postgres"
mode "0640"
set -e sensitive true
# Copy the postgresql certificate and restart the server if it has been renewed
# This is necessary because the postgresql user doesn't have access to the
# letsencrypt live folder
for domain in $RENEWED_DOMAINS; do
case $domain in
#{domain})
cp "${RENEWED_LINEAGE}/privkey.pem" #{postgresql_data_dir}/#{domain}.key
cp "${RENEWED_LINEAGE}/fullchain.pem" #{postgresql_data_dir}/#{domain}.crt
chown postgres:postgres #{postgresql_data_dir}/#{domain}.*
chmod 600 #{postgresql_data_dir}/#{domain}.*
systemctl reload #{postgresql_service}
;;
esac
done
EOF
# This hook will be executed by certbot after every successful certificate
# creation or renewal
file "/etc/letsencrypt/renewal-hooks/post/postgresql" do
content postgresql_post_hook
mode 0755
owner "root"
group "root"
end
template "#{node['nginx']['dir']}/sites-available/#{domain}" do
source 'nginx_conf_empty.erb'
owner node["nginx"]["user"]
mode 0640
notifies :reload, 'service[nginx]', :delayed
end
nginx_certbot_site domain
additional_config[:ssl] = "on"
additional_config[:ssl_cert_file] = "#{postgresql_data_dir}/#{domain}.crt"
additional_config[:ssl_key_file] = "#{postgresql_data_dir}/#{domain}.key"
end end
file ssl_key_path do
content ssl_key
owner "postgres"
group "postgres"
mode "0600"
sensitive true
end
additional_config[:ssl] = "on"
additional_config[:ssl_cert_file] = ssl_cert_path
additional_config[:ssl_key_file] = ssl_key_path
# ejabberd does not support 1.3 yet
additional_config[:ssl_min_protocol_version] = "TLSv1.2"
postgresql_server_conf "main" do postgresql_server_conf "main" do
version postgresql_version version postgresql_version
additional_config additional_config additional_config additional_config