Tomcat: авторизация пользователей по RSA-ключам

Автор: | 11/29/2013
 

apache-tomcat-7-logoЗадача: ограничить доступ к серверу со стороны клиентов, и разрешить доступ только тем, у кого есть выданный нами RSA-ключ.

Общую информацию об SSL можно найти в Wikipedia>>>.

Настройка HTTPS для Apache HTTP Server описана тут>>>.

Для начала — настроим Tomcat для работы через SSL.

Создадим ключ для самого Tomcat:

$ keytool -genkey -alias tomcat-teamcity -keystore ../.ssh/tomcat-teamcity.jks -validity 365
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]:  domain.com
What is the name of your organizational unit?
[Unknown]:
What is the name of your organization?
[Unknown]:  Company
What is the name of your City or Locality?
[Unknown]:  Kiev
What is the name of your State or Province?
[Unknown]:
What is the two-letter country code for this unit?
[Unknown]:  UA
Is CN=lms-domain.com, OU=Unknown, O=Company, L=Kiev, ST=Unknown, C=UA correct?
[no]:  yes

Enter key password for <tomcat-teamcity>
(RETURN if same as keystore password):

Расширение .jks (jks — «java key storage«) не является обязательным, так же как и указание пути к файлу хранилища. Если не указать параметр -keystore — то будет создан файл .keystore в корне домашней директории пользователя, от имени которого выполняется keytool.

В начале операции предлагается создать пароль для доступа к самому хранилищу, а в конце — для доступа к самому ключу. Что бы для ключа создать пароль такой же, как и для хранилища — жмём ENTER.

При создании ключа можно так же использовать:

-keysize — размер ключа, по-умолчанию 1024байт;
-keyalg — алгоритм шифрования ключа, по-умолчанию SHA1withDSA;
-storepass — пароль, которым будет защищен файл-хранилище;
-keypass — пароль самого ключа;
-validity — срок действия ключа;
-alias — имя ключа, по которому будет осуществляться поиск в хранилище;
-storetype — тип хранилища и/или ключа, по-умолчанию JKS.

В поле «What is your first and last name?» рекомендуется указывать полное FQDN (Fully Qualified Domain Name, т.е. полное доменное имя) имя сервера, на котором будет применяться этот ключ (хотя — разницы не заметил никакой).

Больше информации — тут>>>.

Редактируем файл conf/server.xml:

<Connector port="8444" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="/home/tomcats/.ssh/tomcat-teamcity.jks"
keyAlias="tomcat-teamcity"
keystorePass="password" />

Запускаем Tomcat:

$ ./bin/startup.sh
Using CATALINA_BASE:   /home/tomcats/apache-tomcat-5.5.36
Using CATALINA_HOME:   /home/tomcats/apache-tomcat-5.5.36
Using CATALINA_TMPDIR: /home/tomcats/apache-tomcat-5.5.36/temp
Using JRE_HOME:        /usr/java/jdk1.6.0_45
Using CLASSPATH:       /home/tomcats/apache-tomcat-5.5.36/bin/bootstrap.jar

Проверяем лог:

$ tail -n 2 logs/catalina.2013-11-27.log
Nov 27, 2013 3:06:48 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 2280 ms

Проверяем порт:

$ netstat -anp | grep 8444
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp        0      0 :::8444                     :::*                        LISTEN      25884/java

ОК, теперь SSL работает.

При попытке зайти браузером на страницу — нам предложит подтвердить, что мы доверяем этому узлу (так как сертификат у нас самоподписанный, а не выданный службой типа VeriSign).

Осталось сконфигурировать на запрос сертификатов от клиентов.

Создаём сертификат, который будет использоваться клиентом, и сохраняем его в файл-хранилище:

$ keytool -genkey -alias setevoy -keystore ../.ssh/setevoy-tc.p12 -storetype PKCS12 -validity 365
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]:  user_host_name
What is the name of your organizational unit?
[Unknown]:
What is the name of your organization?
[Unknown]:
What is the name of your City or Locality?
[Unknown]:  Kiev
What is the name of your State or Province?
[Unknown]:
What is the two-letter country code for this unit?
[Unknown]:  UA
Is CN=user_host_name, OU=Unknown, O=Unknown, L=Kiev, ST=Unknown, C=UA correct?
[no]:  yes

Обратите внимание — тут явно задан тип ключа — PKCS12 и расширение файла — .p12 вместо .jks.

Просмотреть созданный в хранилище сертификат:

$ keytool -list -v -keystore ../.ssh/setevoy-tc.p12 -storetype PKCS12
Enter keystore password:

Keystore type: PKCS12
Keystore provider: SunJSSE

