redMineのユーザでsvnリポジトリを認証する
http://d.hatena.ne.jp/rucifer_hacker/20070803/1186105118 みたいな感じの話。私の場合は、svnのリポジトリとredMineのプロジェクトを連動させて、redMineのプロジェクトメンバー以外は書き込みできない、とかしたかった。
そこで、mod_perlのモジュールを書いてみた。Perl書いたのは、6年ぶりくらいだぜ。http://redmine.soutaro.com/projects/show/2とかにおいてありますが、redmine.soutaro.comは、まだまだ気分で止めると思うので、こっちにもこぴぺしておきます。
package Apache::Authn::redMine; # file: Apache/Authn/redMine.pm use strict; use DBI; use Digest::SHA1; use Apache2::Module; use Apache2::Access; use Apache2::ServerRec qw(); use Apache2::RequestRec qw(); use Apache2::RequestUtil qw(); use Apache2::Const qw(:common); sub handler { my $r = shift; my $id = $r->dir_config('identity'); my ($res, $redmine_pass) = $r->get_basic_auth_pw(); return $res if $res != Apache2::Const::OK; my $dsn = $r->dir_config("dsn"); my $user = $r->dir_config("db_user"); my $pass = $r->dir_config("db_pass"); my $redmine_user = $r->user(); if (try_redmine($dsn, $user, $pass, $id, $redmine_user, $redmine_pass)) { return Apache2::Const::OK; } else { $r->note_auth_failure(); return Apache2::Const::AUTH_REQUIRED; } } sub try_redmine { my $dsn = shift; my $db_user = shift; my $db_pass = shift; my $redmine_id = shift; my $redmine_user = shift; my $redmine_pass = shift; my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass); my $dbh = DBI->connect($dsn, $db_user, $db_pass); my $sth = $dbh->prepare( "SELECT hashed_password FROM members, projects, users WHERE projects.id=members.project_id AND users.id=members.user_id AND login=? AND identifier=?;" ); $sth->execute($redmine_user, $redmine_id); while (my @row = $sth->fetchrow_array) { if ($row[0] eq $pass_digest) { return 1; } } $dbh->disconnect(); return 0; } 1;
使い方は、どっか適当なところに保存して、
# Add @INC to path this library is located in. # or install to your system. PerlSwitches -I[どっか適当なところ] <Location [/authnredmine] > DAV svn SVNPath [/var/svn/authnredmine] AuthType Basic AuthName ["authnredmine respotiroy"] # Select authentication handler PerlAuthenHandler Apache::Authn::redMine # Setup some variables PerlSetVar identity [authnredmine] PerlSetVar dsn [DBI:mysql:redmine:localhost:3306] PerlSetVar db_user [redmine] PerlSetVar db_pass [password] Require valid-user </Location>
みたいに書いてあげればいけるとおもう。
本当は、ユーザーのroleも見ないとダメだけど、そこまでやってられないので省略。あと、なんかの拍子にredMineのDB構造が変わると、アウトです。まあ、redMineはしばらく使ってみようと思うので、当面は面倒見ると思いますが。
LDAP使えばできるかもとか、mod_auth_dbdでいけないかとか、mod_auth_externalとか、考えたんですが、めんどくさくなりました。もっと適切な方法があったら教えてください。