diff options
| author | Russ Allbery <rra@stanford.edu> | 2007-11-15 05:42:29 +0000 | 
|---|---|---|
| committer | Russ Allbery <rra@stanford.edu> | 2007-11-15 05:42:29 +0000 | 
| commit | 2393ffbc3c52c6552e00212d5209d6b870a55d4e (patch) | |
| tree | 2eaca996ede5d9b835db69f6ac143e8cba051d36 /perl/t | |
| parent | b6bb3f3a72ec1dc32991cffeeab4f8b1cc27cc46 (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.conf | 10 | ||||
| -rwxr-xr-x | perl/t/data/netdb-fake | 58 | ||||
| -rw-r--r-- | perl/t/data/netdb.conf | 10 | ||||
| -rwxr-xr-x | perl/t/verifier.t | 134 | 
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'); +} | 
