File-SOPS
view release on metacpan or search on metacpan
t/84-max-stanzas-public-api.t view on Meta::CPAN
###############################################################################
# 4. Absence is byte-identical: an ordinary few-recipient document is
# unaffected by max_stanzas ever existing.
###############################################################################
subtest 'a normal document round-trips unchanged with max_stanzas absent' => sub {
my ($public2, $secret2) = Crypt::Age->generate_keypair();
my $yaml = File::SOPS->encrypt(
recipients => [ $public, $public2 ],
format => 'yaml',
data => { host => 'db.example.com', port => 5432 },
);
is_deeply(
File::SOPS->decrypt(encrypted => $yaml, identities => [$secret]),
{ host => 'db.example.com', port => 5432 },
'decrypts correctly via the first recipient, max_stanzas never mentioned',
);
is_deeply(
File::SOPS->decrypt(encrypted => $yaml, identities => [$secret2]),
{ host => 'db.example.com', port => 5432 },
' ... and via the second, same result',
);
};
###############################################################################
# 3. decrypt_file -- its own $class->decrypt(...) call site.
###############################################################################
subtest 'decrypt_file forwards max_stanzas through its own decrypt() call' => sub {
my ($file) = stanza_fixture(data => { secret => 'shh' });
my $output = "$dir/out-" . ++$serial . '.yaml';
my $err = do {
local $@;
eval {
File::SOPS->decrypt_file(
input => $file,
output => $output,
identities => [$secret],
);
};
$@;
};
like $err, qr/exceeding the max_stanzas limit of 64/,
'decrypt_file refuses the 65-stanza document without max_stanzas';
ok !-e $output, ' ... and never wrote the output file';
my $ok = eval {
File::SOPS->decrypt_file(
input => $file,
output => $output,
identities => [$secret],
max_stanzas => 65,
);
1;
};
is $@, '', 'max_stanzas => 65: decrypt_file does not croak';
ok $ok, ' ... and reports success';
is_deeply(
Load(do { local (@ARGV, $/) = $output; <> }),
{ secret => 'shh' },
' ... having written the correct plaintext',
);
};
###############################################################################
# 3. extract -- its own $class->decrypt(...) call site.
###############################################################################
subtest 'extract forwards max_stanzas through its own decrypt() call' => sub {
my ($file) = stanza_fixture(data => { secret => 'shh' });
my $err = do {
local $@;
eval {
File::SOPS->extract(
file => $file,
path => '["secret"]',
identities => [$secret],
);
};
$@;
};
like $err, qr/exceeding the max_stanzas limit of 64/,
'extract refuses the 65-stanza document without max_stanzas';
my $value = eval {
File::SOPS->extract(
file => $file,
path => '["secret"]',
identities => [$secret],
max_stanzas => 65,
);
};
is $@, '', 'max_stanzas => 65: extract does not croak';
is $value, 'shh', ' ... and returns the correct value';
};
###############################################################################
# 3. rotate -- its own $class->decrypt(...) call site. recipients is passed
# explicitly so the re-encryption step (which by default re-wraps for every
# entry in metadata->age) never has to touch the 64 dummy, non-age-shaped
# stanzas -- this test is about decrypt()'s max_stanzas guard inside rotate,
# not about rotate's separate "no foreign key material" contract.
###############################################################################
subtest 'rotate forwards max_stanzas through its own decrypt() call' => sub {
my ($file, $before_yaml) = stanza_fixture(data => { secret => 'shh' });
my $err = do {
local $@;
eval {
File::SOPS->rotate(
file => $file,
identities => [$secret],
recipients => [$public],
);
};
$@;
};
like $err, qr/exceeding the max_stanzas limit of 64/,
'rotate refuses the 65-stanza document without max_stanzas';
( run in 2.654 seconds using v1.01-cache-2.11-cpan-ac8be02dad9 )