App-Netdisco
view release on metacpan or search on metacpan
xt/91-external-credentials-host.t view on Meta::CPAN
#!/usr/bin/env perl
# get_credentials is a command template run through a shell, and %HOST% is
# filled from the device's DNS name, which the device's owner does not control.
# A name that is not shaped like a hostname is replaced by the address.
#
# The command below writes a file. Its absence after a run is what proves the
# injected text never reached the shell.
use strict;
use warnings;
BEGIN { $ENV{DANCER_ENVIRONMENT} = 'testing' }
use Test::More 0.88;
use File::Temp ();
use File::Spec::Functions 'catfile';
use App::Netdisco;
use Dancer qw/setting/;
use App::Netdisco::Util::DeviceAuth 'get_external_credentials';
my $dir = File::Temp->newdir();
{ package Test::FakeDevice;
sub new { my ($c, %a) = @_; return bless {%a}, $c }
sub ip { $_[0]->{ip} }
sub dns { $_[0]->{dns} }
}
subtest 'getExternalCredentials__an_ordinary_name__is_used' => sub {
setting('get_credentials' => 'echo community=%HOST%');
my @got = get_external_credentials(
Test::FakeDevice->new(ip => '192.0.2.10', dns => 'switch.example.com'), 'read');
is scalar @got, 1, 'one credential returned';
is $got[0]->{community}, 'switch.example.com', 'the name reached the command';
};
subtest 'getExternalCredentials__a_name_carrying_shell_syntax__never_reaches_the_shell' => sub {
my $marker = catfile($dir, 'fired');
setting('get_credentials' => 'echo community=%HOST%');
my @got = get_external_credentials(
Test::FakeDevice->new(ip => '192.0.2.10',
dns => "x.example.com'; touch '$marker"), 'read');
ok !-e $marker, 'the injected command did not run';
is $got[0]->{community}, '192.0.2.10', 'the address was used in place of the name';
};
subtest 'getExternalCredentials__a_name_with_a_metacharacter__falls_back_to_the_address' => sub {
setting('get_credentials' => 'echo community=%HOST%');
foreach my $dns ('a b', 'a;b', 'a`b`', 'a$(b)', 'a|b', '-leading', 'trailing-') {
my @got = get_external_credentials(
Test::FakeDevice->new(ip => '192.0.2.10', dns => $dns), 'read');
is $got[0]->{community}, '192.0.2.10', "[$dns] fell back to the address";
}
};
done_testing;
( run in 1.587 second using v1.01-cache-2.11-cpan-007c89162af )