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