Subversion + https + Basic認証を知る

what

[hoge@fuga test_svn]$ svn checkout https://barbaz.com/svn/repos foo
svn: PROPFIND request failed on '/svn/repos'
svn: PROPFIND of '/svn/repos': could not connect to server (https://barbaz.com)

https://barbaz.com/svn/repos には、Basic認証がかかっていて、ブラウザでアクセスすると、アクセス可能です。


上記のエラーがでて、チェックアウトできなくて、困っている・・・。
https://barbaz.com/svn/repos のWebサーバーはApacheです。
※barbaz.com=グローバルIP でアクセス


やりたいことは、
Seasons.NET
↑このあたりです

今回は、基本的な設定は出来ている状態です。



Basic認証を知る

ブラウザでアクセスするのであれば、Basic認証は username と password の入力を促すわけだが、コマンドラインだとどうなるんだろうね?
ということで、Basic認証を知らなすぎるので、学びましょう。


Basic認証 - Wikipedia
↑まず、読みましょうか。

HTTPで定義される認証方式の一つ。

ふむふむ。

Basic認証では、ユーザ名とパスワードの組みをコロン ":" で繋ぎ、Base64エンコードして送信する。このため、盗聴や改竄が簡単であるという欠点を持つが、ほぼ全てのWebサーバおよびブラウザで対応しているため、広く使われている。

なるほど。

1. クライアントは認証が必要なページをリクエストする。しかし、通常ここではユーザ名とパスワードを送っていない。なぜならばブラウザはそのページが認証を必要とするか否か知らないためである。
2. サーバは401レスポンスコードを返し、認証領域 (authentication realm) や認証方式 (Basic認証) に関する情報をクライアントに知らせる。

なるほど、サーバーは401を返して、認証を促すのかー。ちなみに、svnは401が帰ってきたとき、Basic認証の処理を、ちゃんと処理して対話型にしてくれるようです。

3. ここでクライアントは、認証領域(通常アクセスしているコンピュータやシステムの簡単な説明)をユーザに提示して、ユーザ名とパスワードの入力を求める。ユーザはここでキャンセルすることもできる。
4. ユーザ名とパスワードが入れられると、クライアントは認証ヘッダを含めたリクエストを再送信する。
5. 以下の例では、サーバは認証に成功して認証の必要なページのリクエストを処理するが、ユーザ名が不正だったりパスワードが間違っていた時にはサーバが再び401レスポンスコードを返す。このときは、クライアントは再びユーザにユーザ名とパスワードの入力をもとめる。

典型的なBasic認証の通信がわかりました。


  • 認証を伴わないリクエス
GET /private/index.html HTTP/1.1
Host: example.com
  • 認証が必要であることを示すサーバのレスポンス:
HTTP/1.1 401 Authorization Required
Date: Wed, 11 May 2005 07:50:26 GMT
Server: Apache/1.3.33 (Unix)
WWW-Authenticate: Basic realm="SECRET AREA"
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1

(ここに人間が読めるエラーメッセージが入る)
  • 認証を伴うリクエスト (ユーザ名 "Aladdin"、パスワード "open sesame"):
GET /private/index.html HTTP/1.1
Host: example.com
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==


なるほど、「認証を伴わないリクエスト」と「認証を伴うリクエスト」を比較すると、

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

があるかないか、なので、最初からこのリクエストにすれば、「認証が必要であることを示すサーバのレスポンス」は飛ばせるわけですね。
TortoiseSVNBasic認証のかかったリポジトリから一度認証してソースを持ってくると、次回からは認証がいらないのは、認証情報をどこかに保存しておいて、次回のリクエストのときには、それと一緒にリクエストするから認証は飛ばせるわけですね。



ためしに、開発サーバーと同じローカルネットワーク内にあるサーバからやってみた(barbaz.com=ローカルIP でアクセス)

[hoge_b@fuga_b test_svn]$ svn co https://barbaz.com/svn/repos foo
'https://barbaz.com:443'サーバ証明書の認証中にエラーが発生しました:

  • 証明書の期限が切れています。

証明書情報:

  • ホスト名: barbaz.com
  • 有効範囲: Apr 28 00:00:00 2005 GMT から Apr 28 23:59:59 2006 GMT まで
  • 発行者: www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign, VeriSign International Server CA - Class 3, VeriSign, Inc., VeriSign Trust Network
  • フィンガープリント: xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx

拒否しますか (R)、一時的に承認しますか (t)、常に承認しますか (p)? t
認証領域: https://barbaz.com:443 Subversion repository
'hoge_b' のパスワード:
認証領域: https://barbaz.com:443 Subversion repository
ユーザ名: hoge_b
'fukushige' のパスワード:
A rixi/test/fixtures/xxxxxx.yml
A rixi/test/fixtures/zzzzzz.yml
 ・
 ・
 ・

むむ!なんか、認証作業がはじまって、チェックアウトできた!!

これは・・・ barbaz.com 側の問題ではなく、他に問題がありそうだな。
ファイヤーウォールを解除してもだめだった・・・。


結論

https://barbaz.com/svn/repos 直前のルータが 443 ポートの通過を許していなかった・・・。

$ telnet barbaz.com 443
$ Trying xxx.xxx.xxx.xxx...

そもそも、つながらん・・・。
ということで、ルータの設定で、特定のIPからの443アクセスを許すことにしました。


1つ1つ順番にちゃんと見ていかないと、はまりますね・・・orz