Mercurial 勉強中 (7) - Web 経由の push と HTTP 認証
Web 経由で Mercurial のレポジトリを公開すると,デフォルトの状態では clone / pull しかできません。push するためには設定が必要になります。
なお今回は hgweb.cgi
や mod_wsgi
経由*1等で Apache と絡めた場合の話になります。
というのは,hg serve
コマンドで起動される HTTP サーバは BaseHTTPServer をもとにしているのですが,ビルトインの機能としては Authentication をサポートしておらず((自力で WWW-Authenticate
ヘッダ等やりとりすればいけるんじゃとは思います。詳しくないので自信ないです。)),また hgweb.server モジュールでもハンドリングしていないので認証関連の機能が実装されていないためです。
push 可能に設定する
[][web][]
セクションの allow_push
設定子を指定します。
hgrc
allow_push
- Whether to allow pushing to the repository. If empty or not set, push is not allowed. If the special value "
*
", any remote user can push, including unauthenticated users. Otherwise, the remote user must have been authenticated, and the authenticated user name must be present in this list (separated by whitespace or ",
"). The contents of the allow_push list are examined after thedeny_push
list.
レポジトリ下の .hg/hgrc
ファイルに下記の内容を追加します。
[web] allow_push = *
暫定的に「*
」を指定しています。下記で説明している HTTP 認証と絡めて具体的なユーザ名を指定することもできます。
非 HTTPS(HTTP)でも push 可能に
デフォルトでは HTTPS 経由でないと push できません。イントラなど HTTP 経由で構わない場合は [][web][]
セクションの push_ssl
設定子に false
を指定します。
hgrc
push_ssl
- Whether to require that inbound pushes be transported over SSL to prevent password sniffing. Default is
true
.
具体的にはレポジトリ下の .hg/hgrc
ファイルに下記の内容を追加します。
[web] push_ssl = false
HTTP 認証の設定を加える
Mercurial の Web インタフェースの認証関連の機能は Remote-User
ヘッダを見ています。ですので,通常の Apache と同様に設定すれば OK です。
<Location path-to-repository> AuthType Basic AuthUserFile /foo/bar/htpasswd Require valid-user </Location>
これで allow_push
設定子に具体的なユーザ名を指定することができるようになります。
ちなみに上の例では Basic 認証ですが,実際には私の環境では mod_auth_ntlm_winbind で AuthType NTLM
を使用しています*2。
push だけ認証を要求したい
clone だけは anonymous OK だけど push できるのは認証したユーザだけにしたい,というのはよくある要件です。
アクセスログを見ると,どうやら push の際には
POST
repository URI?cmd=unbundle&heads=
HOGEHOGEHOGE
というアクセスが発行されるようです。
ですので <LocationMatch>
で ?cmd=unbundle
をひっかけてもいいんですが,ざっとみた感じメソッドが POST
に限定されているようなので,Subversion と揃えて次のような設定で制限をかけるようにしました。
AuthType Basic <LimitExcept GET PROPFIND OPTIONS REPORT> Require valid-user </LimitExcept>
念のため deny_push も指定しておく
も指定しておく
いままでの内容では allow_push
に「*
」を設定しました。もし手違いで Apache 側の認証関連の設定を lost してしまった場合,anonymous に push 可能になってしまいます。
あくまで認証しているユーザには push をさせたい,だけど anonymous に push されてしまうのも困る,ということを Mercurial 側に設定しておきましょう。deny_push
を使うと可能になります。
hgrc
deny_push
- Whether to deny pushing to the repository. If empty or not set, push is not denied. If the special value "
*
", all remote users are denied push. Otherwise, unauthenticated users are all denied, and any authenticated user name present in this list (separated by whitespace or ",
") is also denied. The contents of the deny_push list are examined before theallow_push
list.
副次的効果ですが deny_push
になんらかの設定がなされている場合,REMOTE_USER
が設定されていない場合に push できなくなります(コードも見て確認しました)。
ですので,ダミーですが
[web] allow_push = * deny_push = unauthenticated_user
のようにしておくと,万一 Apache の設定が失われても push できなくなります。
push するたびに毎度ユーザ名とパスワードを聞かれてうざい
Subversion の場合,一度 commit する際にユーザ名とパスワード入力すると,その後は認証情報を覚えてくれます。ですが,Mercurial の場合,push する度に聞かれます。
% hg push pushing to http://localhost/hg/example searching for changes http authorization required realm: Mercurial user: dayflower password: ******** adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files
なんとかなりませんか。
その答え,FAQ にあります。
How can I store my HTTP login once and for all ? - FAQ - MercurialHow can I store my HTTP login once and for all ?
You can specify the usename and password in the URL like:
http://user:password@mydomain.orgThen add a new entry in the
paths
section of yourhgrc
file.
ううう,なんかダサい。
どうでもいいけど
Unauthorized でハネられるときにも Status 200 を返すのがダサいと思いました。