source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Acls.pm @ 2422

Last change on this file since 2422 was 2381, checked in by nanardon, 4 years ago

Fix ACL, replace $ROOT by @ROOT: '$' has special meaning here

File size: 5.7 KB
Line 
1package LATMOS::Accounts::Acls;
2
3use strict;
4use warnings;
5use LATMOS::Accounts::Log;
6use LATMOS::Accounts::Acls::Acl;
7
8our $VERSION = (q$Rev: 330 $ =~ /^Rev: (\d+) /)[0];
9
10=head1 NAME
11
12LATMOS::Accounts::Acls - Acl support in L<LATMOS::Accounts>
13
14=head1 FUNCTIONS
15
16=cut
17
18=head2 new ($file)
19
20Instanciate Acls from C<$file>
21
22=cut
23
24sub new {
25    my ($class, $file) = @_;
26    my $acls = bless(
27        {
28            _acls => [
29                LATMOS::Accounts::Acls::Acl->new( '*.*', [ '@ROOT: read,write' ] ),
30            ],
31            _default_acls => [
32                LATMOS::Accounts::Acls::Acl->new( '*.log', [ '$uid: read', '*: deny' ] ),
33                LATMOS::Accounts::Acls::Acl->new(
34                    'user.{userPasswd,userPassword,encryptedPassword,oldPassword}',
35                    [ '$uid: write', '*: deny' ],
36                ),
37            ]
38        }, $class
39    );
40
41    if ($file) {
42        $acls->read_acl_file($file) or return;
43    }
44
45    $acls
46}
47
48=head1 ACL FILE FORMAT
49
50    OBJ_TYPE.ATTRIBUTE
51        USER:  read,write
52        USER2: read
53
54=over 4
55
56=item OBJ_TYPE is the type the object, '*' match all
57
58=item ATTRIBUTE is either an attribute, either an comma separate attribute
59enclose into bracket, either a '*' to match any attribute.
60
61Special keyword C<@CREATE> and C<@DELETE> can be used to allow or deny object
62creation and deletion. In this case read permission and USER in form C<$...> for
63C<@CREATE> have no effect (see below). C<*> do not include C<@CREATE> and
64C<@DELETE> action.
65
66=item USER can be
67
68=over 4
69
70=item a username
71
72=item group, prefixed by a '%'
73
74=item an attribute of the accessed object which should contains the username,
75prefixed by '$'
76
77=item C<*> to math any user
78
79=item @authenticated or @anonymous for any authenticated user and non
80authenticated user ('*' include both)
81
82=back
83
84=item Permission are read and or write, or deny.
85
86=back
87
88ACL are applied in the order they appear in the file.
89
90=cut
91
92=head2 read_acl_file ($file)
93
94Load acls from file C<$file>.
95
96=cut
97
98sub read_acl_file {
99    my ($self, $file) = @_;
100
101    my $acl;
102    my $line_nb = 0;
103    my $prevline = "";
104    if (open(my $handle, '<', $file)) {
105        while(my $realline = <$handle>) {
106            $line_nb++;
107            chomp($realline);
108            if ($realline =~ /\\$/) {
109                # continuation line
110                $prevline .= $realline;
111                $prevline =~ s/\s*\\$//;
112                next;
113            }
114            my $line = $prevline . $realline; # keep track to report malformed file
115            $prevline = "";
116            $line =~ s/\s*#.*//;
117            if ($line =~ /^(\S.*)/) {
118                if ($acl) {
119                    push(@{$self->{_acls}}, $acl);
120                }
121                $acl = LATMOS::Accounts::Acls::Acl->new($1) or do {
122                    la_log(LA_ERR, "Error in %s at line %d", $file,
123                        $line_nb);
124                    return;
125                };
126            } elsif ($line =~ /^\s+(\S.*)/) {
127                if ($acl) {
128                    $acl->add_perm($line) or do {
129                        la_log(LA_ERR, "Error in %s at line %d", $file,
130                            $line_nb);
131                        return;
132                    };
133                } else {
134                    # err no acl
135                    return;
136                }
137            } elsif ($line =~ /^\s*$/) {
138                # just empty line
139            } else {
140            }
141        }
142        if ($acl) {
143            push(@{$self->{_acls}}, $acl);
144        }
145    } else {
146        la_log(LA_ERR, "Cannot open acl file %s", $file);
147        return;
148    }
149    1;
150}
151
152=head2 add ($obj_dot_attr, $list)
153
154A new acl for C<$obj_dot_attr> (in form C<object.attribute>) with C<$list>
155permissions.
156
157=cut
158
159sub add {
160    my ($self, $obj, $list) = @_;
161    my $acl = LATMOS::Accounts::Acls::Acl->new(
162        $obj, $list) or return;
163    push(@{$self->{_acls}}, $acl);
164    return 1;
165}
166
167=head2 check ($obj, $attr, $perm, $who, $groups)
168
169Return true is this acl apply to C<$obj>/C<$attr> for C<$perm> by user
170C<$who> in groups C<$groups>.
171
172=cut
173
174sub check {
175    my ($self, $obj, $attr, $perm, $who, $groups, $base) = @_;
176    # Asking 'r' perm over create or delete has no sense:
177    $attr =~ /^@(CREATE|DELETE)$/ && $perm eq 'r' and return;
178
179    foreach my $acl (@{$self->{_acls}}, @{$self->{_default_acls}}) {
180        my $res = $acl->match($obj, $attr, $perm, $who, $groups, $base);
181        if ( defined($res) ) {
182            if ( $ENV{LA_ACL_DEBUG} ) {
183                la_log(
184                    LA_DEBUG,
185                    "Acl: %s %s for %s by %s => %s :\n%s",
186                    (ref $obj ? $obj->type . '/' . $obj->id : $obj),
187                    $attr,
188                    $perm,
189                    $res,
190                    $who,
191                    $acl->dump,
192                );
193            }
194            return $res;
195        }
196    }
197
198    if ( $ENV{LA_ACL_DEBUG} ) {
199        la_log(
200            LA_DEBUG,
201            "Acl: %s %s for %s => No match",
202            ref $obj ? $obj->type . '/' . $obj->id : $obj,
203            $attr,
204            $perm,
205        )
206    }
207    return 0;
208}
209
210
211=head2 dump
212
213Return currently load acl as text
214
215=cut
216
217sub dump {
218    my ($self) = @_;
219    foreach my $acl (@{$self->{_acls}}, @{$self->{_default_acls}}) {
220        print $acl->dump, "\n";
221    }
222}
223
2241;
225
226__END__
227
228=head1 SEE ALSO
229
230L<LATMOS::Accounts::Acls::Acl>
231
232=head1 AUTHOR
233
234Thauvin Olivier, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
235
236=head1 COPYRIGHT AND LICENSE
237
238Copyright (C) 2009, 2010, 2011, 2012 by Thauvin Olivier
239
240This library is free software; you can redistribute it and/or modify
241it under the same terms as Perl itself, either Perl version 5.10.0 or,
242at your option, any later version of Perl 5 you may have available.
243
244=cut
Note: See TracBrowser for help on using the repository browser.