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",
"ejabberd_user_password": {
"encrypted_data": "egFuX4xov+JZUq/GUbCBEQUnxDKczzxdJiYeRDisNEIVPYLNO/piG701sw==\n",
"iv": "G0JpgKtcPnTQ5d6v\n",
"auth_tag": "NoNoLmZZT+2qgIuDBEdGKQ==\n",
"encrypted_data": "hz0xHS2wl66X6xxqLE5/6apQb8SvIR7r8hCd9ZzEcHf7VaWoFMNLmrmwqw==\n",
"iv": "PfEp9Jhqfp0o7Cje\n",
"auth_tag": "ckEADxPfymTvSVLLXUxTWA==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"server_password": {
"encrypted_data": "vJ3cK8vzUKI97YJVLE11I9Ti/Z3Rits+UQjIDZMZDx4cvTiGN0QX\n",
"iv": "ENFE12MnoSta++6j\n",
"auth_tag": "JbeVb+zdrkHvj9g9end/2Q==\n",
"encrypted_data": "9aV4IykJB3lISayq/crmowTjrQjwSWSrh7+O9LMq0IgZaWZ6Bk6R\n",
"iv": "XFeNPuZAh4nCX9NU\n",
"auth_tag": "LoAIWrqSAmcuA+r3nyHu2Q==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"mastodon_user_password": {
"encrypted_data": "PTCEBIB+qYe+lBoFjgLxendhx2ccJJ4UbUEwnPf8MT39fsF9MFQwFiytvg==\n",
"iv": "j59Ndhijtj/YQNp5\n",
"auth_tag": "bbdA+OmJvTfjwNHzrF19tg==\n",
"encrypted_data": "LGU8N2C9Ax17QvFCWNV9m1rbRpBT9YH1qVn/Cmz0/p+1aUcOUN8rzxb57Q==\n",
"iv": "FiYQKLmfJ/CYO50H\n",
"auth_tag": "t3NwAMqoGCJ/c/5H2KjQ+Q==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"replication_password": {
"encrypted_data": "OFLn4FHP8BbCgBJzlqG+Zo3wjzXtklyKgk3OBKdkcUzzgno=\n",
"iv": "xHiYpKX90SF7Blqi\n",
"auth_tag": "VO/xnf+N+zX6F3DQ8EdSBQ==\n",
"encrypted_data": "6UildEd3UactuYufRp+UjHFlK3zLZ8Vmggfc8URBRNVfWHs=\n",
"iv": "e4SpyAt32vXuX4un\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": "envd5qBpUVHD5+pFmtRm99y3n+Fi6PtEwjgQl1l1VTn/bRMosMGSbWJ9VmPk\nd1tu/Nr1Z1SZcNyBiUxhAaKI2vU6BsNIpy0lnZN3R0bT4OMH/lPIJyIRqAXU\nPu+73++H41SC47Nt+9UhwRkNifIl3lFo0AhqqeHpJQbhCPVVW6oJf2Q7TGDF\nGhU5y3sat5r7FNSRCNvErv8QX/cIOSTHn76350ktgVG29+31Qp9HDhg01jac\ne8XrAiZXPxzNO7tA6zFlsRr6WVaLJeMd4bTXQpfgy/wcl+UG91n02ODdveqj\n2P+Z+ZnKvgAgmTrWpwHalJ6KkWBjuYPdaawnRPbMVUCm7usPFOurpuvYwX61\ncysFOylwCaw3vCEBWFlQAaV5GJAiaMujI8OFkioQS0FZ8M7slLs9famJzz6c\nR24BJHHb7eJRHsGZptHnEx6JGA4WGQD1e5Z8JtKnUff0WVtiSe9lwEwWNPPx\ntMJX0H8+bXdLC5W+R7pbHQfSWmbk9CP9ehlReJw9Kj1neQfm4W1Vevi42Jz2\n9JkBZ+P0ympsYb+qk0juNUrP5mC8rfW+/RktRihp4sufOW4KcK2nwWka4HeQ\nql2Xh6gHyniB2pe60lFmt2XR/0k47/tz+i6Xim67apfr8vapDzA4vBnJRVNv\nz8OVgBjJ124K5j+V4jJkWem7YfgLVpmzbkOsQp6YAsNitYUeiRwF8ijckkYF\nqEOXq4HTvyCKiPsy+myd6fjyJGCTFz4lFwQa54PFb45BsjApN78SEzWj0fxL\nT/LZF3HxA4vR72zajAFs/Vf6W7Ho5mKG/h21vjw1gDeN7U8FLOzUQX6uSJZh\nDF46Bn9WOilKvUpJrrcFCWcypwtxc6oFvRl05P31Dm0+2R6gNhOlckSsXDjY\nBTOJWI2pN4En8oTN7EF7JkOwG/9O7wUOpGBKrIvn/Z0Ith8O99X8fJnBuqlw\nuz20B2q5KIfNvr2Aw1nALsmPEuQtj+JQ2wj4fxY9P5f6bK31psTymWvLe7Fl\n1t2ec4x6H6cEFBULax1WJaRGHsZJ+U3fxn3SMMVJwkCBvepWM7gM6LdKH0a9\n9qOk2mlLTtFmYjZxMkL5kt457XtAYlK6YZSMLZgIZob5Bfnltrmodv4BpJop\nV7Qffwqmh18E1k8hH4tQrQ7At/gvfMY4IQb/m9H7MCgFODn1NtIAD9+8VFRR\n9Lt3BjAwZpakv6tYBW3q7rr5+17fY5O0kZ7Ns8qnhc7/5ZBjuT38828rJO12\nhLNfp7xFm8oNTlDmQeN2RSmOnt42QYKsDdUG8hzhzOjeHMq/ZzTcKPCHTxlw\nln2F/t7PHV1lvOTzwueDuI8+KAGxhb6OVkQz0Fq60Feq4Bc1/YkX5jHNcPvQ\nL5z9pJJyZ1RhP5/Z9JekzaLn8TDigW3zri2YTKQZedLKHFjzRM9FjkXgn/l6\nETWwN2hK1iryFeoNKDBslRVx89LG96MdABF1x0ZRctZfWLPHmCosqw1rVJs7\nbK3vi1W+i8FVjimu0WH2mPwnP8rMxi+RPul5QJKakHlzUKcGGLfSaTxJ0cKr\nye4u68S8ikAGu9nVmy79NASgkoBETF5EcgjD+r+gH8eYv+Dt3qV+GJAZu5wK\n3ILwGn9HpCJGhwSQCOkj0JqH1fFOZXrGlrnbtCl8QfqILP6IjQvFMO8QvcJX\nDh+kfFKmuKMSAVUwplNHIF65TBpLEr6iFoC9wfTMmha5xdScLxYa9oxFeeQp\n3TdLBFm4X+rXufOp+L1oLgOtKaETvzxHTIi0A0ZPtG2NAgGIxxtmcl6Cl4mZ\nZkWJYAlbsh+suYTAiqtoBSbyl1y8/WayeINOwBWGGl3dvRfuJMH4oQDYhAZ+\ng5UBS5YcSBsIWYairl56w7OeF/1jq702HLqm0+j2qf1gLuefBPG8/Yxo1VSr\nctElIJZwobdtW27uaycczckEuc2rlOc7DSxcTWhz95oBzeWyeB8z8AmOHVsJ\nLKkAINcxyEUfwN0Sq2Z4mQ+vFADR22RPPUWAAM96Udc6cMZyHCWWA6D4nlSl\nLBUDXujfV/ssapX1n3WVR9cc7rsHxTQ0o6ci6YPk0SWUASKP+ITamz31T0HW\nH7urYZleUWKgthcm/7YoEuKUPYBD9RjHz1cIXCO7Xz8zwfVUnMCXaqJzJ7bn\nFUvFb2qmPqc4KxhVoWU7p6NQRQNJC/qtAb27/YwZM3/gEj0qL4eT1jr8DInE\nZxa4GPUCgNf8Q8H0BtXv/WWmee2KakHXoMcawmeJBtPpyo/eAHPTihxSjPDq\nEdTgqwSCzzRETU3ZgsRc3KpawUm8kPkyxoCGFt5FwS/PFJWredsSAHCWJQ==\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,
"cipher": "aes-256-gcm"
}

