summaryrefslogtreecommitdiff
path: root/examples/monkeysphere-monitor-keys
blob: 8a951180557d77363e81c2ae6e2280e88ef06103 (plain)
  1. #!/usr/bin/perl
  2. # This script automatically runs:
  3. #
  4. # monkeysphere-authentication update-users <user>
  5. #
  6. # every time it detects a change in an authorized_keys or authorized_user_ids
  7. # file. The update-users command operates on the username that owns the file
  8. # that was updated.
  9. #
  10. # The list of files to monitor is generated from the AUTHORIZED_USER_IDS and
  11. # RAW_AUTHORIZED_KEYS variables found in
  12. # /etc/monkeysphere/monkeysphere-authentication.conf and expanded using a list
  13. # of users on the system.
  14. #
  15. # Additionally, the /var/lib/monkeysphere/user-update/lastchange file is
  16. # monitored. If a change is made to that file, the list of files to monitor is
  17. # re-generated based on a fresh listing of users. If you run a hook on user
  18. # creation and deletion that generates a file in this directory, you can ensure
  19. # that the list of files to monitor is always up-to-date.
  20. #
  21. # On debian system you can install required perl modules with: aptitude install
  22. # libfile-changenotify-perl libfile-spec-perl libconfig-general-perl
  23. #
  24. # This script is designed to run at system start and should be run with root
  25. # privileges.
  26. #
  27. # File::ChangeNotify is cross platform - it will choose a sub class for
  28. # monitoring file system changes appropriate to your operating system (if you
  29. # are running Linux, liblinux-inotify2-perl is recommended).
  30. use strict;
  31. use File::ChangeNotify;
  32. use File::Basename;
  33. use File::Spec;
  34. use Config::General;
  35. my $user_update_file = '/var/lib/monkeysphere/user-update/lastchange';
  36. my $debug = 0;
  37. sub debug {
  38. if ($debug eq 1) { print $_[0]; }
  39. }
  40. sub get_watch_files() {
  41. my @watch_files;
  42. my %key_file_locations = get_key_file_locations();
  43. # get list of users on the system
  44. while((my $name,my $passwd,my $uid,my $gid,my $gcos,my $dir,my $shell,my $home) = getpwent( )){
  45. while (my ($key, $file) = each (%key_file_locations)) {
  46. $file =~ s/%h/$home/;
  47. $file =~ s/%u/$name/;
  48. push(@watch_files,$file);
  49. }
  50. }
  51. endpwent();
  52. push(@watch_files,$user_update_file);
  53. return @watch_files;
  54. }
  55. sub get_key_file_locations {
  56. # set defaults
  57. my %key_file_locations;
  58. $key_file_locations{ 'authorized_user_ids' } = '%h/.monkeysphere/authorized_user_ids';
  59. $key_file_locations{ 'authorized_keys' } = '%h/.ssh/authorized_keys';
  60. # check monkeysphere-authentication configuration
  61. my $config_file = '/etc/monkeysphere/monkeysphere-authentication.conf';
  62. if (-f $config_file) {
  63. if (-r $config_file) {
  64. my %config;
  65. %config = Config::General::ParseConfig($config_file);
  66. if (exists $config{'AUTHORIZED_USER_IDS'}) {
  67. $key_file_locations{'authorized_user_ids'} = $config{'AUTHORIZED_USER_IDS'};
  68. }
  69. if (exists $config{'RAW_AUTHORIZED_KEYS'}) {
  70. $key_file_locations{'authorized_keys'} = $config{'RAW_AUTHORIZED_KEYS'};
  71. }
  72. }
  73. }
  74. return %key_file_locations;
  75. }
  76. sub get_watcher {
  77. my @filters;
  78. my @dirs;
  79. my(@files) = get_watch_files();
  80. for my $file (@files) {
  81. my $dir = dirname($file);
  82. if ( -d $dir && !grep $_ eq $dir, @dirs ) {
  83. debug "Watching dir: $dir\n";
  84. push(@dirs,$dir);
  85. my $file = basename($file);
  86. if ( !grep $_ eq $file, @filters ) {
  87. debug "Adding file filter: $file\n";
  88. push(@filters,$file);
  89. }
  90. }
  91. }
  92. # create combined file filters to limit our monitor
  93. my $filter = '^(' . join("|",@filters) . ')$';
  94. # return a watcher object
  95. return my $watcher =
  96. File::ChangeNotify->instantiate_watcher
  97. ( directories => [ @dirs ],
  98. filter => qr/$filter/,
  99. );
  100. }
  101. sub watch {
  102. my $watcher = get_watcher();
  103. while ( my @events = $watcher->wait_for_events() ) {
  104. my @users;
  105. for my $event (@events) {
  106. if($event->path eq "$user_update_file") {
  107. debug "Reloading user list";
  108. $watcher = get_watcher();
  109. } else {
  110. # if user deleted, file might not exist
  111. if( -f $event->path) {
  112. my $username = getpwuid((stat($event->path))[4]);
  113. if ( !grep $_ eq $username, @users ) {
  114. push(@users,$username);
  115. }
  116. }
  117. }
  118. }
  119. for my $user (@users) {
  120. my @args = ('u',$user);
  121. debug "Updating user: $user";
  122. system 'monkeysphere-authentication', @args;
  123. }
  124. }
  125. }
  126. watch();