Skip to content

Commit a7a6d89

Browse files
committed
PG-2258: Create WAL principal key eagerly with default keys
Previously we only created a global principal key on the first restart after creating a default key. This caused a basebackup taken immediately after it, without a restart between the two to fail. The fix is simple, we create the global principal key eagerly together with the default key if it doesn't exists yet. This additionally results in a better "normal" workflow since we no longer create a new principal key during startup.
1 parent 9464e50 commit a7a6d89

2 files changed

Lines changed: 80 additions & 0 deletions

File tree

src/catalog/tde_principal_key.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,13 +537,30 @@ pg_tde_set_default_key_using_global_key_provider(PG_FUNCTION_ARGS)
537537
{
538538
char *principal_key_name = PG_ARGISNULL(0) ? NULL : text_to_cstring(PG_GETARG_TEXT_PP(0));
539539
char *provider_name = PG_ARGISNULL(1) ? NULL : text_to_cstring(PG_GETARG_TEXT_PP(1));
540+
bool need_server_key;
540541

541542
/* Using a global provider for the default encryption setting */
542543
pg_tde_set_principal_key_internal(GLOBAL_DATA_TDE_OID,
543544
DEFAULT_DATA_TDE_OID,
544545
principal_key_name,
545546
provider_name);
546547

548+
/*
549+
* Ensure a server (WAL) principal key exists so that operations needing
550+
* it (e.g. pg_basebackup -E) work without first restarting the server.
551+
* Without this, the server key is only materialized lazily during the
552+
* next startup when WAL encryption is initialized.
553+
*/
554+
LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED);
555+
need_server_key = (GetPrincipalKeyNoDefault(GLOBAL_DATA_TDE_OID, LW_SHARED) == NULL);
556+
LWLockRelease(tde_lwlock_enc_keys());
557+
558+
if (need_server_key)
559+
pg_tde_set_principal_key_internal(GLOBAL_DATA_TDE_OID,
560+
GLOBAL_DATA_TDE_OID,
561+
principal_key_name,
562+
provider_name);
563+
547564
PG_RETURN_VOID();
548565
}
549566

t/basebackup_default_key.pl

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/usr/bin/perl
2+
3+
# Tests that pg_tde_basebackup -E works after setting just a default
4+
# principal key, without first restarting the primary. Before the fix,
5+
# the server (WAL) principal key was only materialized lazily on the
6+
# next server start, so taking an encrypted-WAL base backup of a freshly
7+
# configured cluster would fail with "could not find server principal key".
8+
9+
use strict;
10+
use warnings;
11+
use File::Basename;
12+
use Test::More;
13+
use PostgreSQL::Test::Cluster;
14+
use PostgreSQL::Test::Utils;
15+
use PostgreSQL::Test::RecursiveCopy;
16+
17+
my $keyfile = '/tmp/basebackup_default_key.per';
18+
unlink($keyfile);
19+
20+
my $primary = PostgreSQL::Test::Cluster->new('primary');
21+
$primary->init(allows_streaming => 1);
22+
$primary->append_conf('postgresql.conf',
23+
"shared_preload_libraries = 'pg_tde'");
24+
$primary->start;
25+
26+
$primary->safe_psql('postgres', 'CREATE EXTENSION pg_tde;');
27+
$primary->safe_psql('postgres',
28+
"SELECT pg_tde_add_global_key_provider_file('file-provider','$keyfile');"
29+
);
30+
$primary->safe_psql('postgres',
31+
"SELECT pg_tde_create_key_using_global_key_provider('key1','file-provider');"
32+
);
33+
$primary->safe_psql('postgres',
34+
"SELECT pg_tde_set_default_key_using_global_key_provider('key1','file-provider');"
35+
);
36+
37+
my $server_key = $primary->safe_psql('postgres',
38+
'SELECT key_name FROM pg_tde_server_key_info();');
39+
is($server_key, 'key1',
40+
'server principal key auto-configured when default key is set');
41+
42+
my $tempdir = PostgreSQL::Test::Utils::tempdir;
43+
my $backup_dir = "$tempdir/backup";
44+
45+
mkdir $backup_dir or die "mkdir $backup_dir failed: $!";
46+
PostgreSQL::Test::RecursiveCopy::copypath($primary->data_dir . '/pg_tde',
47+
$backup_dir . '/pg_tde');
48+
49+
$primary->command_ok(
50+
[
51+
'pg_tde_basebackup', '-D',
52+
$backup_dir, '-h',
53+
$primary->host, '-p',
54+
$primary->port, '--checkpoint',
55+
'fast', '--no-sync',
56+
'-E', '-X',
57+
'stream',
58+
],
59+
'pg_tde_basebackup -E succeeds after only setting default key');
60+
61+
$primary->stop;
62+
63+
done_testing();

0 commit comments

Comments
 (0)