summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>2010-12-20 19:54:59 -0500
committerDaniel Kahn Gillmor <dkg@fifthhorseman.net>2010-12-20 19:54:59 -0500
commit032d02da2b12b4f0f596d795e921e8654510a750 (patch)
tree50d750922d00789b6f059a93e7efabad9002ef30
parent4e233d779705befcee77a45c57799f429aa371c5 (diff)
parent617031b0585dacb75ced234e04984ca6b4b0568c (diff)
Merge remote branch 'jamie/master'
-rw-r--r--examples/monkeysphere-monitor-keys139
1 files changed, 139 insertions, 0 deletions
diff --git a/examples/monkeysphere-monitor-keys b/examples/monkeysphere-monitor-keys
new file mode 100644
index 0000000..8a95118
--- /dev/null
+++ b/examples/monkeysphere-monitor-keys
@@ -0,0 +1,139 @@
+#!/usr/bin/perl
+
+# This script automatically runs:
+#
+# monkeysphere-authentication update-users <user>
+#
+# every time it detects a change in an authorized_keys or authorized_user_ids
+# file. The update-users command operates on the username that owns the file
+# that was updated.
+#
+# The list of files to monitor is generated from the AUTHORIZED_USER_IDS and
+# RAW_AUTHORIZED_KEYS variables found in
+# /etc/monkeysphere/monkeysphere-authentication.conf and expanded using a list
+# of users on the system.
+#
+# Additionally, the /var/lib/monkeysphere/user-update/lastchange file is
+# monitored. If a change is made to that file, the list of files to monitor is
+# re-generated based on a fresh listing of users. If you run a hook on user
+# creation and deletion that generates a file in this directory, you can ensure
+# that the list of files to monitor is always up-to-date.
+#
+# On debian system you can install required perl modules with: aptitude install
+# libfile-changenotify-perl libfile-spec-perl libconfig-general-perl
+#
+# This script is designed to run at system start and should be run with root
+# privileges.
+#
+# File::ChangeNotify is cross platform - it will choose a sub class for
+# monitoring file system changes appropriate to your operating system (if you
+# are running Linux, liblinux-inotify2-perl is recommended).
+
+use strict;
+use File::ChangeNotify;
+use File::Basename;
+use File::Spec;
+use Config::General;
+
+my $user_update_file = '/var/lib/monkeysphere/user-update/lastchange';
+my $debug = 0;
+
+sub debug {
+ if ($debug eq 1) { print $_[0]; }
+}
+
+sub get_watch_files() {
+ my @watch_files;
+ my %key_file_locations = get_key_file_locations();
+ # get list of users on the system
+ while((my $name,my $passwd,my $uid,my $gid,my $gcos,my $dir,my $shell,my $home) = getpwent( )){
+ while (my ($key, $file) = each (%key_file_locations)) {
+ $file =~ s/%h/$home/;
+ $file =~ s/%u/$name/;
+ push(@watch_files,$file);
+ }
+ }
+ endpwent();
+ push(@watch_files,$user_update_file);
+ return @watch_files;
+}
+
+sub get_key_file_locations {
+ # set defaults
+ my %key_file_locations;
+ $key_file_locations{ 'authorized_user_ids' } = '%h/.monkeysphere/authorized_user_ids';
+ $key_file_locations{ 'authorized_keys' } = '%h/.ssh/authorized_keys';
+
+ # check monkeysphere-authentication configuration
+ my $config_file = '/etc/monkeysphere/monkeysphere-authentication.conf';
+ if (-f $config_file) {
+ if (-r $config_file) {
+ my %config;
+ %config = Config::General::ParseConfig($config_file);
+ if (exists $config{'AUTHORIZED_USER_IDS'}) {
+ $key_file_locations{'authorized_user_ids'} = $config{'AUTHORIZED_USER_IDS'};
+ }
+ if (exists $config{'RAW_AUTHORIZED_KEYS'}) {
+ $key_file_locations{'authorized_keys'} = $config{'RAW_AUTHORIZED_KEYS'};
+ }
+ }
+ }
+ return %key_file_locations;
+}
+
+sub get_watcher {
+ my @filters;
+ my @dirs;
+
+ my(@files) = get_watch_files();
+ for my $file (@files) {
+ my $dir = dirname($file);
+ if ( -d $dir && !grep $_ eq $dir, @dirs ) {
+ debug "Watching dir: $dir\n";
+ push(@dirs,$dir);
+ my $file = basename($file);
+ if ( !grep $_ eq $file, @filters ) {
+ debug "Adding file filter: $file\n";
+ push(@filters,$file);
+ }
+ }
+ }
+ # create combined file filters to limit our monitor
+ my $filter = '^(' . join("|",@filters) . ')$';
+
+ # return a watcher object
+ return my $watcher =
+ File::ChangeNotify->instantiate_watcher
+ ( directories => [ @dirs ],
+ filter => qr/$filter/,
+ );
+}
+
+sub watch {
+ my $watcher = get_watcher();
+ while ( my @events = $watcher->wait_for_events() ) {
+ my @users;
+ for my $event (@events) {
+ if($event->path eq "$user_update_file") {
+ debug "Reloading user list";
+ $watcher = get_watcher();
+ } else {
+ # if user deleted, file might not exist
+ if( -f $event->path) {
+ my $username = getpwuid((stat($event->path))[4]);
+
+ if ( !grep $_ eq $username, @users ) {
+ push(@users,$username);
+ }
+ }
+ }
+ }
+ for my $user (@users) {
+ my @args = ('u',$user);
+ debug "Updating user: $user";
+ system 'monkeysphere-authentication', @args;
+ }
+ }
+}
+
+watch();