Авторизация на веб-сервере apache по сертификату

На днях для внутренних нужд компании потребовалось настроить веб-сервер Apache для авторизации пользователей в приложении с использованием цифровых сертификатов. Причем так, чтобы все было кошерно 🙂 т.е. все сертификаты должны быть подписаны внутренним удостоверяющим центром
Microsoft CA
.
Стоит признаться, что пришлось несколько повозиться, ибо подробного howto на просторах нашей бескрайней мне найти не удалось. Потому предположил, что шпаргалка на эту тему может оказаться полезной.
Постановка задачи:
требуется настроить авторизацию на веб-сервере Apache с использованием подписанных цифровых сертификатов внутренним удостоверяющим центром Microsoft CA.
name=’more’> Решение:
1. Создаем пару ключей (server.key) и запрос сертификата для центра сертификации (request.der)
openssl req -new -inform DER -sha1 -newkey rsa:2048 -nodes -keyout server.key -out request.der -subj “/CN=site.name.ru”
2. В оснастке “Шаблоны сертификатов” на сервере Microsoft CA разрешаем требуемому пользователю (например, себе) осуществлять подачу заявки на шаблон сертификата “Проверка подлинности сервера”. Далее, в оснастке центра сертификации, создаем выдаваемый шаблон этого сертификата.
3. Отправляемся по адресу http(s):///certsrv/, где выбираем “Запроса сертификата”, после чего “расширенный запрос сертификата” и “Выдать запрос, используя base-64 шифрованный файл PKCS #10…”. В поле “Сохраненный запрос” передаем содержимое файла request.der, а в выпадающем списке выбираем имя шаблона сертификата, созданного на предыдущем этапе. После чего, сертификат в формате DER-шифрования (certnew.cer) можно переместить в каталог с файлом server.key.
4. Теперь необходимо выполнить:
openssl x509 -in certnew.cer -inform DER -out server.crt
Проверка контрольных сумм. Открытый ключ: openssl x509 -noout -modulus -in server.crt | openssl sha1
Закрытый ключ: openssl rsa -noout -modulus -in server.key | openssl sha1
На этом этапе уже можно использовать стандартную конфигурацию веб-сервера Apache для работы с односторонним SSL.
5. Для того чтобы пользователи могли запрашивать сертификаты проверки подлинности, отвечающие определенным требованиям, может вновь потребоваться шаманство с оснасткой “Шаблоны сертификатов” на сервере Microsoft CA. Есть и другой путь стать владельцем сертификата “Enrollment Agent” и уже самостоятельно раздавать сертификаты конечным пользователям.
6. Чтобы веб-сервер Apache запрашивал клиентские сертификаты, необходимо внести следующие директивы в его конфигурационный файл (предполагается, что остальные директивы дополнены используемой конфигурацией настроек SSL по умолчанию, поставляемой с веб-сервером Apache):
… SSLCACertificateFile /etc/ssl/certs.list
SSLVerifyClient require
SSLOptions FakeBasicAuth
AuthName “Auth require”
AuthType Basic
AuthUserFile /etc/ssl/certs.users
require valid-user
…
…
, где файл “/etc/ssl/certs.list” содержит открытый ключ (или цепочку сертификатов) удостоверяющего центра Microsoft CA в формате base64 (его можно подгрузить из точки распространения);
файл “/etc/ssl/certs.users” содержит список пользователей, которым разрешен доступ к каталогу “/secure/www/”.
Формат файла “/etc/ssl/certs.users”:
/DC=local/DC=dc/OU=users/CN=username1/emailAddress=username1@dc.local:xxj31ZMTZzkVA
/DC=local/DC=dc/OU=users/CN=username2/emailAddress=username2@dc.local:xxj31ZMTZzkVA
…
Чтобы получить указанный формат, можно воспользоваться командой:
openssl x509 -noout -subject -in client.crt
Магическая строка “xxj31ZMTZzkVA” всегда неизменна (это результат шифрования строки “password” с помощью алгоритма DES).
Вот собственно и все.
Авторизация по сертификатам?
Имеем сервер на убунту, до этого был и Centos и freebsd, на всех ситуация абсолютно идентичная.
Итак имеем Nginx.
На сервере создан виртуалхост и для него созданы сертификат LetsEncrypt.
Пробовал разные инструкции, суть которых заключалась в создании центра сертификации, потом создание сертификата сервера и клиентского сертификата.
Все создал, в конфигурации прописал, вес вроде как должно работать, но нет.
Пробовал сертификат сервера использовать и самоподписанный и LetsEncrypt.
При обращении и вводе пароля от клиентского сертификата получаю ошибку:
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL ALPN supported by client: http/1.1
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL ALPN selected: http/1.1
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL_do_handshake: -1
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL_get_error: 2
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL handshake handler: 0
2021/12/13 11:01:10 [debug] 3862#3862: *<b>3 verify:0, error:18, depth:0, subject:"/C=RU/ST=Sverdlovskaya/L=Yekaterinburg/O=domain/OU=User/CN=etc/emailAddress=support@domain.ru", issuer:"/C=RU/ST=Sverdlovskaya/L=Yekaterinburg/O=domain/OU=User/CN=etc/emailAddress=support@domain.ru"
2021/12/13 11:01:10 [debug] 3862#3862: *3 verify:1, error:18, depth:0, subject:"/C=RU/ST=Sverdlovskaya/L=Yekaterinburg/O=domain/OU=User/CN=etc/emailAddress=support@domain.ru", issuer:"/C=RU/ST=Sverdlovskaya/L=Yekaterinburg/O=domain/OU=User/CN=etc/emailAddress=support@domain.ru"</b>
2021/12/13 11:01:10 [debug] 3862#3862: *3 ssl new session: 7D45FB3F:32:1098
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL_do_handshake: 1
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL: TLSv1.2, cipher: "ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD"
2021/12/13 11:01:10 [debug] 3862#3862: *3 reusable connection: 1
2021/12/13 11:01:10 [debug] 3862#3862: *3 http wait request handler
2021/12/13 11:01:10 [debug] 3862#3862: *3 malloc: 000055793AC585A0:1024
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL_read: -1
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL_get_error: 2
2021/12/13 11:01:10 [debug] 3862#3862: *3 free: 000055793AC585A0
2021/12/13 11:01:10 [debug] 3862#3862: *3 http wait request handler
2021/12/13 11:01:10 [debug] 3862#3862: *3 malloc: 000055793AC585A0:1024
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL_read: 465
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL_read: -1
2021/12/13 11:01:10 [debug] 3862#3862: *3 SSL_get_error: 2
2021/12/13 11:01:10 [debug] 3862#3862: *3 reusable connection: 0
2021/12/13 11:01:10 [debug] 3862#3862: *3 posix_memalign: 000055793AC5EBF0:4096 @16
2021/12/13 11:01:10 [debug] 3862#3862: *3 http process request line
2021/12/13 11:01:10 [debug] 3862#3862: *3 http request line: "POST /Base/e1cib/login?nm=3463004214345805875&vl=ru_RU&ni=-1202199248&version=8.3.10.2580&clnId=4638a353-facb-45a4-9faa-f2eaa86678f5 HTTP/1.1"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http uri: "/base/e1cib/login"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http args: "nm=3463004214345805875&vl=ru_RU&ni=-1202199248&version=8.3.10.2580&clnId=4638a353-facb-45a4-9faa-f2eaa86678f5"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http exten: ""
2021/12/13 11:01:10 [debug] 3862#3862: *3 posix_memalign: 000055793ABF6D60:4096 @16
2021/12/13 11:01:10 [debug] 3862#3862: *3 http process request header line
2021/12/13 11:01:10 [debug] 3862#3862: *3 http header: "Host: domain.ru"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http header: "Accept-Charset: utf-8"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http header: "User-Agent: 1CV8C"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http header: "1C-ApplicationName: 1CV8C"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http header: "Accept: application/xml"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http header: "Accept-Encoding: deflate,1CSDC;q=0.5"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http header: "Accept-Language: ru-RU"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http header: "1C-BaseLocation: https://domain.ru/Base"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http header: "Content-Length: 0"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http header: "Content-Type: application/x-www-form-urlencoded"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http header done
2021/12/13 11:01:10 [info] 3862#3862: *3 <b>client SSL certificate verify error: (18:self signed certificate) while reading client request headers, client: 212.49.112.114, server: domain.ru, request: "POST /Base/e1cib/login?nm=3463004214345805875&vl=ru_RU&ni=-1202199248&version=8.3.10.2580&clnId=4638a353-facb-45a4-9faa-f2eaa86678f5 HTTP/1.1", host: "domain.ru"</b>
2021/12/13 11:01:10 [debug] 3862#3862: *3 http finalize request: 495, "/Base/e1cib/login?nm=3463004214345805875&vl=ru_RU&ni=-1202199248&version=8.3.10.2580&clnId=4638a353-facb-45a4-9faa-f2eaa86678f5" a:1, c:1
2021/12/13 11:01:10 [debug] 3862#3862: *3 event timer del: 14: 3740928
2021/12/13 11:01:10 [debug] 3862#3862: *3 http special response: 495, "/Base/e1cib/login?nm=3463004214345805875&vl=ru_RU&ni=-1202199248&version=8.3.10.2580&clnId=4638a353-facb-45a4-9faa-f2eaa86678f5"
2021/12/13 11:01:10 [debug] 3862#3862: *3 http set discard body
2021/12/13 11:01:10 [debug] 3862#3862: *3 xslt filter header
2021/12/13 11:01:10 [debug] 3862#3862: *3 <b>HTTP/1.1 400 Bad Request</b>
Server: nginx/1.18.0 (Ubuntu)
Date: Mon, 13 Dec 2021 11:01:10 GMT
Content-Type: text/html
Content-Length: 224
Connection: closeПочему не принимает сертификат?
Авторизация с помощью сертификата ssl на nginx let’s encrypt
Решение проблемы, когда значения скопированных ячеек из табличных документов 1С в Excel воспринимаются последним как текст, т.е. без дополнительного форматирования значений невозможно применить арифметические операции. Поводом для публикации послужило понимание того, что целое предприятие с более сотней активных пользователей уже на протяжении года мучилось с такой, казалось бы на первый взгляд, тривиальной проблемой. Варианты решения, предложенные специалистами helpdesk, обслуживающими данное предприятие, а так же многочисленные обсуждения на форумах, только подтвердили убеждение в необходимости описания способа, который позволил мне качественно и быстро справиться с ситуацией.
15.01.2021
35758
itriot11
27
Генерация сертификата
Первое что нужно сделать, это собственно получить сертификат, с которым можно будет работать. Если у вас уже есть готовый сертификат, можете переходить к следующему разделу.
Получение private key из хранилища средствами c#
Для поиска сертификата в хранилище я буду использовать Thumbprint. Посмотреть его значения можно в Details разделе требуемого сертификата.
Код для поиска максимально простой и представляет из себя следующее:
var thumbprint = "170af897569602508cc81d65c18b983ab0ad8cff"; X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly); var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false); store.Close();
Фактически, в данном случае ищутся все сертификаты, содержащие данный thumbprint, в том числе не валидные. Если установить true в четвёртой строке, тогда не валидные сертификаты будут проигнорированы. Дальше получаем private key и соединяемся с SFTP сервером:
Примечание
В случае, если Центр Идентификации не сможет извлечь клиентский сертификат из запроса и корректно аутентифицировать пользователя, Пользователю будет предложена интерактивная аутентификация в Веб-Интерфейсе ЦИ.
Для запрета интерактивного взаимодействия с Веб-Интерфейсом ЦИ необходимо передать в запросе дополнительный параметр prompt=none. В этом случае при невозможности аутентификации пользователя по сертификату ЦИ вернет ошибку.
Проверка sftp через filezilla
Если у вас не получается установить соединения с SFTP сервером, попробуйте сперва проверить корректность работы самого сервера и имеющихся сертификатов. Сделать это можно через FileZilla клиент.
Выбрать File – Site Manager. Добавить новый сайт, заполнить данные, в качестве Logon Type выбрать “Key file”, указать сам .ppk ключ и нажать Connect
Если все данные верны, тогда вы соединитесь с вашим SFTP сервером.
На этом всё, надеюсь информация будет полезной.
Приятного программирования.
Установка сертификата
Для работы с private кодом, мы можем хранить его где-то в ресурсах приложения, что не очень правильно с точки зрения безопасности, либо если это возможно, использовать хранилище. Я покажу как работать со вторым вариантом.
Выполним установку сертификата:
В качестве места хранения выберем Local Machine
Укажем текущий пароль от сертификата, а также установим опцию «Mark this key as exportable. This will allow you to back up or transport your keys at a later time.» В таком виде ваш сертификат будет содержать private ключ после установки, который можно будет использовать из вашего приложения.
После завершения установки можно проверить корректность размещения:
В данном случае сертификат установился корректно и готов к использованию.