Your keystore contains 1 entry

Alias name: setevoy
Creation date: Nov 29, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=user_host_name, OU=Unknown, O=Unknown, L=Kiev, ST=Unknown, C=UA
Issuer: CN=user_host_name, OU=Unknown, O=Unknown, L=Kiev, ST=Unknown, C=UA
Serial number: 529856d9
Valid from: Fri Nov 29 10:56:57 EET 2013 until: Thu Feb 27 10:56:57 EET 2014
Certificate fingerprints:
MD5:  D5:D8:50:44:65:63:BD:94:C5:8B:76:CB:00:AA:9D:36
SHA1: 6E:5C:F1:85:B7:60:E3:08:0D:19:BE:E2:AD:32:E1:97:27:42:2A:29
Signature algorithm name: SHA1withDSA
Version: 3

*******************************************
*******************************************

И ключ для самого Tomcat:

$ keytool -list -v -keystore ../.ssh/tomcat-teamcity.jks
Enter keystore password:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: tomcat-teamcity
Creation date: Nov 29, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=domain.com, OU=Unknown, O=Unknown, L=Kiev, ST=Unknown, C=UA
Issuer: CN=domain.com, OU=Unknown, O=Unknown, L=Kiev, ST=Unknown, C=UA
Serial number: 5298519f
Valid from: Fri Nov 29 10:34:39 EET 2013 until: Thu Feb 27 10:34:39 EET 2014
Certificate fingerprints:
MD5:  CE:8C:73:50:B1:50:AE:28:BF:54:F9:42:15:C2:0E:65
SHA1: FC:65:1F:AF:5B:F2:AF:40:08:16:C6:38:67:93:0C:73:32:93:DA:51
Signature algorithm name: SHA1withDSA
Version: 3

*******************************************
*******************************************

И снова — внимание на разные -storetype — в случае с хранилищем Tomcat — мы его не указываем, т.к. keytool по-умолчанию пробует тип JKS, а в случае с ключём setevoy-tc.p12 — указываем тип явно, иначе получим ошибку:

keytool error: java.io.IOException: Invalid keystore format
java.io.IOException: Invalid keystore format

Что бы удалить сертификат из хранилища — выполняем:

$ keytool -delete -alias setevoy -keystore ../.ssh/setevoy-tc.p12 -storetype PKCS12

Далее нам необходимо экспортировать публичную часть ключа, которая будет использоваться сервером для проверки валидности клиента:

$ keytool -export -alias setevoy -file ../.ssh/setevoy-tc.cer -keystore ../.ssh/setevoy-tc.p12 -storetype PKCS12
Enter keystore password:
Certificate stored in file <../.ssh/setevoy-tc.cer>

Далее — создадим хранилище для доверенных сертификатов, и добавим в него публичную часть ключа клиента:

$ keytool -import -v -trustcacerts -alias setevoy -file ../.ssh/setevoy-tc.cer -keystore ../.ssh/trustcacerts-teamcity.jks
Enter keystore password:
Re-enter new password:
Owner: CN=user_host_name, OU=Unknown, O=Unknown, L=Kiev, ST=Unknown, C=UA
Issuer: CN=user_host_name, OU=Unknown, O=Unknown, L=Kiev, ST=Unknown, C=UA
Serial number: 529856d9
Valid from: Fri Nov 29 10:56:57 EET 2013 until: Thu Feb 27 10:56:57 EET 2014
Certificate fingerprints:
MD5:  D5:D8:50:44:65:63:BD:94:C5:8B:76:CB:00:AA:9D:36
SHA1: 6E:5C:F1:85:B7:60:E3:08:0D:19:BE:E2:AD:32:E1:97:27:42:2A:29
Signature algorithm name: SHA1withDSA
Version: 3
Trust this certificate? [no]:  yes
Certificate was added to keystore
[Storing ../.ssh/trustcacerts-teamcity.jks]

Просмотрим его:

$ keytool -list -v -keystore ../.ssh/trustcacerts-teamcity.jks
Enter keystore password:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: setevoy
Creation date: Nov 29, 2013
Entry type: trustedCertEntry

Owner: CN=user_host_name, OU=Unknown, O=Unknown, L=Kiev, ST=Unknown, C=UA
Issuer: CN=user_host_name, OU=Unknown, O=Unknown, L=Kiev, ST=Unknown, C=UA
Serial number: 529856d9
Valid from: Fri Nov 29 10:56:57 EET 2013 until: Thu Feb 27 10:56:57 EET 2014
Certificate fingerprints:
MD5:  D5:D8:50:44:65:63:BD:94:C5:8B:76:CB:00:AA:9D:36
SHA1: 6E:5C:F1:85:B7:60:E3:08:0D:19:BE:E2:AD:32:E1:97:27:42:2A:29
Signature algorithm name: SHA1withDSA
Version: 3

