aboutsummaryrefslogtreecommitdiff
path: root/perl/lib
diff options
context:
space:
mode:
authorJon Robertson <jonrober@stanford.edu>2015-04-16 14:58:58 -0700
committerJon Robertson <jonrober@stanford.edu>2015-06-08 15:24:34 -0700
commit45a7c9d2896cf2e0d1548fd98b3b78f9f812744f (patch)
treea8fc5f7ec8ae6c634f80c404a3c015d9300f4987 /perl/lib
parentf3da929ff35f24163ab56dbd9615ee6a1c5336d8 (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.pm28
-rw-r--r--perl/lib/Wallet/Policy/Stanford.pm49
-rw-r--r--perl/lib/Wallet/Report.pm70
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