ApacheでSVNのアクセス制御とリポジトリ一覧表示を同時にやる

ことの発端

  • SVNリポジトリ一覧を表示するためには、SVNListParentPathをon(デフォルトoff)にする設定をすればいい。
  • SVNでアクセス制御をするためには、AuthzSVNAccessFileを設定をすればいい。

一応それは知っていて仕事で使ってるリポジトリは以下のような感じの設定をしていた。

<Location />
    SVNListParentPath on
    DAV svn
    SVNParentPath /srv/svn

    # Htpasswd Logins
    AuthType Basic
    AuthName "SVN Repository"
    AuthUserFile /etc/apache2/default.htpasswd

    AuthzSVNAccessFile /srv/svn/svnaccess.conf
    Require valid-user

</Location>

しかーし!これだとなぜかリポジトリ一覧がForbiddenで返ってきてしまう。
「なんでじゃろ?」とは思っていたが、リポジトリ一覧が見えないくらい大して困らないのでこれまで放置していた。

んで、今日じっくり調べたら、これは以下のようなバグで結構みんな困ってることがわかった。
http://subversion.tigris.org/issues/show_bug.cgi?id=2753
まあ前述のとおり、困るといっても大して困らない問題であるためか、なかなかパッチが出ないようである。

回避策(その1)

このバグに対する回避策はWeb上にたくさん転がっていた。
リポジトリのURLがホストのルートでない場合は

<Location /svn>
    DAV svn
    SVNParentPath /srv/svn
    ....
</Location>

と書くところを

<Location /svn/>
    DAV svn
    SVNParentPath /srv/svn
    ....
</Location>

と書くことで回避可能とのことだ。が、 http://example.com/svnといった風に / で終わらないURL指定だとちゃんと受け付けてもらえずhttp://example.com/svn/とかかないといけなくなる副作用があるらしいし、そもそも私はvhostを使ってhttp://svn.example.com/という風にルートのURLでリポジトリ一覧が出るようにしたいのだ。

回避策(その2:ルートのURLでリポジトリ一覧としたい場合)

よくよく探してみると、上記のバグDBの中で(Vilar Camara Neto 2007/11/16 11:35:49 -0800)さんが以下のような回避策をコメントで挙げられていたのを見つけた。

<Location />
    DAV svn
    SVNParentPath /srv/svn
    SVNListParentPath on
</Location>
<LocationMatch /.+>
    DAV svn
    SVNParentPath /srv/svn

    # Htpasswd Logins
    AuthType Basic
    AuthName "SVN Repository"
    AuthUserFile /etc/apache2/default.htpasswd

    AuthzSVNAccessFile /srv/svn/svnaccess.conf
    Require valid-user

</LocationMatch>

上記コメント曰く冗長で「汚い」回避策だと認めていたが、確かに Dav svnだとか2回ずつ書いてるのがちょっといやだ。それに、これだとリポジトリ一覧は完全にオープンになってしまう。かといって、そこにも認証をかけるとなると、さらに4行以上も冗長な行ができてしまい、汚さが大幅パワーアップしてしまう。。

回避策(その3:改良版)

そこで、上記回避策をもうちょっと改良して以下のようにしてみた。

<Location />
    SVNListParentPath on
</Location>
<LocationMatch /.*>
    DAV svn
    SVNParentPath /srv/svn
 
    # Htpasswd Logins
    AuthType Basic
    AuthName "SVN Repository"
    AuthUserFile /etc/apache2/default.htpasswd
 
    Require valid-user
</LocationMatch>
<LocationMatch /.+>
    AuthzSVNAccessFile /srv/svn/svnaccess.conf
</LocationMatch>

冗長性は排除したので、まあ綺麗とはいわないが、許せないほど汚くもない気もする。しかも、ちゃんとリポジトリ一覧も「認証」だけは求められるようになる。(アクセス制御はできないが・・)

とりあえずしばらくは、これでいっとこうと思う。

得られた知見?

よくわからないが、上記が動いたということは

ApacheのLocationMatchディレクティブは、マッチしたブロックの定義を全部重ね合わせた設定がなされる

ということだろうか。