Cleanup and adapt for new vault.mkpki.sh template

This commit is contained in:
Daniel Berteaud 2024-01-18 15:10:19 +01:00
parent e3d7111002
commit 19daff3eab
12 changed files with 89 additions and 108 deletions

View File

@ -12,7 +12,7 @@ RUN set -eux &&\
chown root:root ldap2pg &&\
chmod 755 ldap2pg
FROM danielberteaud/alpine:24.1-2
FROM danielberteaud/alpine:24.1-5
MAINTAINER Daniel Berteaud <dbd@ehtrace.com>
ENV LANG=fr_FR.utf8 \

View File

@ -1,4 +1,4 @@
FROM danielberteaud/alpine:24.1-2
FROM danielberteaud/alpine:24.1-5
MAINTAINER Daniel Berteaud <dbd@ehtrace.com>
ARG PG_FROM= \

View File

@ -90,7 +90,6 @@ job "postgres-manage" {
LDAP2PG_MODE = "dry"
}
# Use a template block instead of env {} so we can fetch values from vault
template {
data = <<_EOT

View File

@ -18,7 +18,7 @@ job "postgres" {
value = "true"
}
count = 1
count = "1"
network {
mode = "bridge"
# Patroni API for node to check each others
@ -39,6 +39,8 @@ job "postgres" {
service {
name = "postgres"
port = 5432
connect {
sidecar_service {
}
@ -100,20 +102,21 @@ job "postgres" {
enable_tag_override = true
}
volume "data" {
volume "backup" {
source = "postgres-backup"
type = "csi"
access_mode = "multi-node-multi-writer"
attachment_mode = "file-system"
}
volume "data" {
source = "postgres-data"
type = "csi"
access_mode = "single-node-writer"
attachment_mode = "file-system"
per_alloc = true
}
volume "backup" {
type = "csi"
source = "postgres-backup"
access_mode = "multi-node-multi-writer"
attachment_mode = "file-system"
}
task "postgres" {
driver = "docker"
@ -130,15 +133,18 @@ job "postgres" {
pids_limit = 700
}
vault {
policies = ["postgres"]
env = false
disable_file = true
}
# Use a template block instead of env {} so we can fetch values from vault
template {
data = <<_EOT
LANG=fr_FR.utf8
PGBACKREST_STANZA=postgres
TZ=Europe/Paris
_EOT
destination = "secrets/.env"
@ -152,7 +158,6 @@ _EOT
# Get a Consul token from vault, so we're able to update the tags in Consul from the containers
CONSUL_HTTP_TOKEN={{ with secret "consul/creds/postgres" }}{{ .Data.token }}{{ end }}
PATRONICTL_CONFIG_FILE=/secrets/patroni.yml
PGBACKREST_STANZA=postgres
_EOT
destination = "secrets/pg.env"
uid = 100000
@ -291,9 +296,9 @@ postgresql:
- hostssl all all 0.0.0.0/0 cert clientcert=verify-full
pg_ident:
- patroni-map postgres.service.consul postgres
- patroni-map postgres.service.consul replicator
- patroni-map postgres.service.consul rewind
- patroni-map pg-{{ env "NOMAD_ALLOC_INDEX" }}.postgres.service.consul postgres
- patroni-map pg-{{ env "NOMAD_ALLOC_INDEX" }}.postgres.service.consul replicator
- patroni-map pg-{{ env "NOMAD_ALLOC_INDEX" }}.postgres.service.consul rewind
parameters:
ssl: on
@ -423,7 +428,8 @@ _EOT
data = <<_EOT
{{ with pkiCert
"pki/postgres/issue/postgres-server"
"common_name=postgres.service.consul"
(printf "common_name=pg-%s.postgres.service.consul" (env "NOMAD_ALLOC_INDEX"))
"alt_name=postgres.service.consul"
(printf "ip_sans=%s" (env "NOMAD_IP_patroni")) "ttl=72h" }}
{{ .Cert }}
{{ .Key }}

View File

@ -1,6 +1,7 @@
#!/bin/sh
#!/bin/sh
# vim: syntax=sh
@ -26,7 +27,6 @@ fi
echo "Tune PKI secret engine"
vault secrets tune -max-lease-ttl=131400h pki/postgres
# Configure PKI URLs
echo "Configure URL endpoints"
vault write pki/postgres/config/urls \
@ -59,10 +59,10 @@ if [ "${INITIAL_SETUP}" = "true" ]; then
# Generate an internal CA
echo "Generating an internal CA"
vault write -format=json pki/postgres/intermediate/generate/internal \
common_name="postgres Certificate Authority " \
common_name="postgres Certificate Authority" \
ttl="131400h" \
organization="Ehtrace" \
ou="PostgreSQL" \
ou="Postgres" \
locality="Pessac" \
key_type=rsa \
key_bits=4096 \

View File

@ -36,7 +36,6 @@ job "postgres-upgrade" {
PG_DO_UPGRADE = false
}
# Use a template block instead of env {} so we can fetch values from vault
template {
data = <<_EOT

View File

@ -1,20 +0,0 @@
#!/bin/sh
[[ template "common/vault.mkpki.sh.tpl" dict
"ctx" .
"pki" (dict
"name" .instance
"ou" "PostgreSQL"
"issuer" "pki/root"
)
]]
vault write [[ .vault.prefix ]]pki/[[ .instance ]]/roles/postgres-server \
allowed_domains="[[ .instance ]].service.[[ .consul.domain ]]" \
allow_bare_domains=true \
allow_subdomains=true \
allow_localhost=false \
allow_ip_sans=true \
allow_wildcard_certificates=false \
max_ttl=72h

View File

@ -1,6 +1,6 @@
[[ $c := merge .pg.server . -]]
job "[[ .instance ]]" {
job [[ .instance | toJSON ]] {
[[- $c := merge .pg.server .pg . ]]
[[ template "common/job_start" $c ]]
@ -17,7 +17,7 @@ job [[ .instance | toJSON ]] {
value = "true"
}
count = [[ .pg.server.recovery | ternary 1 .pg.server.count ]]
count = "[[ $c.recovery | ternary 1 $c.count ]]"
network {
mode = "bridge"
[[- if $c.prometheus.enabled ]]
@ -44,17 +44,17 @@ job [[ .instance | toJSON ]] {
service {
name = "[[ .instance ]][[ $c.consul.suffix ]]"
port = 5432
[[- template "common/prometheus_meta" $c ]]
[[- template "common/connect" $c ]]
[[ template "common/prometheus_meta" $c ]]
[[ template "common/connect" $c ]]
tags = [
"postgres-${NOMAD_ALLOC_INDEX}",
[[- if .pg.server.traefik.enabled ]]
[[- if $c.traefik.enabled ]]
# Note : we don't add traefik.enable=true
# This will be done dynamically only on the current master node using the update_tags.sh script
"[[ $c.traefik.instance ]].tcp.routers.[[ .instance ]][[ $c.consul.suffix ]].rule=HostSNI(`[[ if has .pg.server "public_url" ]][[ (urlParse .pg.server.public_url).Hostname ]][[ else ]]*[[ end ]]`)",
"[[ $c.traefik.instance ]].tcp.routers.[[ .instance ]][[ $c.consul.suffix ]].tls=true",
"[[ $c.traefik.instance ]].tcp.routers.[[ .instance ]][[ $c.consul.suffix ]].entrypoints=[[ join $c.traefik.entrypoints "," ]]",
[[- if gt (len .pg.server.traefik.middlewares) 0 ]]
[[- if gt (len $c.traefik.middlewares) 0 ]]
"[[ $c.traefik.instance ]].tcp.routers.[[ .instance ]][[ $c.consul.suffix ]].middlewares=[[ join $c.traefik.middlewares "," ]]",
[[- end ]]
[[- end ]]
@ -114,34 +114,17 @@ job [[ .instance | toJSON ]] {
[[- end ]]
[[- end ]]
volume "data" {
type = [[ .pg.volumes.data.type | toJSON ]]
source = [[ .pg.volumes.data.source | toJSON ]]
[[- if ne .pg.volumes.data.type "host" ]]
access_mode = "single-node-writer"
attachment_mode = "file-system"
[[- end ]]
per_alloc = true
}
volume "backup" {
type = [[ .pg.volumes.backup.type | toJSON ]]
source = [[ .pg.volumes.backup.source | toJSON ]]
[[- if ne .pg.volumes.backup.type "host" ]]
access_mode = "multi-node-multi-writer"
attachment_mode = "file-system"
[[- end ]]
}
[[ template "common/volumes" $c ]]
task "postgres" {
driver = [[ $c.nomad.driver | toJSON ]]
driver = "[[ $c.nomad.driver ]]"
leader = true
[[- if not .pg.server.recovery ]]
[[- if not $c.recovery ]]
kill_timeout = "10m"
[[- end ]]
config {
image = [[ .pg.server.image | toJSON ]]
image = "[[ $c.image ]]"
# Set shm_size to half of the total size
shm_size = [[ mul .pg.server.resources.memory 524288 ]]
volumes = ["local/mkdir-socket.sh:/entrypoint.d/70-mkdir-socket.sh"]
@ -157,20 +140,14 @@ job [[ .instance | toJSON ]] {
[[- end ]]
}
vault {
policies = ["[[ .instance ]][[ $c.consul.suffix ]]"]
env = false
disable_file = true
}
[[- template "common/file_env" $c.env ]]
[[ template "common/vault.policies" $c ]]
[[ template "common/file_env" $c ]]
template {
data = <<_EOT
# Get a Consul token from vault, so we're able to update the tags in Consul from the containers
CONSUL_HTTP_TOKEN={{ with secret "[[ .vault.prefix ]]consul/creds/[[ .instance ]]" }}{{ .Data.token }}{{ end }}
PATRONICTL_CONFIG_FILE=/secrets/patroni.yml
PGBACKREST_STANZA=[[ .instance ]]
_EOT
destination = "secrets/pg.env"
uid = 100000
@ -254,8 +231,9 @@ _EOT
template {
data = <<_EOT
{{ with pkiCert
"[[ .vault.prefix ]]pki/[[ .instance ]]/issue/postgres-server"
"common_name=[[ .instance ]].service.[[ .consul.domain ]]"
"[[ $c.vault.pki.path ]]/issue/postgres-server"
(printf "common_name=pg-%s.[[ .instance ]][[ .consul.suffix ]].service.[[ .consul.domain ]]" (env "NOMAD_ALLOC_INDEX"))
"alt_name=[[ .instance ]][[ .consul.suffix ]].service.[[ .consul.domain ]]"
(printf "ip_sans=%s" (env "NOMAD_IP_patroni")) "ttl=72h" }}
{{ .Cert }}
{{ .Key }}
@ -272,7 +250,7 @@ _EOT
# CA certificate chains
template {
data = <<_EOT
{{ with secret "[[ .vault.prefix ]]pki/[[ .instance ]]/cert/ca_chain" }}{{ .Data.ca_chain }}{{ end }}
{{ with secret "[[ $c.vault.pki.path ]]/cert/ca_chain" }}{{ .Data.ca_chain }}{{ end }}
_EOT
destination = "local/postgres.ca.pem"
change_mode = "signal"
@ -290,22 +268,20 @@ _EOT
destination = "/backup"
}
[[ template "common/resources" .pg.server.resources ]]
[[ template "common/resources" $c ]]
}
[[- if and (not .pg.server.recovery) (or .pg.backup.pgbackrest.enabled .pg.backup.dumps.enabled) ]]
[[ $c = merge .pg.backup .pg.server . -]]
[[ $b := merge .pg.backup .pg.server .pg . -]]
task "backup" {
driver = [[ $c.nomad.driver | toJSON ]]
driver = "[[ $c.nomad.driver ]]"
config {
image = [[ .pg.server.image | toJSON ]]
image = "[[ $c.image ]]"
command = "supercronic"
args = [
"/secrets/backup.cron"
]
args = ["/secrets/backup.cron"]
readonly_rootfs = true
pids_limit = 100
}
@ -316,12 +292,11 @@ _EOT
}
env {
PGBACKREST_STANZA = [[ .instance | toJSON ]]
# Use the socket from the shared dir
PGHOST = "/alloc/data/postgres"
}
[[- template "common/file_env" $c.env ]]
[[- template "common/file_env" $c ]]
template {
data =<<_EOT
@ -350,17 +325,17 @@ _EOT
destination = "/data"
}
[[ template "common/resources" .pg.backup.resources ]]
[[ template "common/resources" $b ]]
}
[[- end ]]
[[- if and $c.prometheus.enabled (not .pg.server.recovery) ]]
[[ template "common/task.metrics_proxy" merge (dict "prometheus" (dict "additional_proxy_conf" (tmpl.Exec "postgres/nginx_patroni.conf.tpl" $c))) $c ]]
[[ $e := merge .pg.exporter .pg . ]]
[[ template "common/task.metrics_proxy" merge (dict "prometheus" (dict "additional_proxy_conf" (tmpl.Exec "postgres/nginx_patroni.conf.tpl" $e))) $e ]]
task "exporter" {
driver = [[ $c.nomad.driver | toJSON ]]
driver = "[[ $e.nomad.driver ]]"
user = 9187
lifecycle {
@ -369,7 +344,7 @@ _EOT
}
config {
image = [[ .pg.exporter.image | toJSON ]]
image = "[[ $e.image ]]"
args = [
"--web.listen-address=127.0.0.1:9187"
]
@ -377,22 +352,15 @@ _EOT
pids_limit = 20
}
vault {
policies = ["[[ .instance ]][[ $c.consul.suffix ]]"]
env = false
disable_file = true
}
env {
[[ template "common/env" .pg.exporter.env ]]
}
[[ template "common/vault.policies" $c ]]
[[ template "common/file_env" $e ]]
template {
data = <<_EOT
PG_EXPORTER_AUTO_DISCOVER_DATABASES=true
DATA_SOURCE_URI=127.0.0.1:5432/postgres
DATA_SOURCE_USER=monitor
DATA_SOURCE_PASS={{ with secret "[[ .vault.prefix ]]kv/service/postgres" }}{{ .Data.data.monitor_pwd | sprig_squote }}{{ end }}
DATA_SOURCE_PASS={{ with secret "[[ .vault.prefix ]]kv/service/[[ .instance ]]" }}{{ .Data.data.monitor_pwd | sprig_squote }}{{ end }}
_EOT
destination = "secrets/env"
perms = "0400"

14
prep.d/20-pki.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
[[ $c := merge .pg.server .pg . ]]
[[ template "common/vault.mkpki.sh.tpl" $c ]]
vault write [[ $c.vault.pki.path ]]/roles/postgres-server \
allowed_domains="[[ .instance ]][[ .consul.suffix ]].service.[[ .consul.domain ]]" \
allow_bare_domains=true \
allow_subdomains=true \
allow_localhost=false \
allow_ip_sans=true \
allow_wildcard_certificates=false \
max_ttl=72h

View File

@ -65,9 +65,9 @@ postgresql:
- hostssl all all 0.0.0.0/0 cert clientcert=verify-full
pg_ident:
- patroni-map [[ .instance ]].service.[[ .consul.domain ]] postgres
- patroni-map [[ .instance ]].service.[[ .consul.domain ]] replicator
- patroni-map [[ .instance ]].service.[[ .consul.domain ]] rewind
- patroni-map pg-{{ env "NOMAD_ALLOC_INDEX" }}.[[ .instance ]].service.[[ .consul.domain ]] postgres
- patroni-map pg-{{ env "NOMAD_ALLOC_INDEX" }}.[[ .instance ]].service.[[ .consul.domain ]] replicator
- patroni-map pg-{{ env "NOMAD_ALLOC_INDEX" }}.[[ .instance ]].service.[[ .consul.domain ]] rewind
parameters:
ssl: on

View File

@ -6,6 +6,12 @@ instance: postgres
pg:
vault:
pki:
path: '[[ .vault.prefix ]]pki/[[ .instance ]]'
ou: Postgres
issuer: '[[ .vault.prefix ]]pki/root'
# Postgres server settings
server:
# The image to use
@ -29,7 +35,13 @@ pg:
# # awk '{print $2}' ssh_host_ecdsa_key.pub | base64 -d | sha256sum
# PGBACKREST_REPO1_SFTP_HOST_FINGERPRINT: ce6eb1c79ce6596d7580f3b08021b48e39e5a30f2fd751a7fa82b480d821eb99
# PGBACKREST_REPO1_SFTP_HOST_KEY_CHECK_TYPE: fingerprint
env: {}
env:
PGBACKREST_STANZA: '[[ .instance ]]'
vault:
# List of vault policies to attach to the task
policies:
- '[[ .instance ]][[ .consul.suffix ]]'
# Set higher priority for the postgres job
nomad:
@ -347,8 +359,10 @@ pg:
data:
type: csi
source: '[[ .instance ]]-data'
per_alloc: true
# Backup volume (can be used for pgbackrest and dumps)
# Will be opened as multi-node-multi-writer. Can be NFS
backup:
type: csi
source: '[[ .instance ]]-backup'
access_mode: multi-node-multi-writer

View File

@ -9,6 +9,7 @@ path "[[ .vault.prefix ]]consul/creds/[[ .instance ]]" {
}
# Get a certificate for patroni REST API and Postgres
path "[[ .vault.prefix ]]pki/[[ .instance ]]/issue/postgres-server" {
[[- $c := merge .pg.server .pg . ]]
path "[[ $c.vault.pki.path ]]/issue/postgres-server" {
capabilities = ["update"]
}