[PATCH] Wallet: implement updating owner of objects

Ross Smith rjsm at umich.edu
Mon Apr 1 15:01:18 EDT 2013


This patch implements a way that objects can have their owner updated
automatically.  The method relies on the existing default_owner
behavior and adds Wallet::Config::replace_acl to configure which
keytabs can be updated.  replace_acl works in the same manner as
verify_name in that returning a value will disallow an object from
having it's owner automatically updated.

Our use cases for this behavior is based around host provisioning.  We
use it to allow computers to update their host keytab to match the
fqdn if the system is redeployed.  It is also used to automate the
ability of new staff to load machines without manually updating a
large number of acls.

This patch should apply cleanly to the released 1.0 version of wallet.

Ross Smith <rjsm at umich.edu>
---------------------------------------------------------------------------

diff --git a/perl/Wallet/ACL.pm b/perl/Wallet/ACL.pm
index 2a06442..a5828aa 100644
--- a/perl/Wallet/ACL.pm
+++ b/perl/Wallet/ACL.pm
@@ -311,6 +311,19 @@ sub remove {
     return 1;
 }

+sub replace {
+	my ($self, $ref_acl, $user, $host) = @_;
+	my @acl = @$ref_acl;
+	my @entries = $self->list;
+	for my $i (0 .. $#entries) {
+		return unless ($self->remove ($entries[$i][0], $entries[$i][1],
$user, $host));
+    }
+    for my $i (0 .. $#acl) {
+        return unless ($self->add ($acl[$i][0],$acl[$i][1], $user, $host));
+    }
+    return 1;
+}
+
 ##############################################################################
 # ACL checking
 ##############################################################################
diff --git a/perl/Wallet/Server.pm b/perl/Wallet/Server.pm
index dfb7dbb..feb4e81 100644
--- a/perl/Wallet/Server.pm
+++ b/perl/Wallet/Server.pm
@@ -82,6 +82,60 @@ sub DESTROY {
     }
 }

+# Update the owner of an object based on default_owner.
+sub update_owner {
+    my ($self, $type, $name) = @_;
+    my $user = $self->{user};
+    my $host = $self->{host};
+    my $schema = $self->{schema};
+    return 1 unless (defined (&Wallet::Config::default_owner));
+    return 1 unless (defined (&Wallet::Config::replace_acl));
+    my $result = Wallet::Config::replace_acl($type, $name);
+    return 1 if ($result);
+    my ($aname, @acl) = Wallet::Config::default_owner($type, $name);
+    my $object = $self->retrieve ($type, $name);
+    return 1 unless ($object);
+    my $owner  = $object->owner;
+    my $oacl = Wallet::ACL->new ($owner, $schema)  unless ($owner == '');
+    $owner = $oacl->name unless ($owner == '');
+
+    if (($owner eq $aname) and ($owner != '')) { #only update existing
+        my $acl = Wallet::ACL->new ($aname, $schema);
+        unless ($acl->replace (\@acl, $user, $host)) {
+            $self->error($acl->error);
+            return;
+        }
+        return 1;
+    } elsif ($aname) { #now have a different owner
+        $object-> owner ($aname, $user, $host);
+        $oacl->destroy ($user, $host) if ($owner);
+        my $acl = eval { Wallet::ACL->new ($aname, $schema) };
+        if ($@) {
+            $acl = eval { Wallet::ACL->create ($aname, $schema,
$user, $host) };
+            if ($@) {
+                $self->error ($@);
+                return;
+            }
+            for my $entry (@acl) {
+                unless ($acl->add ($entry->[0], $entry->[1], $user, $host)) {
+                    $self->error ($acl->error);
+                    return;
+                }
+            }
+        } else {
+            $acl->replace(\@acl, $user, $host);
+        }
+
+        return 1;
+    } elsif ($owner) { #no longer have an owner!
+        $object->owner ('',$user, $host);
+        $oacl->destroy;
+        return 1;
+    } else { #didn't and don't
+        return 1;
+    }
+}
+
 ##############################################################################
 # Object methods
 ##############################################################################
@@ -125,6 +179,7 @@ sub create_check {
     my $user = $self->{user};
     my $host = $self->{host};
     my $schema = $self->{schema};
+    $self->update_owner($type, $name);
     unless (defined (&Wallet::Config::default_owner)) {
         $self->error ("$user not authorized to create ${type}:${name}");
         return;
@@ -329,6 +384,7 @@ sub acl_verify {
 sub acl {
     my ($self, $type, $name, $acl, $id) = @_;
     undef $self->{error};
+    $self->update_owner($type, $name);
     my $object = $self->retrieve ($type, $name);
     return unless defined $object;
     unless ($self->{admin}->check ($self->{user})) {
@@ -351,6 +407,7 @@ sub acl {
 sub attr {
     my ($self, $type, $name, $attr, @values) = @_;
     undef $self->{error};
+    $self->update_owner($type, $name);
     my $object = $self->retrieve ($type, $name);
     return unless defined $object;
     my $user = $self->{user};
@@ -379,6 +436,7 @@ sub attr {
 sub comment {
     my ($self, $type, $name, $comment) = @_;
     undef $self->{error};
+    $self->update_owner($type, $name);
     my $object = $self->retrieve ($type, $name);
     return unless defined $object;
     my $result;
@@ -399,6 +457,7 @@ sub comment {
 sub expires {
     my ($self, $type, $name, $expires) = @_;
     undef $self->{error};
+    $self->update_owner($type, $name);
     my $object = $self->retrieve ($type, $name);
     return unless defined $object;
     unless ($self->{admin}->check ($self->{user})) {
@@ -421,6 +480,7 @@ sub expires {
 sub owner {
     my ($self, $type, $name, $owner) = @_;
     undef $self->{error};
+    $self->update_owner($type, $name);
     my $object = $self->retrieve ($type, $name);
     return unless defined $object;
     unless ($self->{admin}->check ($self->{user})) {
@@ -461,6 +521,7 @@ sub check {
 # object using the default ACL mappings (if any).
 sub get {
     my ($self, $type, $name) = @_;
+    $self->update_owner($type, $name);
     my $object = $self->retrieve ($type, $name);
     return unless defined $object;
     return unless $self->acl_verify ($object, 'get');
@@ -476,6 +537,7 @@ sub get {
 # default ACL mappings (if any).
 sub store {
     my ($self, $type, $name, $data) = @_;
+    $self->update_owner($type, $name);
     my $object = $self->retrieve ($type, $name);
     return unless defined $object;
     return unless $self->acl_verify ($object, 'store');
@@ -493,6 +555,7 @@ sub store {
 # user isn't authorized.
 sub show {
     my ($self, $type, $name) = @_;
+    $self->update_owner($type, $name);
     my $object = $self->retrieve ($type, $name);
     return unless defined $object;
     return unless $self->acl_verify ($object, 'show');
@@ -506,6 +569,7 @@ sub show {
 # isn't authorized.
 sub history {
     my ($self, $type, $name) = @_;
+    $self->update_owner($type, $name);
     my $object = $self->retrieve ($type, $name);
     return unless defined $object;
     return unless $self->acl_verify ($object, 'show');
@@ -518,6 +582,7 @@ sub history {
 # object can't be found or if the user isn't authorized.
 sub destroy {
     my ($self, $type, $name) = @_;
+    $self->update_owner($type, $name);
     my $object = $self->retrieve ($type, $name);
     return unless defined $object;
     return unless $self->acl_verify ($object, 'destroy');


More information about the Kerberos mailing list