3.5. OpenID Connect를 사용하여 OpenShift에서 JBoss EAP 애플리케이션 보안
외부 OpenID 공급자를 사용하여 인증을 위임하려면 JBoss EAP 기본 OpenID Connect(OIDC) 클라이언트를 사용합니다. OIDC는 JBoss EAP와 같은 클라이언트가 OpenID 공급자가 수행한 인증을 기반으로 사용자 ID를 확인할 수 있는 ID 계층입니다.
elytron-oidc-client
하위 시스템 및 elytron-oidc-client
Galleon 계층은 JBoss EAP에서 기본 OIDC 클라이언트를 제공하여 OpenID 공급자와 연결합니다. JBoss EAP는 OpenID 공급자 구성에 따라 애플리케이션의 가상 보안 도메인을 자동으로 생성합니다.
elytron-oidc-client
하위 시스템을 다음과 같은 세 가지 방법으로 구성할 수 있습니다.
-
배포에
oidc.json
추가 -
CLI 스크립트를 실행하여
elytron-oidc-client
하위 시스템을 구성합니다. -
OpenShift에서 JBoss EAP 서버 시작 시
elytron-oidc-client
하위 시스템을 구성하는 환경 변수를 정의합니다.
다음 절차에서는 OIDC로 애플리케이션을 보호하기 위해 환경 변수를 사용하여 elytron-oidc-client
하위 시스템을 구성하는 방법을 설명합니다.
3.5.1. JBoss EAP의 OpenID Connect 구성
OpenID 공급자를 사용하여 애플리케이션을 보호하면 보안 도메인 리소스를 로컬로 구성할 필요가 없습니다. elytron-oidc-client
하위 시스템은 JBoss EAP에서 기본 OpenID Connect(OIDC) 클라이언트를 제공하여 OpenID 공급자와 연결합니다. JBoss EAP는 OpenID 공급자 구성에 따라 애플리케이션의 가상 보안 도메인을 자동으로 생성합니다.
Red Hat build of Keycloak과 함께 OIDC 클라이언트를 사용합니다. JSON 웹 토큰(JWT)인 액세스 토큰을 사용하도록 구성할 수 있고 RS256, RS384, ES256, ES384 또는 ES512 서명 알고리즘을 사용하도록 구성할 수 있는 경우 다른 OpenID 공급자를 사용할 수 있습니다.
OIDC 사용을 활성화하려면 elytron-oidc-client
하위 시스템 또는 애플리케이션 자체를 구성할 수 있습니다. JBoss EAP는 다음과 같이 OIDC 인증을 활성화합니다.
-
애플리케이션을 JBoss EAP에 배포할 때
elytron-oidc-client
하위 시스템은 배포를 검사하여 OIDC 인증 메커니즘이 필요한지 감지합니다. -
하위 시스템에서
elytron-oidc-client
하위 시스템 또는 애플리케이션 배포 설명자 중 하나에서 배포에 대한 OIDC 구성을 감지하면 JBoss EAP는 애플리케이션에 대한 OIDC 인증 메커니즘을 활성화합니다. -
하위 시스템이 두 위치에서 OIDC 구성을 감지하면
elytron-oidc-client
하위 시스템secure-deployment
속성의 구성이 애플리케이션 배포 설명자의 구성보다 우선합니다.
3.5.2. OpenID Connect로 보안된 애플리케이션 생성
웹 애플리케이션을 생성하려면 필수 종속성 및 디렉터리 구조가 포함된 Maven 프로젝트를 생성합니다. 로그인한 사용자의 주체 및 특성에서 얻은 사용자 이름을 반환하는 서블릿이 포함된 웹 애플리케이션을 생성합니다. 로그인한 사용자가 없는 경우 서블릿은 "NO AUTHENTICATED USER" 텍스트를 반환합니다.
사전 요구 사항
- Maven이 설치되어 있어야 합니다. 자세한 내용은 Apache Maven 다운로드를 참조하십시오.
프로세스
mvn
명령을 사용하여 Maven 프로젝트를 설정합니다. 명령은 프로젝트에 대한 디렉터리 구조와pom.xml
구성 파일을 생성합니다.구문
$ mvn archetype:generate \ -DgroupId=${group-to-which-your-application-belongs} \ -DartifactId=${name-of-your-application} \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-webapp \ -DinteractiveMode=false
예제
$ mvn archetype:generate \ -DgroupId=com.example.app \ -DartifactId=simple-webapp-example \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-webapp \ -DinteractiveMode=false
애플리케이션 루트 디렉터리로 이동합니다.
구문
$ cd <name-of-your-application>
예제
$ cd simple-webapp-example
생성된
pom.xml
파일의 내용을 다음 텍스트로 바꿉니다.<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example.app</groupId> <artifactId>simple-webapp-example</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>simple-webapp-example Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <version.maven.war.plugin>3.3.2</version.maven.war.plugin> <version.eap.plugin>1.0.0.Final-redhat-00014</version.eap.plugin> <version.server>8.0.0.GA-redhat-00009</version.server> <version.bom.ee>${version.server}</version.bom.ee> </properties> <repositories> <repository> <id>jboss</id> <url>https://maven.repository.redhat.com/ga/</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>jboss</id> <url>https://maven.repository.redhat.com/ga/</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> <dependencyManagement> <dependencies> <dependency> <groupId>org.jboss.bom</groupId> <artifactId>jboss-eap-ee-with-tools</artifactId> <version>${version.bom.ee}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.wildfly.security</groupId> <artifactId>wildfly-elytron-auth-server</artifactId> </dependency> </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>${version.maven.war.plugin}</version> </plugin> <plugin> <groupId>org.jboss.eap.plugins</groupId> <artifactId>eap-maven-plugin</artifactId> <version>${version.eap.plugin}</version> <configuration> <channels> <channel> <manifest> <groupId>org.jboss.eap.channels</groupId> <artifactId>eap-8.0</artifactId> </manifest> </channel> </channels> <feature-packs> <feature-pack> <location>org.jboss.eap:wildfly-ee-galleon-pack</location> </feature-pack> <feature-pack> <location>org.jboss.eap.cloud:eap-cloud-galleon-pack</location> </feature-pack> </feature-packs> <layers> <layer>cloud-server</layer> <layer>elytron-oidc-client</layer> </layers> <galleon-options> <jboss-fork-embedded>true</jboss-fork-embedded> </galleon-options> </configuration> <executions> <execution> <goals> <goal>package</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
참고-
<
version.eap.plugin>1.0.0.Final-redhat-00014</version.eap.plugin
>은 JBoss EAP Maven 플러그인의 예제 버전입니다. JBoss EAP Maven 플러그인 릴리스에 대한 자세한 내용은 Red Hat Maven 리포지토리를 참조하십시오. https://maven.repository.redhat.com/earlyaccess/all/org/jboss/eap/plugins/eap-maven-plugin/.
-
<
Java 파일을 저장할 디렉터리를 만듭니다.
구문
$ mkdir -p src/main/java/<path_based_on_artifactID>
예제
$ mkdir -p src/main/java/com/example/app
새 디렉터리로 이동합니다.
구문
$ cd src/main/java/<path_based_on_artifactID>
예제
$ cd src/main/java/com/example/app
다음 콘텐츠를 사용하여
SecuredServlet.java
파일을 생성합니다.package com.example.app; import java.io.IOException; import java.io.PrintWriter; import java.security.Principal; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Set; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.wildfly.security.auth.server.SecurityDomain; import org.wildfly.security.auth.server.SecurityIdentity; import org.wildfly.security.authz.Attributes; import org.wildfly.security.authz.Attributes.Entry; /** * A simple secured HTTP servlet. It returns the user name and * attributes obtained from the logged-in user's Principal. If * there is no logged-in user, it returns the text * "NO AUTHENTICATED USER". */ @WebServlet("/secured") public class SecuredServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try (PrintWriter writer = resp.getWriter()) { Principal user = req.getUserPrincipal(); SecurityIdentity identity = SecurityDomain.getCurrent().getCurrentSecurityIdentity(); Attributes identityAttributes = identity.getAttributes(); Set <String> keys = identityAttributes.keySet(); String attributes = "<ul>"; for (String attr : keys) { attributes += "<li> " + attr + " : " + identityAttributes.get(attr).toString() + "</li>"; } attributes+="</ul>"; writer.println("<html>"); writer.println(" <head><title>Secured Servlet</title></head>"); writer.println(" <body>"); writer.println(" <h1>Secured Servlet</h1>"); writer.println(" <p>"); writer.print(" Current Principal '"); writer.print(user != null ? user.getName() : "NO AUTHENTICATED USER"); writer.print("'"); writer.print(user != null ? "\n" + attributes : ""); writer.println(" </p>"); writer.println(" </body>"); writer.println("</html>"); } } }
애플리케이션 리소스를 보호하도록 애플리케이션의
web.xml
을 구성합니다.예제
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" metadata-complete="false"> <security-constraint> <web-resource-collection> <web-resource-name>secured</web-resource-name> <url-pattern>/secured</url-pattern> </web-resource-collection> <auth-constraint> <role-name>Users</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>OIDC</auth-method> </login-config> <security-role> <role-name>*</role-name> </security-role> </web-app>
이 예에서는
사용자가
역할이 있는 사용자만 애플리케이션에 액세스할 수 있습니다.
3.5.3. OpenShift에 애플리케이션 배포
JBoss EAP 애플리케이션 개발자는 OpenID Connect 하위 시스템을 사용하는 OpenShift에 애플리케이션을 배포하고 Red Hat build of Keycloak 서버와 통합할 수 있습니다. 아래 절차에 따라 애플리케이션을 배포합니다.
사전 요구 사항
다음 구성을 사용하여 OpenShift에서 Red Hat build of Keycloak 서버를 구성했습니다. 자세한 내용은 Red Hat build of Keycloak Operator 를 참조하십시오.
- Cryostat라는 영역을 생성합니다.
- demo 라는 사용자를 만듭니다.
- demo 라는 사용자의 암호를 설정합니다. 임시 를 OFF 로 전환하고 암호 설정을 클릭합니다. 확인 프롬프트에서 암호 설정을 클릭합니다.
- Users 라는 역할을 생성합니다.
- 사용자 demo 에 사용자 역할을 할당합니다.
- 클라이언트 역할 필드에서 JBoss EAP에 대해 구성한 realm-management 를 선택합니다.
- create-client 역할을 클라이언트 realm-management 에 할당합니다.
프로세스
- 애플리케이션 코드를 Git 리포지토리에 배포합니다.
OIDC 구성이 포함된 보안을 생성합니다.
다음 콘텐츠를 사용하여
oidc-secret.yaml
이라는 파일을 생성합니다.apiVersion: v1 kind: Secret metadata: name: oidc-secret type: Opaque stringData: OIDC_PROVIDER_NAME: rh-sso OIDC_USER_NAME: demo OIDC_USER_PASSWORD: demo OIDC_SECURE_DEPLOYMENT_SECRET: mysecret
다음 명령을 사용하여 보안을 생성합니다.
$ oc apply -f oidc-secret.yaml
다음 콘텐츠를 사용하여
helm.yaml
이라는 파일을 생성합니다.build: uri: [URL TO YOUR GIT REPOSITORY] deploy: envFrom: - secretRef: name: oidc-secret
JBoss EAP Helm 차트를 사용하여 예제 애플리케이션을 배포합니다.
$ helm install eap-oidc-test-app -f helm.yaml jboss-eap/eap8
oidc-secret.yaml
파일에 환경 변수를 추가하여 OIDC 공급자 URL 및 애플리케이션 호스트 이름을 구성합니다.yaml stringData: ... OIDC_HOSTNAME_HTTPS: <host of the application> OIDC_PROVIDER_URL: https://<host of the SSO provider>/realms/JBossEAP
OIDC_HOSTNAME_HTTPS
의 값은 다음 출력에 해당합니다.echo $(oc get route eap-oidc-test-app --template='{{ .spec.host }}')
OIDC_PROVIDER_URL
값은 다음 출력에 해당합니다.echo https://$(oc get route sso --template='{{ .spec.host }}')/realms/JBossEAP
OIDC_HOSTNAME_HTTP(S)
가 설정되지 않은 경우 경로 검색 시도가 수행됩니다. 경로 검색을 활성화하려면 OpenShift 사용자가경로
리소스를 나열할 수 있어야 합니다. 예를 들어routeview
역할을 생성하고view
사용자와 연결하려면 다음oc
명령을 사용합니다.$ oc create role <role-name> --verb=list --resource=route $ oc adm policy add-role-to-user <role-name> <user-name> --role-namespace=<your namespace>
-
oc apply -f oidc-secret.yaml
을 사용하여 시크릿을 업데이트합니다. 애플리케이션을 다시 배포하여 OpenShift에서 새 환경 변수를 사용하는지 확인합니다.
$ oc rollout restart deploy eap-oidc-test-app
검증
브라우저에서
https://<eap-oidc-test-app route>/ 로
이동합니다.Red Hat build of Keycloak 로그인 페이지로 리디렉션됩니다.
- 보안 서블릿에 액세스합니다.
다음 인증 정보로 로그인합니다.
username: demo password: demo
보안 주체 ID가 포함된 페이지가 나타납니다.
3.5.4. 환경 변수 기반 구성
이러한 환경 변수를 사용하여 OpenShift 이미지에서 JBoss EAP OIDC 지원을 구성합니다.
표 3.1. 환경 변수
환경 변수 | 레거시 SSO 환경 변수 | 설명 | 필수 항목 | 기본값 |
---|---|---|---|---|
OIDC_PROVIDER_NAME |
없음. |
OIDC_PROVIDER_NAME 변수를 사용할 때 | 제공됨 | |
OIDC_PROVIDER_URL |
| 공급자의 URL입니다. | 제공됨 | |
OIDC_USER_NAME | SSO_USERNAME | 동적 클라이언트 등록에는 토큰을 받으려면 사용자 이름이 필요합니다. | 제공됨 | |
OIDC_USER_PASSWORD | SSO_PASSWORD | 동적 클라이언트 등록에는 토큰을 받으려면 사용자 암호가 필요합니다. | 제공됨 | |
OIDC_SECURE_DEPLOYMENT_SECRET | SSO_SECRET | secure-deployment 하위 시스템과 인증 서버 클라이언트 모두 알려져 있습니다. | 없음 | |
OIDC_SECURE_DEPLOYMENT_PRINCIPAL_ATTRIBUTE | SSO_PRINCIPAL_ATTRIBUTE | 보안 주체 이름 값을 구성합니다. | 없음 |
일반적인 값: preferred_username. |
OIDC_SECURE_DEPLOYMENT_ENABLE_CORS | SSO_ENABLE_CORS | Single Sign-On 애플리케이션에 대해 CORS를 활성화합니다. | 없음 |
기본값은 |
OIDC_SECURE_DEPLOYMENT_BEARER_ONLY | SSO_BEARER_ONLY | 전달자 토큰만 허용하고 로깅을 지원하지 않는 배포입니다. | 없음 |
기본값은 |
OIDC_PROVIDER_SSL_REQUIRED | NONE | 기본값은 private 및 local 주소와 같은 external이지만 https는 지원하지 않습니다. | 없음 | 외부 |
OIDC_PROVIDER_TRUSTSTORE | SSO_TRUSTSTORE |
realm | 없음 | |
OIDC_PROVIDER_TRUSTSTORE_DIR | SSO_TRUSTSTORE_DIR |
영역 | 없음 | |
OIDC_PROVIDER_TRUSTSTORE_PASSWORD | SSO_TRUSTSTORE_PASSWORD |
realm | 없음 | |
OIDC_PROVIDER_TRUSTSTORE_CERTIFICATE_ALIAS | SSO_TRUSTSTORE_CERTIFICATE_ALIAS |
realm | 없음 | |
OIDC_DISABLE_SSL_CERTIFICATE_VALIDATION | SSO_DISABLE_SSL_CERTIFICATE_VALIDATION | 클라이언트를 등록하기 위해 인증 서버와 상호 작용할 때 인증서 검증을 비활성화합니다. | 없음 | |
OIDC_HOSTNAME_HTTP | HOSTNAME_HTTP | 비보안 경로에 사용되는 호스트 이름입니다. | 없음 | 경로가 검색됩니다. |
OIDC_HOSTNAME_HTTPS | HOSTNAME_HTTPS | 보안 경로에 사용되는 호스트 이름입니다. | 없음 | 보안 경로가 검색됩니다. |
NONE | SSO_PUBLIC_KEY | Single Sign-On 영역의 공개 키입니다. 이 옵션은 사용되지 않으며 공개 키는 OIDC 하위 시스템에서 자동으로 검색됩니다. | 없음 | 설정되어 있으면 이 옵션이 무시되고 있다는 경고가 표시됩니다. |