aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO8
-rw-r--r--client/wallet.pod29
-rwxr-xr-xserver/wallet-backend85
-rw-r--r--tests/server/backend-t.in66
4 files changed, 135 insertions, 53 deletions
diff --git a/TODO b/TODO
index bb5c926..dcf5b90 100644
--- a/TODO
+++ b/TODO
@@ -2,14 +2,12 @@
Required to replace leland_srvtab:
-* Add arbitrary attribute setting and retrieval to objects and include the
- attributes in the object show display.
-
* Add support for limiting the enctypes of created keytabs by setting the
- enctype attribute on the object.
+ enctype attribute on the object and include the enctypes in the object
+ show display.
* Add an attribute indicating that the principal should be synchronized
- with Kerberos v4.
+ with Kerberos v4 and include it in the object show display.
* Implement creation of srvtabs from keytabs in the wallet client.
diff --git a/client/wallet.pod b/client/wallet.pod
index 263e623..3f7c60b 100644
--- a/client/wallet.pod
+++ b/client/wallet.pod
@@ -102,10 +102,12 @@ options and commands are ignored.
As mentioned above, most commands are only available to wallet
administrators. The exceptions are C<get>, C<store>, C<show>, C<destroy>,
-C<flag clear>, and C<flag set>. All of those commands have their own
-ACLs, and if the appropriate ACL is set, it alone is checked to see if the
-user has access. Otherwise, C<get>, C<store>, and C<show> access is
-permitted if the user is authorized by the owner ACL of the object.
+C<flag clear>, C<flag set>, C<getattr>, and C<setattr>. All of those
+commands have their own ACLs except C<getattr>, which uses the C<show>
+ACL, and C<setattr>, which uses the C<show> ACL. If the appropriate ACL
+is set, it alone is checked to see if the user has access. Otherwise,
+C<get>, C<store>, C<show>, C<getattr>, and C<setattr> access is permitted
+if the user is authorized by the owner ACL of the object.
Administrators can run any command on any object or ACL except for C<get>
and C<store>. For C<get> and C<show>, they must still be authorized by
@@ -205,6 +207,15 @@ if the C<get>, C<store>, or C<show> ACLs aren't set, authorization falls
back to checking the owner ACL. See the C<owner> command for displaying
or setting it.
+=item getattr <type> <name> <attr>
+
+Prints the object attribute <attr> for the object identified by <type> and
+<name>. Attributes are used to store backend-specific information for a
+particular object type, and <attr> must be an attribute type known to the
+underlying object implementation. The attribute values, if any, are
+printed one per line. If the attribute is not set on this object, nothing
+is printed.
+
=item owner <type> <name> [<owner>]
If <owner> is not given, displays the current owner ACL of the object
@@ -221,6 +232,16 @@ Sets the ACL <acl>, which must be one of C<get>, C<store>, C<show>,
C<destroy>, or C<flags>, to <id> on the object identified by <type> and
<name>. If <id> is the empty string, clears that ACL on the object.
+=item setattr <type> <name> <attr> <value> [<value> ...]
+
+Sets the object attribute <attr> for the object identified by <type> and
+<name>. Attributes are used to store backend-specific information for a
+particular object type, and <attr> must be an attribute type known to the
+underlying object implementation. To clear the attribute for this object,
+pass in a <value> of the empty string (C<''>).
+
+Currently, no object attributes are implemented.
+
=item show <type> <name>
Displays the current object metadata for the object identified by <type>
diff --git a/server/wallet-backend b/server/wallet-backend
index b54f6c3..2ab3daf 100755
--- a/server/wallet-backend
+++ b/server/wallet-backend
@@ -23,16 +23,16 @@ use Wallet::Server;
# Check all arguments against a very restricted set of allowed characters and
# to ensure the right number of arguments are taken. The arguments are the
-# number of arguments expected, a reference to an array of which argument
-# numbers shouldn't be checked, and then the arguments.
+# number of arguments expected (minimum and maximum), a reference to an array
+# of which argument numbers shouldn't be checked, and then the arguments.
#
# This function is probably temporary and will be replaced with something that
# knows more about the syntax of each command and can check more things.
sub check_args {
- my ($count, $exclude, @args) = @_;
- if (@args < $count) {
+ my ($min, $max, $exclude, @args) = @_;
+ if (@args < $min) {
die "insufficient arguments\n";
- } elsif (@args > $count) {
+ } elsif (@args > $max and $max != -1) {
die "too many arguments\n";
}
my %exclude = map { $_ => 1 } @$exclude;
@@ -63,22 +63,22 @@ sub command {
if ($command eq 'acl') {
my $action = shift @args;
if ($action eq 'add') {
- check_args (3, [], @args);
+ check_args (3, 3, [], @args);
$server->acl_add (@args) or die $server->error;
} elsif ($action eq 'create') {
- check_args (1, [], @args);
+ check_args (1, 1, [], @args);
$server->acl_create (@args) or die $server->error;
} elsif ($action eq 'destroy') {
- check_args (1, [], @args);
+ check_args (1, 1, [], @args);
$server->acl_destroy (@args) or die $server->error;
} elsif ($action eq 'remove') {
- check_args (3, [], @args);
+ check_args (3, 3, [], @args);
$server->acl_remove (@args) or die $server->error;
} elsif ($action eq 'rename') {
- check_args (2, [], @args);
+ check_args (2, 2, [], @args);
$server->acl_rename (@args) or die $server->error;
} elsif ($action eq 'show') {
- check_args (1, [], @args);
+ check_args (1, 1, [], @args);
my $output = $server->acl_show (@args);
if (defined $output) {
print $output;
@@ -89,17 +89,16 @@ sub command {
die "unknown command acl $action\n";
}
} elsif ($command eq 'create') {
- check_args (2, [], @args);
+ check_args (2, 2, [], @args);
$server->create (@args) or die $server->error;
} elsif ($command eq 'destroy') {
- check_args (2, [], @args);
+ check_args (2, 2, [], @args);
$server->destroy (@args) or die $server->error;
} elsif ($command eq 'expires') {
+ check_args (2, 3, [], @args);
if (@args > 2) {
- check_args (3, [], @args);
$server->expires (@args) or die $server->error;
} else {
- check_args (2, [], @args);
my $output = $server->expires (@args);
if (defined $output) {
print $output, "\n";
@@ -111,17 +110,16 @@ sub command {
}
} elsif ($command eq 'flag') {
my $action = shift @args;
+ check_args (3, 3, [], @args);
if ($action eq 'clear') {
- check_args (3, [], @args);
$server->flag_clear (@args) or die $server->error;
} elsif ($action eq 'set') {
- check_args (3, [], @args);
$server->flag_set (@args) or die $server->error;
} else {
die "unknown command flag $action\n";
}
} elsif ($command eq 'get') {
- check_args (2, [], @args);
+ check_args (2, 2, [], @args);
my $output = $server->get (@args);
if (defined $output) {
print $output;
@@ -129,7 +127,7 @@ sub command {
die $server->error;
}
} elsif ($command eq 'getacl') {
- check_args (3, [], @args);
+ check_args (3, 3, [], @args);
my $output = $server->acl (@args);
if (defined $output) {
print $output, "\n";
@@ -138,12 +136,19 @@ sub command {
} else {
die $server->error;
}
+ } elsif ($command eq 'getattr') {
+ check_args (3, 3, [], @args);
+ my @result = $server->attr (@args);
+ if (not @result and $server->error) {
+ die $server->error;
+ } elsif (@result) {
+ print join ("\n", @result, '');
+ }
} elsif ($command eq 'owner') {
+ check_args (2, 3, [], @args);
if (@args > 2) {
- check_args (3, [], @args);
$server->owner (@args) or die $server->error;
} else {
- check_args (2, [], @args);
my $output = $server->owner (@args);
if (defined $output) {
print $output, "\n";
@@ -154,10 +159,13 @@ sub command {
}
}
} elsif ($command eq 'setacl') {
- check_args (4, [], @args);
+ check_args (4, 4, [], @args);
$server->acl (@args) or die $server->error;
+ } elsif ($command eq 'setattr') {
+ check_args (4, -1, [], @args);
+ $server->attr (@args) or die $server->error;
} elsif ($command eq 'show') {
- check_args (2, [], @args);
+ check_args (2, 2, [], @args);
my $output = $server->show (@args);
if (defined $output) {
print $output;
@@ -165,7 +173,7 @@ sub command {
die $server->error;
}
} elsif ($command eq 'store') {
- check_args (3, [3], @args);
+ check_args (3, 3, [3], @args);
$server->store (@args) or die $server->error;
} else {
die "unknown command $command\n";
@@ -214,10 +222,12 @@ B<wallet-backend> takes no traditional options.
Most commands are only available to wallet administrators (users on the
C<ADMIN> ACL). The exceptions are C<get>, C<store>, C<show>, C<destroy>,
-C<flag clear>, and C<flag set>. All of those commands have their own ACLs,
-and if the appropriate ACL is set, it alone is checked to see if the user
-has access. Otherwise, C<get>, C<store>, and C<show> access is permitted if
-the user is authorized by the owner ACL of the object.
+C<flag clear>, C<flag set>, C<getattr>, and C<setattr>. All of those
+commands have their own ACLs except C<getattr>, which uses the C<show> ACL,
+and C<setattr>, which uses the C<show> ACL. If the appropriate ACL is set,
+it alone is checked to see if the user has access. Otherwise, C<get>,
+C<store>, C<show>, C<getattr>, and C<setattr> access is permitted if the
+user is authorized by the owner ACL of the object.
Administrators can run any command on any object or ACL except for C<get>
and C<store>. For C<get> and C<show>, they must still be authorized by
@@ -316,6 +326,15 @@ if the C<get>, C<store>, or C<show> ACLs aren't set, authorization falls
back to checking the owner ACL. See the C<owner> command for displaying
or setting it.
+=item getattr <type> <name> <attr>
+
+Prints the object attribute <attr> for the object identified by <type> and
+<name>. Attributes are used to store backend-specific information for a
+particular object type, and <attr> must be an attribute type known to the
+underlying object implementation. The attribute values, if any, are printed
+one per line. If the attribute is not set on this object, nothing is
+printed.
+
=item owner <type> <name> [<owner>]
If <owner> is not given, displays the current owner ACL of the object
@@ -332,6 +351,16 @@ Sets the ACL <acl>, which must be one of C<get>, C<store>, C<show>,
C<destroy>, or C<flags>, to <id> on the object identified by <type> and
<name>. If <id> is the empty string, clears that ACL on the object.
+=item setattr <type> <name> <attr> <value> [<value> ...]
+
+Sets the object attribute <attr> for the object identified by <type> and
+<name>. Attributes are used to store backend-specific information for a
+particular object type, and <attr> must be an attribute type known to the
+underlying object implementation. To clear the attribute for this object,
+pass in a <value> of the empty string (C<''>).
+
+Currently, no object attributes are implemented.
+
=item show <type> <name>
Displays the current object metadata for the object identified by <type>
diff --git a/tests/server/backend-t.in b/tests/server/backend-t.in
index bac2105..c844d5e 100644
--- a/tests/server/backend-t.in
+++ b/tests/server/backend-t.in
@@ -5,7 +5,7 @@
use strict;
use IO::String;
-use Test::More tests => 750;
+use Test::More tests => 790;
# Create a dummy class for Wallet::Server that prints what method was called
# with its arguments and returns data for testing.
@@ -66,6 +66,21 @@ sub acl {
}
}
+sub attr {
+ shift;
+ print "attr @_\n";
+ if ($_[0] eq 'error') {
+ return;
+ } elsif ($_[1] eq 'empty') {
+ $okay = 1;
+ return;
+ } elsif (@_ == 3) {
+ return ('attr1', 'attr2');
+ } else {
+ return 'attr';
+ }
+}
+
sub expires {
shift;
print "expires @_\n";
@@ -144,7 +159,7 @@ is ($out, "$new\n", ' and nothing ran');
($out, $err) = run_backend ('acl', 'foo');
is ($err, "unknown command acl foo\n", 'Unknown ACL command');
is ($out, "$new\n", ' and nothing ran');
-($out, $err) = run_backend ('flag', 'foo');
+($out, $err) = run_backend ('flag', 'foo', 'service', 'foo', 'foo');
is ($err, "unknown command flag foo\n", 'Unknown flag command');
is ($out, "$new\n", ' and nothing ran');
@@ -154,8 +169,10 @@ my %commands = (create => [2, 2],
expires => [2, 3],
get => [2, 2],
getacl => [3, 3],
+ getattr => [3, 3],
owner => [2, 3],
setacl => [4, 4],
+ setattr => [4, 9],
show => [2, 2],
store => [3, 3]);
my %acl_commands = (add => [3, 3],
@@ -171,9 +188,11 @@ for my $command (sort keys %commands) {
($out, $err) = run_backend ($command, ('foo') x ($min - 1));
is ($err, "insufficient arguments\n", "Too few arguments for $command");
is ($out, "$new\n", ' and nothing ran');
- ($out, $err) = run_backend ($command, ('foo') x ($max + 1));
- is ($err, "too many arguments\n", "Too many arguments for $command");
- is ($out, "$new\n", ' and nothing ran');
+ unless ($max >= 9) {
+ ($out, $err) = run_backend ($command, ('foo') x ($max + 1));
+ is ($err, "too many arguments\n", "Too many arguments for $command");
+ is ($out, "$new\n", ' and nothing ran');
+ }
my @base = ('foobar') x $max;
for my $arg (0 .. ($max - 1)) {
my @args = @base;
@@ -231,8 +250,9 @@ for my $command (sort keys %flag_commands) {
# Now, test that we ran the right functions and passed the correct arguments.
my $error = 1;
-for my $command (qw/create destroy setacl store/) {
- my $method = ($command eq 'setacl') ? 'acl' : $command;
+for my $command (qw/create destroy setacl setattr store/) {
+ my $method = { setacl => 'acl', setattr => 'attr' }->{$command};
+ $method ||= $command;
my @extra = ('foo') x ($commands{$command}[0] - 2);
my $extra = @extra ? join (' ', '', @extra) : '';
($out, $err) = run_backend ($command, 'type', 'name', @extra);
@@ -245,22 +265,30 @@ for my $command (qw/create destroy setacl store/) {
' and ran the right method');
$error++;
}
-for my $command (qw/expires get getacl owner show/) {
- my $method = ($command eq 'getacl') ? 'acl' : $command;
+for my $command (qw/expires get getacl getattr owner show/) {
+ my $method = { getacl => 'acl', getattr => 'attr' }->{$command};
+ $method ||= $command;
my @extra = ('foo') x ($commands{$command}[0] - 2);
my $extra = @extra ? join (' ', '', @extra) : '';
- my $newline = ($command eq 'get' or $command eq 'show') ? '' : "\n";
- ($out, $err) = run_backend ($command, 'type', 'name', @extra);
- is ($err, '', "Command $command ran with no errors");
- is ($out, "$new\n$method type name$extra\n$method$newline",
- ' and ran the right method with output');
- if ($command ne 'get' and $command ne 'getacl' and $command ne 'show') {
+ if ($command eq 'getattr') {
+ ($out, $err) = run_backend ($command, 'type', 'name', @extra);
+ is ($err, '', "Command $command ran with no errors");
+ is ($out, "$new\n$method type name$extra\nattr1\nattr2\n",
+ ' and ran the right method with output');
+ } else {
+ my $newline = ($command eq 'get' or $command eq 'show') ? '' : "\n";
+ ($out, $err) = run_backend ($command, 'type', 'name', @extra);
+ is ($err, '', "Command $command ran with no errors");
+ is ($out, "$new\n$method type name$extra\n$method$newline",
+ ' and ran the right method with output');
+ }
+ if ($command eq 'expires' or $command eq 'owner') {
($out, $err) = run_backend ($command, 'type', 'name', @extra, 'foo');
is ($err, '', "Command $command ran with no errors (setting)");
is ($out, "$new\n$method type name$extra foo\n",
' and ran the right method');
}
- if ($command ne 'get' and $command ne 'show') {
+ if ($command eq 'expires' or $command eq 'getacl' or $command eq 'owner') {
($out, $err) = run_backend ($command, 'type', 'empty', @extra);
is ($err, '', "Command $command ran with no errors (empty)");
my $desc;
@@ -270,6 +298,12 @@ for my $command (qw/expires get getacl owner show/) {
is ($out, "$new\n$method type empty$extra\nNo $desc set\n",
' and ran the right method with output');
$error++;
+ } elsif ($command eq 'getattr') {
+ ($out, $err) = run_backend ($command, 'type', 'empty', @extra);
+ is ($err, '', "Command $command ran with no errors (empty)");
+ is ($out, "$new\n$method type empty$extra\n",
+ ' and ran the right method with output');
+ $error++;
}
($out, $err) = run_backend ($command, 'error', 'name', @extra);
is ($err, "error count $error\n", "Command $command ran with errors");