use more reusable utils for I/O operations, better error handling, have a top-level...
[scpubgit/System-Introspector.git] / lib / System / Introspector / Users.pm
1 package System::Introspector::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->{uid} } = $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         unless -d $ssh_dir;
54     my %key;
55     for my $item (files_from_dir $ssh_dir) {
56         next unless $item =~ m{\.pub$};
57         $key{ $item } = transform_exceptions {
58             return {
59                 body => scalar output_from_file "$ssh_dir/$item",
60             };
61         };
62     }
63     return { files => \%key };
64 }
65
66 sub _gather_user_groups {
67     my ($self, $user) = @_;
68     my $groups = output_from_command "groups $user";
69     return { list => [split m{\s+}, $groups] };
70 }
71
72 sub _deparse_htpasswd_line {
73     my ($self, $line) = @_;
74     chomp $line;
75     my %value;
76     @value{qw( username uid gid comment home shell )}
77         = (split m{:}, $line)[0, 2..6];
78     return \%value;
79 }
80
81 sub _open_passwd_fh {
82     my ($self) = @_;
83     return handle_from_file '/etc/passwd';
84 }
85
86 1;
87
88 __END__
89
90 =head1 NAME
91
92 System::Introspector::Users - Gather user information
93
94 =head1 DESCRIPTION
95
96 Gathers information for all users in C</etc/passwd>, including cronjobs and
97 installed SSH public keys.
98
99 =head1 SEE ALSO
100
101 =over
102
103 =item L<System::Introspector>
104
105 =back
106
107 =cut
108