Я знаю, что он редко используется, но можно ли получить доступ к сертификату клиента в Snap?
Если нет, возможно ли использовать другой веб-стек?
Я знаю, что он редко используется, но можно ли получить доступ к сертификату клиента в Snap?
Если нет, возможно ли использовать другой веб-стек?
Это недоступно для вас в пакете Snap snap-server
, который, как я предполагаю, является тем, как вы используете свой сервер.
Buuuuut это не сложно построить, либо путем разметки, либо как отдельный модуль (вам придется скопировать некоторый код, хотя, поскольку некоторые внутренние значения вам понадобятся, не экспортируются). bindHttps
, расположенный в Snap.Internal.Http.Server.TLS, это то, что вы хотите настроить. Эта функция в основном является оберткой вокруг вызовов OpenSSL.Session из библиотеки HsOpenSSL
, которая сама по себе является свободной оболочкой библиотеки OpenSSL.
К счастью для нас OpenSSL имеет полную поддержку клиентских сертификатов. Вам просто нужно установить режим проверки на SSL_VERIFY_PEER
. Есть и другие кнопки, с которыми вы можете играть. Вы также должны убедиться, что вы установили цепочку сертификатов для фактического подтверждения сертификата клиента. Цепочка доверия и весь этот джаз. Для справки см., Как nginx делает это.
Еще лучше, эта функция показана в HsOpenSSL
как функция contextSetVerificationMode :: SSLContext -> VerificationMode -> IO ()
. Вы заметите, что ctx :: SSLContext
существует в определении Snap bindHttps
. Все, что вам нужно сделать, это либо скопировать, либо переделать этот модуль и ввести ваши вызовы.
Он будет выглядеть примерно так (предупреждение непроверенного кода):
± % diff -u /tmp/{old,new}
--- /tmp/old 2016-04-11 11:02:42.000000000 -0400
+++ /tmp/new 2016-04-11 11:02:56.000000000 -0400
@@ -19,6 +19,7 @@
ctx <- SSL.context
SSL.contextSetPrivateKeyFile ctx key
+ SSL.contextSetVerificationMode ctx (SSL.VerifyPeer True True (Just (\_ _ -> return True)))
if chainCert
then SSL.contextSetCertificateChainFile ctx cert
else SSL.contextSetCertificateFile ctx cert
Первый логический параметр указывает, что OpenSSL завершится с ошибкой, если сертификат клиента отсутствует. Второе логическое значение указывает OpenSSL, что сертификат клиента требуется только по первому запросу и больше не нужен для повторных переговоров. Третье значение - это обратный вызов. Я думаю, что правильная вещь - просто вернуть True в обратном вызове. Это то, что nginx делает, в любом случае.