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 )