svnserve, 専用サーバ

svnserve プログラムは軽量なサーバで専用の状態プロトコル によって TCP/IP 上でクライアントと通信することができます。クライアントは svn://またはsvn+ssh:// で始まる URL によって svnserveサーバと通信します。この節 では svnserveを実行する別の方法を説明しクライアントが どうやってサーバに認証するか、またリポジトリに適切なアクセス制御を設定 するにはどうしたら良いかについて説明します。

サーバの起動

svnserveプログラムの起動にはいくつかの異なる方法が あります。オプションなしで起動した場合は何もせずヘルプメッセージを 表示するだけです。しかしinetd経由で起動するなら -i(--inetd) オプションを指定すること ができます:

$ svnserve -i
( success ( 1 2 ( ANONYMOUS ) ( edit-pipeline ) ) )

--inetd オプション付きで起動すると svnserve はSubversion クライアントとの間 で、専用のプロトコルを使い、stdinstdoutチャンネル経由で通信しようとします。 これは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に接続しにきた時点で inetdsvnserve プロセスを起動し、処理を任せます。

Windows システムではsvnserveをサービスとして 起動するためのサードパーティーのツールがあります。このようなツールの 一覧については Subversion のウェブサイトを見てください。

第二の方法はsvnserveを単独のデーモンプロセスとして 起動する方法です。これには-dオプションを使って ください:

$ svnserve -d
$               # svnserve is now running, listening on port 3690

デーモンモードでsvnserveを実行するときには --listen-port=--listen-host=オプションで待ち受けポートとホスト 名を指定することができます。

さらにsvnserveを起動する第三の方法があり、 それはトンネルモードと呼ばれますが、-tオプション を付けて起動します。このモードは RSHSSHのようなリモートサービスプログラムがユーザを 正しく認証しそのユーザでプライベートな svnserve サーバを起動している状況を仮定しています。 svnserve プログラムは普通に振る舞い(stdinstdout を通じて)、通信データは自動的にクライアントの背後にいる何らかのトンネル にリダイレクトされると仮定しています。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-accessauth-accessnoneread、 あるいは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 スクリプトの中で利用することができます。

SSH 認証と認可

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 設定の技法

クライアントが 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/svnservesvnserve に対するカスタマイズされたラッパースクリプ トで、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_keyscommandの 形の設定をした場合でもそうです。たとえば、ユーザは依然として 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



[24] RFC 2195を参照してください