svnserve プログラムは軽量なサーバで専用の状態プロトコル
によって TCP/IP 上でクライアントと通信することができます。クライアントは
svn://
またはsvn+ssh://
で始まる URL によって svnserveサーバと通信します。この節
では svnserveを実行する別の方法を説明しクライアントが
どうやってサーバに認証するか、またリポジトリに適切なアクセス制御を設定
するにはどうしたら良いかについて説明します。
svnserveプログラムの起動にはいくつかの異なる方法が
あります。オプションなしで起動した場合は何もせずヘルプメッセージを
表示するだけです。しかしinetd経由で起動するなら
-i
(--inetd
) オプションを指定すること
ができます:
$ svnserve -i ( success ( 1 2 ( ANONYMOUS ) ( edit-pipeline ) ) )
--inetd
オプション付きで起動すると
svnserve はSubversion クライアントとの間
で、専用のプロトコルを使い、stdinと
stdoutチャンネル経由で通信しようとします。
これはinetdを経由して
実行されるプログラムの標準的な振る舞い方です。IANAはポート3690
をSubversion プロトコルのために予約しているため Unix風のシステム上
なら/etc/services
ファイルに(もしまだ追加されていない
のなら)以下の行を追加することができます:
svn 3690/tcp # Subversion svn 3690/udp # Subversion
そしてもし伝統的な Unix風のinetdデーモンを使って
いるのなら /etc/inetd.conf
に以下のような行を
追加することができます:
svn stream tcp nowait svnowner /usr/bin/svnserve svnserve -i
「svnowner」はリポジトリにアクセスするのに適切な パーミッションをもったユーザであることを確認してください。 これでクライアントがサーバのポート3690に接続しにきた時点で inetdはsvnserve プロセスを起動し、処理を任せます。
Windows システムではsvnserveをサービスとして 起動するためのサードパーティーのツールがあります。このようなツールの 一覧については Subversion のウェブサイトを見てください。
第二の方法はsvnserveを単独の「デーモン」プロセスとして
起動する方法です。これには-d
オプションを使って
ください:
$ svnserve -d $ # svnserve is now running, listening on port 3690
デーモンモードでsvnserveを実行するときには
--listen-port=
と
--listen-host=
オプションで待ち受けポートとホスト
名を「指定」することができます。
さらにsvnserveを起動する第三の方法があり、
それは「トンネルモード」と呼ばれますが、-t
オプション
を付けて起動します。このモードは
RSHや
SSHのようなリモートサービスプログラムがユーザを
正しく認証しそのユーザでプライベートな svnserve
サーバを起動している状況を仮定しています。 svnserve
プログラムは普通に振る舞い(stdinとstdout
を通じて)、通信データは自動的にクライアントの背後にいる何らかのトンネル
にリダイレクトされると仮定しています。svnserveが
このようなトンネルエージェントによって起動された場合は認証ユーザは
リポジトリデータベースファイルに完全な読み書きアクセスを持つことに注意
してください。(サーバとパーミッション: 留意点を参照してください)。
これは本質的には file:///
URLを使ってリポジトリにアクセス
するローカルユーザと同じになります。
一度svnserveプログラムが実行されるとネットワーク越しに
システム上のすべてのリポジトリが利用可能になります。クライアントは
リポジトリ URL の絶対パスを指定する必要があります。
たとえば、リポジトリが/usr/local/repositories/project1
にあるならクライアントは svn://host.example.com/usr/local/repositories/project1
によってそこにアクセスするでしょう。セキュリティー
を高めるため svnserveに -r
オプションを渡すこともできますが、これはそのパス以下のリポジトリだけを公開
するように制限します:
$ svnserve -d -r /usr/local/repositories …
-r
オプションの利用は
リモートファイルシステム空間のルートとしてプログラムが扱う場所
を効果的に変更することができます。この場合クライアントはそのルート
までの部分を除いたパスを指定することになり、もっと短い(そしてより情報制限された)
URL を利用できます:
$ svn checkout svn://host.example.com/project1 …
クライアントがsvnserveプロセスに接続する とき、以下のことが起こります:
クライアントは特定のリポジトリを選択します。
サーバはリポジトリの conf/svnserve.conf
ファイルを処理しその中に定義されている認証と認可の方式に強制的に
従います。
そのときの状況と認可の方式により、以下のどれかになります。
クライアントは要求を匿名で行うことができ、どのような認証確認も 要求されないか、
クライアントは常に認証許可を求められるか、
もし"トンネルモード"で実行されている場合であれば、クライアント は既に外部的に認証されたことを宣言するか、です。
これを書いている時点では、サーバはCRAM-MD5 [24] 認証確認の方法だけを知っています。本質的にサーバはクライアント に対して少しのデータを送ります。 クライアントはMD5ハッシュのアルゴリズムを使ってデータとパスワードを一 緒にしたデータについてのフィンガープリントを作成し、これを応答メッセー ジとして送信します。サーバは同じ計算を保存してあるパスワードについて おこない結果が同じであることを確認します。いかなる場合でも ネットワーク上に実際のパスワードが流れることはありません。
もちろんクライアントはトンネルエージェント、たとえば SSHのようなものを経由して外部的に 認証することもできます。この場合サーバは単に実行している ユーザを確認し、それを認証されたユーザ名であるとして 利用します。より詳しくは SSH 認証と認可項を見てください。
もうおわかりだと思いますが、リポジトリのsvnserve.conf
ファイルは認証と認可の方式を制御する中心的な仕組みです。このファイルは他の
設定ファイルと同じ形式をしています。(実行時設定領域項
参照): セクション名は角かっこ([
and ]
)
で示され、コメントはハッシュ文字(#
)で始まり、セクションの
それぞれには設定可能な特定の変数が含まれています。(variable = value
)。
このファイルを見てどのように利用されているか理解してください。
ここでは svnserve.conf
の
[general]
セクションに必要な変数のすべてがあります。
ユーザ名とパスワードを含むファイルの定義で始まり、認証範囲を設定
しています:
[general] password-db = userfile realm = example realm
realm
は自分で定義できる名前です。
それはクライアントに接続先の「認証用の名前空間」の種別を伝えます;
Subversion クライアントは認証プロンプトでそれを表示し、ディスク上の
キャッシュされた証明のキーとして(サーバのホスト名、ポートと共に)
利用します。(クライアント証明のキャッシュ項参照。)
password-db
変数はユーザ名称とパスワードのリスト
を含む個別のファイルを指す変数で、やはり同じ形式が利用されます。
たとえば:
[users] harry = foopassword sally = barpassword
password-db
の値はユーザファイルの相対または
絶対パスです。多くの管理者にとって、svnserve.conf
に従ったリポジトリの conf/
領域にファイルを
正しく保つのは容易なことです。一方、同じユーザファイルを共有するような
二つ以上のリポジトリがほしいこともあります; そのような場合は
ファイルは多分もっと公開された場所に移動すべきでしょう。ユーザファイルを共有
するリポジトリは同じ認証範囲を持つよう設定されていなくてはならず、それは
ユーザ全員が本質的にただ一つの認証範囲を定義するためです。
ファイルがある場所であればどこでもファイルの読み書きパーミッション
を正しく設定してください。もし svnserveを
どのユーザが実行しているかわかるのであれば、必要に応じて
ユーザファイルに対する読み出しアクセス制限をかけてください。
svnserve.conf
ファイル中に、さらに二つの変数を
設定できます: それは認証されていない(匿名の)ユーザと、認証された
ユーザに何を許すかを決めるものです。その変数anon-access
と auth-access
はnone
、read
、
あるいはwrite
に設定できます。
none
はどのようなタイプのアクセスも制限します。
read
はそのリポジトリに読み出し許可のみを与え、
write
はリポジトリに完全な読み書きアクセスを許します。
たとえば:
[general] password-db = userfile realm = example realm # anonymous users can only read the repository anon-access = read # authenticated users can both read and write auth-access = write
この例としての設定は、実際にはこれらの変数のデフォルト値なので定義 しなくても問題ありません。もしさらに保守的に設定したいのなら、 匿名のアクセスを完全に遮断することもできます:
[general] password-db = userfile realm = example realm # anonymous users aren't allowed anon-access = none # authenticated users can both read and write auth-access = write
svnserveは単に「無制限の」アクセスコントロールのみ を理解することに注意してください。ユーザは完全な読み書きアクセス、 完全な読み出しアクセス、あるいは、まったくアクセスできない、のいずれか です。リポジトリ中の特定のパスに対する詳細なアクセス制御は 存在しません。多くのプロジェクトとサイトではこのレベルのアクセス制御 は十分すぎるものです。しかしもしディレクトリごとのアクセス制御が必要 なら、Apache をmod_authz_svn と一緒に使うか (ディレクトリごとのアクセス制御項を見てください)、書き込み制御を 行う pre-commit フックスクリプトを使う必要があります (フックスクリプト項を見てください)。Subversion の ディストリビューション中には commit-access-control.pl と、さらに洗練された svnperms.py スクリプトがあって、 pre-commit スクリプトの中で利用することができます。
svnserveの組み込み認証は非常に使いやすいものですが、 それは本当のシステム上のアカウントを作る必要がないからです。一方 管理者によっては既に確立された SSH 認証の仕組みを運用しているかも 知れません。そのような場合、プロジェクトユーザのすべてはシステムアカウント を持っており、サーバマシンに対して 「SSH による」 アクセスが可能なはず です。
SSH とsvnserveの組み合わせは簡単なものです。クライアントは
単にsvn+ssh://
URLスキーマを使って接続することができます:
$ whoami harry $ svn list svn+ssh://host.example.com/repos/project harry@host.example.com's password: ***** foo bar baz …
この例では、Subversionクライアントはローカルなssh
プロセスを起動し host.example.com
に接続し、ユーザ
harry
として認証し、そのあとプライベートな
svnserveプロセスをリモートマシン上で、ユーザ
harry
として実行する、というものです。
svnserveコマンドはトンネルモード(-t
)
起動され、そのネットワークプロトコルはトンネルエージェントであるssh
によって暗号化された接続上で「トンネル」された形で動作します。
svnserveはユーザharry
で実行されていることを知って
いるのでクライアントがコミットしようとすると、その認証済みのユーザ名は新しい
リビジョンの変更者として利用されます。
ここで重要なのは Subversion クライアントはsvnserve デーモンに接続するわけではないということです。 このアクセス方法はデーモンは不要で、存在しているかどうかを知る必要も ありません。実際には sshが一時的に起動する svnserve プロセスにだけ依存していて、ネットワーク接続が閉じるとそのプロセスも終了します。
svn+ssh://
の URL を使ってリポジトリにアクセスする
場合、認証を要求するのはsshプログラムであり
svnクライアントプログラムではないことを思い出して
ください。これは自動的なパスワードのキャッシュが起きないことを
意味します(クライアント証明のキャッシュ項を見てください)。
Subversion クライアントはリポジトリに複数の接続を張ることもよくあります
がユーザはパスワードキャッシュの仕組みによって通常そのことに気づくことは
ありません。しかし svn+ssh://
URL を使う場合には
ユーザは接続ごとに sshが繰り返しパスワードをうながす
ことに悩ませられるかも知れません。解決策は Unix 風のシステムなら
ssh-agent、Windows なら pageant
のような独立した SSH パスワードキャッシュツールを利用することです。
トンネル上で実行する場合、認可は基本的にはリポジトリデータベースファイルに
対するオペレーティングシステムのパーミッションによって一義的には制御
されます; それはちょうど harry が直接file:///
URLで
リポジトリにアクセスした場合と同じことになります。
複数のシステムユーザがリポジトリに対して直接アクセスしようとしている場合
そのようなユーザを一つのグループにまとめ、umask を注意して設定する必要が
あるでしょう。(複数リポジトリアクセス方法のサポート項をぜひ読んでください)。
しかしトンネルモードを利用する場合でもauth-access = read
またはauth-access = none
と設定すれば、
svnserve.conf
ファイルはやはりアクセス遮断のために
利用できます。
SSH トンネルの話はこれで終わりかと思うかも知れませんが、そうではありません。
Subversion では実行時config
ファイル中に専用のトンネル
モードに関する動作設定をすることができます。(実行時設定領域項
を見てください)。たとえば SSH のかわりに RSH を使いたいとします。config
ファイルの[tunnels]
セクションに以下のように指定してください:
[tunnels] rsh = rsh
これで新しい変数の名前にマッチする URL スキーマを使って
この新しいトンネル定義を利用することができます:
svn+rsh://host/path
となります。
新しい URL スキーマを利用すると Subversion クライアントは実際には裏で
rsh host svnserve -tコマンドを実行します。もしURL
にユーザ名が含まれている場合(たとえば svn+rsh://username@host/path
)
クライアントはやはりそのコマンドに含めます(rsh username@host svnserve -t.)
しかし、以下のようにもっと賢いトンネルスキーマを定義することもできます:
[tunnels] joessh = $JOESSH /opt/alternate/ssh -p 29934
この例はいろいろなことの参考になります。まずそれはどのようにして
Subversion クライアントが非常に特殊なトンネリングのためのプログラムを
特定のオプション付きで起動するかを示しています(この場合それは
/opt/alternate/ssh
にあります)。
この場合svn+joessh://
URLにアクセスすると
引数として-p 29934
の付いた特定のSSHプログラム
が起動されるでしょう— もし標準ではないポートにトンネルプログラム
を接続したいと考えているならこれは便利です。
次にそれはどのように
してトンネルプログラムの名前を上書きする環境変数を定義してやれば
良いかを示しています。
SVN_SSH
環境変数を設定するのはデフォルトの SSH トンネル
エージェントを上書きする便利な方法です。
しかしもし異なるサーバ上でいくつもの異なる上書きが必要で、それぞれが
異なるポートや異なるオプションを SSH に渡しているような場合には、この例で
示すような仕組みを利用することができます。
もしJOESSH
環境変数を設定
してあれば、その値はトンネル変数全体を上書きします—
$JOESSHは
/opt/alternate/ssh -p 29934のかわりに実行
されるでしょう。
クライアントが sshを起動する方法を制御できるだけ ではなく、サーバマシン上の sshdの動作の仕方も 制御することができます。この節では sshd によって起動される svnserveコマンドを正しく制御する 方法を示して、複数のユーザが単一システムアカウントをどのように共有すれば 良いかについて説明します。
まずsvnserveを起動するのに使うアカウントの
ホームディレクトリを用意します。そのアカウントに SSH の公開鍵/秘密鍵
がインストールされていて、ユーザがその公開鍵でログインできることを
確認してください。パスワード認証は動作しなくなりますが、それは以下の
SSH の技法を使うと、すべての処理に SSH authorized_keys
ファイル
を使うためです。
まだ存在していなければauthorized_keys
ファイルを
作ってください(Unix では普通 ‾/.ssh/authorized_keys
になります)。このファイルの各行には接続を許す相手先の公開鍵の記述があります。
各行は普通以下のような形をしています:
ssh-dsa AAAABtce9euch.... user@example.com
最初のフィールドはキーの型で、二番目のフィールドは uuencode された鍵そのもの
であり、三番目のフィールドはコメントです。あまり知られていませんが、実は
行全体を command
フィールドの後におくこともできます。
command="program" ssh-dsa AAAABtce9euch.... user@example.com
command
フィールドが設定されると 通常の svnserve -t
のかわりに SSH デーモンがその名前のプログラムを実行します。このプログラムが
Subversion クライアントの接続先になります。これがサーバ上でのいろいろな技法を
可能にする鍵です。以下の例では、ファイル中で次のように行を省略して説明します:
command="program" TYPE KEY COMMENT
実行されるサーバ側コマンドを指定することができるので、特定の svnserveバイナリを指定したり、追加の引数を 指定して実行することが簡単にできます:
command="/path/to/svnserve -t -r /virtual/root" TYPE KEY COMMENT
この例では /path/to/svnserve
は
svnserve に対するカスタマイズされたラッパースクリプ
トで、umask を設定するようなものかも知れません(複数リポジトリアクセス方法のサポート項を見てください)。それはまた
svnserve用の仮想ルートディレクトリをどのように設定
するかも示しています。これはデーモンプロセスとして
svnserveする場合によく起こることです。たとえばシス
テムの特定の部分にアクセス制限する場合や、単に
svn+ssh://
URL の絶対パス名を入力する手間を省くため
であったりします。
複数のユーザが単一アカウントを共有するようにもできます。それにはまずユー
ザごとに独立したシステムアカウントを作るかわりに、メンバーごとに公開鍵
/秘密鍵のペアを生成します。つぎに一行に公開鍵をひとつづつ
authorized_users
ファイルにおきます。そして
--tunnel-user
オプションを使うとうまくいきます。
command="svnserve -t --tunnel-user=harry" TYPE1 KEY1 harry@example.com command="svnserve -t --tunnel-user=sally" TYPE2 KEY2 sally@example.com
この例では Harry も Sally も公開鍵認証方式によって同じアカウントで接続する
ように設定しています。どちらもそれぞれにカスタマイズされたコマンドが実行されます;
--tunnel-user
オプションは svnserve -t
が名前つき引数が認証されたユーザであることを認めるように指示しています。
--tunnel-user
がなければ、すべてのコミットはひとつの共有された
システムアカウントから発行したように見えるようになります。
最後の注意です: 共有アカウントにある公開鍵を経由してユーザにアクセス権を
与えても、他の形の SSH アクセスを禁止したことにはなりません。これは
authorized_keys
にcommand
の
形の設定をした場合でもそうです。たとえば、ユーザは依然として SSH 経由で
シェルを使ったアクセスができますし、あなたのサーバ経由で X11 や、より
一般的なポートフォワードを実行することもできます。ユーザにできるかぎり
わずかな権限しか与えないようにするには command
の
すぐ後にそれぞれの制限オプションを指定する必要があります:
command="svnserve -t --tunnel-user=harry",no-port-forwarding,¥ no-agent-forwarding,no-X11-forwarding,no-pty ¥ TYPE1 KEY1 harry@example.com