1 | package LATMOS::Accounts::Maintenance; |
---|
2 | |
---|
3 | use strict; |
---|
4 | use warnings; |
---|
5 | use base qw(LATMOS::Accounts); |
---|
6 | use FindBin qw($Bin); |
---|
7 | use Crypt::RSA; |
---|
8 | use Crypt::RSA::Key::Public::SSH; |
---|
9 | use Crypt::RSA::Key::Private::SSH; |
---|
10 | use MIME::Base64; |
---|
11 | |
---|
12 | sub _base { |
---|
13 | my ($self) = @_; |
---|
14 | my $base = $self->SUPER::default_base; |
---|
15 | $base->type eq 'sql' or die "This module work only with SQL base type\n"; |
---|
16 | $base |
---|
17 | } |
---|
18 | |
---|
19 | sub find_next_expire_users { |
---|
20 | my ($self, $expire) = @_; |
---|
21 | my $base = $self->_base; |
---|
22 | |
---|
23 | my $sth= $base->db->prepare(q{ |
---|
24 | select name, justify_hours(expire - now()) as delay from "user" where |
---|
25 | expire < now() + ?::interval |
---|
26 | and expire > now() |
---|
27 | and expire is not null |
---|
28 | and exported = True |
---|
29 | order by expire |
---|
30 | } |
---|
31 | ); |
---|
32 | $sth->execute($expire || '1 month'); |
---|
33 | my @users; |
---|
34 | while (my $res = $sth->fetchrow_hashref) { |
---|
35 | $res->{delay} =~ s/(day.?) .*/$1/; |
---|
36 | $res->{obj} = $base->get_object('user', $res->{name}); |
---|
37 | push(@users, $res); |
---|
38 | } |
---|
39 | @users |
---|
40 | } |
---|
41 | |
---|
42 | =head2 warn_next_expire_users(%options) |
---|
43 | |
---|
44 | Send a mail to user having account expiring soon |
---|
45 | |
---|
46 | C<%options are> |
---|
47 | |
---|
48 | =over 4 |
---|
49 | |
---|
50 | =item users => [] |
---|
51 | |
---|
52 | Warn only this users (if need) |
---|
53 | |
---|
54 | =item to |
---|
55 | |
---|
56 | Send the only to this person. |
---|
57 | |
---|
58 | =back |
---|
59 | |
---|
60 | =cut |
---|
61 | |
---|
62 | sub warn_next_expire_users { |
---|
63 | my ($self, %options) = @_; |
---|
64 | |
---|
65 | require Mail::Sendmail; |
---|
66 | require Template; |
---|
67 | my $template = Template->new( |
---|
68 | INCLUDE_PATH => [ |
---|
69 | ($self->val('_default_', 'templatespath') |
---|
70 | ? $self->val('_default_', 'templatespath') . '/mail' |
---|
71 | : ()), |
---|
72 | "$FindBin::Bin/../templates" . '/mail', |
---|
73 | '/usr/share/latmos-accounts/templates/mail', |
---|
74 | ], |
---|
75 | POST_CHOMP => 1, |
---|
76 | EXTENSION => '.mail', |
---|
77 | ); |
---|
78 | foreach my $user ($self->find_next_expire_users($options{delay})) { |
---|
79 | if ($options{users} && ! grep { $_ eq $user->{name} } @{$options{users}}) { |
---|
80 | next; |
---|
81 | } |
---|
82 | my %mail = ( |
---|
83 | From => $self->val('_default_', 'mailFrom', 'nomail@localhost'), |
---|
84 | Subject => 'LATMOS Expire in ' . $user->{delay}, |
---|
85 | smtp => $self->val('_default_', 'smtp'), |
---|
86 | 'Content-Type' => 'text/plain; charset=utf-8', |
---|
87 | 'X-LATMOS-Accounts' => '$Rev$', |
---|
88 | 'X-LATMOS-Reason' => 'Account expiration', |
---|
89 | ); |
---|
90 | my ($manager, $mail) = ($user->{obj}->get_c_field('manager'), |
---|
91 | $user->{obj}->get_c_field('mail')); |
---|
92 | my $managermail = $manager ? $user->{obj}->base-> |
---|
93 | get_object('user', $manager)->get_c_field('mail') : undef; |
---|
94 | # if user have no mail, mail only to manager, avoiding empty To |
---|
95 | # NB: at time, for testing purpose, mail is not really sent |
---|
96 | my ($to, @cc) = grep { $_ } ($mail, $managermail, $self->val('_default_', |
---|
97 | 'allwayscc')); |
---|
98 | if ($options{to}) { |
---|
99 | $mail{to} = $options{to}; |
---|
100 | } else { |
---|
101 | $mail{to} = $to; |
---|
102 | $mail{cc} = join(', ', @cc); |
---|
103 | } |
---|
104 | $mail{to} or next; |
---|
105 | my $message; |
---|
106 | $template->process('account_expire.mail', $user, \$message) |
---|
107 | or die $template->error(); |
---|
108 | |
---|
109 | if (Mail::Sendmail::sendmail( |
---|
110 | %mail, |
---|
111 | Message => $message, |
---|
112 | )) { |
---|
113 | printf("Mail normally sent to %s; cc to %s\n", |
---|
114 | $to, (join(', ', @cc) || '')); |
---|
115 | } else { |
---|
116 | warn $Mail::Sendmail::error |
---|
117 | } |
---|
118 | } |
---|
119 | |
---|
120 | 1; |
---|
121 | } |
---|
122 | |
---|
123 | sub generate_rsa_key { |
---|
124 | my ($self, $password) = @_; |
---|
125 | |
---|
126 | my $rsa = new Crypt::RSA ES => 'PKCS1v15'; |
---|
127 | my ($public, $private) = $rsa->keygen ( |
---|
128 | Identity => 'LATMOS-Accounts', |
---|
129 | Size => 768, |
---|
130 | Password => $password, |
---|
131 | Verbosity => 0, |
---|
132 | KF=>'SSH', |
---|
133 | ) or die |
---|
134 | $self->rsa->errstr(); # TODO avoid die |
---|
135 | return ($public, $private); |
---|
136 | } |
---|
137 | |
---|
138 | sub store_rsa_key { |
---|
139 | my ($self, $public, $private) = @_; |
---|
140 | my $base = $self->_base; |
---|
141 | $base->set_global_value('rsa_private_key', |
---|
142 | encode_base64($private->serialize)); |
---|
143 | $base->set_global_value('rsa_public_key', |
---|
144 | $public->serialize); |
---|
145 | return; |
---|
146 | } |
---|
147 | |
---|
148 | sub private_key { |
---|
149 | my ($self, $password) = @_; |
---|
150 | my $base = $self->_base; |
---|
151 | my $serialize = $base->get_global_value('rsa_private_key') or return; |
---|
152 | my $privkey = Crypt::RSA::Key::Private::SSH->new; |
---|
153 | $privkey->deserialize(String => [ decode_base64($serialize) ], |
---|
154 | Passphrase => $password); |
---|
155 | $privkey |
---|
156 | } |
---|
157 | |
---|
158 | sub get_rsa_password { |
---|
159 | my ($self) = @_; |
---|
160 | my $base = $self->_base; |
---|
161 | my $sth = $base->db->prepare(q{ |
---|
162 | select "name", value from "user" join user_attributes_base |
---|
163 | on "user".ikey = user_attributes_base.okey |
---|
164 | where user_attributes_base.attr = 'encryptedPassword' |
---|
165 | }); |
---|
166 | $sth->execute; |
---|
167 | my %users; |
---|
168 | while (my $res = $sth->fetchrow_hashref) { |
---|
169 | $users{$res->{name}} = $res->{value}; |
---|
170 | } |
---|
171 | %users |
---|
172 | } |
---|
173 | |
---|
174 | 1; |
---|