From a80a194b4440c67243f4dd2e2c7b2854d8e0cd9d Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Wed, 15 Jul 2026 02:28:01 +0600 Subject: [PATCH 01/11] Support pg_tde Transparent Data Encryption in init scripts Compose pg_tde into shared_preload_libraries in every config-authoring path (including the PITR restore path, so encrypted clusters recover without corruption), add the pg_tde GUCs (wal_encrypt, enforce_encryption, cipher) and the default_table_access_method=tde_heap flip in the post-bootstrap rewrite, add the principal-key bootstrap block (CREATE EXTENSION, key provider, principal and server keys) on first primary init, and seed replicas with pg_tde_basebackup when TDE is enabled. All behavior is gated on TDE_ENABLED so non-TDE clusters are unaffected. Signed-off-by: Tamal Saha --- role_scripts/10/primary/start.sh | 54 +++++++++++++++++++++- role_scripts/10/standby/ha_backup_job.sh | 17 +++++-- role_scripts/10/standby/run.sh | 18 ++++++-- role_scripts/10/standby/warm_stanby.sh | 11 ++++- role_scripts/11/primary/start.sh | 54 +++++++++++++++++++++- role_scripts/11/standby/ha_backup_job.sh | 17 +++++-- role_scripts/11/standby/run.sh | 17 +++++-- role_scripts/11/standby/warm_stanby.sh | 11 ++++- role_scripts/12/primary/start.sh | 53 +++++++++++++++++++++- role_scripts/12/standby/ha_backup_job.sh | 17 +++++-- role_scripts/12/standby/run.sh | 19 +++++--- role_scripts/12/standby/warm_stanby.sh | 11 ++++- role_scripts/13/primary/start.sh | 53 +++++++++++++++++++++- role_scripts/13/standby/ha_backup_job.sh | 17 +++++-- role_scripts/13/standby/remote-replica.sh | 17 +++++-- role_scripts/13/standby/run.sh | 18 ++++++-- role_scripts/13/standby/warm_stanby.sh | 11 ++++- role_scripts/14/primary/start.sh | 55 +++++++++++++++++++++-- role_scripts/14/standby/ha_backup_job.sh | 17 +++++-- role_scripts/14/standby/remote-replica.sh | 17 +++++-- role_scripts/14/standby/run.sh | 18 ++++++-- role_scripts/14/standby/warm_stanby.sh | 11 ++++- role_scripts/15/primary/start.sh | 53 +++++++++++++++++++++- role_scripts/15/standby/ha_backup_job.sh | 17 +++++-- role_scripts/15/standby/remote-replica.sh | 17 +++++-- role_scripts/15/standby/run.sh | 18 ++++++-- role_scripts/15/standby/warm_stanby.sh | 11 ++++- role_scripts/16/primary/start.sh | 53 +++++++++++++++++++++- role_scripts/16/standby/ha_backup_job.sh | 17 +++++-- role_scripts/16/standby/remote-replica.sh | 17 +++++-- role_scripts/16/standby/run.sh | 19 +++++--- role_scripts/16/standby/warm_stanby.sh | 11 ++++- role_scripts/17/primary/start.sh | 53 +++++++++++++++++++++- role_scripts/17/standby/ha_backup_job.sh | 17 +++++-- role_scripts/17/standby/remote-replica.sh | 17 +++++-- role_scripts/17/standby/run.sh | 20 ++++++--- role_scripts/17/standby/warm_stanby.sh | 11 ++++- role_scripts/18/primary/start.sh | 53 +++++++++++++++++++++- role_scripts/18/standby/ha_backup_job.sh | 17 +++++-- role_scripts/18/standby/remote-replica.sh | 17 +++++-- role_scripts/18/standby/run.sh | 20 ++++++--- role_scripts/18/standby/warm_stanby.sh | 11 ++++- role_scripts/9/primary/start.sh | 54 +++++++++++++++++++++- role_scripts/9/standby/ha_backup_job.sh | 18 ++++++-- role_scripts/9/standby/run.sh | 17 +++++-- role_scripts/9/standby/warm_stanby.sh | 11 ++++- scripts/do_pg_basebackup.sh | 6 ++- scripts/recover_replica.sh | 6 ++- scripts/restore.sh | 13 +++++- 49 files changed, 1004 insertions(+), 123 deletions(-) diff --git a/role_scripts/10/primary/start.sh b/role_scripts/10/primary/start.sh index 62ffbfc..c090cd9 100755 --- a/role_scripts/10/primary/start.sh +++ b/role_scripts/10/primary/start.sh @@ -35,7 +35,11 @@ echo "max_replication_slots = 90" >>/tmp/postgresql.conf echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${SSL:-0}" == "ON" ]]; then echo "ssl =on" >>/tmp/postgresql.conf @@ -88,6 +92,45 @@ echo psql+=(--username "$POSTGRES_USER" --dbname "$POSTGRES_DB") echo +# pg_tde principal-key bootstrap. Runs once on first initialization, after the +# database and superuser exist and before any encrypted table or the +# default_table_access_method flip can be used. Idempotent on retries. +if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Enable the extension in the default databases. template1 makes it the + # default for future databases. + for TDE_DB in template1 "$POSTGRES_DB"; do + psql -U postgres -d "$TDE_DB" -v ON_ERROR_STOP=1 <>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf else @@ -212,4 +263,3 @@ if [[ "$STREAMING" == "synchronous" ]]; then fi # ref: https://superuser.com/a/246841/985093 cat /tmp/postgresql.conf $PGDATA/postgresql.conf >"/tmp/postgresql.conf.tmp" && mv "/tmp/postgresql.conf.tmp" "$PGDATA/postgresql.conf" - diff --git a/role_scripts/10/standby/ha_backup_job.sh b/role_scripts/10/standby/ha_backup_job.sh index d4c1064..8c8f0cd 100755 --- a/role_scripts/10/standby/ha_backup_job.sh +++ b/role_scripts/10/standby/ha_backup_job.sh @@ -60,10 +60,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi fi @@ -84,7 +86,16 @@ else echo "wal_keep_segments = 160" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi echo "max_replication_slots = 90" >>/tmp/postgresql.conf echo "wal_log_hints = on" >>/tmp/postgresql.conf diff --git a/role_scripts/10/standby/run.sh b/role_scripts/10/standby/run.sh index 31a441c..53313d3 100755 --- a/role_scripts/10/standby/run.sh +++ b/role_scripts/10/standby/run.sh @@ -89,7 +89,6 @@ if [[ "$WAL_LIMIT_POLICY" == "ReplicationSlot" ]]; then done fi - if [[ ! -e "$PGDATA/PG_VERSION" ]]; then if [[ ! -e "/var/pv/IGNORE_FILESYSTEM_MOUNT_CHECK" ]]; then # Robust /var/pv mount availability check before any destructive operation or basebackup @@ -118,10 +117,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi touch $PGDATA/recovery.conf else @@ -154,7 +155,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi echo "max_replication_slots = 90" >>/tmp/postgresql.conf if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/10/standby/warm_stanby.sh b/role_scripts/10/standby/warm_stanby.sh index aa7a7d4..2b76050 100755 --- a/role_scripts/10/standby/warm_stanby.sh +++ b/role_scripts/10/standby/warm_stanby.sh @@ -33,7 +33,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi echo "hot_standby = off" >>/tmp/postgresql.conf diff --git a/role_scripts/11/primary/start.sh b/role_scripts/11/primary/start.sh index 88639ca..efba1da 100755 --- a/role_scripts/11/primary/start.sh +++ b/role_scripts/11/primary/start.sh @@ -41,7 +41,11 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${SSL:-0}" == "ON" ]]; then echo "ssl =on" >>/tmp/postgresql.conf @@ -97,6 +101,45 @@ echo psql+=(--username "$POSTGRES_USER" --dbname "$POSTGRES_DB") echo +# pg_tde principal-key bootstrap. Runs once on first initialization, after the +# database and superuser exist and before any encrypted table or the +# default_table_access_method flip can be used. Idempotent on retries. +if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Enable the extension in the default databases. template1 makes it the + # default for future databases. + for TDE_DB in template1 "$POSTGRES_DB"; do + psql -U postgres -d "$TDE_DB" -v ON_ERROR_STOP=1 <>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf else @@ -253,4 +304,3 @@ if [[ "$STREAMING" == "synchronous" ]]; then fi # ref: https://superuser.com/a/246841/985093 cat /tmp/postgresql.conf $PGDATA/postgresql.conf >"/tmp/postgresql.conf.tmp" && mv "/tmp/postgresql.conf.tmp" "$PGDATA/postgresql.conf" - diff --git a/role_scripts/11/standby/ha_backup_job.sh b/role_scripts/11/standby/ha_backup_job.sh index f5083be..5eef524 100755 --- a/role_scripts/11/standby/ha_backup_job.sh +++ b/role_scripts/11/standby/ha_backup_job.sh @@ -60,10 +60,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi fi @@ -88,7 +90,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/11/standby/run.sh b/role_scripts/11/standby/run.sh index 4eb0a72..264f253 100755 --- a/role_scripts/11/standby/run.sh +++ b/role_scripts/11/standby/run.sh @@ -116,10 +116,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi touch /var/pv/data/standby.signal else @@ -157,7 +159,16 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/11/standby/warm_stanby.sh b/role_scripts/11/standby/warm_stanby.sh index 006617f..fc7bc1e 100755 --- a/role_scripts/11/standby/warm_stanby.sh +++ b/role_scripts/11/standby/warm_stanby.sh @@ -35,7 +35,16 @@ echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf echo "hot_standby = off" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [[ "$STREAMING" == "synchronous" ]]; then # setup synchronous streaming replication diff --git a/role_scripts/12/primary/start.sh b/role_scripts/12/primary/start.sh index d11f018..099bd56 100755 --- a/role_scripts/12/primary/start.sh +++ b/role_scripts/12/primary/start.sh @@ -42,7 +42,11 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${SSL:-0}" == "ON" ]]; then echo "ssl =on" >>/tmp/postgresql.conf @@ -117,6 +121,45 @@ echo psql+=(--username "$POSTGRES_USER" --dbname "$POSTGRES_DB") echo +# pg_tde principal-key bootstrap. Runs once on first initialization, after the +# database and superuser exist and before any encrypted table or the +# default_table_access_method flip can be used. Idempotent on retries. +if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Enable the extension in the default databases. template1 makes it the + # default for future databases. + for TDE_DB in template1 "$POSTGRES_DB"; do + psql -U postgres -d "$TDE_DB" -v ON_ERROR_STOP=1 <>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf else diff --git a/role_scripts/12/standby/ha_backup_job.sh b/role_scripts/12/standby/ha_backup_job.sh index 1ae79cc..b7e81c9 100755 --- a/role_scripts/12/standby/ha_backup_job.sh +++ b/role_scripts/12/standby/ha_backup_job.sh @@ -59,10 +59,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi fi @@ -89,7 +91,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf # we are not doing any archiving by default but it's better to have this config in our postgresql.conf file in case of customization. echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/12/standby/run.sh b/role_scripts/12/standby/run.sh index d60ff98..3d76fa0 100755 --- a/role_scripts/12/standby/run.sh +++ b/role_scripts/12/standby/run.sh @@ -89,7 +89,6 @@ if [[ "$WAL_LIMIT_POLICY" == "ReplicationSlot" ]]; then done fi - if [[ ! -e "$PGDATA/PG_VERSION" ]]; then if [[ ! -e "/var/pv/IGNORE_FILESYSTEM_MOUNT_CHECK" ]]; then # Robust /var/pv mount availability check before any destructive operation or basebackup @@ -117,10 +116,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi touch /var/pv/data/standby.signal else @@ -150,13 +151,21 @@ if [[ "$WAL_LIMIT_POLICY" == "ReplicationSlot" ]]; then echo "primary_slot_name = "$CLEAN_HOSTNAME"" >>/tmp/postgresql.conf fi - echo "wal_log_hints = on" >>/tmp/postgresql.conf # we are not doing any archiving by default but it's better to have this config in our postgresql.conf file in case of customization. echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/12/standby/warm_stanby.sh b/role_scripts/12/standby/warm_stanby.sh index 7c182c6..e5e0305 100755 --- a/role_scripts/12/standby/warm_stanby.sh +++ b/role_scripts/12/standby/warm_stanby.sh @@ -42,7 +42,16 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi echo "hot_standby = off" >>/tmp/postgresql.conf diff --git a/role_scripts/13/primary/start.sh b/role_scripts/13/primary/start.sh index 50e446c..b1d6f5f 100755 --- a/role_scripts/13/primary/start.sh +++ b/role_scripts/13/primary/start.sh @@ -42,7 +42,11 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${SSL:-0}" == "ON" ]]; then echo "ssl =on" >>/tmp/postgresql.conf @@ -138,6 +142,45 @@ echo psql+=(--username "$POSTGRES_USER" --dbname "$POSTGRES_DB") echo +# pg_tde principal-key bootstrap. Runs once on first initialization, after the +# database and superuser exist and before any encrypted table or the +# default_table_access_method flip can be used. Idempotent on retries. +if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Enable the extension in the default databases. template1 makes it the + # default for future databases. + for TDE_DB in template1 "$POSTGRES_DB"; do + psql -U postgres -d "$TDE_DB" -v ON_ERROR_STOP=1 <>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf else diff --git a/role_scripts/13/standby/ha_backup_job.sh b/role_scripts/13/standby/ha_backup_job.sh index 9dbdf52..1fb4501 100755 --- a/role_scripts/13/standby/ha_backup_job.sh +++ b/role_scripts/13/standby/ha_backup_job.sh @@ -59,10 +59,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi fi @@ -89,7 +91,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf # we are not doing any archiving by default but it's better to have this config in our postgresql.conf file in case of customization. echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/13/standby/remote-replica.sh b/role_scripts/13/standby/remote-replica.sh index eacece0..20ea5d0 100755 --- a/role_scripts/13/standby/remote-replica.sh +++ b/role_scripts/13/standby/remote-replica.sh @@ -69,10 +69,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" fi fi @@ -99,7 +101,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/13/standby/run.sh b/role_scripts/13/standby/run.sh index 259d4f7..6654ae1 100755 --- a/role_scripts/13/standby/run.sh +++ b/role_scripts/13/standby/run.sh @@ -89,7 +89,6 @@ if [[ "$WAL_LIMIT_POLICY" == "ReplicationSlot" ]]; then done fi - if [[ ! -e "$PGDATA/PG_VERSION" ]]; then if [[ ! -e "/var/pv/IGNORE_FILESYSTEM_MOUNT_CHECK" ]]; then # Robust /var/pv mount availability check before any destructive operation or basebackup @@ -117,10 +116,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi touch /var/pv/data/standby.signal else @@ -159,7 +160,16 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/13/standby/warm_stanby.sh b/role_scripts/13/standby/warm_stanby.sh index f77be34..5e01023 100755 --- a/role_scripts/13/standby/warm_stanby.sh +++ b/role_scripts/13/standby/warm_stanby.sh @@ -38,7 +38,16 @@ echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf echo "hot_standby = off" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [[ "$STREAMING" == "synchronous" ]]; then # setup synchronous streaming replication diff --git a/role_scripts/14/primary/start.sh b/role_scripts/14/primary/start.sh index 9bff7aa..00c2e62 100755 --- a/role_scripts/14/primary/start.sh +++ b/role_scripts/14/primary/start.sh @@ -42,7 +42,11 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${SSL:-0}" == "ON" ]]; then echo "ssl =on" >>/tmp/postgresql.conf @@ -59,8 +63,6 @@ if [[ "$CLIENT_AUTH_MODE" == "scram" ]]; then echo "password_encryption = scram-sha-256" >>/tmp/postgresql.conf fi - - # ****************** Recovery config ************************** echo "recovery_target_timeline = 'latest'" >>/tmp/postgresql.conf # primary_conninfo is used for streaming replication @@ -144,6 +146,45 @@ echo psql+=(--username "$POSTGRES_USER" --dbname "$POSTGRES_DB") echo +# pg_tde principal-key bootstrap. Runs once on first initialization, after the +# database and superuser exist and before any encrypted table or the +# default_table_access_method flip can be used. Idempotent on retries. +if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Enable the extension in the default databases. template1 makes it the + # default for future databases. + for TDE_DB in template1 "$POSTGRES_DB"; do + psql -U postgres -d "$TDE_DB" -v ON_ERROR_STOP=1 <>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf else diff --git a/role_scripts/14/standby/ha_backup_job.sh b/role_scripts/14/standby/ha_backup_job.sh index 5038380..8ed742d 100755 --- a/role_scripts/14/standby/ha_backup_job.sh +++ b/role_scripts/14/standby/ha_backup_job.sh @@ -59,10 +59,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi fi @@ -89,7 +91,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/14/standby/remote-replica.sh b/role_scripts/14/standby/remote-replica.sh index 0999e7f..cc911cf 100755 --- a/role_scripts/14/standby/remote-replica.sh +++ b/role_scripts/14/standby/remote-replica.sh @@ -69,10 +69,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" fi fi @@ -99,7 +101,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/14/standby/run.sh b/role_scripts/14/standby/run.sh index 74ea25a..033aee1 100755 --- a/role_scripts/14/standby/run.sh +++ b/role_scripts/14/standby/run.sh @@ -89,7 +89,6 @@ if [[ "$WAL_LIMIT_POLICY" == "ReplicationSlot" ]]; then done fi - if [[ ! -e "$PGDATA/PG_VERSION" ]]; then if [[ ! -e "/var/pv/IGNORE_FILESYSTEM_MOUNT_CHECK" ]]; then # Robust /var/pv mount availability check before any destructive operation or basebackup @@ -117,10 +116,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi touch /var/pv/data/standby.signal else @@ -159,7 +160,16 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/14/standby/warm_stanby.sh b/role_scripts/14/standby/warm_stanby.sh index df05ee9..1e367af 100755 --- a/role_scripts/14/standby/warm_stanby.sh +++ b/role_scripts/14/standby/warm_stanby.sh @@ -38,7 +38,16 @@ echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf echo "hot_standby = off" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [[ "$STREAMING" == "synchronous" ]]; then # setup synchronous streaming replication diff --git a/role_scripts/15/primary/start.sh b/role_scripts/15/primary/start.sh index 5f73009..a8d78d1 100755 --- a/role_scripts/15/primary/start.sh +++ b/role_scripts/15/primary/start.sh @@ -42,7 +42,11 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${SSL:-0}" == "ON" ]]; then echo "ssl =on" >>/tmp/postgresql.conf @@ -145,6 +149,45 @@ echo psql+=(--username "$POSTGRES_USER" --dbname "$POSTGRES_DB") echo +# pg_tde principal-key bootstrap. Runs once on first initialization, after the +# database and superuser exist and before any encrypted table or the +# default_table_access_method flip can be used. Idempotent on retries. +if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Enable the extension in the default databases. template1 makes it the + # default for future databases. + for TDE_DB in template1 "$POSTGRES_DB"; do + psql -U postgres -d "$TDE_DB" -v ON_ERROR_STOP=1 <>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf else diff --git a/role_scripts/15/standby/ha_backup_job.sh b/role_scripts/15/standby/ha_backup_job.sh index 040a43c..25fc9d8 100755 --- a/role_scripts/15/standby/ha_backup_job.sh +++ b/role_scripts/15/standby/ha_backup_job.sh @@ -61,10 +61,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi fi @@ -91,7 +93,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/15/standby/remote-replica.sh b/role_scripts/15/standby/remote-replica.sh index 0999e7f..cc911cf 100755 --- a/role_scripts/15/standby/remote-replica.sh +++ b/role_scripts/15/standby/remote-replica.sh @@ -69,10 +69,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" fi fi @@ -99,7 +101,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/15/standby/run.sh b/role_scripts/15/standby/run.sh index 2db653a..a007eb6 100755 --- a/role_scripts/15/standby/run.sh +++ b/role_scripts/15/standby/run.sh @@ -89,7 +89,6 @@ if [[ "$WAL_LIMIT_POLICY" == "ReplicationSlot" ]]; then done fi - if [[ ! -e "$PGDATA/PG_VERSION" ]]; then if [[ ! -e "/var/pv/IGNORE_FILESYSTEM_MOUNT_CHECK" ]]; then pv_df_output=$(cat /proc/mounts) @@ -116,10 +115,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi touch /var/pv/data/standby.signal else @@ -158,7 +159,16 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/15/standby/warm_stanby.sh b/role_scripts/15/standby/warm_stanby.sh index d6ae859..38736da 100755 --- a/role_scripts/15/standby/warm_stanby.sh +++ b/role_scripts/15/standby/warm_stanby.sh @@ -39,7 +39,16 @@ echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf echo "hot_standby = off" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [[ "$STREAMING" == "synchronous" ]]; then # setup synchronous streaming replication diff --git a/role_scripts/16/primary/start.sh b/role_scripts/16/primary/start.sh index 5dc2a7b..aaa962f 100755 --- a/role_scripts/16/primary/start.sh +++ b/role_scripts/16/primary/start.sh @@ -43,7 +43,11 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${SSL:-0}" == "ON" ]]; then echo "ssl =on" >>/tmp/postgresql.conf @@ -143,6 +147,45 @@ echo psql+=(--username "$POSTGRES_USER" --dbname "$POSTGRES_DB") echo +# pg_tde principal-key bootstrap. Runs once on first initialization, after the +# database and superuser exist and before any encrypted table or the +# default_table_access_method flip can be used. Idempotent on retries. +if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Enable the extension in the default databases. template1 makes it the + # default for future databases. + for TDE_DB in template1 "$POSTGRES_DB"; do + psql -U postgres -d "$TDE_DB" -v ON_ERROR_STOP=1 <>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf else diff --git a/role_scripts/16/standby/ha_backup_job.sh b/role_scripts/16/standby/ha_backup_job.sh index e9c8003..11ac6b0 100755 --- a/role_scripts/16/standby/ha_backup_job.sh +++ b/role_scripts/16/standby/ha_backup_job.sh @@ -61,10 +61,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi fi @@ -91,7 +93,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/16/standby/remote-replica.sh b/role_scripts/16/standby/remote-replica.sh index 2b1728a..6e6a1f0 100755 --- a/role_scripts/16/standby/remote-replica.sh +++ b/role_scripts/16/standby/remote-replica.sh @@ -69,10 +69,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" fi fi @@ -99,7 +101,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/16/standby/run.sh b/role_scripts/16/standby/run.sh index 7a865db..0dca3b2 100755 --- a/role_scripts/16/standby/run.sh +++ b/role_scripts/16/standby/run.sh @@ -116,18 +116,18 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi touch /var/pv/data/standby.signal else /run_scripts/role/warm_stanby.sh fi - - # setup postgresql.conf touch /tmp/postgresql.conf @@ -160,7 +160,16 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/16/standby/warm_stanby.sh b/role_scripts/16/standby/warm_stanby.sh index a1eff58..8866a03 100755 --- a/role_scripts/16/standby/warm_stanby.sh +++ b/role_scripts/16/standby/warm_stanby.sh @@ -39,7 +39,16 @@ echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf echo "hot_standby = off" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [[ "$STREAMING" == "synchronous" ]]; then # setup synchronous streaming replication diff --git a/role_scripts/17/primary/start.sh b/role_scripts/17/primary/start.sh index 0eae773..ddbb134 100755 --- a/role_scripts/17/primary/start.sh +++ b/role_scripts/17/primary/start.sh @@ -44,7 +44,11 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${SSL:-0}" == "ON" ]]; then echo "ssl =on" >>/tmp/postgresql.conf @@ -148,6 +152,45 @@ echo psql+=(--username "$POSTGRES_USER" --dbname "$POSTGRES_DB") echo +# pg_tde principal-key bootstrap. Runs once on first initialization, after the +# database and superuser exist and before any encrypted table or the +# default_table_access_method flip can be used. Idempotent on retries. +if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Enable the extension in the default databases. template1 makes it the + # default for future databases. + for TDE_DB in template1 "$POSTGRES_DB"; do + psql -U postgres -d "$TDE_DB" -v ON_ERROR_STOP=1 <>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf else diff --git a/role_scripts/17/standby/ha_backup_job.sh b/role_scripts/17/standby/ha_backup_job.sh index e9c8003..11ac6b0 100755 --- a/role_scripts/17/standby/ha_backup_job.sh +++ b/role_scripts/17/standby/ha_backup_job.sh @@ -61,10 +61,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi fi @@ -91,7 +93,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/17/standby/remote-replica.sh b/role_scripts/17/standby/remote-replica.sh index 2b1728a..6e6a1f0 100755 --- a/role_scripts/17/standby/remote-replica.sh +++ b/role_scripts/17/standby/remote-replica.sh @@ -69,10 +69,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" fi fi @@ -99,7 +101,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/17/standby/run.sh b/role_scripts/17/standby/run.sh index 5e54fe0..0dca3b2 100755 --- a/role_scripts/17/standby/run.sh +++ b/role_scripts/17/standby/run.sh @@ -89,7 +89,6 @@ if [[ "$WAL_LIMIT_POLICY" == "ReplicationSlot" ]]; then done fi - if [[ ! -e "$PGDATA/PG_VERSION" ]]; then if [[ ! -e "/var/pv/IGNORE_FILESYSTEM_MOUNT_CHECK" ]]; then # Robust /var/pv mount availability check before any destructive operation or basebackup @@ -117,18 +116,18 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi touch /var/pv/data/standby.signal else /run_scripts/role/warm_stanby.sh fi - - # setup postgresql.conf touch /tmp/postgresql.conf @@ -161,7 +160,16 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/17/standby/warm_stanby.sh b/role_scripts/17/standby/warm_stanby.sh index a1eff58..8866a03 100755 --- a/role_scripts/17/standby/warm_stanby.sh +++ b/role_scripts/17/standby/warm_stanby.sh @@ -39,7 +39,16 @@ echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf echo "hot_standby = off" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [[ "$STREAMING" == "synchronous" ]]; then # setup synchronous streaming replication diff --git a/role_scripts/18/primary/start.sh b/role_scripts/18/primary/start.sh index 85c91fc..3b4c905 100755 --- a/role_scripts/18/primary/start.sh +++ b/role_scripts/18/primary/start.sh @@ -44,7 +44,11 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${SSL:-0}" == "ON" ]]; then echo "ssl =on" >>/tmp/postgresql.conf @@ -141,6 +145,45 @@ echo psql+=(--username "$POSTGRES_USER" --dbname "$POSTGRES_DB") echo +# pg_tde principal-key bootstrap. Runs once on first initialization, after the +# database and superuser exist and before any encrypted table or the +# default_table_access_method flip can be used. Idempotent on retries. +if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Enable the extension in the default databases. template1 makes it the + # default for future databases. + for TDE_DB in template1 "$POSTGRES_DB"; do + psql -U postgres -d "$TDE_DB" -v ON_ERROR_STOP=1 <>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf else diff --git a/role_scripts/18/standby/ha_backup_job.sh b/role_scripts/18/standby/ha_backup_job.sh index e9c8003..11ac6b0 100755 --- a/role_scripts/18/standby/ha_backup_job.sh +++ b/role_scripts/18/standby/ha_backup_job.sh @@ -61,10 +61,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi fi @@ -91,7 +93,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/18/standby/remote-replica.sh b/role_scripts/18/standby/remote-replica.sh index 2b1728a..6e6a1f0 100755 --- a/role_scripts/18/standby/remote-replica.sh +++ b/role_scripts/18/standby/remote-replica.sh @@ -69,10 +69,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" fi fi @@ -99,7 +101,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/18/standby/run.sh b/role_scripts/18/standby/run.sh index 5e54fe0..0dca3b2 100755 --- a/role_scripts/18/standby/run.sh +++ b/role_scripts/18/standby/run.sh @@ -89,7 +89,6 @@ if [[ "$WAL_LIMIT_POLICY" == "ReplicationSlot" ]]; then done fi - if [[ ! -e "$PGDATA/PG_VERSION" ]]; then if [[ ! -e "/var/pv/IGNORE_FILESYSTEM_MOUNT_CHECK" ]]; then # Robust /var/pv mount availability check before any destructive operation or basebackup @@ -117,18 +116,18 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi touch /var/pv/data/standby.signal else /run_scripts/role/warm_stanby.sh fi - - # setup postgresql.conf touch /tmp/postgresql.conf @@ -161,7 +160,16 @@ else echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf fi -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/18/standby/warm_stanby.sh b/role_scripts/18/standby/warm_stanby.sh index a1eff58..8866a03 100755 --- a/role_scripts/18/standby/warm_stanby.sh +++ b/role_scripts/18/standby/warm_stanby.sh @@ -39,7 +39,16 @@ echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf echo "hot_standby = off" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [[ "$STREAMING" == "synchronous" ]]; then # setup synchronous streaming replication diff --git a/role_scripts/9/primary/start.sh b/role_scripts/9/primary/start.sh index 9978c85..6141afc 100755 --- a/role_scripts/9/primary/start.sh +++ b/role_scripts/9/primary/start.sh @@ -29,7 +29,11 @@ fi echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf echo "max_replication_slots = 90" >>/tmp/postgresql.conf if [[ "${SSL:-0}" == "ON" ]]; then @@ -83,6 +87,45 @@ echo psql+=(--username "$POSTGRES_USER" --dbname "$POSTGRES_DB") echo +# pg_tde principal-key bootstrap. Runs once on first initialization, after the +# database and superuser exist and before any encrypted table or the +# default_table_access_method flip can be used. Idempotent on retries. +if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Enable the extension in the default databases. template1 makes it the + # default for future databases. + for TDE_DB in template1 "$POSTGRES_DB"; do + psql -U postgres -d "$TDE_DB" -v ON_ERROR_STOP=1 <>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf else @@ -208,4 +259,3 @@ fi # ref: https://superuser.com/a/246841/985093 cat /tmp/postgresql.conf $PGDATA/postgresql.conf >"/tmp/postgresql.conf.tmp" && mv "/tmp/postgresql.conf.tmp" "$PGDATA/postgresql.conf" - diff --git a/role_scripts/9/standby/ha_backup_job.sh b/role_scripts/9/standby/ha_backup_job.sh index 28c891b..5479492 100755 --- a/role_scripts/9/standby/ha_backup_job.sh +++ b/role_scripts/9/standby/ha_backup_job.sh @@ -60,10 +60,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi fi @@ -84,9 +86,17 @@ else echo "wal_keep_segments = 160" >>/tmp/postgresql.conf fi - echo "wal_log_hints = on" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi echo "max_replication_slots = 90" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf diff --git a/role_scripts/9/standby/run.sh b/role_scripts/9/standby/run.sh index 5b47a9f..d4f8e35 100755 --- a/role_scripts/9/standby/run.sh +++ b/role_scripts/9/standby/run.sh @@ -119,10 +119,12 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then mkdir -p "$PGDATA" rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" + BASEBACKUP=pg_basebackup + [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" + "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else - pg_basebackup -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" + "$BASEBACKUP" -X fetch --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" fi else /run_scripts/role/warm_stanby.sh @@ -149,7 +151,16 @@ echo "wal_log_hints = on" >>/tmp/postgresql.conf echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi if [ "$STANDBY" == "hot" ]; then echo "hot_standby = on" >>/tmp/postgresql.conf diff --git a/role_scripts/9/standby/warm_stanby.sh b/role_scripts/9/standby/warm_stanby.sh index 48184af..d1e2296 100755 --- a/role_scripts/9/standby/warm_stanby.sh +++ b/role_scripts/9/standby/warm_stanby.sh @@ -31,7 +31,16 @@ fi echo "max_replication_slots = 90" >>/tmp/postgresql.conf echo "wal_log_hints = on" >>/tmp/postgresql.conf -echo "shared_preload_libraries = 'pg_stat_statements'" >>/tmp/postgresql.conf +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf diff --git a/scripts/do_pg_basebackup.sh b/scripts/do_pg_basebackup.sh index 6341b98..c3f6937 100755 --- a/scripts/do_pg_basebackup.sh +++ b/scripts/do_pg_basebackup.sh @@ -8,8 +8,10 @@ rm -rf "$PGDATA"/* chmod 0700 "$PGDATA" echo "attempting pg_basebackup..." +BASEBACKUP=pg_basebackup +[[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "password=$POSTGRES_PASSWORD sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" &>/dev/null + "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "password=$POSTGRES_PASSWORD sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" &>/dev/null else - pg_basebackup -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "password=$POSTGRES_PASSWORD" &>/dev/null + "$BASEBACKUP" -Xs -c fast --no-password --max-rate=1024M --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "password=$POSTGRES_PASSWORD" &>/dev/null fi diff --git a/scripts/recover_replica.sh b/scripts/recover_replica.sh index 7744474..5d2abc4 100755 --- a/scripts/recover_replica.sh +++ b/scripts/recover_replica.sh @@ -8,10 +8,12 @@ mv /run_scripts/role/run.sh /run_scripts/role/run.sh.bc pg_ctl stop -D $PGDATA rm -rf /var/pv/data +BASEBACKUP=pg_basebackup +[[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup if [[ "${SSL:-0}" == "ON" ]]; then - pg_basebackup -Xs -c fast --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "password=$POSTGRES_PASSWORD sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" &>/dev/null + "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "password=$POSTGRES_PASSWORD sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" &>/dev/null else - pg_basebackup -Xs -c fast --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "password=$POSTGRES_PASSWORD" &>/dev/null + "$BASEBACKUP" -Xs -c fast --no-password --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "password=$POSTGRES_PASSWORD" &>/dev/null fi touch /var/pv/data/standby.signal diff --git a/scripts/restore.sh b/scripts/restore.sh index 5c3e694..a5c7723 100755 --- a/scripts/restore.sh +++ b/scripts/restore.sh @@ -84,6 +84,18 @@ fi echo "archive_mode = always" >>/tmp/postgresql.conf echo "archive_command = '/bin/true'" >>/tmp/postgresql.conf echo "logging_collector = on" >>/tmp/postgresql.conf +# pg_tde must be preloaded during recovery/restore or an encrypted +# cluster corrupts. Compose the list with pg_tde first when enabled. +PRELOAD="pg_stat_statements" +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + PRELOAD="${TDE_EXTENSION:-pg_tde},${PRELOAD}" +fi +echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf +if [[ "${TDE_ENABLED:-false}" == "true" ]]; then + [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf + [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf +fi cat /run_scripts/role/postgresql.conf >>/tmp/postgresql.conf mv /tmp/postgresql.conf "$PGDATA/postgresql.conf" echo "max_replication_slots = 90" >>/tmp/postgresql.conf @@ -112,7 +124,6 @@ until pg_isready -U postgres; do fi done - if [[ "$HOST" =~ -0$ ]]; then echo "Primary restore mode" From 328d3544ba2a560176562e1b9072567b7d60f6a9 Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Wed, 15 Jul 2026 03:35:04 +0600 Subject: [PATCH 02/11] Set the file-provider principal key with the database-scoped setter The file key provider is registered with pg_tde_add_database_key_provider_file, so its principal key must be set with pg_tde_set_key_using_database_key_provider. The global setter cannot see a database-scoped provider, so file-provider TDE never got a principal key (the failure was masked by || true). Branch the setter on TDE_PROVIDER_KIND: database-scoped for file, global for vault and kmip. Signed-off-by: Tamal Saha --- role_scripts/10/primary/start.sh | 12 +++++++++--- role_scripts/11/primary/start.sh | 12 +++++++++--- role_scripts/12/primary/start.sh | 12 +++++++++--- role_scripts/13/primary/start.sh | 12 +++++++++--- role_scripts/14/primary/start.sh | 12 +++++++++--- role_scripts/15/primary/start.sh | 12 +++++++++--- role_scripts/16/primary/start.sh | 12 +++++++++--- role_scripts/17/primary/start.sh | 12 +++++++++--- role_scripts/18/primary/start.sh | 12 +++++++++--- role_scripts/9/primary/start.sh | 12 +++++++++--- 10 files changed, 90 insertions(+), 30 deletions(-) diff --git a/role_scripts/10/primary/start.sh b/role_scripts/10/primary/start.sh index c090cd9..24c4058 100755 --- a/role_scripts/10/primary/start.sh +++ b/role_scripts/10/primary/start.sh @@ -120,9 +120,15 @@ SQL ;; esac - # Set the per-database principal key. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + # Set the per-database principal key with the setter that matches the + # provider scope: file providers are database-scoped, vault/kmip are global. + if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + fi # If WAL encryption is requested, set the server key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then diff --git a/role_scripts/11/primary/start.sh b/role_scripts/11/primary/start.sh index efba1da..7db7e27 100755 --- a/role_scripts/11/primary/start.sh +++ b/role_scripts/11/primary/start.sh @@ -129,9 +129,15 @@ SQL ;; esac - # Set the per-database principal key. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + # Set the per-database principal key with the setter that matches the + # provider scope: file providers are database-scoped, vault/kmip are global. + if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + fi # If WAL encryption is requested, set the server key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then diff --git a/role_scripts/12/primary/start.sh b/role_scripts/12/primary/start.sh index 099bd56..dce0b23 100755 --- a/role_scripts/12/primary/start.sh +++ b/role_scripts/12/primary/start.sh @@ -149,9 +149,15 @@ SQL ;; esac - # Set the per-database principal key. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + # Set the per-database principal key with the setter that matches the + # provider scope: file providers are database-scoped, vault/kmip are global. + if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + fi # If WAL encryption is requested, set the server key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then diff --git a/role_scripts/13/primary/start.sh b/role_scripts/13/primary/start.sh index b1d6f5f..553217d 100755 --- a/role_scripts/13/primary/start.sh +++ b/role_scripts/13/primary/start.sh @@ -170,9 +170,15 @@ SQL ;; esac - # Set the per-database principal key. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + # Set the per-database principal key with the setter that matches the + # provider scope: file providers are database-scoped, vault/kmip are global. + if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + fi # If WAL encryption is requested, set the server key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then diff --git a/role_scripts/14/primary/start.sh b/role_scripts/14/primary/start.sh index 00c2e62..ffe1be7 100755 --- a/role_scripts/14/primary/start.sh +++ b/role_scripts/14/primary/start.sh @@ -174,9 +174,15 @@ SQL ;; esac - # Set the per-database principal key. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + # Set the per-database principal key with the setter that matches the + # provider scope: file providers are database-scoped, vault/kmip are global. + if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + fi # If WAL encryption is requested, set the server key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then diff --git a/role_scripts/15/primary/start.sh b/role_scripts/15/primary/start.sh index a8d78d1..16e2de8 100755 --- a/role_scripts/15/primary/start.sh +++ b/role_scripts/15/primary/start.sh @@ -177,9 +177,15 @@ SQL ;; esac - # Set the per-database principal key. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + # Set the per-database principal key with the setter that matches the + # provider scope: file providers are database-scoped, vault/kmip are global. + if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + fi # If WAL encryption is requested, set the server key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then diff --git a/role_scripts/16/primary/start.sh b/role_scripts/16/primary/start.sh index aaa962f..33f8c63 100755 --- a/role_scripts/16/primary/start.sh +++ b/role_scripts/16/primary/start.sh @@ -175,9 +175,15 @@ SQL ;; esac - # Set the per-database principal key. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + # Set the per-database principal key with the setter that matches the + # provider scope: file providers are database-scoped, vault/kmip are global. + if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + fi # If WAL encryption is requested, set the server key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then diff --git a/role_scripts/17/primary/start.sh b/role_scripts/17/primary/start.sh index ddbb134..fef73e2 100755 --- a/role_scripts/17/primary/start.sh +++ b/role_scripts/17/primary/start.sh @@ -180,9 +180,15 @@ SQL ;; esac - # Set the per-database principal key. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + # Set the per-database principal key with the setter that matches the + # provider scope: file providers are database-scoped, vault/kmip are global. + if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + fi # If WAL encryption is requested, set the server key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then diff --git a/role_scripts/18/primary/start.sh b/role_scripts/18/primary/start.sh index 3b4c905..8a25269 100755 --- a/role_scripts/18/primary/start.sh +++ b/role_scripts/18/primary/start.sh @@ -173,9 +173,15 @@ SQL ;; esac - # Set the per-database principal key. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + # Set the per-database principal key with the setter that matches the + # provider scope: file providers are database-scoped, vault/kmip are global. + if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + fi # If WAL encryption is requested, set the server key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then diff --git a/role_scripts/9/primary/start.sh b/role_scripts/9/primary/start.sh index 6141afc..202e517 100755 --- a/role_scripts/9/primary/start.sh +++ b/role_scripts/9/primary/start.sh @@ -115,9 +115,15 @@ SQL ;; esac - # Set the per-database principal key. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + # Set the per-database principal key with the setter that matches the + # provider scope: file providers are database-scoped, vault/kmip are global. + if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + fi # If WAL encryption is requested, set the server key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then From a26b8a832422896cf78e0fff9b483da67f47f107 Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Wed, 15 Jul 2026 15:29:53 +0600 Subject: [PATCH 03/11] pg_tde: create principal key before setting it in bootstrap pg_tde 2.2.1 split key creation from activation: pg_tde_set_key_* errors with 'key does not exist' unless pg_tde_create_key_* was called first. The bootstrap previously called only the set function guarded by || true, which silently swallowed the missing-key error and left the principal key unset. Create the key first, use the database-scoped setter for file providers and the global setter otherwise, and fail loudly if the set does not succeed. Signed-off-by: Tamal Saha --- role_scripts/10/primary/start.sh | 27 +++++++++++++++++++++------ role_scripts/11/primary/start.sh | 27 +++++++++++++++++++++------ role_scripts/12/primary/start.sh | 27 +++++++++++++++++++++------ role_scripts/13/primary/start.sh | 27 +++++++++++++++++++++------ role_scripts/14/primary/start.sh | 27 +++++++++++++++++++++------ role_scripts/15/primary/start.sh | 27 +++++++++++++++++++++------ role_scripts/16/primary/start.sh | 27 +++++++++++++++++++++------ role_scripts/17/primary/start.sh | 27 +++++++++++++++++++++------ role_scripts/18/primary/start.sh | 27 +++++++++++++++++++++------ role_scripts/9/primary/start.sh | 27 +++++++++++++++++++++------ 10 files changed, 210 insertions(+), 60 deletions(-) diff --git a/role_scripts/10/primary/start.sh b/role_scripts/10/primary/start.sh index 24c4058..d636259 100755 --- a/role_scripts/10/primary/start.sh +++ b/role_scripts/10/primary/start.sh @@ -120,20 +120,35 @@ SQL ;; esac - # Set the per-database principal key with the setter that matches the - # provider scope: file providers are database-scoped, vault/kmip are global. + # Create then set the per-database principal key. pg_tde requires the key to + # exist before it can be set as principal, so create precedes set. The setter + # matches the provider scope (file is database-scoped, vault/kmip are global). + # Key setup is strict: a failure fails the bootstrap loudly rather than booting + # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } fi - # If WAL encryption is requested, set the server key too (global only). + # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } fi fi diff --git a/role_scripts/11/primary/start.sh b/role_scripts/11/primary/start.sh index 7db7e27..e72eaef 100755 --- a/role_scripts/11/primary/start.sh +++ b/role_scripts/11/primary/start.sh @@ -129,20 +129,35 @@ SQL ;; esac - # Set the per-database principal key with the setter that matches the - # provider scope: file providers are database-scoped, vault/kmip are global. + # Create then set the per-database principal key. pg_tde requires the key to + # exist before it can be set as principal, so create precedes set. The setter + # matches the provider scope (file is database-scoped, vault/kmip are global). + # Key setup is strict: a failure fails the bootstrap loudly rather than booting + # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } fi - # If WAL encryption is requested, set the server key too (global only). + # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } fi fi diff --git a/role_scripts/12/primary/start.sh b/role_scripts/12/primary/start.sh index dce0b23..e752c26 100755 --- a/role_scripts/12/primary/start.sh +++ b/role_scripts/12/primary/start.sh @@ -149,20 +149,35 @@ SQL ;; esac - # Set the per-database principal key with the setter that matches the - # provider scope: file providers are database-scoped, vault/kmip are global. + # Create then set the per-database principal key. pg_tde requires the key to + # exist before it can be set as principal, so create precedes set. The setter + # matches the provider scope (file is database-scoped, vault/kmip are global). + # Key setup is strict: a failure fails the bootstrap loudly rather than booting + # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } fi - # If WAL encryption is requested, set the server key too (global only). + # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } fi fi diff --git a/role_scripts/13/primary/start.sh b/role_scripts/13/primary/start.sh index 553217d..90a3933 100755 --- a/role_scripts/13/primary/start.sh +++ b/role_scripts/13/primary/start.sh @@ -170,20 +170,35 @@ SQL ;; esac - # Set the per-database principal key with the setter that matches the - # provider scope: file providers are database-scoped, vault/kmip are global. + # Create then set the per-database principal key. pg_tde requires the key to + # exist before it can be set as principal, so create precedes set. The setter + # matches the provider scope (file is database-scoped, vault/kmip are global). + # Key setup is strict: a failure fails the bootstrap loudly rather than booting + # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } fi - # If WAL encryption is requested, set the server key too (global only). + # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } fi fi diff --git a/role_scripts/14/primary/start.sh b/role_scripts/14/primary/start.sh index ffe1be7..f71749f 100755 --- a/role_scripts/14/primary/start.sh +++ b/role_scripts/14/primary/start.sh @@ -174,20 +174,35 @@ SQL ;; esac - # Set the per-database principal key with the setter that matches the - # provider scope: file providers are database-scoped, vault/kmip are global. + # Create then set the per-database principal key. pg_tde requires the key to + # exist before it can be set as principal, so create precedes set. The setter + # matches the provider scope (file is database-scoped, vault/kmip are global). + # Key setup is strict: a failure fails the bootstrap loudly rather than booting + # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } fi - # If WAL encryption is requested, set the server key too (global only). + # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } fi fi diff --git a/role_scripts/15/primary/start.sh b/role_scripts/15/primary/start.sh index 16e2de8..e9f6eea 100755 --- a/role_scripts/15/primary/start.sh +++ b/role_scripts/15/primary/start.sh @@ -177,20 +177,35 @@ SQL ;; esac - # Set the per-database principal key with the setter that matches the - # provider scope: file providers are database-scoped, vault/kmip are global. + # Create then set the per-database principal key. pg_tde requires the key to + # exist before it can be set as principal, so create precedes set. The setter + # matches the provider scope (file is database-scoped, vault/kmip are global). + # Key setup is strict: a failure fails the bootstrap loudly rather than booting + # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } fi - # If WAL encryption is requested, set the server key too (global only). + # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } fi fi diff --git a/role_scripts/16/primary/start.sh b/role_scripts/16/primary/start.sh index 33f8c63..a44e8ca 100755 --- a/role_scripts/16/primary/start.sh +++ b/role_scripts/16/primary/start.sh @@ -175,20 +175,35 @@ SQL ;; esac - # Set the per-database principal key with the setter that matches the - # provider scope: file providers are database-scoped, vault/kmip are global. + # Create then set the per-database principal key. pg_tde requires the key to + # exist before it can be set as principal, so create precedes set. The setter + # matches the provider scope (file is database-scoped, vault/kmip are global). + # Key setup is strict: a failure fails the bootstrap loudly rather than booting + # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } fi - # If WAL encryption is requested, set the server key too (global only). + # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } fi fi diff --git a/role_scripts/17/primary/start.sh b/role_scripts/17/primary/start.sh index fef73e2..81ffd23 100755 --- a/role_scripts/17/primary/start.sh +++ b/role_scripts/17/primary/start.sh @@ -180,20 +180,35 @@ SQL ;; esac - # Set the per-database principal key with the setter that matches the - # provider scope: file providers are database-scoped, vault/kmip are global. + # Create then set the per-database principal key. pg_tde requires the key to + # exist before it can be set as principal, so create precedes set. The setter + # matches the provider scope (file is database-scoped, vault/kmip are global). + # Key setup is strict: a failure fails the bootstrap loudly rather than booting + # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } fi - # If WAL encryption is requested, set the server key too (global only). + # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } fi fi diff --git a/role_scripts/18/primary/start.sh b/role_scripts/18/primary/start.sh index 8a25269..728f668 100755 --- a/role_scripts/18/primary/start.sh +++ b/role_scripts/18/primary/start.sh @@ -173,20 +173,35 @@ SQL ;; esac - # Set the per-database principal key with the setter that matches the - # provider scope: file providers are database-scoped, vault/kmip are global. + # Create then set the per-database principal key. pg_tde requires the key to + # exist before it can be set as principal, so create precedes set. The setter + # matches the provider scope (file is database-scoped, vault/kmip are global). + # Key setup is strict: a failure fails the bootstrap loudly rather than booting + # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } fi - # If WAL encryption is requested, set the server key too (global only). + # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } fi fi diff --git a/role_scripts/9/primary/start.sh b/role_scripts/9/primary/start.sh index 202e517..60e19b7 100755 --- a/role_scripts/9/primary/start.sh +++ b/role_scripts/9/primary/start.sh @@ -115,20 +115,35 @@ SQL ;; esac - # Set the per-database principal key with the setter that matches the - # provider scope: file providers are database-scoped, vault/kmip are global. + # Create then set the per-database principal key. pg_tde requires the key to + # exist before it can be set as principal, so create precedes set. The setter + # matches the provider scope (file is database-scoped, vault/kmip are global). + # Key setup is strict: a failure fails the bootstrap loudly rather than booting + # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } fi - # If WAL encryption is requested, set the server key too (global only). + # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" || true + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ + || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } fi fi From 31ce18e152e7e4e653e955993568648688210a03 Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Wed, 15 Jul 2026 15:51:01 +0600 Subject: [PATCH 04/11] pg_tde: log which basebackup binary seeds the standby (debug visibility) Make the pg_tde_basebackup vs pg_basebackup selection visible in standby logs so a wrong-binary seed (which silently corrupts an encrypted cluster) is greppable, per the TDE debug-logging requirement. Signed-off-by: Tamal Saha --- role_scripts/10/standby/ha_backup_job.sh | 1 + role_scripts/10/standby/run.sh | 1 + role_scripts/11/standby/ha_backup_job.sh | 1 + role_scripts/11/standby/run.sh | 1 + role_scripts/12/standby/ha_backup_job.sh | 1 + role_scripts/12/standby/run.sh | 1 + role_scripts/13/standby/ha_backup_job.sh | 1 + role_scripts/13/standby/remote-replica.sh | 1 + role_scripts/13/standby/run.sh | 1 + role_scripts/14/standby/ha_backup_job.sh | 1 + role_scripts/14/standby/remote-replica.sh | 1 + role_scripts/14/standby/run.sh | 1 + role_scripts/15/standby/ha_backup_job.sh | 1 + role_scripts/15/standby/remote-replica.sh | 1 + role_scripts/15/standby/run.sh | 1 + role_scripts/16/standby/ha_backup_job.sh | 1 + role_scripts/16/standby/remote-replica.sh | 1 + role_scripts/16/standby/run.sh | 1 + role_scripts/17/standby/ha_backup_job.sh | 1 + role_scripts/17/standby/remote-replica.sh | 1 + role_scripts/17/standby/run.sh | 1 + role_scripts/18/standby/ha_backup_job.sh | 1 + role_scripts/18/standby/remote-replica.sh | 1 + role_scripts/18/standby/run.sh | 1 + role_scripts/9/standby/ha_backup_job.sh | 1 + role_scripts/9/standby/run.sh | 1 + 26 files changed, 26 insertions(+) diff --git a/role_scripts/10/standby/ha_backup_job.sh b/role_scripts/10/standby/ha_backup_job.sh index 8c8f0cd..dd871c9 100755 --- a/role_scripts/10/standby/ha_backup_job.sh +++ b/role_scripts/10/standby/ha_backup_job.sh @@ -62,6 +62,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/10/standby/run.sh b/role_scripts/10/standby/run.sh index 53313d3..0643db0 100755 --- a/role_scripts/10/standby/run.sh +++ b/role_scripts/10/standby/run.sh @@ -119,6 +119,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/11/standby/ha_backup_job.sh b/role_scripts/11/standby/ha_backup_job.sh index 5eef524..2e1eef5 100755 --- a/role_scripts/11/standby/ha_backup_job.sh +++ b/role_scripts/11/standby/ha_backup_job.sh @@ -62,6 +62,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/11/standby/run.sh b/role_scripts/11/standby/run.sh index 264f253..85e6ad0 100755 --- a/role_scripts/11/standby/run.sh +++ b/role_scripts/11/standby/run.sh @@ -118,6 +118,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/12/standby/ha_backup_job.sh b/role_scripts/12/standby/ha_backup_job.sh index b7e81c9..720388b 100755 --- a/role_scripts/12/standby/ha_backup_job.sh +++ b/role_scripts/12/standby/ha_backup_job.sh @@ -61,6 +61,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/12/standby/run.sh b/role_scripts/12/standby/run.sh index 3d76fa0..5cf7b11 100755 --- a/role_scripts/12/standby/run.sh +++ b/role_scripts/12/standby/run.sh @@ -118,6 +118,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/13/standby/ha_backup_job.sh b/role_scripts/13/standby/ha_backup_job.sh index 1fb4501..e0326f0 100755 --- a/role_scripts/13/standby/ha_backup_job.sh +++ b/role_scripts/13/standby/ha_backup_job.sh @@ -61,6 +61,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/13/standby/remote-replica.sh b/role_scripts/13/standby/remote-replica.sh index 20ea5d0..60c9141 100755 --- a/role_scripts/13/standby/remote-replica.sh +++ b/role_scripts/13/standby/remote-replica.sh @@ -71,6 +71,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else diff --git a/role_scripts/13/standby/run.sh b/role_scripts/13/standby/run.sh index 6654ae1..4acb3a7 100755 --- a/role_scripts/13/standby/run.sh +++ b/role_scripts/13/standby/run.sh @@ -118,6 +118,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/14/standby/ha_backup_job.sh b/role_scripts/14/standby/ha_backup_job.sh index 8ed742d..d720031 100755 --- a/role_scripts/14/standby/ha_backup_job.sh +++ b/role_scripts/14/standby/ha_backup_job.sh @@ -61,6 +61,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/14/standby/remote-replica.sh b/role_scripts/14/standby/remote-replica.sh index cc911cf..1487746 100755 --- a/role_scripts/14/standby/remote-replica.sh +++ b/role_scripts/14/standby/remote-replica.sh @@ -71,6 +71,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else diff --git a/role_scripts/14/standby/run.sh b/role_scripts/14/standby/run.sh index 033aee1..216dc86 100755 --- a/role_scripts/14/standby/run.sh +++ b/role_scripts/14/standby/run.sh @@ -118,6 +118,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/15/standby/ha_backup_job.sh b/role_scripts/15/standby/ha_backup_job.sh index 25fc9d8..9137ff9 100755 --- a/role_scripts/15/standby/ha_backup_job.sh +++ b/role_scripts/15/standby/ha_backup_job.sh @@ -63,6 +63,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/15/standby/remote-replica.sh b/role_scripts/15/standby/remote-replica.sh index cc911cf..1487746 100755 --- a/role_scripts/15/standby/remote-replica.sh +++ b/role_scripts/15/standby/remote-replica.sh @@ -71,6 +71,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else diff --git a/role_scripts/15/standby/run.sh b/role_scripts/15/standby/run.sh index a007eb6..f011440 100755 --- a/role_scripts/15/standby/run.sh +++ b/role_scripts/15/standby/run.sh @@ -117,6 +117,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/16/standby/ha_backup_job.sh b/role_scripts/16/standby/ha_backup_job.sh index 11ac6b0..b0d4fc2 100755 --- a/role_scripts/16/standby/ha_backup_job.sh +++ b/role_scripts/16/standby/ha_backup_job.sh @@ -63,6 +63,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/16/standby/remote-replica.sh b/role_scripts/16/standby/remote-replica.sh index 6e6a1f0..fc5bfd9 100755 --- a/role_scripts/16/standby/remote-replica.sh +++ b/role_scripts/16/standby/remote-replica.sh @@ -71,6 +71,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else diff --git a/role_scripts/16/standby/run.sh b/role_scripts/16/standby/run.sh index 0dca3b2..415e1dc 100755 --- a/role_scripts/16/standby/run.sh +++ b/role_scripts/16/standby/run.sh @@ -118,6 +118,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/17/standby/ha_backup_job.sh b/role_scripts/17/standby/ha_backup_job.sh index 11ac6b0..b0d4fc2 100755 --- a/role_scripts/17/standby/ha_backup_job.sh +++ b/role_scripts/17/standby/ha_backup_job.sh @@ -63,6 +63,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/17/standby/remote-replica.sh b/role_scripts/17/standby/remote-replica.sh index 6e6a1f0..fc5bfd9 100755 --- a/role_scripts/17/standby/remote-replica.sh +++ b/role_scripts/17/standby/remote-replica.sh @@ -71,6 +71,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else diff --git a/role_scripts/17/standby/run.sh b/role_scripts/17/standby/run.sh index 0dca3b2..415e1dc 100755 --- a/role_scripts/17/standby/run.sh +++ b/role_scripts/17/standby/run.sh @@ -118,6 +118,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/18/standby/ha_backup_job.sh b/role_scripts/18/standby/ha_backup_job.sh index 11ac6b0..b0d4fc2 100755 --- a/role_scripts/18/standby/ha_backup_job.sh +++ b/role_scripts/18/standby/ha_backup_job.sh @@ -63,6 +63,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/18/standby/remote-replica.sh b/role_scripts/18/standby/remote-replica.sh index 6e6a1f0..fc5bfd9 100755 --- a/role_scripts/18/standby/remote-replica.sh +++ b/role_scripts/18/standby/remote-replica.sh @@ -71,6 +71,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SOURCE_SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=$PRIMARY_USER_NAME --progress --host="$PRIMARY_HOST" -d "sslmode=$SOURCE_SSL_MODE sslrootcert=/tls/certs/remote/ca.crt sslcert=/tls/certs/remote/client.crt sslkey=/tls/certs/remote/client.key" else diff --git a/role_scripts/18/standby/run.sh b/role_scripts/18/standby/run.sh index 0dca3b2..415e1dc 100755 --- a/role_scripts/18/standby/run.sh +++ b/role_scripts/18/standby/run.sh @@ -118,6 +118,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -Xs -c fast --pgdata "$PGDATA" --max-rate=1024M --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/9/standby/ha_backup_job.sh b/role_scripts/9/standby/ha_backup_job.sh index 5479492..462006f 100755 --- a/role_scripts/9/standby/ha_backup_job.sh +++ b/role_scripts/9/standby/ha_backup_job.sh @@ -62,6 +62,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else diff --git a/role_scripts/9/standby/run.sh b/role_scripts/9/standby/run.sh index d4f8e35..31e0de7 100755 --- a/role_scripts/9/standby/run.sh +++ b/role_scripts/9/standby/run.sh @@ -121,6 +121,7 @@ if [[ ! -e "$PGDATA/PG_VERSION" ]]; then chmod 0700 "$PGDATA" BASEBACKUP=pg_basebackup [[ "${TDE_ENABLED:-false}" == "true" ]] && BASEBACKUP=pg_tde_basebackup + echo "pg_tde: seeding standby with '$BASEBACKUP' (TDE_ENABLED=${TDE_ENABLED:-false})" if [[ "${SSL:-0}" == "ON" ]]; then "$BASEBACKUP" -X fetch --pgdata "$PGDATA" --username=postgres --progress --host="$PRIMARY_HOST" -d "sslmode=$SSL_MODE sslrootcert=/tls/certs/client/ca.crt sslcert=/tls/certs/client/client.crt sslkey=/tls/certs/client/client.key" else From c7853709553792706650f3c590ac2471c383ecc8 Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Wed, 15 Jul 2026 15:56:33 +0600 Subject: [PATCH 05/11] pg_tde: create principal key at the configured cipher length The bootstrap creates the principal key before the post-bootstrap config (which carries pg_tde.cipher) is loaded, so with cipher aes_256 the key was created at the default 16-byte aes_128 length and pg_tde warned that the key length did not match the cipher. Pass PGOPTIONS='-c pg_tde.cipher=' on the create calls so the key is generated at the right length. Day-2 ops (RotatePrincipalKey) are unaffected: they run against the live server whose session default already carries the configured cipher. Signed-off-by: Tamal Saha --- role_scripts/10/primary/start.sh | 6 +++--- role_scripts/11/primary/start.sh | 6 +++--- role_scripts/12/primary/start.sh | 6 +++--- role_scripts/13/primary/start.sh | 6 +++--- role_scripts/14/primary/start.sh | 6 +++--- role_scripts/15/primary/start.sh | 6 +++--- role_scripts/16/primary/start.sh | 6 +++--- role_scripts/17/primary/start.sh | 6 +++--- role_scripts/18/primary/start.sh | 6 +++--- role_scripts/9/primary/start.sh | 6 +++--- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/role_scripts/10/primary/start.sh b/role_scripts/10/primary/start.sh index d636259..3127301 100755 --- a/role_scripts/10/primary/start.sh +++ b/role_scripts/10/primary/start.sh @@ -126,14 +126,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -143,7 +143,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/11/primary/start.sh b/role_scripts/11/primary/start.sh index e72eaef..b66b8c8 100755 --- a/role_scripts/11/primary/start.sh +++ b/role_scripts/11/primary/start.sh @@ -135,14 +135,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -152,7 +152,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/12/primary/start.sh b/role_scripts/12/primary/start.sh index e752c26..d644149 100755 --- a/role_scripts/12/primary/start.sh +++ b/role_scripts/12/primary/start.sh @@ -155,14 +155,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -172,7 +172,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/13/primary/start.sh b/role_scripts/13/primary/start.sh index 90a3933..a3490ec 100755 --- a/role_scripts/13/primary/start.sh +++ b/role_scripts/13/primary/start.sh @@ -176,14 +176,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -193,7 +193,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/14/primary/start.sh b/role_scripts/14/primary/start.sh index f71749f..c9c137c 100755 --- a/role_scripts/14/primary/start.sh +++ b/role_scripts/14/primary/start.sh @@ -180,14 +180,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -197,7 +197,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/15/primary/start.sh b/role_scripts/15/primary/start.sh index e9f6eea..094cfe8 100755 --- a/role_scripts/15/primary/start.sh +++ b/role_scripts/15/primary/start.sh @@ -183,14 +183,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -200,7 +200,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/16/primary/start.sh b/role_scripts/16/primary/start.sh index a44e8ca..e3ae93c 100755 --- a/role_scripts/16/primary/start.sh +++ b/role_scripts/16/primary/start.sh @@ -181,14 +181,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -198,7 +198,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/17/primary/start.sh b/role_scripts/17/primary/start.sh index 81ffd23..fdf9adb 100755 --- a/role_scripts/17/primary/start.sh +++ b/role_scripts/17/primary/start.sh @@ -186,14 +186,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -203,7 +203,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/18/primary/start.sh b/role_scripts/18/primary/start.sh index 728f668..d171d1f 100755 --- a/role_scripts/18/primary/start.sh +++ b/role_scripts/18/primary/start.sh @@ -179,14 +179,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -196,7 +196,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/9/primary/start.sh b/role_scripts/9/primary/start.sh index 60e19b7..d73f449 100755 --- a/role_scripts/9/primary/start.sh +++ b/role_scripts/9/primary/start.sh @@ -121,14 +121,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -138,7 +138,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ From 5eddc73277488723ed72017119aa923993ac57d9 Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Wed, 15 Jul 2026 15:59:04 +0600 Subject: [PATCH 06/11] pg_tde: export PGOPTIONS cipher for the whole bootstrap key block Scope the configured cipher to every pg_tde key call in the bootstrap (create and set, principal and WAL) via a single exported PGOPTIONS, so both key creation and activation run at the configured length. Setting it only on create left the separate set_key session at the default cipher, which warned that the 32-byte aes_256 key mismatched the session's cipher. Unset it after the block so later connections keep the server default. Signed-off-by: Tamal Saha --- role_scripts/10/primary/start.sh | 12 +++++++++--- role_scripts/11/primary/start.sh | 12 +++++++++--- role_scripts/12/primary/start.sh | 12 +++++++++--- role_scripts/13/primary/start.sh | 12 +++++++++--- role_scripts/14/primary/start.sh | 12 +++++++++--- role_scripts/15/primary/start.sh | 12 +++++++++--- role_scripts/16/primary/start.sh | 12 +++++++++--- role_scripts/17/primary/start.sh | 12 +++++++++--- role_scripts/18/primary/start.sh | 12 +++++++++--- role_scripts/9/primary/start.sh | 12 +++++++++--- 10 files changed, 90 insertions(+), 30 deletions(-) diff --git a/role_scripts/10/primary/start.sh b/role_scripts/10/primary/start.sh index 3127301..d3df50d 100755 --- a/role_scripts/10/primary/start.sh +++ b/role_scripts/10/primary/start.sh @@ -96,6 +96,10 @@ echo # database and superuser exist and before any encrypted table or the # default_table_access_method flip can be used. Idempotent on retries. if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Run every pg_tde key operation in this block at the configured cipher. The + # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without + # this the principal key would be created (and validated) at the wrong length. + export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -126,14 +130,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -143,7 +147,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -152,6 +156,8 @@ SQL fi fi +unset PGOPTIONS + if [[ "$BOOTSTRAP" == "true" ]];then # initialize database for f in "$INITDB"/*; do diff --git a/role_scripts/11/primary/start.sh b/role_scripts/11/primary/start.sh index b66b8c8..e43ee0c 100755 --- a/role_scripts/11/primary/start.sh +++ b/role_scripts/11/primary/start.sh @@ -105,6 +105,10 @@ echo # database and superuser exist and before any encrypted table or the # default_table_access_method flip can be used. Idempotent on retries. if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Run every pg_tde key operation in this block at the configured cipher. The + # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without + # this the principal key would be created (and validated) at the wrong length. + export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -135,14 +139,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -152,7 +156,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -161,6 +165,8 @@ SQL fi fi +unset PGOPTIONS + if [[ "$BOOTSTRAP" == "true" ]];then # initialize database for f in "$INITDB"/*; do diff --git a/role_scripts/12/primary/start.sh b/role_scripts/12/primary/start.sh index d644149..2d894ac 100755 --- a/role_scripts/12/primary/start.sh +++ b/role_scripts/12/primary/start.sh @@ -125,6 +125,10 @@ echo # database and superuser exist and before any encrypted table or the # default_table_access_method flip can be used. Idempotent on retries. if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Run every pg_tde key operation in this block at the configured cipher. The + # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without + # this the principal key would be created (and validated) at the wrong length. + export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -155,14 +159,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -172,7 +176,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -181,6 +185,8 @@ SQL fi fi +unset PGOPTIONS + if [[ "$BOOTSTRAP" == "true" ]];then # initialize database for f in "$INITDB"/*; do diff --git a/role_scripts/13/primary/start.sh b/role_scripts/13/primary/start.sh index a3490ec..271b764 100755 --- a/role_scripts/13/primary/start.sh +++ b/role_scripts/13/primary/start.sh @@ -146,6 +146,10 @@ echo # database and superuser exist and before any encrypted table or the # default_table_access_method flip can be used. Idempotent on retries. if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Run every pg_tde key operation in this block at the configured cipher. The + # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without + # this the principal key would be created (and validated) at the wrong length. + export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -176,14 +180,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -193,7 +197,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -202,6 +206,8 @@ SQL fi fi +unset PGOPTIONS + if [[ "$BOOTSTRAP" == "true" ]];then # initialize database for f in "$INITDB"/*; do diff --git a/role_scripts/14/primary/start.sh b/role_scripts/14/primary/start.sh index c9c137c..e718433 100755 --- a/role_scripts/14/primary/start.sh +++ b/role_scripts/14/primary/start.sh @@ -150,6 +150,10 @@ echo # database and superuser exist and before any encrypted table or the # default_table_access_method flip can be used. Idempotent on retries. if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Run every pg_tde key operation in this block at the configured cipher. The + # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without + # this the principal key would be created (and validated) at the wrong length. + export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -180,14 +184,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -197,7 +201,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -206,6 +210,8 @@ SQL fi fi +unset PGOPTIONS + if [[ "$BOOTSTRAP" == "true" ]];then # initialize database for f in "$INITDB"/*; do diff --git a/role_scripts/15/primary/start.sh b/role_scripts/15/primary/start.sh index 094cfe8..7708c26 100755 --- a/role_scripts/15/primary/start.sh +++ b/role_scripts/15/primary/start.sh @@ -153,6 +153,10 @@ echo # database and superuser exist and before any encrypted table or the # default_table_access_method flip can be used. Idempotent on retries. if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Run every pg_tde key operation in this block at the configured cipher. The + # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without + # this the principal key would be created (and validated) at the wrong length. + export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -183,14 +187,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -200,7 +204,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -209,6 +213,8 @@ SQL fi fi +unset PGOPTIONS + if [[ "$BOOTSTRAP" == "true" ]];then # initialize database for f in "$INITDB"/*; do diff --git a/role_scripts/16/primary/start.sh b/role_scripts/16/primary/start.sh index e3ae93c..a2c707d 100755 --- a/role_scripts/16/primary/start.sh +++ b/role_scripts/16/primary/start.sh @@ -151,6 +151,10 @@ echo # database and superuser exist and before any encrypted table or the # default_table_access_method flip can be used. Idempotent on retries. if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Run every pg_tde key operation in this block at the configured cipher. The + # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without + # this the principal key would be created (and validated) at the wrong length. + export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -181,14 +185,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -198,7 +202,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -207,6 +211,8 @@ SQL fi fi +unset PGOPTIONS + if [[ "$BOOTSTRAP" == "true" ]];then # initialize database for f in "$INITDB"/*; do diff --git a/role_scripts/17/primary/start.sh b/role_scripts/17/primary/start.sh index fdf9adb..5a7e308 100755 --- a/role_scripts/17/primary/start.sh +++ b/role_scripts/17/primary/start.sh @@ -156,6 +156,10 @@ echo # database and superuser exist and before any encrypted table or the # default_table_access_method flip can be used. Idempotent on retries. if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Run every pg_tde key operation in this block at the configured cipher. The + # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without + # this the principal key would be created (and validated) at the wrong length. + export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -186,14 +190,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -203,7 +207,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -212,6 +216,8 @@ SQL fi fi +unset PGOPTIONS + if [[ "$BOOTSTRAP" == "true" ]];then # initialize database for f in "$INITDB"/*; do diff --git a/role_scripts/18/primary/start.sh b/role_scripts/18/primary/start.sh index d171d1f..bd425aa 100755 --- a/role_scripts/18/primary/start.sh +++ b/role_scripts/18/primary/start.sh @@ -149,6 +149,10 @@ echo # database and superuser exist and before any encrypted table or the # default_table_access_method flip can be used. Idempotent on retries. if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Run every pg_tde key operation in this block at the configured cipher. The + # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without + # this the principal key would be created (and validated) at the wrong length. + export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -179,14 +183,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -196,7 +200,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -205,6 +209,8 @@ SQL fi fi +unset PGOPTIONS + if [[ "$BOOTSTRAP" == "true" ]];then # initialize database for f in "$INITDB"/*; do diff --git a/role_scripts/9/primary/start.sh b/role_scripts/9/primary/start.sh index d73f449..e168dbb 100755 --- a/role_scripts/9/primary/start.sh +++ b/role_scripts/9/primary/start.sh @@ -91,6 +91,10 @@ echo # database and superuser exist and before any encrypted table or the # default_table_access_method flip can be used. Idempotent on retries. if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then + # Run every pg_tde key operation in this block at the configured cipher. The + # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without + # this the principal key would be created (and validated) at the wrong length. + export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -121,14 +125,14 @@ SQL # Key setup is strict: a failure fails the bootstrap loudly rather than booting # with no principal key, which would silently break encrypted-table creation. if [[ "${TDE_PROVIDER_KIND:-}" == "file" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } else - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -138,7 +142,7 @@ SQL # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then - PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ @@ -147,6 +151,8 @@ SQL fi fi +unset PGOPTIONS + if [[ "$BOOTSTRAP" == "true" ]];then # initialize database for f in "$INITDB"/*; do From 44a8c7cabff81e9a14a993423038d75d0829cbbd Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Wed, 15 Jul 2026 18:01:42 +0600 Subject: [PATCH 07/11] pg_tde: crash-loop instead of keyless boot when bootstrap key setup fails When the principal/WAL key could not be set during first-time init (e.g. an unreachable or unauthorized key provider), the bootstrap exited non-zero but the init loop simply retried with BOOTSTRAP=false, skipped the TDE block, and booted a database with no principal key: a silent, broken-encryption boot. Since this path runs only during initial init (no user data), wipe the half-initialized data dir on failure so the pod re-runs a full bootstrap and crash-loops visibly until the key provider is reachable, rather than silently disabling TDE. Signed-off-by: Tamal Saha --- role_scripts/10/primary/start.sh | 18 +++++++++++++++--- role_scripts/11/primary/start.sh | 18 +++++++++++++++--- role_scripts/12/primary/start.sh | 18 +++++++++++++++--- role_scripts/13/primary/start.sh | 18 +++++++++++++++--- role_scripts/14/primary/start.sh | 18 +++++++++++++++--- role_scripts/15/primary/start.sh | 18 +++++++++++++++--- role_scripts/16/primary/start.sh | 18 +++++++++++++++--- role_scripts/17/primary/start.sh | 18 +++++++++++++++--- role_scripts/18/primary/start.sh | 18 +++++++++++++++--- role_scripts/9/primary/start.sh | 18 +++++++++++++++--- 10 files changed, 150 insertions(+), 30 deletions(-) diff --git a/role_scripts/10/primary/start.sh b/role_scripts/10/primary/start.sh index d3df50d..b805b96 100755 --- a/role_scripts/10/primary/start.sh +++ b/role_scripts/10/primary/start.sh @@ -100,6 +100,18 @@ if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without # this the principal key would be created (and validated) at the wrong length. export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" + # tde_bootstrap_fatal aborts a failed first-time TDE bootstrap loudly. This runs + # only during initial initialization (BOOTSTRAP=true), so there is no user data + # yet; wipe the half-initialized data dir and exit non-zero. That forces a full + # re-bootstrap on the next start instead of falling through to a keyless boot + # (which would silently disable encryption). The pod crash-loops visibly until + # the key provider is reachable. + tde_bootstrap_fatal() { + echo "pg_tde FATAL: $1" + pg_ctl -D "$PGDATA" -m immediate -w stop || true + rm -rf "${PGDATA:?}"/* || true + exit 1 + } # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -135,14 +147,14 @@ SQL || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set database principal key '${TDE_KEY_NAME}'" else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). @@ -152,7 +164,7 @@ SQL || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } + || tde_bootstrap_fatal "failed to set WAL server key '${TDE_KEY_NAME}-wal'" fi fi diff --git a/role_scripts/11/primary/start.sh b/role_scripts/11/primary/start.sh index e43ee0c..b397cc1 100755 --- a/role_scripts/11/primary/start.sh +++ b/role_scripts/11/primary/start.sh @@ -109,6 +109,18 @@ if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without # this the principal key would be created (and validated) at the wrong length. export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" + # tde_bootstrap_fatal aborts a failed first-time TDE bootstrap loudly. This runs + # only during initial initialization (BOOTSTRAP=true), so there is no user data + # yet; wipe the half-initialized data dir and exit non-zero. That forces a full + # re-bootstrap on the next start instead of falling through to a keyless boot + # (which would silently disable encryption). The pod crash-loops visibly until + # the key provider is reachable. + tde_bootstrap_fatal() { + echo "pg_tde FATAL: $1" + pg_ctl -D "$PGDATA" -m immediate -w stop || true + rm -rf "${PGDATA:?}"/* || true + exit 1 + } # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -144,14 +156,14 @@ SQL || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set database principal key '${TDE_KEY_NAME}'" else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). @@ -161,7 +173,7 @@ SQL || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } + || tde_bootstrap_fatal "failed to set WAL server key '${TDE_KEY_NAME}-wal'" fi fi diff --git a/role_scripts/12/primary/start.sh b/role_scripts/12/primary/start.sh index 2d894ac..746d9da 100755 --- a/role_scripts/12/primary/start.sh +++ b/role_scripts/12/primary/start.sh @@ -129,6 +129,18 @@ if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without # this the principal key would be created (and validated) at the wrong length. export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" + # tde_bootstrap_fatal aborts a failed first-time TDE bootstrap loudly. This runs + # only during initial initialization (BOOTSTRAP=true), so there is no user data + # yet; wipe the half-initialized data dir and exit non-zero. That forces a full + # re-bootstrap on the next start instead of falling through to a keyless boot + # (which would silently disable encryption). The pod crash-loops visibly until + # the key provider is reachable. + tde_bootstrap_fatal() { + echo "pg_tde FATAL: $1" + pg_ctl -D "$PGDATA" -m immediate -w stop || true + rm -rf "${PGDATA:?}"/* || true + exit 1 + } # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -164,14 +176,14 @@ SQL || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set database principal key '${TDE_KEY_NAME}'" else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). @@ -181,7 +193,7 @@ SQL || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } + || tde_bootstrap_fatal "failed to set WAL server key '${TDE_KEY_NAME}-wal'" fi fi diff --git a/role_scripts/13/primary/start.sh b/role_scripts/13/primary/start.sh index 271b764..4df0ea1 100755 --- a/role_scripts/13/primary/start.sh +++ b/role_scripts/13/primary/start.sh @@ -150,6 +150,18 @@ if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without # this the principal key would be created (and validated) at the wrong length. export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" + # tde_bootstrap_fatal aborts a failed first-time TDE bootstrap loudly. This runs + # only during initial initialization (BOOTSTRAP=true), so there is no user data + # yet; wipe the half-initialized data dir and exit non-zero. That forces a full + # re-bootstrap on the next start instead of falling through to a keyless boot + # (which would silently disable encryption). The pod crash-loops visibly until + # the key provider is reachable. + tde_bootstrap_fatal() { + echo "pg_tde FATAL: $1" + pg_ctl -D "$PGDATA" -m immediate -w stop || true + rm -rf "${PGDATA:?}"/* || true + exit 1 + } # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -185,14 +197,14 @@ SQL || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set database principal key '${TDE_KEY_NAME}'" else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). @@ -202,7 +214,7 @@ SQL || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } + || tde_bootstrap_fatal "failed to set WAL server key '${TDE_KEY_NAME}-wal'" fi fi diff --git a/role_scripts/14/primary/start.sh b/role_scripts/14/primary/start.sh index e718433..7814ce1 100755 --- a/role_scripts/14/primary/start.sh +++ b/role_scripts/14/primary/start.sh @@ -154,6 +154,18 @@ if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without # this the principal key would be created (and validated) at the wrong length. export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" + # tde_bootstrap_fatal aborts a failed first-time TDE bootstrap loudly. This runs + # only during initial initialization (BOOTSTRAP=true), so there is no user data + # yet; wipe the half-initialized data dir and exit non-zero. That forces a full + # re-bootstrap on the next start instead of falling through to a keyless boot + # (which would silently disable encryption). The pod crash-loops visibly until + # the key provider is reachable. + tde_bootstrap_fatal() { + echo "pg_tde FATAL: $1" + pg_ctl -D "$PGDATA" -m immediate -w stop || true + rm -rf "${PGDATA:?}"/* || true + exit 1 + } # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -189,14 +201,14 @@ SQL || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set database principal key '${TDE_KEY_NAME}'" else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). @@ -206,7 +218,7 @@ SQL || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } + || tde_bootstrap_fatal "failed to set WAL server key '${TDE_KEY_NAME}-wal'" fi fi diff --git a/role_scripts/15/primary/start.sh b/role_scripts/15/primary/start.sh index 7708c26..4adb634 100755 --- a/role_scripts/15/primary/start.sh +++ b/role_scripts/15/primary/start.sh @@ -157,6 +157,18 @@ if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without # this the principal key would be created (and validated) at the wrong length. export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" + # tde_bootstrap_fatal aborts a failed first-time TDE bootstrap loudly. This runs + # only during initial initialization (BOOTSTRAP=true), so there is no user data + # yet; wipe the half-initialized data dir and exit non-zero. That forces a full + # re-bootstrap on the next start instead of falling through to a keyless boot + # (which would silently disable encryption). The pod crash-loops visibly until + # the key provider is reachable. + tde_bootstrap_fatal() { + echo "pg_tde FATAL: $1" + pg_ctl -D "$PGDATA" -m immediate -w stop || true + rm -rf "${PGDATA:?}"/* || true + exit 1 + } # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -192,14 +204,14 @@ SQL || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set database principal key '${TDE_KEY_NAME}'" else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). @@ -209,7 +221,7 @@ SQL || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } + || tde_bootstrap_fatal "failed to set WAL server key '${TDE_KEY_NAME}-wal'" fi fi diff --git a/role_scripts/16/primary/start.sh b/role_scripts/16/primary/start.sh index a2c707d..003dc31 100755 --- a/role_scripts/16/primary/start.sh +++ b/role_scripts/16/primary/start.sh @@ -155,6 +155,18 @@ if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without # this the principal key would be created (and validated) at the wrong length. export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" + # tde_bootstrap_fatal aborts a failed first-time TDE bootstrap loudly. This runs + # only during initial initialization (BOOTSTRAP=true), so there is no user data + # yet; wipe the half-initialized data dir and exit non-zero. That forces a full + # re-bootstrap on the next start instead of falling through to a keyless boot + # (which would silently disable encryption). The pod crash-loops visibly until + # the key provider is reachable. + tde_bootstrap_fatal() { + echo "pg_tde FATAL: $1" + pg_ctl -D "$PGDATA" -m immediate -w stop || true + rm -rf "${PGDATA:?}"/* || true + exit 1 + } # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -190,14 +202,14 @@ SQL || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set database principal key '${TDE_KEY_NAME}'" else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). @@ -207,7 +219,7 @@ SQL || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } + || tde_bootstrap_fatal "failed to set WAL server key '${TDE_KEY_NAME}-wal'" fi fi diff --git a/role_scripts/17/primary/start.sh b/role_scripts/17/primary/start.sh index 5a7e308..26f1c9e 100755 --- a/role_scripts/17/primary/start.sh +++ b/role_scripts/17/primary/start.sh @@ -160,6 +160,18 @@ if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without # this the principal key would be created (and validated) at the wrong length. export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" + # tde_bootstrap_fatal aborts a failed first-time TDE bootstrap loudly. This runs + # only during initial initialization (BOOTSTRAP=true), so there is no user data + # yet; wipe the half-initialized data dir and exit non-zero. That forces a full + # re-bootstrap on the next start instead of falling through to a keyless boot + # (which would silently disable encryption). The pod crash-loops visibly until + # the key provider is reachable. + tde_bootstrap_fatal() { + echo "pg_tde FATAL: $1" + pg_ctl -D "$PGDATA" -m immediate -w stop || true + rm -rf "${PGDATA:?}"/* || true + exit 1 + } # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -195,14 +207,14 @@ SQL || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set database principal key '${TDE_KEY_NAME}'" else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). @@ -212,7 +224,7 @@ SQL || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } + || tde_bootstrap_fatal "failed to set WAL server key '${TDE_KEY_NAME}-wal'" fi fi diff --git a/role_scripts/18/primary/start.sh b/role_scripts/18/primary/start.sh index bd425aa..9cc5ae0 100755 --- a/role_scripts/18/primary/start.sh +++ b/role_scripts/18/primary/start.sh @@ -153,6 +153,18 @@ if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without # this the principal key would be created (and validated) at the wrong length. export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" + # tde_bootstrap_fatal aborts a failed first-time TDE bootstrap loudly. This runs + # only during initial initialization (BOOTSTRAP=true), so there is no user data + # yet; wipe the half-initialized data dir and exit non-zero. That forces a full + # re-bootstrap on the next start instead of falling through to a keyless boot + # (which would silently disable encryption). The pod crash-loops visibly until + # the key provider is reachable. + tde_bootstrap_fatal() { + echo "pg_tde FATAL: $1" + pg_ctl -D "$PGDATA" -m immediate -w stop || true + rm -rf "${PGDATA:?}"/* || true + exit 1 + } # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -188,14 +200,14 @@ SQL || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set database principal key '${TDE_KEY_NAME}'" else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). @@ -205,7 +217,7 @@ SQL || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } + || tde_bootstrap_fatal "failed to set WAL server key '${TDE_KEY_NAME}-wal'" fi fi diff --git a/role_scripts/9/primary/start.sh b/role_scripts/9/primary/start.sh index e168dbb..7909c12 100755 --- a/role_scripts/9/primary/start.sh +++ b/role_scripts/9/primary/start.sh @@ -95,6 +95,18 @@ if [[ "${TDE_ENABLED:-false}" == "true" && "${BOOTSTRAP}" == "true" ]]; then # post-bootstrap config that carries pg_tde.cipher is not loaded yet, so without # this the principal key would be created (and validated) at the wrong length. export PGOPTIONS="-c pg_tde.cipher=${TDE_CIPHER:-aes_128}" + # tde_bootstrap_fatal aborts a failed first-time TDE bootstrap loudly. This runs + # only during initial initialization (BOOTSTRAP=true), so there is no user data + # yet; wipe the half-initialized data dir and exit non-zero. That forces a full + # re-bootstrap on the next start instead of falling through to a keyless boot + # (which would silently disable encryption). The pod crash-loops visibly until + # the key provider is reachable. + tde_bootstrap_fatal() { + echo "pg_tde FATAL: $1" + pg_ctl -D "$PGDATA" -m immediate -w stop || true + rm -rf "${PGDATA:?}"/* || true + exit 1 + } # Enable the extension in the default databases. template1 makes it the # default for future databases. for TDE_DB in template1 "$POSTGRES_DB"; do @@ -130,14 +142,14 @@ SQL || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_database_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set database principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set database principal key '${TDE_KEY_NAME}'" else psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || echo "pg_tde: create principal key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set global principal key '${TDE_KEY_NAME}'"; exit 1; } + || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). @@ -147,7 +159,7 @@ SQL || echo "pg_tde: create WAL server key returned non-zero (may already exist), continuing to set" psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_server_key_using_global_key_provider('${TDE_KEY_NAME}-wal','${TDE_PROVIDER_NAME}');" \ - || { echo "pg_tde FATAL: failed to set WAL server key '${TDE_KEY_NAME}-wal'"; exit 1; } + || tde_bootstrap_fatal "failed to set WAL server key '${TDE_KEY_NAME}-wal'" fi fi From fbfb33bf333e9b8351aff6da587d9d991f7dbcc6 Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Wed, 15 Jul 2026 19:45:35 +0600 Subject: [PATCH 08/11] tde: encrypt tables after failover and fail closed on file+WAL - standby GUC blocks (run.sh, ha_backup_job.sh, remote-replica.sh, warm_stanby.sh across all majors) now emit default_table_access_method = tde_heap when TDE_DEFAULT_AM is set, matching the primary. Without it a promoted standby kept its own postgresql.conf and defaulted new tables to plaintext heap (a silent encryption gap after failover when enforce_encryption is off). - primary start.sh fails closed with a clear message when WAL encryption is requested with the file keyring: WAL encryption is global-only, so the file (database-scoped) provider can never back it. The operator webhook already rejects this combo; this is a diagnosable backstop instead of a swallowed error that crash-loops on the misleading set-key fatal. Signed-off-by: Tamal Saha --- role_scripts/10/primary/start.sh | 7 +++++++ role_scripts/10/standby/ha_backup_job.sh | 1 + role_scripts/10/standby/run.sh | 1 + role_scripts/10/standby/warm_stanby.sh | 1 + role_scripts/11/primary/start.sh | 7 +++++++ role_scripts/11/standby/ha_backup_job.sh | 1 + role_scripts/11/standby/run.sh | 1 + role_scripts/11/standby/warm_stanby.sh | 1 + role_scripts/12/primary/start.sh | 7 +++++++ role_scripts/12/standby/ha_backup_job.sh | 1 + role_scripts/12/standby/run.sh | 1 + role_scripts/12/standby/warm_stanby.sh | 1 + role_scripts/13/primary/start.sh | 7 +++++++ role_scripts/13/standby/ha_backup_job.sh | 1 + role_scripts/13/standby/remote-replica.sh | 1 + role_scripts/13/standby/run.sh | 1 + role_scripts/13/standby/warm_stanby.sh | 1 + role_scripts/14/primary/start.sh | 7 +++++++ role_scripts/14/standby/ha_backup_job.sh | 1 + role_scripts/14/standby/remote-replica.sh | 1 + role_scripts/14/standby/run.sh | 1 + role_scripts/14/standby/warm_stanby.sh | 1 + role_scripts/15/primary/start.sh | 7 +++++++ role_scripts/15/standby/ha_backup_job.sh | 1 + role_scripts/15/standby/remote-replica.sh | 1 + role_scripts/15/standby/run.sh | 1 + role_scripts/15/standby/warm_stanby.sh | 1 + role_scripts/16/primary/start.sh | 7 +++++++ role_scripts/16/standby/ha_backup_job.sh | 1 + role_scripts/16/standby/remote-replica.sh | 1 + role_scripts/16/standby/run.sh | 1 + role_scripts/16/standby/warm_stanby.sh | 1 + role_scripts/17/primary/start.sh | 7 +++++++ role_scripts/17/standby/ha_backup_job.sh | 1 + role_scripts/17/standby/remote-replica.sh | 1 + role_scripts/17/standby/run.sh | 1 + role_scripts/17/standby/warm_stanby.sh | 1 + role_scripts/18/primary/start.sh | 7 +++++++ role_scripts/18/standby/ha_backup_job.sh | 1 + role_scripts/18/standby/remote-replica.sh | 1 + role_scripts/18/standby/run.sh | 1 + role_scripts/18/standby/warm_stanby.sh | 1 + role_scripts/9/primary/start.sh | 7 +++++++ role_scripts/9/standby/ha_backup_job.sh | 1 + role_scripts/9/standby/run.sh | 1 + role_scripts/9/standby/warm_stanby.sh | 1 + 46 files changed, 106 insertions(+) diff --git a/role_scripts/10/primary/start.sh b/role_scripts/10/primary/start.sh index b805b96..914fc4e 100755 --- a/role_scripts/10/primary/start.sh +++ b/role_scripts/10/primary/start.sh @@ -157,6 +157,13 @@ SQL || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi + # WAL encryption is global-only: the file keyring is a database-scoped + # provider and cannot back a server key. The operator webhook already rejects + # this combination, so this is a fail-closed backstop with a clear message + # (instead of a swallowed error that crash-loops on the misleading set-key fatal). + if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" && "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + tde_bootstrap_fatal "WAL encryption requires a global (vault or kmip) key provider; the file keyring cannot back WAL encryption" + fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/10/standby/ha_backup_job.sh b/role_scripts/10/standby/ha_backup_job.sh index dd871c9..b6ee739 100755 --- a/role_scripts/10/standby/ha_backup_job.sh +++ b/role_scripts/10/standby/ha_backup_job.sh @@ -95,6 +95,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi echo "max_replication_slots = 90" >>/tmp/postgresql.conf diff --git a/role_scripts/10/standby/run.sh b/role_scripts/10/standby/run.sh index 0643db0..e7ca899 100755 --- a/role_scripts/10/standby/run.sh +++ b/role_scripts/10/standby/run.sh @@ -164,6 +164,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi echo "max_replication_slots = 90" >>/tmp/postgresql.conf diff --git a/role_scripts/10/standby/warm_stanby.sh b/role_scripts/10/standby/warm_stanby.sh index 2b76050..70d6834 100755 --- a/role_scripts/10/standby/warm_stanby.sh +++ b/role_scripts/10/standby/warm_stanby.sh @@ -41,6 +41,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/11/primary/start.sh b/role_scripts/11/primary/start.sh index b397cc1..7bdcad6 100755 --- a/role_scripts/11/primary/start.sh +++ b/role_scripts/11/primary/start.sh @@ -166,6 +166,13 @@ SQL || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi + # WAL encryption is global-only: the file keyring is a database-scoped + # provider and cannot back a server key. The operator webhook already rejects + # this combination, so this is a fail-closed backstop with a clear message + # (instead of a swallowed error that crash-loops on the misleading set-key fatal). + if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" && "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + tde_bootstrap_fatal "WAL encryption requires a global (vault or kmip) key provider; the file keyring cannot back WAL encryption" + fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/11/standby/ha_backup_job.sh b/role_scripts/11/standby/ha_backup_job.sh index 2e1eef5..15df5dc 100755 --- a/role_scripts/11/standby/ha_backup_job.sh +++ b/role_scripts/11/standby/ha_backup_job.sh @@ -99,6 +99,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/11/standby/run.sh b/role_scripts/11/standby/run.sh index 85e6ad0..ffd1391 100755 --- a/role_scripts/11/standby/run.sh +++ b/role_scripts/11/standby/run.sh @@ -168,6 +168,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/11/standby/warm_stanby.sh b/role_scripts/11/standby/warm_stanby.sh index fc7bc1e..c8e1c58 100755 --- a/role_scripts/11/standby/warm_stanby.sh +++ b/role_scripts/11/standby/warm_stanby.sh @@ -43,6 +43,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/12/primary/start.sh b/role_scripts/12/primary/start.sh index 746d9da..f55e08a 100755 --- a/role_scripts/12/primary/start.sh +++ b/role_scripts/12/primary/start.sh @@ -186,6 +186,13 @@ SQL || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi + # WAL encryption is global-only: the file keyring is a database-scoped + # provider and cannot back a server key. The operator webhook already rejects + # this combination, so this is a fail-closed backstop with a clear message + # (instead of a swallowed error that crash-loops on the misleading set-key fatal). + if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" && "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + tde_bootstrap_fatal "WAL encryption requires a global (vault or kmip) key provider; the file keyring cannot back WAL encryption" + fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/12/standby/ha_backup_job.sh b/role_scripts/12/standby/ha_backup_job.sh index 720388b..d79e8d5 100755 --- a/role_scripts/12/standby/ha_backup_job.sh +++ b/role_scripts/12/standby/ha_backup_job.sh @@ -100,6 +100,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/12/standby/run.sh b/role_scripts/12/standby/run.sh index 5cf7b11..4b3594e 100755 --- a/role_scripts/12/standby/run.sh +++ b/role_scripts/12/standby/run.sh @@ -165,6 +165,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/12/standby/warm_stanby.sh b/role_scripts/12/standby/warm_stanby.sh index e5e0305..d491780 100755 --- a/role_scripts/12/standby/warm_stanby.sh +++ b/role_scripts/12/standby/warm_stanby.sh @@ -50,6 +50,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/13/primary/start.sh b/role_scripts/13/primary/start.sh index 4df0ea1..c91ab2e 100755 --- a/role_scripts/13/primary/start.sh +++ b/role_scripts/13/primary/start.sh @@ -207,6 +207,13 @@ SQL || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi + # WAL encryption is global-only: the file keyring is a database-scoped + # provider and cannot back a server key. The operator webhook already rejects + # this combination, so this is a fail-closed backstop with a clear message + # (instead of a swallowed error that crash-loops on the misleading set-key fatal). + if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" && "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + tde_bootstrap_fatal "WAL encryption requires a global (vault or kmip) key provider; the file keyring cannot back WAL encryption" + fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/13/standby/ha_backup_job.sh b/role_scripts/13/standby/ha_backup_job.sh index e0326f0..ee961bf 100755 --- a/role_scripts/13/standby/ha_backup_job.sh +++ b/role_scripts/13/standby/ha_backup_job.sh @@ -100,6 +100,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/13/standby/remote-replica.sh b/role_scripts/13/standby/remote-replica.sh index 60c9141..5ac1c31 100755 --- a/role_scripts/13/standby/remote-replica.sh +++ b/role_scripts/13/standby/remote-replica.sh @@ -110,6 +110,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/13/standby/run.sh b/role_scripts/13/standby/run.sh index 4acb3a7..c6cc7b9 100755 --- a/role_scripts/13/standby/run.sh +++ b/role_scripts/13/standby/run.sh @@ -169,6 +169,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/13/standby/warm_stanby.sh b/role_scripts/13/standby/warm_stanby.sh index 5e01023..b39e1e8 100755 --- a/role_scripts/13/standby/warm_stanby.sh +++ b/role_scripts/13/standby/warm_stanby.sh @@ -46,6 +46,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/14/primary/start.sh b/role_scripts/14/primary/start.sh index 7814ce1..41a7a32 100755 --- a/role_scripts/14/primary/start.sh +++ b/role_scripts/14/primary/start.sh @@ -211,6 +211,13 @@ SQL || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi + # WAL encryption is global-only: the file keyring is a database-scoped + # provider and cannot back a server key. The operator webhook already rejects + # this combination, so this is a fail-closed backstop with a clear message + # (instead of a swallowed error that crash-loops on the misleading set-key fatal). + if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" && "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + tde_bootstrap_fatal "WAL encryption requires a global (vault or kmip) key provider; the file keyring cannot back WAL encryption" + fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/14/standby/ha_backup_job.sh b/role_scripts/14/standby/ha_backup_job.sh index d720031..444f001 100755 --- a/role_scripts/14/standby/ha_backup_job.sh +++ b/role_scripts/14/standby/ha_backup_job.sh @@ -100,6 +100,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/14/standby/remote-replica.sh b/role_scripts/14/standby/remote-replica.sh index 1487746..6bc6fee 100755 --- a/role_scripts/14/standby/remote-replica.sh +++ b/role_scripts/14/standby/remote-replica.sh @@ -110,6 +110,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/14/standby/run.sh b/role_scripts/14/standby/run.sh index 216dc86..25a5fbe 100755 --- a/role_scripts/14/standby/run.sh +++ b/role_scripts/14/standby/run.sh @@ -169,6 +169,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/14/standby/warm_stanby.sh b/role_scripts/14/standby/warm_stanby.sh index 1e367af..928ec3d 100755 --- a/role_scripts/14/standby/warm_stanby.sh +++ b/role_scripts/14/standby/warm_stanby.sh @@ -46,6 +46,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/15/primary/start.sh b/role_scripts/15/primary/start.sh index 4adb634..7cdda9b 100755 --- a/role_scripts/15/primary/start.sh +++ b/role_scripts/15/primary/start.sh @@ -214,6 +214,13 @@ SQL || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi + # WAL encryption is global-only: the file keyring is a database-scoped + # provider and cannot back a server key. The operator webhook already rejects + # this combination, so this is a fail-closed backstop with a clear message + # (instead of a swallowed error that crash-loops on the misleading set-key fatal). + if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" && "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + tde_bootstrap_fatal "WAL encryption requires a global (vault or kmip) key provider; the file keyring cannot back WAL encryption" + fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/15/standby/ha_backup_job.sh b/role_scripts/15/standby/ha_backup_job.sh index 9137ff9..ff53d0c 100755 --- a/role_scripts/15/standby/ha_backup_job.sh +++ b/role_scripts/15/standby/ha_backup_job.sh @@ -102,6 +102,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/15/standby/remote-replica.sh b/role_scripts/15/standby/remote-replica.sh index 1487746..6bc6fee 100755 --- a/role_scripts/15/standby/remote-replica.sh +++ b/role_scripts/15/standby/remote-replica.sh @@ -110,6 +110,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/15/standby/run.sh b/role_scripts/15/standby/run.sh index f011440..b0df61b 100755 --- a/role_scripts/15/standby/run.sh +++ b/role_scripts/15/standby/run.sh @@ -168,6 +168,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/15/standby/warm_stanby.sh b/role_scripts/15/standby/warm_stanby.sh index 38736da..efecb83 100755 --- a/role_scripts/15/standby/warm_stanby.sh +++ b/role_scripts/15/standby/warm_stanby.sh @@ -47,6 +47,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/16/primary/start.sh b/role_scripts/16/primary/start.sh index 003dc31..a28ba95 100755 --- a/role_scripts/16/primary/start.sh +++ b/role_scripts/16/primary/start.sh @@ -212,6 +212,13 @@ SQL || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi + # WAL encryption is global-only: the file keyring is a database-scoped + # provider and cannot back a server key. The operator webhook already rejects + # this combination, so this is a fail-closed backstop with a clear message + # (instead of a swallowed error that crash-loops on the misleading set-key fatal). + if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" && "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + tde_bootstrap_fatal "WAL encryption requires a global (vault or kmip) key provider; the file keyring cannot back WAL encryption" + fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/16/standby/ha_backup_job.sh b/role_scripts/16/standby/ha_backup_job.sh index b0d4fc2..c654fcf 100755 --- a/role_scripts/16/standby/ha_backup_job.sh +++ b/role_scripts/16/standby/ha_backup_job.sh @@ -102,6 +102,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/16/standby/remote-replica.sh b/role_scripts/16/standby/remote-replica.sh index fc5bfd9..df5ba30 100755 --- a/role_scripts/16/standby/remote-replica.sh +++ b/role_scripts/16/standby/remote-replica.sh @@ -110,6 +110,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/16/standby/run.sh b/role_scripts/16/standby/run.sh index 415e1dc..afde4c0 100755 --- a/role_scripts/16/standby/run.sh +++ b/role_scripts/16/standby/run.sh @@ -169,6 +169,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/16/standby/warm_stanby.sh b/role_scripts/16/standby/warm_stanby.sh index 8866a03..75a59ea 100755 --- a/role_scripts/16/standby/warm_stanby.sh +++ b/role_scripts/16/standby/warm_stanby.sh @@ -47,6 +47,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/17/primary/start.sh b/role_scripts/17/primary/start.sh index 26f1c9e..3928841 100755 --- a/role_scripts/17/primary/start.sh +++ b/role_scripts/17/primary/start.sh @@ -217,6 +217,13 @@ SQL || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi + # WAL encryption is global-only: the file keyring is a database-scoped + # provider and cannot back a server key. The operator webhook already rejects + # this combination, so this is a fail-closed backstop with a clear message + # (instead of a swallowed error that crash-loops on the misleading set-key fatal). + if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" && "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + tde_bootstrap_fatal "WAL encryption requires a global (vault or kmip) key provider; the file keyring cannot back WAL encryption" + fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/17/standby/ha_backup_job.sh b/role_scripts/17/standby/ha_backup_job.sh index b0d4fc2..c654fcf 100755 --- a/role_scripts/17/standby/ha_backup_job.sh +++ b/role_scripts/17/standby/ha_backup_job.sh @@ -102,6 +102,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/17/standby/remote-replica.sh b/role_scripts/17/standby/remote-replica.sh index fc5bfd9..df5ba30 100755 --- a/role_scripts/17/standby/remote-replica.sh +++ b/role_scripts/17/standby/remote-replica.sh @@ -110,6 +110,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/17/standby/run.sh b/role_scripts/17/standby/run.sh index 415e1dc..afde4c0 100755 --- a/role_scripts/17/standby/run.sh +++ b/role_scripts/17/standby/run.sh @@ -169,6 +169,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/17/standby/warm_stanby.sh b/role_scripts/17/standby/warm_stanby.sh index 8866a03..75a59ea 100755 --- a/role_scripts/17/standby/warm_stanby.sh +++ b/role_scripts/17/standby/warm_stanby.sh @@ -47,6 +47,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/18/primary/start.sh b/role_scripts/18/primary/start.sh index 9cc5ae0..f283ad2 100755 --- a/role_scripts/18/primary/start.sh +++ b/role_scripts/18/primary/start.sh @@ -210,6 +210,13 @@ SQL || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi + # WAL encryption is global-only: the file keyring is a database-scoped + # provider and cannot back a server key. The operator webhook already rejects + # this combination, so this is a fail-closed backstop with a clear message + # (instead of a swallowed error that crash-loops on the misleading set-key fatal). + if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" && "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + tde_bootstrap_fatal "WAL encryption requires a global (vault or kmip) key provider; the file keyring cannot back WAL encryption" + fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/18/standby/ha_backup_job.sh b/role_scripts/18/standby/ha_backup_job.sh index b0d4fc2..c654fcf 100755 --- a/role_scripts/18/standby/ha_backup_job.sh +++ b/role_scripts/18/standby/ha_backup_job.sh @@ -102,6 +102,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/18/standby/remote-replica.sh b/role_scripts/18/standby/remote-replica.sh index fc5bfd9..df5ba30 100755 --- a/role_scripts/18/standby/remote-replica.sh +++ b/role_scripts/18/standby/remote-replica.sh @@ -110,6 +110,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/18/standby/run.sh b/role_scripts/18/standby/run.sh index 415e1dc..afde4c0 100755 --- a/role_scripts/18/standby/run.sh +++ b/role_scripts/18/standby/run.sh @@ -169,6 +169,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/18/standby/warm_stanby.sh b/role_scripts/18/standby/warm_stanby.sh index 8866a03..75a59ea 100755 --- a/role_scripts/18/standby/warm_stanby.sh +++ b/role_scripts/18/standby/warm_stanby.sh @@ -47,6 +47,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/9/primary/start.sh b/role_scripts/9/primary/start.sh index 7909c12..3f4bb60 100755 --- a/role_scripts/9/primary/start.sh +++ b/role_scripts/9/primary/start.sh @@ -152,6 +152,13 @@ SQL || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" fi + # WAL encryption is global-only: the file keyring is a database-scoped + # provider and cannot back a server key. The operator webhook already rejects + # this combination, so this is a fail-closed backstop with a clear message + # (instead of a swallowed error that crash-loops on the misleading set-key fatal). + if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" && "${TDE_PROVIDER_KIND:-}" == "file" ]]; then + tde_bootstrap_fatal "WAL encryption requires a global (vault or kmip) key provider; the file keyring cannot back WAL encryption" + fi # If WAL encryption is requested, create + set the server (WAL) key too (global only). if [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]]; then psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/9/standby/ha_backup_job.sh b/role_scripts/9/standby/ha_backup_job.sh index 462006f..6b2830c 100755 --- a/role_scripts/9/standby/ha_backup_job.sh +++ b/role_scripts/9/standby/ha_backup_job.sh @@ -96,6 +96,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi echo "max_replication_slots = 90" >>/tmp/postgresql.conf diff --git a/role_scripts/9/standby/run.sh b/role_scripts/9/standby/run.sh index 31e0de7..bb43de4 100755 --- a/role_scripts/9/standby/run.sh +++ b/role_scripts/9/standby/run.sh @@ -160,6 +160,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi diff --git a/role_scripts/9/standby/warm_stanby.sh b/role_scripts/9/standby/warm_stanby.sh index d1e2296..779897a 100755 --- a/role_scripts/9/standby/warm_stanby.sh +++ b/role_scripts/9/standby/warm_stanby.sh @@ -39,6 +39,7 @@ echo "shared_preload_libraries = '${PRELOAD}'" >>/tmp/postgresql.conf if [[ "${TDE_ENABLED:-false}" == "true" ]]; then [[ "${TDE_ENCRYPT_WAL:-false}" == "true" ]] && echo "pg_tde.wal_encrypt = on" >>/tmp/postgresql.conf [[ "${TDE_ENFORCE:-false}" == "true" ]] && echo "pg_tde.enforce_encryption = on" >>/tmp/postgresql.conf + [[ "${TDE_DEFAULT_AM:-false}" == "true" ]] && echo "default_table_access_method = tde_heap" >>/tmp/postgresql.conf echo "pg_tde.cipher = '${TDE_CIPHER:-aes_128}'" >>/tmp/postgresql.conf fi From 92e78e70ff806bd041f721d3fb0d9f523efe828b Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Wed, 15 Jul 2026 20:57:33 +0600 Subject: [PATCH 09/11] tde: set a server-wide default principal key so new databases inherit encryption pg_tde stores the principal key per database OID and CREATE DATABASE does not copy it, so a key set in template1 is not inherited by databases cloned from it. Under a cluster-wide default_table_access_method = tde_heap, the first encrypted CREATE TABLE in a freshly created database therefore failed with 'principal key not configured'. Set a server-wide default principal key at bootstrap via pg_tde_set_default_key_using_global_key_provider (create-before-set, strict); databases without their own principal key fall back to it, so new databases can create encrypted tables out of the box. The default key is a global-provider feature, so it is set for the vault/kmip providers only (the file keyring is a standalone, database-scoped provider). Verified on k3s-188: a brand-new database created an encrypted table with no manual key setup. Signed-off-by: Tamal Saha --- role_scripts/10/primary/start.sh | 16 ++++++++++++++++ role_scripts/11/primary/start.sh | 16 ++++++++++++++++ role_scripts/12/primary/start.sh | 16 ++++++++++++++++ role_scripts/13/primary/start.sh | 16 ++++++++++++++++ role_scripts/14/primary/start.sh | 16 ++++++++++++++++ role_scripts/15/primary/start.sh | 16 ++++++++++++++++ role_scripts/16/primary/start.sh | 16 ++++++++++++++++ role_scripts/17/primary/start.sh | 16 ++++++++++++++++ role_scripts/18/primary/start.sh | 16 ++++++++++++++++ role_scripts/9/primary/start.sh | 16 ++++++++++++++++ 10 files changed, 160 insertions(+) diff --git a/role_scripts/10/primary/start.sh b/role_scripts/10/primary/start.sh index 914fc4e..d7f0fef 100755 --- a/role_scripts/10/primary/start.sh +++ b/role_scripts/10/primary/start.sh @@ -155,6 +155,22 @@ SQL psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" + + # Set a server-wide DEFAULT principal key so databases created later inherit + # encryption. pg_tde stores the principal key per database OID and CREATE + # DATABASE does NOT copy it (a key set in template1 is not carried to its + # clones), so without a server default the first encrypted CREATE TABLE in a + # newly created database fails "principal key not configured" under a + # cluster-wide default_table_access_method = tde_heap. The default key is a + # global-provider feature; the file keyring (standalone, database-scoped) has + # no server default, so this applies to the vault/kmip providers only. Create + # precedes set, and the set is strict like the principal-key set above. + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/11/primary/start.sh b/role_scripts/11/primary/start.sh index 7bdcad6..1c68bd3 100755 --- a/role_scripts/11/primary/start.sh +++ b/role_scripts/11/primary/start.sh @@ -164,6 +164,22 @@ SQL psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" + + # Set a server-wide DEFAULT principal key so databases created later inherit + # encryption. pg_tde stores the principal key per database OID and CREATE + # DATABASE does NOT copy it (a key set in template1 is not carried to its + # clones), so without a server default the first encrypted CREATE TABLE in a + # newly created database fails "principal key not configured" under a + # cluster-wide default_table_access_method = tde_heap. The default key is a + # global-provider feature; the file keyring (standalone, database-scoped) has + # no server default, so this applies to the vault/kmip providers only. Create + # precedes set, and the set is strict like the principal-key set above. + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/12/primary/start.sh b/role_scripts/12/primary/start.sh index f55e08a..c8181fa 100755 --- a/role_scripts/12/primary/start.sh +++ b/role_scripts/12/primary/start.sh @@ -184,6 +184,22 @@ SQL psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" + + # Set a server-wide DEFAULT principal key so databases created later inherit + # encryption. pg_tde stores the principal key per database OID and CREATE + # DATABASE does NOT copy it (a key set in template1 is not carried to its + # clones), so without a server default the first encrypted CREATE TABLE in a + # newly created database fails "principal key not configured" under a + # cluster-wide default_table_access_method = tde_heap. The default key is a + # global-provider feature; the file keyring (standalone, database-scoped) has + # no server default, so this applies to the vault/kmip providers only. Create + # precedes set, and the set is strict like the principal-key set above. + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/13/primary/start.sh b/role_scripts/13/primary/start.sh index c91ab2e..5206430 100755 --- a/role_scripts/13/primary/start.sh +++ b/role_scripts/13/primary/start.sh @@ -205,6 +205,22 @@ SQL psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" + + # Set a server-wide DEFAULT principal key so databases created later inherit + # encryption. pg_tde stores the principal key per database OID and CREATE + # DATABASE does NOT copy it (a key set in template1 is not carried to its + # clones), so without a server default the first encrypted CREATE TABLE in a + # newly created database fails "principal key not configured" under a + # cluster-wide default_table_access_method = tde_heap. The default key is a + # global-provider feature; the file keyring (standalone, database-scoped) has + # no server default, so this applies to the vault/kmip providers only. Create + # precedes set, and the set is strict like the principal-key set above. + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/14/primary/start.sh b/role_scripts/14/primary/start.sh index 41a7a32..dac577c 100755 --- a/role_scripts/14/primary/start.sh +++ b/role_scripts/14/primary/start.sh @@ -209,6 +209,22 @@ SQL psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" + + # Set a server-wide DEFAULT principal key so databases created later inherit + # encryption. pg_tde stores the principal key per database OID and CREATE + # DATABASE does NOT copy it (a key set in template1 is not carried to its + # clones), so without a server default the first encrypted CREATE TABLE in a + # newly created database fails "principal key not configured" under a + # cluster-wide default_table_access_method = tde_heap. The default key is a + # global-provider feature; the file keyring (standalone, database-scoped) has + # no server default, so this applies to the vault/kmip providers only. Create + # precedes set, and the set is strict like the principal-key set above. + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/15/primary/start.sh b/role_scripts/15/primary/start.sh index 7cdda9b..caef58c 100755 --- a/role_scripts/15/primary/start.sh +++ b/role_scripts/15/primary/start.sh @@ -212,6 +212,22 @@ SQL psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" + + # Set a server-wide DEFAULT principal key so databases created later inherit + # encryption. pg_tde stores the principal key per database OID and CREATE + # DATABASE does NOT copy it (a key set in template1 is not carried to its + # clones), so without a server default the first encrypted CREATE TABLE in a + # newly created database fails "principal key not configured" under a + # cluster-wide default_table_access_method = tde_heap. The default key is a + # global-provider feature; the file keyring (standalone, database-scoped) has + # no server default, so this applies to the vault/kmip providers only. Create + # precedes set, and the set is strict like the principal-key set above. + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/16/primary/start.sh b/role_scripts/16/primary/start.sh index a28ba95..239ce96 100755 --- a/role_scripts/16/primary/start.sh +++ b/role_scripts/16/primary/start.sh @@ -210,6 +210,22 @@ SQL psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" + + # Set a server-wide DEFAULT principal key so databases created later inherit + # encryption. pg_tde stores the principal key per database OID and CREATE + # DATABASE does NOT copy it (a key set in template1 is not carried to its + # clones), so without a server default the first encrypted CREATE TABLE in a + # newly created database fails "principal key not configured" under a + # cluster-wide default_table_access_method = tde_heap. The default key is a + # global-provider feature; the file keyring (standalone, database-scoped) has + # no server default, so this applies to the vault/kmip providers only. Create + # precedes set, and the set is strict like the principal-key set above. + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/17/primary/start.sh b/role_scripts/17/primary/start.sh index 3928841..fb6e75b 100755 --- a/role_scripts/17/primary/start.sh +++ b/role_scripts/17/primary/start.sh @@ -215,6 +215,22 @@ SQL psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" + + # Set a server-wide DEFAULT principal key so databases created later inherit + # encryption. pg_tde stores the principal key per database OID and CREATE + # DATABASE does NOT copy it (a key set in template1 is not carried to its + # clones), so without a server default the first encrypted CREATE TABLE in a + # newly created database fails "principal key not configured" under a + # cluster-wide default_table_access_method = tde_heap. The default key is a + # global-provider feature; the file keyring (standalone, database-scoped) has + # no server default, so this applies to the vault/kmip providers only. Create + # precedes set, and the set is strict like the principal-key set above. + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/18/primary/start.sh b/role_scripts/18/primary/start.sh index f283ad2..96d5aa2 100755 --- a/role_scripts/18/primary/start.sh +++ b/role_scripts/18/primary/start.sh @@ -208,6 +208,22 @@ SQL psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" + + # Set a server-wide DEFAULT principal key so databases created later inherit + # encryption. pg_tde stores the principal key per database OID and CREATE + # DATABASE does NOT copy it (a key set in template1 is not carried to its + # clones), so without a server default the first encrypted CREATE TABLE in a + # newly created database fails "principal key not configured" under a + # cluster-wide default_table_access_method = tde_heap. The default key is a + # global-provider feature; the file keyring (standalone, database-scoped) has + # no server default, so this applies to the vault/kmip providers only. Create + # precedes set, and the set is strict like the principal-key set above. + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/9/primary/start.sh b/role_scripts/9/primary/start.sh index 3f4bb60..a89a753 100755 --- a/role_scripts/9/primary/start.sh +++ b/role_scripts/9/primary/start.sh @@ -150,6 +150,22 @@ SQL psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ "SELECT pg_tde_set_key_using_global_key_provider('${TDE_KEY_NAME}','${TDE_PROVIDER_NAME}');" \ || tde_bootstrap_fatal "failed to set global principal key '${TDE_KEY_NAME}'" + + # Set a server-wide DEFAULT principal key so databases created later inherit + # encryption. pg_tde stores the principal key per database OID and CREATE + # DATABASE does NOT copy it (a key set in template1 is not carried to its + # clones), so without a server default the first encrypted CREATE TABLE in a + # newly created database fails "principal key not configured" under a + # cluster-wide default_table_access_method = tde_heap. The default key is a + # global-provider feature; the file keyring (standalone, database-scoped) has + # no server default, so this applies to the vault/kmip providers only. Create + # precedes set, and the set is strict like the principal-key set above. + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" fi # WAL encryption is global-only: the file keyring is a database-scoped From 17a631157997ca1693b78ed1f528a5a4c2c484fe Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Wed, 15 Jul 2026 21:41:40 +0600 Subject: [PATCH 10/11] tde: gate the server default key on TDE_DEFAULT_AM/TDE_ENFORCE The server-wide default principal key only matters when new tables are encrypted by default (default_table_access_method=tde_heap) or enforced cluster-wide, so gate its strict create/set on TDE_DEFAULT_AM or TDE_ENFORCE, mirroring how the WAL server-key block gates on TDE_ENCRYPT_WAL. A plain opt-in-per-table cluster no longer runs the strict set (and its crash-loop-on-failure path) for a default key it never uses. Signed-off-by: Tamal Saha --- role_scripts/10/primary/start.sh | 27 ++++++++++++++++----------- role_scripts/11/primary/start.sh | 27 ++++++++++++++++----------- role_scripts/12/primary/start.sh | 27 ++++++++++++++++----------- role_scripts/13/primary/start.sh | 27 ++++++++++++++++----------- role_scripts/14/primary/start.sh | 27 ++++++++++++++++----------- role_scripts/15/primary/start.sh | 27 ++++++++++++++++----------- role_scripts/16/primary/start.sh | 27 ++++++++++++++++----------- role_scripts/17/primary/start.sh | 27 ++++++++++++++++----------- role_scripts/18/primary/start.sh | 27 ++++++++++++++++----------- role_scripts/9/primary/start.sh | 27 ++++++++++++++++----------- 10 files changed, 160 insertions(+), 110 deletions(-) diff --git a/role_scripts/10/primary/start.sh b/role_scripts/10/primary/start.sh index d7f0fef..f45508c 100755 --- a/role_scripts/10/primary/start.sh +++ b/role_scripts/10/primary/start.sh @@ -160,17 +160,22 @@ SQL # encryption. pg_tde stores the principal key per database OID and CREATE # DATABASE does NOT copy it (a key set in template1 is not carried to its # clones), so without a server default the first encrypted CREATE TABLE in a - # newly created database fails "principal key not configured" under a - # cluster-wide default_table_access_method = tde_heap. The default key is a - # global-provider feature; the file keyring (standalone, database-scoped) has - # no server default, so this applies to the vault/kmip providers only. Create - # precedes set, and the set is strict like the principal-key set above. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + # newly created database fails "principal key not configured". This only + # matters when new tables are encrypted by default or enforced cluster-wide, + # so gate it on TDE_DEFAULT_AM/TDE_ENFORCE (mirroring how the WAL block below + # gates on TDE_ENCRYPT_WAL): a plain opt-in-per-table cluster does not need a + # server default and should not take the strict-set crash-loop risk for it. + # The default key is a global-provider feature; the file keyring (standalone, + # database-scoped) has no server default, so this applies to vault/kmip only. + # Create precedes set, and the set is strict like the principal-key set above. + if [[ "${TDE_DEFAULT_AM:-false}" == "true" || "${TDE_ENFORCE:-false}" == "true" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + fi fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/11/primary/start.sh b/role_scripts/11/primary/start.sh index 1c68bd3..8275950 100755 --- a/role_scripts/11/primary/start.sh +++ b/role_scripts/11/primary/start.sh @@ -169,17 +169,22 @@ SQL # encryption. pg_tde stores the principal key per database OID and CREATE # DATABASE does NOT copy it (a key set in template1 is not carried to its # clones), so without a server default the first encrypted CREATE TABLE in a - # newly created database fails "principal key not configured" under a - # cluster-wide default_table_access_method = tde_heap. The default key is a - # global-provider feature; the file keyring (standalone, database-scoped) has - # no server default, so this applies to the vault/kmip providers only. Create - # precedes set, and the set is strict like the principal-key set above. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + # newly created database fails "principal key not configured". This only + # matters when new tables are encrypted by default or enforced cluster-wide, + # so gate it on TDE_DEFAULT_AM/TDE_ENFORCE (mirroring how the WAL block below + # gates on TDE_ENCRYPT_WAL): a plain opt-in-per-table cluster does not need a + # server default and should not take the strict-set crash-loop risk for it. + # The default key is a global-provider feature; the file keyring (standalone, + # database-scoped) has no server default, so this applies to vault/kmip only. + # Create precedes set, and the set is strict like the principal-key set above. + if [[ "${TDE_DEFAULT_AM:-false}" == "true" || "${TDE_ENFORCE:-false}" == "true" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + fi fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/12/primary/start.sh b/role_scripts/12/primary/start.sh index c8181fa..0fc26d2 100755 --- a/role_scripts/12/primary/start.sh +++ b/role_scripts/12/primary/start.sh @@ -189,17 +189,22 @@ SQL # encryption. pg_tde stores the principal key per database OID and CREATE # DATABASE does NOT copy it (a key set in template1 is not carried to its # clones), so without a server default the first encrypted CREATE TABLE in a - # newly created database fails "principal key not configured" under a - # cluster-wide default_table_access_method = tde_heap. The default key is a - # global-provider feature; the file keyring (standalone, database-scoped) has - # no server default, so this applies to the vault/kmip providers only. Create - # precedes set, and the set is strict like the principal-key set above. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + # newly created database fails "principal key not configured". This only + # matters when new tables are encrypted by default or enforced cluster-wide, + # so gate it on TDE_DEFAULT_AM/TDE_ENFORCE (mirroring how the WAL block below + # gates on TDE_ENCRYPT_WAL): a plain opt-in-per-table cluster does not need a + # server default and should not take the strict-set crash-loop risk for it. + # The default key is a global-provider feature; the file keyring (standalone, + # database-scoped) has no server default, so this applies to vault/kmip only. + # Create precedes set, and the set is strict like the principal-key set above. + if [[ "${TDE_DEFAULT_AM:-false}" == "true" || "${TDE_ENFORCE:-false}" == "true" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + fi fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/13/primary/start.sh b/role_scripts/13/primary/start.sh index 5206430..4301e52 100755 --- a/role_scripts/13/primary/start.sh +++ b/role_scripts/13/primary/start.sh @@ -210,17 +210,22 @@ SQL # encryption. pg_tde stores the principal key per database OID and CREATE # DATABASE does NOT copy it (a key set in template1 is not carried to its # clones), so without a server default the first encrypted CREATE TABLE in a - # newly created database fails "principal key not configured" under a - # cluster-wide default_table_access_method = tde_heap. The default key is a - # global-provider feature; the file keyring (standalone, database-scoped) has - # no server default, so this applies to the vault/kmip providers only. Create - # precedes set, and the set is strict like the principal-key set above. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + # newly created database fails "principal key not configured". This only + # matters when new tables are encrypted by default or enforced cluster-wide, + # so gate it on TDE_DEFAULT_AM/TDE_ENFORCE (mirroring how the WAL block below + # gates on TDE_ENCRYPT_WAL): a plain opt-in-per-table cluster does not need a + # server default and should not take the strict-set crash-loop risk for it. + # The default key is a global-provider feature; the file keyring (standalone, + # database-scoped) has no server default, so this applies to vault/kmip only. + # Create precedes set, and the set is strict like the principal-key set above. + if [[ "${TDE_DEFAULT_AM:-false}" == "true" || "${TDE_ENFORCE:-false}" == "true" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + fi fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/14/primary/start.sh b/role_scripts/14/primary/start.sh index dac577c..08dd11a 100755 --- a/role_scripts/14/primary/start.sh +++ b/role_scripts/14/primary/start.sh @@ -214,17 +214,22 @@ SQL # encryption. pg_tde stores the principal key per database OID and CREATE # DATABASE does NOT copy it (a key set in template1 is not carried to its # clones), so without a server default the first encrypted CREATE TABLE in a - # newly created database fails "principal key not configured" under a - # cluster-wide default_table_access_method = tde_heap. The default key is a - # global-provider feature; the file keyring (standalone, database-scoped) has - # no server default, so this applies to the vault/kmip providers only. Create - # precedes set, and the set is strict like the principal-key set above. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + # newly created database fails "principal key not configured". This only + # matters when new tables are encrypted by default or enforced cluster-wide, + # so gate it on TDE_DEFAULT_AM/TDE_ENFORCE (mirroring how the WAL block below + # gates on TDE_ENCRYPT_WAL): a plain opt-in-per-table cluster does not need a + # server default and should not take the strict-set crash-loop risk for it. + # The default key is a global-provider feature; the file keyring (standalone, + # database-scoped) has no server default, so this applies to vault/kmip only. + # Create precedes set, and the set is strict like the principal-key set above. + if [[ "${TDE_DEFAULT_AM:-false}" == "true" || "${TDE_ENFORCE:-false}" == "true" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + fi fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/15/primary/start.sh b/role_scripts/15/primary/start.sh index caef58c..3b8ede1 100755 --- a/role_scripts/15/primary/start.sh +++ b/role_scripts/15/primary/start.sh @@ -217,17 +217,22 @@ SQL # encryption. pg_tde stores the principal key per database OID and CREATE # DATABASE does NOT copy it (a key set in template1 is not carried to its # clones), so without a server default the first encrypted CREATE TABLE in a - # newly created database fails "principal key not configured" under a - # cluster-wide default_table_access_method = tde_heap. The default key is a - # global-provider feature; the file keyring (standalone, database-scoped) has - # no server default, so this applies to the vault/kmip providers only. Create - # precedes set, and the set is strict like the principal-key set above. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + # newly created database fails "principal key not configured". This only + # matters when new tables are encrypted by default or enforced cluster-wide, + # so gate it on TDE_DEFAULT_AM/TDE_ENFORCE (mirroring how the WAL block below + # gates on TDE_ENCRYPT_WAL): a plain opt-in-per-table cluster does not need a + # server default and should not take the strict-set crash-loop risk for it. + # The default key is a global-provider feature; the file keyring (standalone, + # database-scoped) has no server default, so this applies to vault/kmip only. + # Create precedes set, and the set is strict like the principal-key set above. + if [[ "${TDE_DEFAULT_AM:-false}" == "true" || "${TDE_ENFORCE:-false}" == "true" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + fi fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/16/primary/start.sh b/role_scripts/16/primary/start.sh index 239ce96..212dfca 100755 --- a/role_scripts/16/primary/start.sh +++ b/role_scripts/16/primary/start.sh @@ -215,17 +215,22 @@ SQL # encryption. pg_tde stores the principal key per database OID and CREATE # DATABASE does NOT copy it (a key set in template1 is not carried to its # clones), so without a server default the first encrypted CREATE TABLE in a - # newly created database fails "principal key not configured" under a - # cluster-wide default_table_access_method = tde_heap. The default key is a - # global-provider feature; the file keyring (standalone, database-scoped) has - # no server default, so this applies to the vault/kmip providers only. Create - # precedes set, and the set is strict like the principal-key set above. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + # newly created database fails "principal key not configured". This only + # matters when new tables are encrypted by default or enforced cluster-wide, + # so gate it on TDE_DEFAULT_AM/TDE_ENFORCE (mirroring how the WAL block below + # gates on TDE_ENCRYPT_WAL): a plain opt-in-per-table cluster does not need a + # server default and should not take the strict-set crash-loop risk for it. + # The default key is a global-provider feature; the file keyring (standalone, + # database-scoped) has no server default, so this applies to vault/kmip only. + # Create precedes set, and the set is strict like the principal-key set above. + if [[ "${TDE_DEFAULT_AM:-false}" == "true" || "${TDE_ENFORCE:-false}" == "true" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + fi fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/17/primary/start.sh b/role_scripts/17/primary/start.sh index fb6e75b..d9094ad 100755 --- a/role_scripts/17/primary/start.sh +++ b/role_scripts/17/primary/start.sh @@ -220,17 +220,22 @@ SQL # encryption. pg_tde stores the principal key per database OID and CREATE # DATABASE does NOT copy it (a key set in template1 is not carried to its # clones), so without a server default the first encrypted CREATE TABLE in a - # newly created database fails "principal key not configured" under a - # cluster-wide default_table_access_method = tde_heap. The default key is a - # global-provider feature; the file keyring (standalone, database-scoped) has - # no server default, so this applies to the vault/kmip providers only. Create - # precedes set, and the set is strict like the principal-key set above. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + # newly created database fails "principal key not configured". This only + # matters when new tables are encrypted by default or enforced cluster-wide, + # so gate it on TDE_DEFAULT_AM/TDE_ENFORCE (mirroring how the WAL block below + # gates on TDE_ENCRYPT_WAL): a plain opt-in-per-table cluster does not need a + # server default and should not take the strict-set crash-loop risk for it. + # The default key is a global-provider feature; the file keyring (standalone, + # database-scoped) has no server default, so this applies to vault/kmip only. + # Create precedes set, and the set is strict like the principal-key set above. + if [[ "${TDE_DEFAULT_AM:-false}" == "true" || "${TDE_ENFORCE:-false}" == "true" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + fi fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/18/primary/start.sh b/role_scripts/18/primary/start.sh index 96d5aa2..87182dd 100755 --- a/role_scripts/18/primary/start.sh +++ b/role_scripts/18/primary/start.sh @@ -213,17 +213,22 @@ SQL # encryption. pg_tde stores the principal key per database OID and CREATE # DATABASE does NOT copy it (a key set in template1 is not carried to its # clones), so without a server default the first encrypted CREATE TABLE in a - # newly created database fails "principal key not configured" under a - # cluster-wide default_table_access_method = tde_heap. The default key is a - # global-provider feature; the file keyring (standalone, database-scoped) has - # no server default, so this applies to the vault/kmip providers only. Create - # precedes set, and the set is strict like the principal-key set above. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + # newly created database fails "principal key not configured". This only + # matters when new tables are encrypted by default or enforced cluster-wide, + # so gate it on TDE_DEFAULT_AM/TDE_ENFORCE (mirroring how the WAL block below + # gates on TDE_ENCRYPT_WAL): a plain opt-in-per-table cluster does not need a + # server default and should not take the strict-set crash-loop risk for it. + # The default key is a global-provider feature; the file keyring (standalone, + # database-scoped) has no server default, so this applies to vault/kmip only. + # Create precedes set, and the set is strict like the principal-key set above. + if [[ "${TDE_DEFAULT_AM:-false}" == "true" || "${TDE_ENFORCE:-false}" == "true" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + fi fi # WAL encryption is global-only: the file keyring is a database-scoped diff --git a/role_scripts/9/primary/start.sh b/role_scripts/9/primary/start.sh index a89a753..8d5eba4 100755 --- a/role_scripts/9/primary/start.sh +++ b/role_scripts/9/primary/start.sh @@ -155,17 +155,22 @@ SQL # encryption. pg_tde stores the principal key per database OID and CREATE # DATABASE does NOT copy it (a key set in template1 is not carried to its # clones), so without a server default the first encrypted CREATE TABLE in a - # newly created database fails "principal key not configured" under a - # cluster-wide default_table_access_method = tde_heap. The default key is a - # global-provider feature; the file keyring (standalone, database-scoped) has - # no server default, so this applies to the vault/kmip providers only. Create - # precedes set, and the set is strict like the principal-key set above. - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ - || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + # newly created database fails "principal key not configured". This only + # matters when new tables are encrypted by default or enforced cluster-wide, + # so gate it on TDE_DEFAULT_AM/TDE_ENFORCE (mirroring how the WAL block below + # gates on TDE_ENCRYPT_WAL): a plain opt-in-per-table cluster does not need a + # server default and should not take the strict-set crash-loop risk for it. + # The default key is a global-provider feature; the file keyring (standalone, + # database-scoped) has no server default, so this applies to vault/kmip only. + # Create precedes set, and the set is strict like the principal-key set above. + if [[ "${TDE_DEFAULT_AM:-false}" == "true" || "${TDE_ENFORCE:-false}" == "true" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_create_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || echo "pg_tde: create default key returned non-zero (may already exist), continuing to set" + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_set_default_key_using_global_key_provider('${TDE_KEY_NAME}-default','${TDE_PROVIDER_NAME}');" \ + || tde_bootstrap_fatal "failed to set default principal key '${TDE_KEY_NAME}-default'" + fi fi # WAL encryption is global-only: the file keyring is a database-scoped From 092a48969f07c9f3d276575f367fa95e2ecd2043 Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Wed, 15 Jul 2026 22:12:18 +0600 Subject: [PATCH 11/11] tde: honor the Vault Enterprise namespace in the key-provider registration The operator maps spec.tde.keyProvider.vault.namespace to the TDE_VAULT_NAMESPACE env, but the bootstrap called the 5-arg pg_tde_add_global_key_provider_vault_v2 and never passed it, so a configured Vault Enterprise namespace was silently dropped. pg_tde 2.x has a 6-arg overload that takes the namespace; use it when TDE_VAULT_NAMESPACE is set, keeping the 5-arg form for the common namespace-less case. Only the primary registers the provider (standbys inherit it via pg_tde_basebackup), so this is the sole registration site. Signed-off-by: Tamal Saha --- role_scripts/10/primary/start.sh | 14 ++++++++++++-- role_scripts/11/primary/start.sh | 14 ++++++++++++-- role_scripts/12/primary/start.sh | 14 ++++++++++++-- role_scripts/13/primary/start.sh | 14 ++++++++++++-- role_scripts/14/primary/start.sh | 14 ++++++++++++-- role_scripts/15/primary/start.sh | 14 ++++++++++++-- role_scripts/16/primary/start.sh | 14 ++++++++++++-- role_scripts/17/primary/start.sh | 14 ++++++++++++-- role_scripts/18/primary/start.sh | 14 ++++++++++++-- role_scripts/9/primary/start.sh | 14 ++++++++++++-- 10 files changed, 120 insertions(+), 20 deletions(-) diff --git a/role_scripts/10/primary/start.sh b/role_scripts/10/primary/start.sh index f45508c..82b95fb 100755 --- a/role_scripts/10/primary/start.sh +++ b/role_scripts/10/primary/start.sh @@ -123,8 +123,18 @@ SQL # Register the key provider (global preferred; file is standalone only). case "${TDE_PROVIDER_KIND:-}" in vault) - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + # pg_tde_add_global_key_provider_vault_v2 has a 5-arg form and a 6-arg + # form that also takes a Vault Enterprise namespace. Pass the namespace + # (spec.tde.keyProvider.vault.namespace -> TDE_VAULT_NAMESPACE) only when + # it is set, so the common namespace-less case keeps the 5-arg form; the + # namespace was otherwise accepted in the CRD but silently dropped here. + if [[ -n "${TDE_VAULT_NAMESPACE:-}" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}','${TDE_VAULT_NAMESPACE}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + fi ;; kmip) psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/11/primary/start.sh b/role_scripts/11/primary/start.sh index 8275950..c57f807 100755 --- a/role_scripts/11/primary/start.sh +++ b/role_scripts/11/primary/start.sh @@ -132,8 +132,18 @@ SQL # Register the key provider (global preferred; file is standalone only). case "${TDE_PROVIDER_KIND:-}" in vault) - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + # pg_tde_add_global_key_provider_vault_v2 has a 5-arg form and a 6-arg + # form that also takes a Vault Enterprise namespace. Pass the namespace + # (spec.tde.keyProvider.vault.namespace -> TDE_VAULT_NAMESPACE) only when + # it is set, so the common namespace-less case keeps the 5-arg form; the + # namespace was otherwise accepted in the CRD but silently dropped here. + if [[ -n "${TDE_VAULT_NAMESPACE:-}" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}','${TDE_VAULT_NAMESPACE}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + fi ;; kmip) psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/12/primary/start.sh b/role_scripts/12/primary/start.sh index 0fc26d2..2c40315 100755 --- a/role_scripts/12/primary/start.sh +++ b/role_scripts/12/primary/start.sh @@ -152,8 +152,18 @@ SQL # Register the key provider (global preferred; file is standalone only). case "${TDE_PROVIDER_KIND:-}" in vault) - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + # pg_tde_add_global_key_provider_vault_v2 has a 5-arg form and a 6-arg + # form that also takes a Vault Enterprise namespace. Pass the namespace + # (spec.tde.keyProvider.vault.namespace -> TDE_VAULT_NAMESPACE) only when + # it is set, so the common namespace-less case keeps the 5-arg form; the + # namespace was otherwise accepted in the CRD but silently dropped here. + if [[ -n "${TDE_VAULT_NAMESPACE:-}" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}','${TDE_VAULT_NAMESPACE}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + fi ;; kmip) psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/13/primary/start.sh b/role_scripts/13/primary/start.sh index 4301e52..cafc761 100755 --- a/role_scripts/13/primary/start.sh +++ b/role_scripts/13/primary/start.sh @@ -173,8 +173,18 @@ SQL # Register the key provider (global preferred; file is standalone only). case "${TDE_PROVIDER_KIND:-}" in vault) - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + # pg_tde_add_global_key_provider_vault_v2 has a 5-arg form and a 6-arg + # form that also takes a Vault Enterprise namespace. Pass the namespace + # (spec.tde.keyProvider.vault.namespace -> TDE_VAULT_NAMESPACE) only when + # it is set, so the common namespace-less case keeps the 5-arg form; the + # namespace was otherwise accepted in the CRD but silently dropped here. + if [[ -n "${TDE_VAULT_NAMESPACE:-}" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}','${TDE_VAULT_NAMESPACE}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + fi ;; kmip) psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/14/primary/start.sh b/role_scripts/14/primary/start.sh index 08dd11a..7ebe72e 100755 --- a/role_scripts/14/primary/start.sh +++ b/role_scripts/14/primary/start.sh @@ -177,8 +177,18 @@ SQL # Register the key provider (global preferred; file is standalone only). case "${TDE_PROVIDER_KIND:-}" in vault) - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + # pg_tde_add_global_key_provider_vault_v2 has a 5-arg form and a 6-arg + # form that also takes a Vault Enterprise namespace. Pass the namespace + # (spec.tde.keyProvider.vault.namespace -> TDE_VAULT_NAMESPACE) only when + # it is set, so the common namespace-less case keeps the 5-arg form; the + # namespace was otherwise accepted in the CRD but silently dropped here. + if [[ -n "${TDE_VAULT_NAMESPACE:-}" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}','${TDE_VAULT_NAMESPACE}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + fi ;; kmip) psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/15/primary/start.sh b/role_scripts/15/primary/start.sh index 3b8ede1..f128bd2 100755 --- a/role_scripts/15/primary/start.sh +++ b/role_scripts/15/primary/start.sh @@ -180,8 +180,18 @@ SQL # Register the key provider (global preferred; file is standalone only). case "${TDE_PROVIDER_KIND:-}" in vault) - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + # pg_tde_add_global_key_provider_vault_v2 has a 5-arg form and a 6-arg + # form that also takes a Vault Enterprise namespace. Pass the namespace + # (spec.tde.keyProvider.vault.namespace -> TDE_VAULT_NAMESPACE) only when + # it is set, so the common namespace-less case keeps the 5-arg form; the + # namespace was otherwise accepted in the CRD but silently dropped here. + if [[ -n "${TDE_VAULT_NAMESPACE:-}" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}','${TDE_VAULT_NAMESPACE}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + fi ;; kmip) psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/16/primary/start.sh b/role_scripts/16/primary/start.sh index 212dfca..21980b6 100755 --- a/role_scripts/16/primary/start.sh +++ b/role_scripts/16/primary/start.sh @@ -178,8 +178,18 @@ SQL # Register the key provider (global preferred; file is standalone only). case "${TDE_PROVIDER_KIND:-}" in vault) - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + # pg_tde_add_global_key_provider_vault_v2 has a 5-arg form and a 6-arg + # form that also takes a Vault Enterprise namespace. Pass the namespace + # (spec.tde.keyProvider.vault.namespace -> TDE_VAULT_NAMESPACE) only when + # it is set, so the common namespace-less case keeps the 5-arg form; the + # namespace was otherwise accepted in the CRD but silently dropped here. + if [[ -n "${TDE_VAULT_NAMESPACE:-}" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}','${TDE_VAULT_NAMESPACE}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + fi ;; kmip) psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/17/primary/start.sh b/role_scripts/17/primary/start.sh index d9094ad..b7b3d57 100755 --- a/role_scripts/17/primary/start.sh +++ b/role_scripts/17/primary/start.sh @@ -183,8 +183,18 @@ SQL # Register the key provider (global preferred; file is standalone only). case "${TDE_PROVIDER_KIND:-}" in vault) - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + # pg_tde_add_global_key_provider_vault_v2 has a 5-arg form and a 6-arg + # form that also takes a Vault Enterprise namespace. Pass the namespace + # (spec.tde.keyProvider.vault.namespace -> TDE_VAULT_NAMESPACE) only when + # it is set, so the common namespace-less case keeps the 5-arg form; the + # namespace was otherwise accepted in the CRD but silently dropped here. + if [[ -n "${TDE_VAULT_NAMESPACE:-}" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}','${TDE_VAULT_NAMESPACE}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + fi ;; kmip) psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/18/primary/start.sh b/role_scripts/18/primary/start.sh index 87182dd..2c108ba 100755 --- a/role_scripts/18/primary/start.sh +++ b/role_scripts/18/primary/start.sh @@ -176,8 +176,18 @@ SQL # Register the key provider (global preferred; file is standalone only). case "${TDE_PROVIDER_KIND:-}" in vault) - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + # pg_tde_add_global_key_provider_vault_v2 has a 5-arg form and a 6-arg + # form that also takes a Vault Enterprise namespace. Pass the namespace + # (spec.tde.keyProvider.vault.namespace -> TDE_VAULT_NAMESPACE) only when + # it is set, so the common namespace-less case keeps the 5-arg form; the + # namespace was otherwise accepted in the CRD but silently dropped here. + if [[ -n "${TDE_VAULT_NAMESPACE:-}" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}','${TDE_VAULT_NAMESPACE}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + fi ;; kmip) psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ diff --git a/role_scripts/9/primary/start.sh b/role_scripts/9/primary/start.sh index 8d5eba4..25a4d9c 100755 --- a/role_scripts/9/primary/start.sh +++ b/role_scripts/9/primary/start.sh @@ -118,8 +118,18 @@ SQL # Register the key provider (global preferred; file is standalone only). case "${TDE_PROVIDER_KIND:-}" in vault) - psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ - "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + # pg_tde_add_global_key_provider_vault_v2 has a 5-arg form and a 6-arg + # form that also takes a Vault Enterprise namespace. Pass the namespace + # (spec.tde.keyProvider.vault.namespace -> TDE_VAULT_NAMESPACE) only when + # it is set, so the common namespace-less case keeps the 5-arg form; the + # namespace was otherwise accepted in the CRD but silently dropped here. + if [[ -n "${TDE_VAULT_NAMESPACE:-}" ]]; then + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}','${TDE_VAULT_NAMESPACE}');" || true + else + psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \ + "SELECT pg_tde_add_global_key_provider_vault_v2('${TDE_PROVIDER_NAME}','${TDE_VAULT_ADDR}','${TDE_VAULT_MOUNT}','${TDE_VAULT_TOKEN_PATH}','${TDE_VAULT_CA_PATH}');" || true + fi ;; kmip) psql -U postgres -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c \