better users probe
[scpubgit/System-Introspector.git] / lib / System / Introspector / Probe / Users.pm
1 package System::Introspector::Probe::Users;
2 use Moo;
3
4 use System::Introspector::Util qw(
5     handle_from_command
6     transform_exceptions
7     output_from_file
8     output_from_command
9     files_from_dir
10     handle_from_file
11 );
12
13 sub gather {
14     my ($self) = @_;
15     return transform_exceptions {
16         my $fh = $self->_open_passwd_fh;
17         my %user;
18         while (defined( my $line = <$fh> )) {
19             my $data = $self->_deparse_htpasswd_line($line);
20             my $user = $data->{username};
21             my $home = $data->{home};
22             $data->{groups} = transform_exceptions {
23                 $self->_gather_user_groups($user);
24             };
25             $data->{ssh}{keys} = transform_exceptions {
26                 $self->_gather_ssh_keys($user, $home);
27             };
28             $data->{crontab} = transform_exceptions {
29                 $self->_gather_crontab($user);
30             };
31             $user{ $data->{username} } = $data;
32         }
33         return { users => \%user };
34     };
35 }
36
37 sub _gather_crontab {
38     my ($self, $user) = @_;
39     my ($out, $err, $ok) = output_from_command
40         ['crontab', '-u', $user, '-l'];
41     unless ($ok) {
42         return {}
43             if $err =~ m{^no crontab}i;
44         return { error => $err };
45     }
46     return { body => $out };
47 }
48
49 sub _gather_ssh_keys {
50     my ($self, $user, $home) = @_;
51     my $ssh_dir = "$home/.ssh";
52     return {
53         files => {},
54         authorized => { file_name => "$ssh_dir/authorized_keys", body => '' }
55     } unless -d $ssh_dir;
56     my %key;
57     for my $item (files_from_dir $ssh_dir) {
58         next unless $item =~ m{\.pub$};
59         $key{ $item } = transform_exceptions {
60             return {
61                 file_name => "$ssh_dir/$item",
62                 body => scalar output_from_file "$ssh_dir/$item",
63             };
64         };
65     }
66     my $auth_keys = transform_exceptions {
67         return {
68             file_name => "$ssh_dir/authorized_keys",
69             body => scalar output_from_file "$ssh_dir/authorized_keys",
70         };
71     };
72     return { files => \%key, authorized => $auth_keys };
73 }
74
75 sub _gather_user_groups {
76     my ($self, $user) = @_;
77     my $groups = output_from_command [groups => $user];
78     return { list => [split m{\s+}, $groups] };
79 }
80
81 sub _deparse_htpasswd_line {
82     my ($self, $line) = @_;
83     chomp $line;
84     my %value;
85     @value{qw( username uid gid comment home shell )}
86         = (split m{:}, $line)[0, 2..6];
87     return \%value;
88 }
89
90 sub _open_passwd_fh {
91     my ($self) = @_;
92     return handle_from_file '/etc/passwd';
93 }
94
95 1;
96
97 __END__
98
99 =head1 NAME
100
101 System::Introspector::Users - Gather user information
102
103 =head1 DESCRIPTION
104
105 Gathers information for all users in C</etc/passwd>, including cronjobs and
106 installed SSH public keys.
107
108 =head1 SEE ALSO
109
110 =over
111
112 =item L<System::Introspector>
113
114 =back
115
116 =cut
117