diff options
| author | Jon Robertson <jonrober@stanford.edu> | 2015-04-16 14:58:58 -0700 | 
|---|---|---|
| committer | Jon Robertson <jonrober@stanford.edu> | 2015-06-08 15:24:34 -0700 | 
| commit | 45a7c9d2896cf2e0d1548fd98b3b78f9f812744f (patch) | |
| tree | a8fc5f7ec8ae6c634f80c404a3c015d9300f4987 /perl/lib | |
| parent | f3da929ff35f24163ab56dbd9615ee6a1c5336d8 (diff) | |
wallet-report: Added report of all host-based objects for host
"wallet-report objects host <hostname>" reports on all objects that
belong to the given host.  This can be used to query things for retiring
systems.
Change-Id: Ib1c8e5978fed141d54ecc8504b56b43c037f9b17
Diffstat (limited to 'perl/lib')
| -rw-r--r-- | perl/lib/Wallet/Config.pm | 28 | ||||
| -rw-r--r-- | perl/lib/Wallet/Policy/Stanford.pm | 49 | ||||
| -rw-r--r-- | perl/lib/Wallet/Report.pm | 70 | 
3 files changed, 130 insertions, 17 deletions
diff --git a/perl/lib/Wallet/Config.pm b/perl/lib/Wallet/Config.pm index 76c7ecd..b3e1931 100644 --- a/perl/lib/Wallet/Config.pm +++ b/perl/lib/Wallet/Config.pm @@ -792,6 +792,34 @@ keytab objects for particular principals have fully-qualified hostnames:  Objects that aren't of type C<keytab> or which aren't for a host-based key  have no naming requirements enforced by this example. +=head1 OBJECT HOST-BASED NAMES + +The above demonstrates having a host-based naming convention, where we +expect one part of an object name to be the name of the host that this +object is for.  The most obvious examples are those keytab objects +above, where we want certain keytab names to be in the form of +<service>/<hostname>.  It's then also useful to provide a Perl function +named is_for_host which then can be used to tell if a given object is a +host-based keytab for a specific host.  This function is then called by +the objects_hostname in Wallet::Report to give a list of all host-based +objects for a given hostname.  It should return true if the given object +is a host-based object for the hostname, otherwise false. + +An example that matches the same policy as the last verify_name example +would be: + +    sub is_for_host { +        my ($type, $name, $hostname) = @_; +        my %host_based = map { $_ => 1 } +            qw(HTTP cifs host imap ldap nfs pop sieve smtp webauth); +        return 0 unless $type eq 'keytab'; +        return 0 unless $name =~ m%/%; +        my ($service, $instance) = split ('/', $name, 2); +        return 0 unless $host_based{$service}; +        return 1 if $hostname eq $instance; +        return 0; +    } +  =head1 ACL NAMING ENFORCEMENT  Similar to object names, by default wallet permits administrators to diff --git a/perl/lib/Wallet/Policy/Stanford.pm b/perl/lib/Wallet/Policy/Stanford.pm index 362f098..86e204e 100644 --- a/perl/lib/Wallet/Policy/Stanford.pm +++ b/perl/lib/Wallet/Policy/Stanford.pm @@ -25,8 +25,8 @@ our (@EXPORT_OK, $VERSION);  # against circular module loading (not that we load any modules, but  # consistency is good).  BEGIN { -    $VERSION   = '1.00'; -    @EXPORT_OK = qw(default_owner verify_name); +    $VERSION   = '1.01'; +    @EXPORT_OK = qw(default_owner verify_name is_for_host);  }  ############################################################################## @@ -87,6 +87,18 @@ our %PASSWORD_TYPE = (      'service'         => {            extra => 1, need_extra => 1 },  ); +# Mappings that let us determine the host for a host-based object, if any. +our %HOST_FOR = ( +    'keytab'     => \&_host_for_keytab, +    'file'       => \&_host_for_file, +    'password'   => \&_host_for_password, +    'duo'        => \&_host_for_duo, +    'duo-pam'    => \&_host_for_duo, +    'duo-radius' => \&_host_for_duo, +    'duo-ldap'   => \&_host_for_duo, +    'duo-rdp'    => \&_host_for_duo, +); +  # Host-based file object types for the legacy file object naming scheme.  our @FILE_HOST_LEGACY = qw(htpasswd ssh-rsa ssh-dsa ssl-key tivoli-key); @@ -204,6 +216,23 @@ sub _host_for_duo {      return $name;  } +# Take a object type and name, along with a host name, and use these to +# decide if the given object is host-based and matches the given host. +sub is_for_host { +    my ($type, $name, $host) = @_; + +    # If we have a possible host mapping, get the host and see if it matches. +    if (defined($HOST_FOR{$type})) { +        my $object_host = $HOST_FOR{$type}->($name); +        return 0 unless $object_host; +        if ($host eq $object_host) { +            return 1; +        } +    } + +    return 0; +} +  # The default owner of host-based objects should be the host keytab and the  # NetDB ACL for that host, with one twist.  If the creator of a new node is  # using a root instance, we want to require everyone managing that node be @@ -211,21 +240,9 @@ sub _host_for_duo {  sub default_owner {      my ($type, $name) = @_; -    # How to determine the host for host-based objects. -    my %host_for = ( -        'keytab'     => \&_host_for_keytab, -        'file'       => \&_host_for_file, -        'password'   => \&_host_for_password, -        'duo'        => \&_host_for_duo, -        'duo-pam'    => \&_host_for_duo, -        'duo-radius' => \&_host_for_duo, -        'duo-ldap'   => \&_host_for_duo, -        'duo-rdp'    => \&_host_for_duo, -    ); -      # If we have a possible host mapping, see if we can use that. -    if (defined($host_for{$type})) { -        my $host = $host_for{$type}->($name); +    if (defined($HOST_FOR{$type})) { +        my $host = $HOST_FOR{$type}->($name);          if ($host) {              my $acl_name = "host/$host";              my @acl; diff --git a/perl/lib/Wallet/Report.pm b/perl/lib/Wallet/Report.pm index 4d92d64..fc7bb4d 100644 --- a/perl/lib/Wallet/Report.pm +++ b/perl/lib/Wallet/Report.pm @@ -249,7 +249,7 @@ sub objects {  # Farms out specific statement to another subroutine for specific search  # types, but each case should return ob_type and ob_name in that order.  sub objects_history { -    my ($self, $type, @args) = @_; +    my ($self, $search_type, @args) = @_;      undef $self->{error};      # All fields in the order we want to see them. @@ -284,6 +284,56 @@ sub objects_history {      return @objects;  } +# Returns a list of all objects stored in the wallet database in the form of +# type and name pairs.  On error and for an empty database, the empty list +# will be returned.  To distinguish between an empty list and an error, call +# error(), which will return undef if there was no error.  Farms out specific +# statement to another subroutine for specific search types, but each case +# should return ob_type and ob_name in that order. +sub objects_hostname { +    my ($self, $type, $hostname) = @_; +    undef $self->{error}; + +    # Make sure we have a given hostname. +    if (!$hostname) { +        $self->error ("object hosts requires one argument to search"); +        return; +    } + +    # If we don't have a way to get host-based object lists, quit. +    unless (defined &Wallet::Config::is_for_host) { +        $self->error ('no host-based policy defined'); +        return; +    } + +    # Search on all objects. +    my %search = (); +    my %options = (order_by => [ qw/ob_type ob_name/ ], +                   select   => [ qw/ob_type ob_name/ ]); + +    my @objects; +    my $schema = $self->{schema}; +    eval { +        my @objects_rs = $schema->resultset('Object')->search (\%search, +                                                               \%options); + +        # Check to see if an object is for the given host and add to list if +        # so. +        for my $object_rs (@objects_rs) { +            my $type = $object_rs->ob_type; +            my $name = $object_rs->ob_name; +            next unless &Wallet::Config::is_for_host($type, $name, $hostname); +            push (@objects, [ $type, $name ]); +        } +    }; +    if ($@) { +        $self->error ("cannot list objects: $@"); +        return; +    } + +    return @objects; +} +  ##############################################################################  # Type reports  ############################################################################## @@ -753,6 +803,24 @@ empty search result, the caller should call error().  error() is  guaranteed to return the error message if there was an error and undef if  there was no error. +=item objects_history(TYPE) + +Returns a dump of the entire object history table.  The return value is +a list of references to each field in that table, in the following order: + +    oh_on, oh_by, oh_type, oh_name, oh_action, oh_from + +=item objects_hostname(TYPE, HOSTNAME) + +Returns a list of all host-based objects for a given hostname.  The +output is identical to the general objects command, but we need to +separate this out because the way it searches is very different. + +Returns the empty list on failure.  To distinguish between this and an +empty search result, the caller should call error().  error() is +guaranteed to return the error message if there was an error and undef if +there was no error. +  =item owners(TYPE, NAME)  Returns a list of all ACL lines contained in owner ACLs for objects  | 
