Мы хотим ограничить доступ на нашем сервере разработки для тех пользователей, у которых есть действительный сертификат SSL Client. Мы используем Apache 2.2.16 на Debian 6.
Однако для некоторых разделов (в основном 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, что применяются любые директивы SSLVerifyClient, которые находятся в блоках Location, соответствующих /test/someLocationили просто /someLocation.
Если у меня следующая конфигурация:
<LocationMatch "^/f">
SSLVerifyClient require
SSLVerifyDepth 2
</LocationMatch>
Затем для следующего URL-адреса требуется клиентский сертификат:https://my.server/test/foo. Однако следующий URL-адрес не соответствует:https://my.server/test/somethingElse/foo
Обратите внимание, что это, похоже, применимо только к конфигурации SSL. Следующее не оказывает никакого влияния наhttps://my.server/test/foo:
<LocationMatch "^/f">
Order allow,deny
Deny from all
</LocationMatch>
Однако он блокирует доступ кhttps://my.server/foo.
Это представляет собой серьезную проблему в случаях, когда у меня есть какой-то проект, запущенный вhttps://my.server/project(что требует авторизации SSL-сертификата клиента),идля этого проекта есть репозиторий githttps://my.server/git/projectкоторый не может требовать сертификат клиента SSL. Поскольку URL-адрес /git/project также сопоставляется с Location
блоками /project, такая конфигурация кажется невозможной, учитывая мои текущие выводы.
Вопрос: Почему это происходит и как решить мою проблему?
В конце концов, я хочу потребовать авторизацию сертификата SSL-клиента для всего сервера, за исключением /git и /someLocation, с минимально возможной конфигурацией (чтобы мне не приходилось изменять конфигурацию каждый раз, когда что-то новое развертывается или добавляется новый репозиторий git).
ОбновлятьДополнительная информация: Обратите внимание, что в некоторых случаяхhttps://my.server/projectна самом деле обратное проксирование, так что <Directory /path/to/project>
директива невозможна. Если я хочу защитить это приложение с помощью сертификата клиента SSL, это должно быть обязательно с <Location /project>
(или более общим <Location />
) блоком.
Обновление 2Я только что проверил это в apache 2.4.3, с тем же результатом. Если это из-за какой-то ошибки, то она присутствует как минимум в двух версиях.
Примечание: я переписал свой вопрос (вместо того, чтобы просто добавить больше обновлений внизу), чтобы учесть мои новые выводы и, надеюсь, сделать его более понятным.
решение1
Согласно текущемуДокументация Apacheэто может быть проблемой:
В контексте каждого сервера он применяется к процессу аутентификации клиента, используемому в стандартном рукопожатии SSL при установлении соединения. В контексте каждого каталога он вызывает повторное согласование SSL с перенастроенным уровнем проверки клиента после прочтения HTTP-запроса, но до отправки HTTP-ответа.
Что насчет использования контекста <Directory> вместо <Location>. Одна запись для корневого уровня, а другая для пути Script-Alias: /path/to/gitolite-shell/
Обновлять:
Я нашел несколько советов по этому случаю ->Вопрос/ответ на Stackoverflow