ScriptAlias により、リクエストが多くの Location ブロックに一致します。何が起こっているのでしょうか?

ScriptAlias により、リクエストが多くの Location ブロックに一致します。何が起こっているのでしょうか?

開発サーバーへのアクセスを、有効な SSL クライアント証明書を持つユーザーのみに制限したいと考えています。Debian 6 で Apache 2.2.16 を実行しています。

ただし、一部のセクション(主にgit-http、gitoliteでセットアップ)では、https://my.server/git/) 多くの git クライアントは SSL クライアント証明書をサポートしていないため、例外が必要になります。

サーバーのクライアント証明書認証を要求し、いくつかの場所に例外を追加することに成功しました。ただし、これは git では機能しないようです。

現在の設定は次のとおりです。

SSLCACertificateFile ssl-certs/client-ca-certs.crt
<Location />
  SSLVerifyClient require
  SSLVerifyDepth 2
</Location>
# this works
<Location /foo>
  SSLVerifyClient none
</Location>
# this does not
<Location /git>
  SSLVerifyClient none
</Location>

別の解決策も試しましたが、結果は同じでした。

# require authentication everywhere except /git and /foo
<LocationMatch "^/(?!git|foo)">
  SSLVerifyClient require
  SSLVerifyDepth 2
</LocationMatch>

どちらの場合も、クライアント証明書を持たないユーザーは my.server/foo/ に完全にアクセスできますが、my.server/git/ にはアクセスできません (有効なクライアント証明書が提供されていないため、アクセスが拒否されます)。SSL クライアント証明書認証を完全に無効にすると、my.server/git/ は正常に動作します。

ScriptAlias の問題

Gitolite は ScriptAlias ディレクティブを使用してセットアップされます。同様の ScriptAlias では問題が発生することがわかりました。

# Gitolite
ScriptAlias /git/ /path/to/gitolite-shell/
ScriptAlias /gitmob/ /path/to/gitolite-shell/
# My test
ScriptAlias /test/ /path/to/test/script/

/path/to/test/script はディレクトリではなくファイルであることに注意してください。/path/to/gitolite-shell/ も同様です。

私のテスト スクリプトは、環境を印刷するだけなので、非常にシンプルです。

#!/usr/bin/perl

print "Content-type:text/plain\n\n";
print "TEST\n";
@keys = sort(keys %ENV);
foreach (@keys) {
    print "$_ => $ENV{$_}\n";
}

どうやら私がhttps://my.server/test/someLocation、/test/someLocationに一致するLocationブロック内のSSLVerifyClientディレクティブが適用されていることを確認します。または単に /someLocation

次のような構成の場合:

<LocationMatch "^/f">
        SSLVerifyClient require
        SSLVerifyDepth 2
</LocationMatch>

次に、次の URL ではクライアント証明書が必要です。https://my.server/test/fooただし、次の URL は該当しません。https://my.server/test/somethingElse/foo

これはSSL設定にのみ適用されるようです。以下はSSL設定にはまったく影響しません。https://my.server/test/foo:

<LocationMatch "^/f">
        Order allow,deny
        Deny from all
</LocationMatch>

ただし、次のアクセスはブロックされますhttps://my.server/foo

これは、いくつかのプロジェクトを同時に実行している場合に大きな問題となります。https://my.server/プロジェクト(SSLクライアント証明書の認証が必要です)そしてこのプロジェクトのgitリポジトリはhttps://my.server/git/プロジェクトSSL クライアント証明書を要求できません。/git/project URL も /projectLocationブロックと照合されるため、現在の調査結果からすると、このような構成は不可能と思われます。

質問: なぜこのようなことが起こるのでしょうか? また、どうすれば問題を解決できるのでしょうか?

最終的には、/git と /someLocation を除くサーバー全体に対して、SSL クライアント証明書の認証を、可能な限り最小限の構成で要求したいと考えています (新しいものがデプロイされるたび、または新しい git リポジトリが追加されるたびに構成を変更する必要がないようにするため)。

アップデート詳細情報: 場合によっては、https://my.server/プロジェクト実際にはリバース プロキシ化されているため、<Directory /path/to/project>ディレクティブは不可能です。SSL クライアント証明書を使用してそのアプリケーションを保護する場合は、必然的に<Location /project>(またはより一般的な<Location />) ブロックを使用する必要があります。

アップデート2これを Apache 2.4.3 でテストしたところ、同じ結果になりました。これが何らかのバグによるものである場合、少なくとも 2 つのバージョンに存在します。


注: 新しい発見を考慮して、より明確にするために、質問を書き直しました (単に下部に更新を追加するのではなく)。

答え1

現在のApache ドキュメントこれは問題になるかもしれません:

サーバーごとのコンテキストでは、接続が確立されたときに標準の SSL ハンドシェイクで使用されるクライアント認証プロセスに適用されます。ディレクトリごとのコンテキストでは、HTTP 要求が読み取られた後、HTTP 応答が送信される前に、再構成されたクライアント検証レベルで SSL 再ネゴシエーションを強制します。

<Location> の代わりに <Directory> コンテキストを使用するのはどうでしょうか。1 つのエントリはルート レベル用、もう 1 つは Script-Alias パス用です: /path/to/gitolite-shell/

アップデート:

このケースに関するアドバイスをいくつか見つけました ->Stackoverflow での質問/回答

関連情報