summaryrefslogtreecommitdiff
path: root/examples/monkeysphere-monitor-keys
blob: 4d89cd5de475cf433c2611ee16f15cbe05771a52 (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 warnings;
  32. use File::ChangeNotify;
  33. use File::Basename;
  34. use File::Spec;
  35. use Config::General;
  36. my $user_update_file = '/var/lib/monkeysphere/user-update/lastchange';
  37. my $debug = 0;
  38. if (defined($ENV{MONKEYSPHERE_LOG_LEVEL}) &&
  39. $ENV{MONKEYSPHERE_LOG_LEVEL} =~ /^debug/i) {
  40. $debug = 1;
  41. }
  42. sub debug {
  43. printf STDERR @_
  44. if ($debug eq 1);
  45. }
  46. sub get_watch_files() {
  47. my @watch_files;
  48. my %key_file_locations = get_key_file_locations();
  49. # get list of users on the system
  50. while(my ($name, $passwd, $uid, $gid, $gcos, $dir, $shell, $home) = getpwent()) {
  51. while (my ($key, $file) = each (%key_file_locations)) {
  52. $file =~ s/%h/$home/;
  53. $file =~ s/%u/$name/;
  54. push(@watch_files,$file);
  55. }
  56. }
  57. endpwent();
  58. push(@watch_files,$user_update_file);
  59. return @watch_files;
  60. }
  61. sub get_key_file_locations {
  62. # set defaults
  63. my %key_file_locations;
  64. $key_file_locations{ 'authorized_user_ids' } = '%h/.monkeysphere/authorized_user_ids';
  65. $key_file_locations{ 'authorized_keys' } = '%h/.ssh/authorized_keys';
  66. # check monkeysphere-authentication configuration
  67. my $config_file = '/etc/monkeysphere/monkeysphere-authentication.conf';
  68. if (-f $config_file) {
  69. if (-r $config_file) {
  70. my %config;
  71. %config = Config::General::ParseConfig($config_file);
  72. if (exists $config{'AUTHORIZED_USER_IDS'}) {
  73. $key_file_locations{'authorized_user_ids'} = $config{'AUTHORIZED_USER_IDS'};
  74. }
  75. if (exists $config{'RAW_AUTHORIZED_KEYS'}) {
  76. $key_file_locations{'authorized_keys'} = $config{'RAW_AUTHORIZED_KEYS'};
  77. }
  78. }
  79. }
  80. return %key_file_locations;
  81. }
  82. sub get_watcher {
  83. my @filters;
  84. my @dirs;
  85. my(@files) = get_watch_files();
  86. for my $file (@files) {
  87. my $dir = dirname($file);
  88. if ( -d $dir && !grep $_ eq $dir, @dirs ) {
  89. debug("Watching dir: %s\n", $dir);
  90. push(@dirs,$dir);
  91. my $file = basename($file);
  92. if ( !grep $_ eq $file, @filters ) {
  93. debug("Adding file filter: %s\n", $file);
  94. push(@filters,$file);
  95. }
  96. }
  97. }
  98. # create combined file filters to limit our monitor
  99. my $filter = '^(' . join("|",@filters) . ')$';
  100. # return a watcher object
  101. return my $watcher =
  102. File::ChangeNotify->instantiate_watcher
  103. ( directories => [ @dirs ],
  104. filter => qr/$filter/,
  105. );
  106. }
  107. sub watch {
  108. my $watcher = get_watcher();
  109. while ( my @events = $watcher->wait_for_events() ) {
  110. my @users;
  111. for my $event (@events) {
  112. if($event->path eq "$user_update_file") {
  113. debug("Reloading user list\n");
  114. $watcher = get_watcher();
  115. } else {
  116. # if user deleted, file might not exist
  117. if( -f $event->path) {
  118. my $username = getpwuid((stat($event->path))[4]);
  119. if ( !grep $_ eq $username, @users ) {
  120. push(@users,$username);
  121. }
  122. }
  123. }
  124. }
  125. for my $user (@users) {
  126. my @args = ('u',$user);
  127. debug("Updating user: %s\n", $user);
  128. system 'monkeysphere-authentication', @args;
  129. }
  130. }
  131. }
  132. watch();