Конфигурация безопасности Spring Cloud Data Flow и интеграция с RedHat SSO
Мы пытаемся включить безопасность для Spring Cloud Data Flow в соответствии с документацией (https://docs.spring.io/spring-cloud-dataflow/docs/current-SNAPSHOT/reference/htmlsingle/), но мы есть пробелы в знаниях, которые мы не можем заполнить.
Согласно пункту 9.2 можно настроить аутентификацию с помощью OAuth 2.0 и интегрировать ее с SSO. Мы используем RedHat SSO, поэтому мы пытаемся интегрировать их обоих, но мы не можем заставить его работать, возможно ли это или есть ограничение на используемый SSO?
Следуя документации, мы установили следующие свойства:
- spring.security.oauth2.client.registration.uaa.client-id = xxxxxxx
- spring.security.oauth2.client.registration.uaa.client-secret = xxxxxx
- spring.security.oauth2.client.registration.uaa.redirect-uri ='{baseUrl} / login / oauth2 / code / {registrationId}'
- spring.security.oauth2.client.registration.uaa.authorization-grant-type=authorization_code
- spring.security.oauth2.client.registration.uaa.scope[0]= openid
- spring.security.oauth2.client.provider.uaa.jwk-set-uri=.. / openid-connect / certs
- spring.security.oauth2.client.provider.uaa.token-uri=.. / openid-connect / токен
- spring.security.oauth2.client.provider.uaa.user-info-uri =.. / openid-connect / userinfo
- spring.security.oauth2.client.provider.uaa.user-name-attribute = имя_пользователя
- spring.security.oauth2.client.provider.uaa.authorization-uri =.. / openid-connect / auth
- spring.security.oauth2.resourceserver.opaquetoken.introspection-uri =.. / openid-connect / токен / интроспект
- spring.security.oauth2.resourceserver.opaquetoken.client-id = xxxxxxx
- spring.security.oauth2.resourceserver.opaquetoken.client-secret = xxxxxxx
Итак, у нас есть некоторые соображения:
- Свойства resourceserver.opaquetoken необходимы для самоанализа токена, поэтому мы почти уверены, что они необходимы, когда мы получаем запрос REST, и он должен иметь заголовок авторизации.
- Если мы не используем UAA, следует ли называть свойства uaa?
- Когда мы пытаемся получить доступ к пользовательскому интерфейсу de UI, он перенаправляется на authorization-uri, потому что authorization-grant-type=authorization_code, поэтому он войдет в систему единого входа, верно?
- Если мы используем пароль типа гранта, он будет запрашивать напрямую имя пользователя / пароль для входа в систему, где он проверяется?
- URI информации о пользователе является обязательным, но действительно ли он используется?
- Для чего используются другие URI (jwk и токен)?
- Почему URI перенаправления имеет такой формат? На что указывают эти переменные?
Наконец, мы протестировали конфигурацию в SCDF, запущенном в контейнере Docker, но он "ничего не делает":
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] org.apache.tomcat.util.http.Parameters : Set query string encoding to UTF-8
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] o.a.t.util.http.Rfc6265CookieProcessor : Cookies: Parsing b[]: JSESSIONID=55694CBB4F694DD2E345AF61AF90B05D
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] o.a.catalina.connector.CoyoteAdapter : Requested cookie session id is 55694CBB4F694DD2E345AF61AF90B05D
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] o.a.c.authenticator.AuthenticatorBase : Security checking request POST /tasks/executions
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] org.apache.catalina.realm.RealmBase : No applicable constraints defined
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] o.a.c.a.jaspic.AuthConfigFactoryImpl : Loading persistent provider registrations from [/tmp/tomcat.1807897745863872641.9393/conf/jaspic-providers.xml]
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] o.a.c.authenticator.AuthenticatorBase : Not subject to any constraint
dataflow-server | INFO 1 --- [nio-9393-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] o.apache.catalina.core.StandardWrapper : Returning non-STM instance
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] org.apache.tomcat.util.http.Parameters : Set encoding to UTF-8
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] org.apache.tomcat.util.http.Parameters : Start processing with input [name=microapabatch&arguments=--my.arguments.sleep=2000+--my.arguments.forceFailure=false]
dataflow-server | TRACE 1 --- [nio-9393-exec-1] s.n.www.protocol.http.HttpURLConnection : ProxySelector Request for https://xxxxxxxxxxxxxxxxxxxxxxxx/openid-connect/token/introspect
dataflow-server | TRACE 1 --- [nio-9393-exec-1] s.n.www.protocol.http.HttpURLConnection : Looking for HttpClient for URL https://xxxxxxxxxxxxxxxxxxxxxxxx/openid-connect/token/introspect and proxy value of DIRECT
dataflow-server | TRACE 1 --- [nio-9393-exec-1] s.n.www.protocol.http.HttpURLConnection : Creating new HttpsClient with url:https://xxxxxxxxxxxxxxxxxxxxxxxx/openid-connect/token/introspect and proxy:DIRECT with connect timeout:-1
dataflow-server | TRACE 1 --- [nio-9393-exec-1] s.n.www.protocol.http.HttpURLConnection : Proxy used: DIRECT
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] o.a.tomcat.util.net.SocketWrapperBase : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@1376a3b7:org.apache.tomcat.util.net.NioChannel@198ec8c7:java.nio.channels.SocketChannel[connected local=/172.18.0.4:9393 remote=/172.18.0.1:33758]], Read from buffer: [0]
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] org.apache.tomcat.util.net.NioEndpoint : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@1376a3b7:org.apache.tomcat.util.net.NioChannel@198ec8c7:java.nio.channels.SocketChannel[connected local=/172.18.0.4:9393 remote=/172.18.0.1:33758]], Read direct from socket: [0]
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] o.apache.coyote.http11.Http11Processor : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@1376a3b7:org.apache.tomcat.util.net.NioChannel@198ec8c7:java.nio.channels.SocketChannel[connected local=/172.18.0.4:9393 remote=/172.18.0.1:33758]], Status in: [OPEN_READ], State out: [OPEN]
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] o.a.coyote.http11.Http11NioProtocol : Pushed Processor [org.apache.coyote.http11.Http11Processor@17492586]
dataflow-server | DEBUG 1 --- [nio-9393-exec-1] org.apache.tomcat.util.net.NioEndpoint : Registered read interest for [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@1376a3b7:org.apache.tomcat.util.net.NioChannel@198ec8c7:java.nio.channels.SocketChannel[connected local=/172.18.0.4:9393 remote=/172.18.0.1:33758]]
Кажется, что проблема заключается в "remote=/172.18.0.1:33758", но мы не можем объяснить, как интроспективный uri может быть преобразован в этот локальный IP-адрес.
2 ответа
For those as newbie as I was, I am going to add some points to take into account when configuring the security in SCDF
First, some comments to the original considerations:
- The properties resourceserver.opaquetoken are needed for the introspection of the token, so we are pretty sure that they are necessary for when we receive a REST request and it must have the Authorization header --> That is.
- If we are not using UAA, should the properties be named uaa? --> It is just a label, you can put whatever you want. It creates the relationship between all the related properties and is the text that appears in the page for login.
- When we try to access to de UI, it redirects to the authorization-uri because the authorization-grant-type=authorization_code, so it will login in the SSO, is that right? --> Yes, this shows a page with the label (link) used in the previous point that redirect to your SSO login page.
- If we use the grant-type Password it would request directly a username/password for login, where does it is validated? --> In older versions of SCDF it was possible to set usernames and passwords directly in the config file, but this is not available anymore. I have not continued investigating this option since with the authorization_code we made it work.
- The user-info URI is mandatory but, is it really used? --> Yes, it is used in a point of the authentication flow.
- What are the other URIs (jwk and token) used for? --> Are part of the authentication flow
- Why the redirect URI has that format? where does that variables point to? --> Once you are authenticated, you are redirected to this url, where 'baseUrl' is your hostname and it is automatically resolved.
Now, the configuration we used to make it work:
- spring.security.oauth2.client.registration.RedHatSSO.client-id=XXXXXXX
- spring.security.oauth2.client.registration.RedHatSSO.client-secret=YYYYYYY
- spring.security.oauth2.client.registration.RedHatSSO.redirect-uri={baseUrl}/login/oauth2/code/{registrationId} --> Beware of the feet mark symbols (') enclosing the value, they are necessary or not depending on the infraestructure used for the deployment.
- spring.security.oauth2.client.registration.RedHatSSO.authorization-grant-type=authorization_code
- spring.security.oauth2.client.registration.RedHatSSO.scope[0]=openid
- spring.security.oauth2.client.provider.RedHatSSO.user-name-attribute=preferred_username --> This property is necessary to indicate the label of the property where the user name is located in the response of the SSO server (when it is not 'username').
- spring.security.oauth2.client.provider.RedHatSSO.jwk-set-uri=https://ZZZZZZZZZZZZ/protocol/openid-connect/certs --> All these endpoint URIs should be set according to the endpoints provided by the SSO.
- spring.security.oauth2.client.provider.RedHatSSO.token-uri=https://ZZZZZZZZZZZZ/protocol/openid-connect/token
- spring.security.oauth2.client.provider.RedHatSSO.user-info-uri=https://ZZZZZZZZZZZZ/protocol/openid-connect/userinfo
- spring.security.oauth2.client.provider.RedHatSSO.authorization-uri=https://ZZZZZZZZZZZZ/protocol/openid-connect/auth
- spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=https://ZZZZZZZZZZZZ/protocol/openid-connect/token/introspect
- spring.security.oauth2.resourceserver.opaquetoken.client-id=XXXXXXX
- spring.security.oauth2.resourceserver.opaquetoken.client-secret=YYYYYYY
- spring.cloud.dataflow.security.authorization.provider-role-mappings.RedHatSSO.map-oauth-scopes=true --> Activates the role mapping configuration
- spring.cloud.dataflow.security.authorization.provider-role-mappings.RedHatSSO.role-mappings.ROLE_CREATE=dataflow.create --> All these properties map each ROLE in SCDF to a client scope included in the user info retrieved by the SSO server.
- spring.cloud.dataflow.security.authorization.provider-role-mappings.RedHatSSO.role-mappings.ROLE_DEPLOY=dataflow.deploy
- spring.cloud.dataflow.security.authorization.provider-role-mappings.RedHatSSO.role-mappings.ROLE_DESTROY=dataflow.destroy
- spring.cloud.dataflow.security.authorization.provider-role-mappings.RedHatSSO.role-mappings.ROLE_MANAGE=dataflow.manage
- spring.cloud.dataflow.security.authorization.provider-role-mappings.RedHatSSO.role-mappings.ROLE_MODIFY=dataflow.modify
- spring.cloud.dataflow.security.authorization.provider-role-mappings.RedHatSSO.role-mappings.ROLE_SCHEDULE=dataflow.schedule
- spring.cloud.dataflow.security.authorization.provider-role-mappings.RedHatSSO.role-mappings.ROLE_VIEW=dataflow.view
Finally, some considerations in the SSO side (this could vary depending on the used tool, this is for Keycloak/RedHatSSO):
- Activate all the necessary URIs (token, userinfo, introspection...).
- Define the 7 client scopes for the 7 SCDF roles.
- Определите клиента в SSO для SCDF, где: активируйте учетные записи служб, определите все желаемые роли для клиента (администратор, операция, обычный пользователь...), назначьте 7 областей действия клиента, определите сопоставитель для поля имени пользователя, чтобы избежать ошибки, если он равен нулю, и включите uri перенаправления (реальный, имя хоста SCDF) в список действительных URI перенаправления (он работает с http://myhostname/*).
- После выполнения предыдущего пункта назначьте каждой клиентской области правильные роли клиентов.
Все это простые настройки Spring Security OAuth, и концепции лучше документированы там. Мы находимся в процессе добавления лучших док-станций для Keycloak, но пока что мой старый тестовый поток данных-keycloak может помочь вам начать.
В последних версиях мы добавили лучший способ использования простых ключей jwt и задокументировали его для Azure / AD. Планируется добавить аналогичный раздел для keycloak.
Я считаю, что простое использование Issueer -uri и jwk-set-uri должно дать вам рабочую настройку (вам все еще нужно выяснить область действия для сопоставления ролей), поскольку Spring Security использует их для автоматической настройки параметров oauth. Все остальные настройки являются своего рода наследием времен, когда мы еще не были полностью на линии Spring Security 5.3.
Для RH SSO я не уверен, говорите ли вы о каком-то глобальном общем экземпляре или о вашей частной настройке.