summaryrefslogtreecommitdiff
path: root/perl/t
diff options
context:
space:
mode:
authorRuss Allbery <rra@stanford.edu>2007-11-15 05:42:29 +0000
committerRuss Allbery <rra@stanford.edu>2007-11-15 05:42:29 +0000
commit2393ffbc3c52c6552e00212d5209d6b870a55d4e (patch)
tree2eaca996ede5d9b835db69f6ac143e8cba051d36 /perl/t
parentb6bb3f3a72ec1dc32991cffeeab4f8b1cc27cc46 (diff)
Add an ACL verifier that checks access against NetDB roles using the
NetDB remctl interface.
Diffstat (limited to 'perl/t')
-rw-r--r--perl/t/data/keytab.conf10
-rwxr-xr-xperl/t/data/netdb-fake58
-rw-r--r--perl/t/data/netdb.conf10
-rwxr-xr-xperl/t/verifier.t134
4 files changed, 204 insertions, 8 deletions
diff --git a/perl/t/data/keytab.conf b/perl/t/data/keytab.conf
index eb105e2..e7908ed 100644
--- a/perl/t/data/keytab.conf
+++ b/perl/t/data/keytab.conf
@@ -1,10 +1,6 @@
# $Id$
#
-# This is the remctl configuration used for testing the keytab backend's
-# ability to retrieve existing keytabs through remctl. Currently the only
-# supported and used command is keytab retrieve. The ACL is written on
-# the fly by the test program.
-#
-# Compare to config/keytab.
+# This is the remctl configuration used for testing the NetDB ACL verifier.
+# The ACL is written on the fly by the test program.
-keytab retrieve t/data/keytab-fake test-acl
+netdb node-roles t/data/netdb-fake test-acl
diff --git a/perl/t/data/netdb-fake b/perl/t/data/netdb-fake
new file mode 100755
index 0000000..56744a7
--- /dev/null
+++ b/perl/t/data/netdb-fake
@@ -0,0 +1,58 @@
+#!/bin/sh
+# $Id$
+#
+# netdb-fake -- Fake NetDB remctl interface.
+#
+# This netdb-fake script is meant to be run by remctld during testing of
+# the NetDB ACL verifier. It returns known roles or errors for different
+# nodes.
+
+set -e
+
+if [ "$1" != "node-roles" ] ; then
+ echo "Invalid command $1" >&2
+ exit 1
+fi
+
+case "$2" in
+test-user)
+ case "$3" in
+ all)
+ echo 'admin'
+ echo 'team'
+ echo 'user'
+ ;;
+ admin)
+ echo 'admin'
+ ;;
+ team)
+ echo 'team'
+ ;;
+ user)
+ echo 'This is just ignored' >&2
+ echo 'user'
+ ;;
+ unknown)
+ echo 'admin' >&2
+ echo 'unknown'
+ ;;
+ none)
+ ;;
+ esac
+ ;;
+error)
+ case "$3" in
+ normal)
+ echo 'some error' >&2
+ exit 1
+ ;;
+ status)
+ exit 1
+ ;;
+ esac
+ ;;
+*)
+ echo "Unknown principal $2" >&2
+ exit 1
+ ;;
+esac
diff --git a/perl/t/data/netdb.conf b/perl/t/data/netdb.conf
new file mode 100644
index 0000000..eb105e2
--- /dev/null
+++ b/perl/t/data/netdb.conf
@@ -0,0 +1,10 @@
+# $Id$
+#
+# This is the remctl configuration used for testing the keytab backend's
+# ability to retrieve existing keytabs through remctl. Currently the only
+# supported and used command is keytab retrieve. The ACL is written on
+# the fly by the test program.
+#
+# Compare to config/keytab.
+
+keytab retrieve t/data/keytab-fake test-acl
diff --git a/perl/t/verifier.t b/perl/t/verifier.t
index 713c495..467115f 100755
--- a/perl/t/verifier.t
+++ b/perl/t/verifier.t
@@ -8,10 +8,67 @@
#
# See LICENSE for licensing terms.
-use Test::More tests => 13;
+use Test::More tests => 37;
use Wallet::ACL::Base;
use Wallet::ACL::Krb5;
+use Wallet::ACL::NetDB;
+use Wallet::Config;
+
+# Returns the one-line contents of a file as a string, removing the newline.
+sub contents {
+ my ($file) = @_;
+ open (FILE, '<', $file) or die "cannot open $file: $!\n";
+ my $data = <FILE>;
+ close FILE;
+ chomp $data;
+ return $data;
+}
+
+# Given a keytab file, try authenticating with kinit.
+sub getcreds {
+ my ($file, $principal) = @_;
+ my @commands = (
+ "kinit -k -t $file $principal >/dev/null </dev/null",
+ "kinit -t $file $principal >/dev/null </dev/null",
+ "kinit -k -K $file $principal >/dev/null </dev/null",
+ );
+ for my $command (@commands) {
+ if (system ($command) == 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+# Start remctld with the appropriate options to run our fake keytab backend.
+sub spawn_remctld {
+ my ($path, $principal, $keytab) = @_;
+ unlink 'test-pid';
+ my $pid = fork;
+ if (not defined $pid) {
+ die "cannot fork: $!\n";
+ } elsif ($pid == 0) {
+ open (STDERR, '>&STDOUT') or die "cannot redirect stderr: $!\n";
+ exec ($path, '-m', '-p', 14373, '-s', $principal, '-P', 'test-pid',
+ '-f', 't/data/keytab.conf', '-S', '-F', '-k', $keytab) == 0
+ or die "cannot exec $path: $!\n";
+ } else {
+ my $tries = 0;
+ while ($tries < 10 && ! -f 'test-pid') {
+ select (undef, undef, undef, 0.25);
+ }
+ }
+}
+
+# Stop the running remctld process.
+sub stop_remctld {
+ open (PID, '<', 'test-pid') or return;
+ my $pid = <PID>;
+ close PID;
+ chomp $pid;
+ kill 15, $pid;
+}
my $verifier = Wallet::ACL::Base->new;
ok (defined $verifier, 'Wallet::ACL::Base creation');
@@ -33,3 +90,78 @@ is ($verifier->check (undef, 'rra@stanford.edu'), undef,
is ($verifier->error, 'no principal specified', ' and right error');
is ($verifier->check ('rra@stanford.edu', ''), undef, 'Empty ACL');
is ($verifier->error, 'malformed krb5 ACL', ' and right error');
+
+# Tests for unchanging support. Skip these if we don't have a keytab or if we
+# can't find remctld.
+SKIP: {
+ skip 'no keytab configuration', 24 unless -f 't/data/test.keytab';
+ my @path = (split (':', $ENV{PATH}), '/usr/local/sbin', '/usr/sbin');
+ my ($remctld) = grep { -x $_ } map { "$_/remctld" } @path;
+ skip 'remctld not found', 24 unless $remctld;
+ eval { require Net::Remctl };
+ skip 'Net::Remctl not available', 24 if $@;
+
+ # Set up our configuration.
+ $Wallet::Config::NETDB_REALM = 'EXAMPLE.COM';
+ my $principal = contents ('t/data/test.principal');
+
+ # Now spawn our remctld server and get a ticket cache.
+ unlink ('krb5cc_test', 'test-acl', 'test-pid');
+ spawn_remctld ($remctld, $principal, 't/data/test.keytab');
+ $ENV{KRB5CCNAME} = 'krb5cc_test';
+ getcreds ('t/data/test.keytab', $principal);
+
+ # Finally, we can test.
+ my $verifier = eval { Wallet::ACL::NetDB->new };
+ is ($verifier, undef, 'Constructor fails without configuration');
+ is ($@, "NetDB ACL support not configured\n", ' with the right exception');
+ $Wallet::Config::NETDB_REMCTL_CACHE = 'krb5cc_test';
+ $verifier = eval { Wallet::ACL::NetDB->new };
+ is ($verifier, undef, ' and still fails without host');
+ is ($@, "NetDB ACL support not configured\n", ' with the right exception');
+ $Wallet::Config::NETDB_REMCTL_HOST = 'localhost';
+ $Wallet::Config::NETDB_REMCTL_PRINCIPAL = $principal;
+ $Wallet::Config::NETDB_REMCTL_PORT = 14373;
+ $verifier = eval { Wallet::ACL::NetDB->new };
+ ok (defined $verifier, ' and now creation succeeds');
+ ok ($verifier->isa ('Wallet::ACL::NetDB'), ' and returns the right class');
+ is ($verifier->check ('test-user', 'all'), undef,
+ ' but verification fails without an ACL');
+ is ($verifier->error, 'cannot check NetDB ACL: Access denied',
+ ' with the right error');
+
+ # Create an ACL so that tests will start working.
+ open (ACL, '>', 'test-acl') or die "cannot create test-acl: $!\n";
+ print ACL "$principal\n";
+ close ACL;
+ is ($verifier->check ('test-user', 'all'), 1,
+ ' and now verification works');
+
+ # Test the successful verifications.
+ for my $node (qw/admin team user/) {
+ is ($verifier->check ('test-user', $node), 1,
+ "Verification succeeds for $node");
+ }
+
+ # Test various failures.
+ is ($verifier->check ('test-user', 'unknown'), 0,
+ 'Verification fails for unknown');
+ is ($verifier->check ('test-user', 'none'), 0, ' and for none');
+ is ($verifier->check (undef, 'all'), undef,
+ 'Undefined principal');
+ is ($verifier->error, 'no principal specified', ' and right error');
+ is ($verifier->check ('test-user', ''), undef, 'Empty ACL');
+ is ($verifier->error, 'malformed netdb ACL', ' and right error');
+ is ($verifier->check ('error', 'normal'), undef, 'Regular error');
+ is ($verifier->error, 'error checking NetDB ACL: some error',
+ ' and correct error return');
+ is ($verifier->check ('error', 'status'), undef, 'Status-only error');
+ is ($verifier->error, 'error checking NetDB ACL', ' and correct error');
+ is ($verifier->check ('unknown', 'unknown'), undef, 'Unknown node');
+ is ($verifier->error,
+ 'error checking NetDB ACL: Unknown principal unknown',
+ ' and correct error');
+ stop_remctld;
+
+ unlink ('krb5cc_test', 'test-acl', 'test-pid');
+}