View File

@ -6,7 +6,6 @@
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
Encrypt and copied to the PostgreSQL data directory and added to the
`postgresql.conf` file
@ -16,7 +15,6 @@ Encrypt and copied to the PostgreSQL data directory and added to the
```ruby
postgresql_custom_server "12" do
role "primary"
tls true
end
```
@ -25,7 +23,6 @@ end
```ruby
postgresql_custom_server "12" do
role "replica"
tls true
end
```
@ -47,3 +44,47 @@ about PostgreSQL client authentication, see the
The primary opens up the PostgreSQL port (5432 TCP) to replicas, and replicas
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 :role, String, required: true # Can be primary or replica
property :tls, [TrueClass, FalseClass], default: false
action :create do
postgresql_version = new_resource.postgresql_version
@ -63,55 +62,32 @@ action :create do
additional_config[:promote_trigger_file] = "#{postgresql_data_dir}/failover.trigger"
end
if new_resource.tls
include_recipe "kosmos-nginx"
include_recipe "kosmos-base::letsencrypt"
ssl_cert = postgresql_data_bag_item['ssl_cert']
ssl_cert_path = "#{postgresql_data_dir}/server.crt"
ssl_key = postgresql_data_bag_item['ssl_key']
ssl_key_path = "#{postgresql_data_dir}/server.key"
domain = node[:fqdn]
postgresql_post_hook = <<-EOF
#!/usr/bin/env bash
set -e
# 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"
file ssl_cert_path do
content ssl_cert
owner "postgres"
group "postgres"
mode "0640"
sensitive true
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
file ssl_key_path do
content ssl_key
owner "postgres"
group "postgres"
mode "0600"
sensitive true
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
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
version postgresql_version