##// END OF EJS Templates
Redmine.pm doc update...
Jean-Philippe Lang -
r1322:fc1a295d8a51
parent child
Show More
@@ -1,235 +1,237
1 1 package Apache::Authn::Redmine;
2 2
3 3 =head1 Apache::Authn::Redmine
4 4
5 5 Redmine - a mod_perl module to authenticate webdav subversion users
6 6 against redmine database
7 7
8 8 =head1 SYNOPSIS
9 9
10 10 This module allow anonymous users to browse public project and
11 11 registred users to browse and commit their project. Authentication is
12 12 done against the redmine database or the LDAP configured in redmine.
13 13
14 14 This method is far simpler than the one with pam_* and works with all
15 15 database without an hassle but you need to have apache/mod_perl on the
16 16 svn server.
17 17
18 18 =head1 INSTALLATION
19 19
20 20 For this to automagically work, you need to have a recent reposman.rb
21 21 (after r860) and if you already use reposman, read the last section to
22 22 migrate.
23 23
24 24 Sorry ruby users but you need some perl modules, at least mod_perl2,
25 25 DBI and DBD::mysql (or the DBD driver for you database as it should
26 26 work on allmost all databases).
27 27
28 28 On debian/ubuntu you must do :
29 29
30 30 aptitude install libapache-dbi-perl libapache2-mod-perl2 libdbd-mysql-perl
31 31
32 32 If your Redmine users use LDAP authentication, you will also need
33 Authen::Simple::LDAP (and IO::Socket::SSL if LDAPS is used).
33 Authen::Simple::LDAP (and IO::Socket::SSL if LDAPS is used):
34
35 aptitude install libauthen-simple-ldap-perl libio-socket-ssl-perl
34 36
35 37 =head1 CONFIGURATION
36 38
37 39 ## if the module isn't in your perl path
38 40 PerlRequire /usr/local/apache/Redmine.pm
39 41 ## else
40 42 # PerlModule Apache::Authn::Redmine
41 43 <Location /svn>
42 44 DAV svn
43 45 SVNParentPath "/var/svn"
44 46
45 47 AuthType Basic
46 48 AuthName redmine
47 49 Require valid-user
48 50
49 51 PerlAccessHandler Apache::Authn::Redmine::access_handler
50 52 PerlAuthenHandler Apache::Authn::Redmine::authen_handler
51 53
52 54 ## for mysql
53 55 PerlSetVar dsn DBI:mysql:database=databasename;host=my.db.server
54 56 ## for postgres
55 57 # PerlSetVar dsn DBI:Pg:dbname=databasename;host=my.db.server
56 58
57 59 PerlSetVar db_user redmine
58 60 PerlSetVar db_pass password
59 61 </Location>
60 62
61 63 To be able to browse repository inside redmine, you must add something
62 64 like that :
63 65
64 66 <Location /svn-private>
65 67 DAV svn
66 68 SVNParentPath "/var/svn"
67 69 Order deny,allow
68 70 Deny from all
69 71 # only allow reading orders
70 72 <Limit GET PROPFIND OPTIONS REPORT>
71 73 Allow from redmine.server.ip
72 74 </Limit>
73 75 </Location>
74 76
75 77 and you will have to use this reposman.rb command line to create repository :
76 78
77 79 reposman.rb --redmine my.redmine.server --svn-dir /var/svn --owner www-data -u http://svn.server/svn-private/
78 80
79 81 =head1 MIGRATION FROM OLDER RELEASES
80 82
81 83 If you use an older reposman.rb (r860 or before), you need to change
82 84 rights on repositories to allow the apache user to read and write
83 85 S<them :>
84 86
85 87 sudo chown -R www-data /var/svn/*
86 88 sudo chmod -R u+w /var/svn/*
87 89
88 90 And you need to upgrade at least reposman.rb (after r860).
89 91
90 92 =cut
91 93
92 94 use strict;
93 95
94 96 use DBI;
95 97 use Digest::SHA1;
96 98 # optional module for LDAP authentication
97 99 my $CanUseLDAPAuth = eval("use Authen::Simple::LDAP; 1");
98 100
99 101 use Apache2::Module;
100 102 use Apache2::Access;
101 103 use Apache2::ServerRec qw();
102 104 use Apache2::RequestRec qw();
103 105 use Apache2::RequestUtil qw();
104 106 use Apache2::Const qw(:common);
105 107 # use Apache2::Directive qw();
106 108
107 109 my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/;
108 110
109 111 sub access_handler {
110 112 my $r = shift;
111 113
112 114 unless ($r->some_auth_required) {
113 115 $r->log_reason("No authentication has been configured");
114 116 return FORBIDDEN;
115 117 }
116 118
117 119 my $method = $r->method;
118 120 return OK unless 1 == $read_only_methods{$method};
119 121
120 122 my $project_id = get_project_identifier($r);
121 123
122 124 $r->set_handlers(PerlAuthenHandler => [\&OK])
123 125 if is_public_project($project_id, $r);
124 126
125 127 return OK
126 128 }
127 129
128 130 sub authen_handler {
129 131 my $r = shift;
130 132
131 133 my ($res, $redmine_pass) = $r->get_basic_auth_pw();
132 134 return $res unless $res == OK;
133 135
134 136 if (is_member($r->user, $redmine_pass, $r)) {
135 137 return OK;
136 138 } else {
137 139 $r->note_auth_failure();
138 140 return AUTH_REQUIRED;
139 141 }
140 142 }
141 143
142 144 sub is_public_project {
143 145 my $project_id = shift;
144 146 my $r = shift;
145 147
146 148 my $dbh = connect_database($r);
147 149 my $sth = $dbh->prepare(
148 150 "SELECT * FROM projects WHERE projects.identifier=? and projects.is_public=true;"
149 151 );
150 152
151 153 $sth->execute($project_id);
152 154 my $ret = $sth->fetchrow_array ? 1 : 0;
153 155 $dbh->disconnect();
154 156
155 157 $ret;
156 158 }
157 159
158 160 # perhaps we should use repository right (other read right) to check public access.
159 161 # it could be faster BUT it doesn't work for the moment.
160 162 # sub is_public_project_by_file {
161 163 # my $project_id = shift;
162 164 # my $r = shift;
163 165
164 166 # my $tree = Apache2::Directive::conftree();
165 167 # my $node = $tree->lookup('Location', $r->location);
166 168 # my $hash = $node->as_hash;
167 169
168 170 # my $svnparentpath = $hash->{SVNParentPath};
169 171 # my $repos_path = $svnparentpath . "/" . $project_id;
170 172 # return 1 if (stat($repos_path))[2] & 00007;
171 173 # }
172 174
173 175 sub is_member {
174 176 my $redmine_user = shift;
175 177 my $redmine_pass = shift;
176 178 my $r = shift;
177 179
178 180 my $dbh = connect_database($r);
179 181 my $project_id = get_project_identifier($r);
180 182
181 183 my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass);
182 184
183 185 my $sth = $dbh->prepare(
184 186 "SELECT hashed_password, auth_source_id FROM members, projects, users WHERE projects.id=members.project_id AND users.id=members.user_id AND users.status=1 AND login=? AND identifier=?;"
185 187 );
186 188 $sth->execute($redmine_user, $project_id);
187 189
188 190 my $ret;
189 191 while (my @row = $sth->fetchrow_array) {
190 192 unless ($row[1]) {
191 193 if ($row[0] eq $pass_digest) {
192 194 $ret = 1;
193 195 last;
194 196 }
195 197 } elsif ($CanUseLDAPAuth) {
196 198 my $sthldap = $dbh->prepare(
197 199 "SELECT host,port,tls,account,account_password,base_dn,attr_login from auth_sources WHERE id = ?;"
198 200 );
199 201 $sthldap->execute($row[1]);
200 202 while (my @rowldap = $sthldap->fetchrow_array) {
201 203 my $ldap = Authen::Simple::LDAP->new(
202 204 host => ($rowldap[2] == 1 || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]" : $rowldap[0],
203 205 port => $rowldap[1],
204 206 basedn => $rowldap[5],
205 207 binddn => $rowldap[3] ? $rowldap[3] : "",
206 208 bindpw => $rowldap[4] ? $rowldap[4] : "",
207 209 filter => "(".$rowldap[6]."=%s)"
208 210 );
209 211 $ret = 1 if ($ldap->authenticate($redmine_user, $redmine_pass));
210 212 }
211 213 $sthldap->finish();
212 214 }
213 215 }
214 216 $sth->finish();
215 217 $dbh->disconnect();
216 218
217 219 $ret;
218 220 }
219 221
220 222 sub get_project_identifier {
221 223 my $r = shift;
222 224
223 225 my $location = $r->location;
224 226 my ($identifier) = $r->uri =~ m{$location/*([^/]+)};
225 227 $identifier;
226 228 }
227 229
228 230 sub connect_database {
229 231 my $r = shift;
230 232
231 233 my ($dsn, $db_user, $db_pass) = map { $r->dir_config($_) } qw/dsn db_user db_pass/;
232 234 return DBI->connect($dsn, $db_user, $db_pass);
233 235 }
234 236
235 237 1;
General Comments 0
You need to be logged in to leave comments. Login now