*******************************************
*******************************************

В дальнейшем — именно в это хранилище мы будем добавлять public-части ключей клиентов.

Возвращаемся к Tomcat:

$ ./bin/shutdown.sh
Using CATALINA_BASE:   /home/tomcats/apache-tomcat-5.5.36
Using CATALINA_HOME:   /home/tomcats/apache-tomcat-5.5.36
Using CATALINA_TMPDIR: /home/tomcats/apache-tomcat-5.5.36/temp
Using JRE_HOME:        /usr/java/jdk1.6.0_45
Using CLASSPATH:       /home/tomcats/apache-tomcat-5.5.36/bin/bootstrap.jar
$ vim conf/server.xml

Дополняем уже имеющуюся конфигурацию строками:

<Connector port="8444" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="/home/tomcats/.ssh/tomcat-teamcity.jks"
keyAlias="tomcat-teamcity"
keystorePass="password"
truststoreFile="/home/tomcats/.ssh/trustcacerts-teamcity.jks"
truststorePass="password" />

clientAuth="true" — включаем требование аутентификации клиентов; truststoreFile= — путь к файлу хранилища доверенных ключей, в которое мы добавляем public-части клиентских ключей.

Запускаем:

$ ./bin/startup.sh
Using CATALINA_BASE:   /home/tomcats/apache-tomcat-5.5.36
Using CATALINA_HOME:   /home/tomcats/apache-tomcat-5.5.36
Using CATALINA_TMPDIR: /home/tomcats/apache-tomcat-5.5.36/temp
Using JRE_HOME:        /usr/java/jdk1.6.0_45
Using CLASSPATH:       /home/tomcats/apache-tomcat-5.5.36/bin/bootstrap.jar

Проверяем лог:

$ tail -n 2 logs/catalina.2013-11-27.log
Nov 27, 2013 3:19:30 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 1650 ms

И пробуем зайти браузером на сервер:

Tomcat: двухфакторная авторизация пользователей по SSL-сертификатам

Импорт SSL-сертификата в браузер

Передаём файл setevoy-tc.p12, и импортируем его в браузер.

Открываем Настройки Advanced > Certificates > View Certificates> Your Certificates:

tomcat_ssl_16

Жмём кнопку Import и выбираем клиентский сертификат:

tomcat_ssl_17

Указываем пароль ключа:

tomcat_ssl_18

Обновляем страницу, и выбираем какой из имеющихся сертифкатов предоставить серверу:

tomcat_ssl_19

Готово.

Что бы использовать только HTTPS — в файл […]webapps/ROOT/WEB-INF/web.xml добавьте:

<security-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTAL</transport-quarantee>
    </user-data-constraint>
</security-constraint>

Что бы ограничить область действия HTTPS — отредактируйте так:

<security-constraint>

        <web-resource-collection>
          <web-resource-name>SECURED</web-resource-name>
          <url-pattern>/web-service</url-pattern>
        </web-resource-collection>

        <user-data-constraint>
          <transport-guarantee>CONFIDENTAL</transport-guarantee>
        </user-data-constraint>

 </security-constraint>

В таком случае — всё приложение будет работать по обычному HTTP-протоколу, а при попытке зайти по адресу http://domain.com/web-service — соединение будет перенаправляться через SSL-connector.

Подробнее о вариантах настройки web.xml — в статье Tomcat: ограничение доступа с помощью файла web.xml.

Другие опции keytool

Просмотреть public-ключ:

$ keytool -printcert -file ../.ssh/setevoy-tc.cer -storetype PKCS12

Просмотреть все ключи в хранилище:

$ keytool -list -v -keystore ../.ssh/trustcacerts-teamcity.jks

Просмотреть только определённый alias:

$ keytool -list -v -keystore ../.ssh/trustcacerts-teamcity.jks -alias setevoy

Удалить ключ из хранилища:

$ keytool -delete -alias setevoy -keystore ../.ssh/trustcacerts-teamcity.jks

Изменить пароль хранилища:

$ keytool -storepasswd -new newpassword -keystore ../.ssh/trustcacerts-teamcity.jks

Добавить клиентский сертификат в хранилище:

$ keytool -importcert -file setevoy-tc.cer -alias setevoy -keystore ../.ssh/trustcacerts-teamcity.jks

Ссылки по теме

http://www.dotkam.com
http://www.maximporges.com
http://www.chesterproductions.net.nz
http://www.mulesoft.com