aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Allbery <rra@stanford.edu>2010-03-05 16:56:47 -0800
committerRuss Allbery <rra@stanford.edu>2010-03-05 16:56:47 -0800
commit0e3df4c4159650e6de7fdcf6a0f0b661f25c03f7 (patch)
tree45759cdf6b16b2f9ca34379df32f82cc182bfe9f
parent2948d66c4c074651820004856284faf7d018a3ee (diff)
Add a report of unused ACLs
Add the acls unused report to wallet-report and Wallet::Report, returning all ACLs not referenced by any database objects.
-rw-r--r--NEWS3
-rw-r--r--perl/Wallet/Report.pm24
-rwxr-xr-xperl/t/report.t37
-rwxr-xr-xserver/wallet-report7
4 files changed, 66 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index 03fe99b..e41b86e 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,9 @@ wallet 0.11 (unreleased)
which returns all objects that do not pass the local naming policy.
The corresponding Wallet::Report method is audit().
+ Add the acls unused report to wallet-report and Wallet::Report,
+ returning all ACLs not referenced by any database objects.
+
Wallet::Config::verify_name may now be called with an undefined third
argument (normally the user attempting to create an object). This
calling convention is used when auditing, and the local policy
diff --git a/perl/Wallet/Report.pm b/perl/Wallet/Report.pm
index 462cd6f..f6e6753 100644
--- a/perl/Wallet/Report.pm
+++ b/perl/Wallet/Report.pm
@@ -195,7 +195,8 @@ sub acls_all {
sub acls_empty {
my ($self) = @_;
my $sql = 'select ac_id, ac_name from acls left join acl_entries
- on (acls.ac_id = acl_entries.ae_id) where ae_id is null';
+ on (acls.ac_id = acl_entries.ae_id) where ae_id is null order by
+ ac_id';
return ($sql);
}
@@ -210,6 +211,18 @@ sub acls_entry {
return ($sql, $type, '%' . $identifier . '%');
}
+# Returns the SQL statement required to find unused ACLs.
+sub acls_unused {
+ my ($self) = @_;
+ my $sql = 'select ac_id, ac_name from acls where not ac_id in (select
+ ob_owner from objects where ob_owner = ac_id)';
+ for my $acl (qw/get store show destroy flags/) {
+ $sql .= " and not ac_id in (select ob_acl_$acl from objects where
+ ob_acl_$acl = ac_id)";
+ }
+ return ($sql);
+}
+
# Returns a list of all ACLs stored in the wallet database as a list of pairs
# of ACL IDs and ACL names, possibly limited by some criteria. On error and
# for an empty database, the empty list will be returned. To distinguish
@@ -234,8 +247,10 @@ sub acls {
}
} elsif ($type eq 'empty') {
($sql) = $self->acls_empty;
+ } elsif ($type eq 'unused') {
+ ($sql) = $self->acls_unused;
} else {
- $self->error ("do not know search type: $type");
+ $self->error ("unknown search type: $type");
return;
}
}
@@ -387,11 +402,12 @@ between an empty report and an error.
Returns a list of all ACLs matching a search type and string in the
database, or all ACLs if no search information is given. There are
-currently two search types. C<empty> takes no arguments and will return
+currently three search types. C<empty> takes no arguments and will return
only those ACLs that have no entries within them. C<entry> takes two
arguments, an entry scheme and a (possibly partial) entry identifier, and
will return any ACLs containing an entry with that scheme and with an
-identifier containing that value.
+identifier containing that value. C<unused> returns all ACLs that are not
+referenced by any object.
The return value is a list of references to pairs of ACL ID and name. For
example, if there are two ACLs in the database, one with name C<ADMIN> and
diff --git a/perl/t/report.t b/perl/t/report.t
index 3b94d00..b283576 100755
--- a/perl/t/report.t
+++ b/perl/t/report.t
@@ -7,7 +7,7 @@
#
# See LICENSE for licensing terms.
-use Test::More tests => 88;
+use Test::More tests => 148;
use Wallet::Admin;
use Wallet::Report;
@@ -166,6 +166,41 @@ is ($server->flag_clear ('base', 'service/admin', 'unchanging'), 1,
is (scalar (@lines), 0, ' and now there are no objects in the report');
is ($report->error, undef, ' with no error');
+# All of our ACLs should be in use.
+@lines = $report->acls ('unused');
+is (scalar (@lines), 0, 'Searching for unused ACLs returns nothing');
+is ($report->error, undef, ' with no error');
+
+# Create some unused ACLs that should show up in the report.
+is ($server->acl_create ('third'), 1, 'Creating an empty ACL succeeds');
+is ($server->acl_create ('fourth'), 1, ' and creating another succeeds');
+@lines = $report->acls ('unused');
+is (scalar (@lines), 2, ' and now we see two unused ACLs');
+is ($server->error, undef, ' with no error');
+is ($lines[0][0], 4, ' and the first has the right ID');
+is ($lines[0][1], 'third', ' and the right name');
+is ($lines[1][0], 5, ' and the second has the right ID');
+is ($lines[1][1], 'fourth', ' and the right name');
+
+# Use one of those ACLs and ensure it drops out of the report. Test that we
+# try all of the possible ACL types.
+for my $type (qw/get store show destroy flags/) {
+ is ($server->acl ('base', 'service/admin', $type, 'fourth'), 1,
+ "Setting ACL $type to fourth succeeds");
+ @lines = $report->acls ('unused');
+ is (scalar (@lines), 1, ' and now we see only one unused ACL');
+ is ($lines[0][0], 4, ' with the right ID');
+ is ($lines[0][1], 'third', ' and the right name');
+ is ($server->acl ('base', 'service/admin', $type, ''), 1,
+ ' and clearing the ACL succeeds');
+ @lines = $report->acls ('unused');
+ is (scalar (@lines), 2, ' and now we see two unused ACLs');
+ is ($lines[0][0], 4, ' and the first has the right ID');
+ is ($lines[0][1], 'third', ' and the right name');
+ is ($lines[1][0], 5, ' and the second has the right ID');
+ is ($lines[1][1], 'fourth', ' and the right name');
+}
+
# The naming audit returns nothing if there's no naming policy.
@lines = $report->audit ('objects', 'name');
is (scalar (@lines), 0, 'Searching for naming violations finds none');
diff --git a/server/wallet-report b/server/wallet-report
index 610e278..2b7cd45 100755
--- a/server/wallet-report
+++ b/server/wallet-report
@@ -110,6 +110,8 @@ B<wallet-report> takes no traditional options.
=item acls entry <scheme> <identifier>
+=item acls unused
+
Returns a list of ACLs in the database. ACLs will be listed in the form:
<name> (ACL ID: <id>)
@@ -137,6 +139,11 @@ Returns all ACLs containing an entry with given scheme and identifier.
The scheme must be an exact match, but the <identifier> string will match
any identifier containing that string.
+=item acls unused
+
+Returns all ACLs that are not referenced by any of the objects in the
+wallet database, either as an owner or on one of the more specific ACLs.
+
=back
=item audit objects name