diff options
author | Daniel Kahn Gillmor <dkg@fifthhorseman.net> | 2010-12-20 19:54:59 -0500 |
---|---|---|
committer | Daniel Kahn Gillmor <dkg@fifthhorseman.net> | 2010-12-20 19:54:59 -0500 |
commit | 032d02da2b12b4f0f596d795e921e8654510a750 (patch) | |
tree | 50d750922d00789b6f059a93e7efabad9002ef30 | |
parent | 4e233d779705befcee77a45c57799f429aa371c5 (diff) | |
parent | 617031b0585dacb75ced234e04984ca6b4b0568c (diff) |
Merge remote branch 'jamie/master'
-rw-r--r-- | examples/monkeysphere-monitor-keys | 139 |
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(); |