Подключение и конфигурирование#
Настройка интеграции с Platform V IAM с использованием проксирования#
При интеграции с использованием прокси-сервера, клиентская часть аутентификации по Open ID Connect(Relay Party)
выполняется на стороне IAM Proxy (AUTH) продукта Platform V IAM (IAM).
Для осуществления проксирования на конкретное приложение/backend, необходимо на новом или уже существующем прокси сервиса аутентификации добавить "ответвление". Ответвление добавляется в компоненте PACMAN (CFGA), администраторами сервисов платформы.

При добавлении ответвления, необходимо указать базовый контекст (по базовому контексту определяется на какой backend будет осуществляться проксирование), необходимость вставки в URL базового контекста, адреса и порты серверов приложений и прочее.
После применения изменений в компоненте PACMAN (CFGA) (кнопка с зеленым треугольником в круге), в течение ~5 секунд, изменения должны попасть на прокси-сервера.
При первом переходе из браузера на прокси, пользователю необходимо пройти аутентификацию. Проксирование на сервера приложений, возможно после успешной аутентификации.
После проксирования ко всем запросам в backend добавляются HTTP-заголовки:
iv-user - логин пользователя (обратная совместимость с webseal);
iv-groups - группы пользователя (обратная совместимость с webseal);
Auth-Svc-User - логин пользователя;
Authorization - аутентификационный токен OIDC (id_token) в формате Authorization: Bearer id_token.
Сервер приложений (СП) использует для авторизации Объединенный cервис авторизации (ОСА). При вызове методов
Объединенного cервиса авторизации (ОСА) (при получении ticket), необходимо на СП взять из HTTP-заголовка, полученный
от прокси jwt-token (id_token или access_token) и использовать его.
Объединенный cервис авторизации (ОСА) умеет самостоятельно валидировать токен от Platform V IAM, на основе которого будет определен пользователь приложения при выдаче авторизационного решения. Также, Объединенный cервис авторизации (ОСА), имеет методы возврата различной информации о пользователе, такой как логин, ФИО, табельный номер, код подразделения и прочее.
В тестовых целях, на стендах тестирования, текущий id_token/access_token/refresh_token доступен для просмотра на
endpoint /jwt/ proxy (доступен только на стендах тестирования).
Пример url - https://mycompany-auth-svc-proxy-dev2.mycompany.ru/jwt/
Настройка интеграции с сервисом аутентификации без использования проксирования#
Информация, о настройке интеграции с сервисом аутентификации без использования проксирования, описана в документации компонента Platform V (IAM) KeyCloak.SE.
Использование в Spring Boot#
Для установки Keycloak Spring Boot starter достаточно добавить зависимость:
pom.xml
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
Добавить использование зависимостей из Keycloak Adapter BOM в pom.xml:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>4.8.3.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Spring Boot Adapter Configuration#
В файле application.properties указать настройки адаптера. Актуальные настройки описаны в документации компонента
Keycloak.SE (KCSE).
application.properties
keycloak.realm = PlatformAuth
keycloak.auth-server-url = https://platform-devb:8443/auth
keycloak.ssl-required = external
keycloak.resource = demoapp
keycloak.credentials.secret = 11111111-1111-1111-1111-111111111111
keycloak.use-resource-role-mappings = true
Spring Boot Adapter установит login-method в KEYCLOAK и настроит security-constraints при запуске.
Пример конфигурации security-constraints :
application.properties
keycloak.securityConstraints[0].authRoles[0] = admin
keycloak.securityConstraints[0].authRoles[1] = user
keycloak.securityConstraints[0].securityCollections[0].name = insecure stuff
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /insecure
keycloak.securityConstraints[1].authRoles[0] = admin
keycloak.securityConstraints[1].securityCollections[0].name = admin stuff
keycloak.securityConstraints[1].securityCollections[0].patterns[0] = /admin
Spring Security Adapter#
Установка адаптера#
Для установки адаптера Spring Security достаточно добавить зависимость:
pom.xml
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-security-adapter</artifactId>
<version>4.8.3.Final</version>
</dependency>
Конфигурация Spring Security в java#
Реализуем WebSecurityConfigurer (KeycloakWebSecurityConfigurerAdapter). При этом будет использоваться конфигурация
из файла keycloak.json, который нужно создать в ресурсном каталоге:
@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
/**
* Registers the KeycloakAuthenticationProvider with the authentication manager.
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
/**
* Defines the session authentication strategy.
*/
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.authorizeRequests()
.antMatchers("/customers*").hasRole("USER")
.antMatchers("/admin*").hasRole("ADMIN")
.anyRequest().permitAll();
}
}
При необходимости можно организовать маппинг
ролей, org.keycloak.adapters.springsecurity.authentication. KeycloakAuthenticationProvider имеет поддержку маппинга
через org.springframework.security.core.authority.mapping. GrantedAuthoritiesMapper.
Конфигурация через XML#
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<context:component-scan base-package="org.keycloak.adapters.springsecurity" />
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="keycloakAuthenticationProvider" />
</security:authentication-manager>
<bean id="adapterDeploymentContext" class="org.keycloak.adapters.springsecurity.AdapterDeploymentContextFactoryBean">
<constructor-arg value="/WEB-INF/keycloak.json" />
</bean>
<bean id="keycloakAuthenticationEntryPoint" class="org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint" />
<bean id="keycloakAuthenticationProvider" class="org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider" />
<bean id="keycloakPreAuthActionsFilter" class="org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter" />
<bean id="keycloakAuthenticationProcessingFilter" class="org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter">
<constructor-arg name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="keycloakLogoutHandler" class="org.keycloak.adapters.springsecurity.authentication.KeycloakLogoutHandler">
<constructor-arg ref="adapterDeploymentContext" />
</bean>
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg name="logoutSuccessUrl" value="/" />
<constructor-arg name="handlers">
<list>
<ref bean="keycloakLogoutHandler" />
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
</list>
</constructor-arg>
<property name="logoutRequestMatcher">
<bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
<constructor-arg name="pattern" value="/sso/logout**" />
<constructor-arg name="httpMethod" value="GET" />
</bean>
</property>
</bean>
<security:http auto-config="false" entry-point-ref="keycloakAuthenticationEntryPoint">
<security:custom-filter ref="keycloakPreAuthActionsFilter" before="LOGOUT_FILTER" />
<security:custom-filter ref="keycloakAuthenticationProcessingFilter" before="FORM_LOGIN_FILTER" />
<security:intercept-url pattern="/customers**" access="ROLE_USER" />
<security:intercept-url pattern="/admin**" access="ROLE_ADMIN" />
<security:custom-filter ref="logoutFilter" position="LOGOUT_FILTER" />
</security:http>
</beans>
Настройка logout пользователя#
С целью предотвращения несанкционированного доступа к данным конечного пользователя в защищаемом приложении, существуют
функции деактивации пользовательской сессии и инвалидации JWT-токена, доступные в IAM Proxy. Данные механизмы являются
частью стандарта OpenID Connect, что позволяет использовать их практически с любым провайдером идентификации. При
рассмотрении данного раздела следует учесть, что IAM Proxy не используется для защиты в межсервисных взаимодействиях, а
предназначен для использования в сценариях работы пользователя с конечными сервисами. Например, с web UI. Для
осуществления выхода пользователя (logout) из защищаемого приложения, необходимо на fronend (браузер, мобильное
приложение или устройство), вызвать сервис завершения сессии пользователя в IAM Proxy, посредством: GET: /openid-connect-auth/logout. В результате вызова сервиса IAM Proxy вернет сообщение с перенаправлением (redirect),
который должен быть корректно обработан в frontend (браузером, мобильным приложением или устройством), для
перенаправления пользователя на веб-страницу сервиса завершении сессии пользователя провайдера идентификации. В ходе
разработки приложения необходимо учитывать определенные особенности реализации механизма завершения сессии пользователя,
накладываемые спецификацией OpenID Connect и текущей реализацией компонента IAM Proxy.
Обратите внимание:
URL страницы или сервиса завершения сессии пользователя (или
logout), должен быть настраиваемым в вашем приложении, так как конкретные значения могут быть изменены, в зависимости от настроек IAM Proxy;при проектировании приложения и встраивании страницы или сервиса завершения сессии пользователя, необходимо учесть, что используемый протокол
OpenIDи текущая реализация решения, предполагает работу с компонентом IAM Proxy конечных пользователей (например, физически существующих людей, использующих браузеры или мобильные устройства), а не межсервисные взаимодействия, для аутентификации которых используются другие средства. В связи с этим, необходимо избежать использования программных решений, которые позволяют имитировать или автоматизировать выполнение запросов к сервису завершения пользовательской сессии. Примером, такого нежелательного решения может являться использование AJAX, который позволяет вызывать сервис с помощьюJS, но при этом непосредственно браузер не обрабатывает результат вызова, а такие вызовы браузером считаются небезопасными из-за возможностиXSS, вследствие чего будут применены политики CORS, что в итоге может не позволить обработать перенаправления наIDPпровайдера (потребуется разрешениеCORSнаIDP). Вызов сервиса завершения пользовательской сессии должен выполняться браузером - это позволит осуществить корректное перенаправление для инвалидации всех, связанных с текущей сессией, объектов.
*Identity provider - СУДИР
Опции logout пользователя#
Доступно переопределение заданных по умолчанию при развертывании опций revoke токенов и выхода на IDP через
параметры URI при завершении сессии (logout).
Параметр
revokeотвечает за включение/выключениеrevokeтокенов приlogout;Параметр
logout_idpотвечает заlogoutизIDP.
Пример: /openid-connect-auth/logout?revoke=true&logout_idp=false.
При таких параметрах будет выполнен revoke токенов и logout на IDP выполнен не будет, ограничившись лишь выходом
из клиента/АС, соответствующего отозванным токенам.
Описание стандартных опций logout доступно для просмотра в демо-профиле развертывания (oidc_revoke_tokens_on_logout
и oidc_disable_logout_in_idp).
Настройка дизайна стартовой страницы IAM Proxy#
IAM Proxy позволяет использовать свой шаблон дизайна стартовой страницы. Для этого необходимо заменить файл
jinja2-шаблона стартовой html-страницы template.index_html.jinja2 на свой (предварительно потребуется создать свой
файл, на основе стандартного). Пример измененной страницы можно скачать.
Для виртуальной машины (ВМ)#
Замена шаблона стартовой страницы на виртуальной машине с использованием профиля развертывания#
При расположении файлов шаблона стартовой страницы и ресурсов для нее, необходимо в профиле развертывания соблюсти следующую структуру каталогов (относительно директории профиля развертывания):
расположение шаблона стартовой страницы:
files/proxy/nginx/rds-client/templates/template.index_html.jinja2;
ВАЖНО! имя файла шаблона должно соответствовать оригинальному имени файла:template.index_html.jinja2.ресурсы используемые стартовой страницей (опционально) размещаются по пути
files/proxy/nginx/html/, например:files/proxy/nginx/html/smartnlp_logo.png.
Применить изменения внесенные в профиль развертывания и запустить
Jenkins Job.
Замена шаблона стартовой страницы на виртуальной машине вручную#
Данный способ применим только при использовании RDS Server, стартовая страница при этом генерируется средствами
rds-client.
Для замены шаблона стартовой страницы, выполните следующие действия:
Скопируйте на виртуальную машину персонализированный шаблон и перенесите в директорию назначения
/opt/iamproxy/rds-client/templates/.Персонализированный шаблон размещен по пути
/opt/iamproxy/rds-client/templates/.
Измените владельца и группу владельцев файла персонализированного шаблона на
IAM Proxy.Владелец и группа владельцев успешно изменена.
Скопируйте файлы ресурсов (изображения, css и прочие, опционально), используемые персонализированным шаблоном, в директорию
/opt/iamproxy/html/.Файлы ресурсов скопированы в директорию
/opt/iamproxy/html/.
Измените владельца и группу владельцев на скопированных файлах на
IAM Proxy.Владелец и группа владельцев успешно изменена.
Перезапустите службы
rds-client(sudo systemctl restart rds-client).Служба
rds-client(sudo systemctl restart rds-client) перезапущена.
Для OpenShift#
Замена шаблона стартовой страницы в контейнере (в OpenShift)#
Подготовка ConfigMap. Подготавливаем файл персонализированного шаблона (пример). Для подключения статических бинарных ресурсов (пример), используемых персонализированным шаблоном (опционально), необходимо выполнить конвертацию подключаемого бинарного файла в формат base64 (например командой
base64 smartnlp_logo.png). Пример формата:iVBORw0KGgoAAAANSUhE....AAACXBIWXMAABYlAAAWJQFJUiTwAAAA. Полученный формат изображения используем на следующем шаге.Создание OSE ConfigMap. Используя OSE UI или шаблон OSE ConfigMap по умолчанию, приводим манифест ConfigMap к следующему виду:
kind: ConfigMap
apiVersion: v1
metadata:
name: iamproxy.custom.template
data:
template.index.html.jinja2: |
# Содержимое персонализированного шаблона (полученный на предыдущем шаге)
binaryData:
smartnlp_logo.png: |
# бинарный файл изображения в формате base64 (полученный на предыдущем шаге)
Подготовка OSE Deployment IAM Proxy. Подключаем созданный в пункте 2 ConfigMap к контейнеру IAM Proxy в качестве volume, для чего приводим Deployment IAM Proxy к следующему виду:
...
spec:
...
template:
...
spec:
volumes:
- name: iamproxy-custom-template-volume
configMap:
name: iamproxy.custom.template
defaultMode: 0400 #Права только на чтение
...
containers:
...
volumeMounts:
- name: iamproxy-custom-template-volume
mountPath: /opt/iamproxy/rds-client/templates/template.index.html.jinja2
subPath: template.index.html.jinja2
- name: iamproxy-custom-template-volume
mountPath: /opt/iamproxy/html/smartnlp_logo.png
subPath: smartnlp_logo.png
...
Использование CORS с IAM Proxy#
Для использования ресурсов IAM Proxy при CORS-запросах, необходимо на ответвлении включить опцию
rds-enable-cors.location.conf.
Так же, чтобы обеспечить работу cookies (аутентификации) при CORS, необходимо чтобы вызывающая страница и источник
размещались на одном родительском домене. Родительский домен необходимо задать как домен для сессионных cookies
IAM Proxy (параметр iamproxy.k8s.session_domain при использовании DOT), и для сервиса задать уникальное имя
сессионной cookie (параметр iamproxy.k8s.session_name при использовании DOT).
При CORS-запросах предполагается, что аутентификация ранее была сделана пользователем на источнике ресурсов (или для нее не требуется действий от пользователя), и запросы через IAM Proxy будут проходить успешно. Если действующей сессии/аутентификации нет, то будет получен ответ с кодом 401 или перенаправление на аутентификацию в провайдере.
При использовании CORS, также необходимо обеспечить отправку cookies в CORS-запросах. Для вызовов из JS, это
XMLHttpRequest с withCredentials="true" или fetch с credentials='include', или аналогичные опции для
используемого фреймворка. Для тегов img, audio, link, script, video это атрибут
crossorigin="use-credentials".
При необходимости аутентификации в
iframe, где потребуются действия от пользователя, от провайдера может потребоваться отдавать заголовокContent-Security-Policy: frame-ancestors 'self' https://example.org, чтобы разрешить отображение контента от провайдера в UI.