3.2. Elytron でのアイデンティティー伝搬および転送
3.2.1. リモート呼び出しのセキュリティーアイデンティティーの伝搬
JBoss EAP 7.1 では、リモーティング呼び出しのためにクライアントからサーバーにセキュリティーアイデンティティーを伝搬するためのサーバーとアプリケーションを簡単に設定できる機能が導入されました。指定のユーザーのセキュリティーアイデンティティー内で実行するようにサーバーコンポーネントを設定することも可能です。
本セクションの例では、セキュリティーアイデンティティーの認証情報を転送する方法を説明します。クライアントとジャカルタエンタープライズビーンズのセキュリティーアイデンティティを、リモートのジャカルタエンタープライズビーンズに伝播します。これは、ユーザーの承認されたロール情報とともにリモート Jakarta Enterprise Beans を呼び出した Principal
の名前が含まれる文字列を返します。この例では、以下のコンポーネントで設定されています。
- 呼び出し元に関する承認情報を返す、すべてのユーザーがアクセスできる単一のメソッドを含むセキュアな Jakarta Enterprise Beans。
- 1 つのメソッドを含む中間的な Jakarta Enterprise Beans です。リモート接続を利用して、セキュアな Jakarta Enterprise Beans 上でメソッドを呼び出します。
- 中間的な Jakarta Enterprise Beans を呼び出すリモートのスタンドアロンクライアントアプリケーションです。
-
認証に使用されるアイデンティティー情報が含まれる
META-INF/wildfly-config.xml
ファイル。
最初に、サーバーを設定して セキュリティーアイデンティティー伝搬を有効化する 必要があります。次に、リモート Jakarta Enterprise Beans を検索して呼び出すために WildFlyInitialContextFactory
を使用する レンプルアプリケーションコードを確認します。
セキュリティーの伝搬のためのサーバーの設定
ApplicationDomain
を使用するようにejb3
サブシステムを設定します。/subsystem=ejb3/application-security-domain=quickstart-domain:add(security-domain=ApplicationDomain)
これにより、以下の
application-security-domain
設定がejb3
サブシステムに追加されます。<subsystem xmlns="urn:jboss:domain:ejb3:5.0"> .... <application-security-domains> <application-security-domain name="quickstart-domain" security-domain="ApplicationDomain"/> </application-security-domains> </subsystem>
PLAIN
認証設定を追加して、プレーンテキストのユーザー名とパスワードと、アウトバウンド接続に使用される認証コンテキストを送信します。アイデンティティー伝搬に対応しているメカニズムのリストは、Mechanisms That Support Security Identity Propagation を参照してください。/subsystem=elytron/authentication-configuration=ejb-outbound-configuration:add(security-domain=ApplicationDomain,sasl-mechanism-selector="PLAIN") /subsystem=elytron/authentication-context=ejb-outbound-context:add(match-rules=[{authentication-configuration=ejb-outbound-configuration}])
これにより、以下の
authentication-client
設定がelytron
サブシステムに追加されます。<subsystem xmlns="urn:wildfly:elytron:4.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto"> <authentication-client> <authentication-configuration name="ejb-outbound-configuration" security-domain="ApplicationDomain" sasl-mechanism-selector="PLAIN"/> <authentication-context name="ejb-outbound-context"> <match-rule authentication-configuration="ejb-outbound-configuration"/> </authentication-context> </authentication-client> .... </subsystem>
リモート宛先アウトバウンドソケットバインディングを
standard-sockets
ソケットバインディンググループに追加します。/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=ejb-outbound:add(host=localhost,port=8080)
これにより、以下の
ejb-outbound
アウトバウンドソケットバインディングがstandard-sockets
ソケットバインディンググループに追加されます。<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}"> .... <outbound-socket-binding name="ejb-outbound"> <remote-destination host="localhost" port="8080"/> </outbound-socket-binding> </socket-binding-group>
リモートアウトバウンド接続を追加し、HTTP コネクターに SASL 認証ファクトリーを設定します。
/subsystem=remoting/remote-outbound-connection=ejb-outbound-connection:add(outbound-socket-binding-ref=ejb-outbound, authentication-context=ejb-outbound-context) /subsystem=remoting/http-connector=http-remoting-connector:write-attribute(name=sasl-authentication-factory,value=application-sasl-authentication)
これにより、
http-remoting-connector
およびejb-outbound-connection
設定がremoting
サブシステムに追加されます。<subsystem xmlns="urn:jboss:domain:remoting:4.0"> .... <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm" sasl-authentication-factory="application-sasl-authentication"/> <outbound-connections> <remote-outbound-connection name="ejb-outbound-connection" outbound-socket-binding-ref="ejb-outbound" authentication-context="ejb-outbound-context"/> </outbound-connections> </subsystem>
Elytron SASL 認証が
PLAIN
メカニズムを使用するように設定します。/subsystem=elytron/sasl-authentication-factory=application-sasl-authentication:write-attribute(name=mechanism-configurations,value=[{mechanism-name=PLAIN},{mechanism-name=JBOSS-LOCAL-USER,realm-mapper=local},{mechanism-name=DIGEST-MD5,mechanism-realm-configurations=[{realm-name=ApplicationRealm}]}])
これにより、以下の
application-sasl-authentication
設定がelytron
サブシステムに追加されます。<subsystem xmlns="urn:wildfly:elytron:4.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto"> .... <sasl> .... <sasl-authentication-factory name="application-sasl-authentication" sasl-server-factory="configured" security-domain="ApplicationDomain"> <mechanism-configuration> <mechanism mechanism-name="PLAIN"/> <mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/> <mechanism mechanism-name="DIGEST-MD5"> <mechanism-realm realm-name="ApplicationRealm"/> </mechanism> </mechanism-configuration> </sasl-authentication-factory> </sasl> .... </subsystem>
上記の例のアプリケーションでは、サーバーがセキュリティー伝搬を有効にするために設定されました。
セキュリティーアイデンティティーを伝搬するアプリケーションサンプルコードの確認
サーバー設定でセキュリティーアイデンティティーの伝搬が有効になっていると、Jakarta Enterprise Beans クライアントアプリケーションは WildFlyInitialContextFactory
を使用して Jakarta Enterprise Beans プロキシーを検索し、呼び出すことができます。Jakarta Enterprise Beans は、以下で示されているように、クライアント例で認証されたユーザーとして呼び出されます。以下の簡単なコード例は、JBoss EAP 7.4 に同梱される ejb-security-context-propagation
クイックスタートから取得されます。セキュリティーアイデンティティーの伝搬の完全な作業例は、クイックスタートを参照してください。
Jakarta Enterprise Beans を別のユーザーとして呼び出すには、コンテキストプロパティーに Context.SECURITY_PRINCIPAL
および Context.SECURITY_CREDENTIALS
を設定します。
例: リモートクライアント
public class RemoteClient { public static void main(String[] args) throws Exception { // invoke the intermediate bean using the identity configured in wildfly-config.xml invokeIntermediateBean(); // now lets programmatically setup an authentication context to switch users before invoking the intermediate bean AuthenticationConfiguration superUser = AuthenticationConfiguration.empty().setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("PLAIN")). useName("superUser").usePassword("superPwd1!"); final AuthenticationContext authCtx = AuthenticationContext.empty(). with(MatchRule.ALL, superUser); AuthenticationContext.getContextManager().setThreadDefault(authCtx); invokeIntermediateBean(); } private static void invokeIntermediateBean() throws Exception { final Hashtable<String, String> jndiProperties = new Hashtable<>(); jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory"); jndiProperties.put(Context.PROVIDER_URL, "remote+http://localhost:8080"); final Context context = new InitialContext(jndiProperties); IntermediateEJBRemote intermediate = (IntermediateEJBRemote) context.lookup("ejb:/ejb-security-context-propagation/IntermediateEJB!" + IntermediateEJBRemote.class.getName()); // Call the intermediate EJB System.out.println(intermediate.makeRemoteCalls()); } }
例: 中間の Jakarta Enterprise Beans
@Stateless @Remote(IntermediateEJBRemote.class) @SecurityDomain("quickstart-domain") @PermitAll public class IntermediateEJB implements IntermediateEJBRemote { @EJB(lookup="ejb:/ejb-security-context-propagation/SecuredEJB!org.jboss.as.quickstarts.ejb_security_context_propagation.SecuredEJBRemote") private SecuredEJBRemote remote; @Resource private EJBContext context; public String makeRemoteCalls() { try { StringBuilder sb = new StringBuilder("** "). append(context.getCallerPrincipal()). append(" * * \n\n"); sb.append("Remote Security Information: "). append(remote.getSecurityInformation()). append("\n"); return sb.toString(); } catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new RuntimeException("Teasting failed.", e); } } }
例: セキュアな Jakarta Enterprise Beans
@Stateless @Remote(SecuredEJBRemote.class) @SecurityDomain("quickstart-domain") public class SecuredEJB implements SecuredEJBRemote { @Resource private SessionContext context; @PermitAll public String getSecurityInformation() { StringBuilder sb = new StringBuilder("["); sb.append("Principal=["). append(context.getCallerPrincipal().getName()). append("], "); userInRole("guest", sb).append(", "); userInRole("user", sb).append(", "); userInRole("admin", sb).append("]"); return sb.toString(); } }
例: wildfly-config.xml ファイル
<?xml version="1.0" encoding="UTF-8"?> <configuration> <authentication-client xmlns="urn:elytron:client:1.2"> <authentication-rules> <rule use-configuration="default"/> </authentication-rules> <authentication-configurations> <configuration name="default"> <set-user-name name="quickstartUser"/> <credentials> <clear-password password="quickstartPwd1!"/> </credentials> <sasl-mechanism-selector selector="PLAIN"/> <providers> <use-service-loader /> </providers> </configuration> </authentication-configurations> </authentication-client> </configuration>
3.2.2. 承認転送モードの使用
Elytron は、認証情報転送の他に、ピア間での信頼できるアイデンティティーの使用をサポートします。これは、以下の場合に役に立ちます。
- 要件は、ネットワークを介してパスワードを送信できないことです。
- 認証タイプは、認証情報転送に対応していない ものです。
- この環境には、伝搬されたリクエストを受信できるシステムを制限する必要があります。
承認転送を使用するには、まず 転送サーバーで認証クライアントを設定し てから、受信サーバーが承認を許可および処理するように設定 します。
転送サーバーでの認証クライアントの設定
承認転送を有効にするには、転送サーバー設定で認証クライアント設定を行う必要があります。
以下の管理 CLI コマンドは、デフォルトの認証クライアント設定を作成し、認証転送を有効にします。必要に応じて、さらに高度なルールベースの選択を設定できます。
例: 認証クライアント設定を作成するための管理 CLI コマンド
/subsystem=elytron/authentication-configuration=forwardit:add(authentication-name=theserver1,security-domain=ApplicationDomain,realm=ApplicationRealm,forwarding-mode=authorization,credential-reference={clear-text=thereallysecretpassword}) /subsystem=elytron/authentication-context=forwardctx:add(match-rules=[{authentication-configuration=forwardit,match-no-user=true}])
以下のコマンドは、以下の authentication-configuration
および authentication-context
設定を elytron
サブシステムに追加します。
例: 認証クライアント設定
<authentication-client> <authentication-configuration name="forwardit" authentication-name="theserver1" security-domain="ApplicationDomain" forwarding-mode="authorization" realm="ApplicationRealm"> <credential-reference clear-text="thereallysecretpassword"/> </authentication-configuration> <authentication-context name="forwardctx"> <match-rule match-no-user="true" authentication-configuration="forwardit"/> </authentication-context> </authentication-client>
転送サーバーがデフォルトの認証ベースのユーザー名と認証情報をを使用する代わりに受信サーバーに接続すると、事前に定義されたサーバーログイン名である theserver1
を使用して信頼関係が確立されます。
受信サーバーでの承認転送の設定
転送を正常に完了するには、受信側のサーバー設定を、転送サーバーによって渡されたアイデンティティーに一致するアイデンティティーで設定する必要があります。この場合、正しい認証情報を使用して、受信側サーバーに server1
という名前のユーザーを設定する必要があります。
また、転送サーバーから渡される theserver1
アイデンティティーのアイデンティティー切り替えを許可するために、elytron
サブシステムの RunAs パーミッションマッピングも設定する必要があります。パーミッションマッピングの詳細は、JBoss EAPHow to Configure Server Securityの Elytron パーミッションマッパーの作成 を参照してください。
以下のコマンドは、以下の設定を含む auth-forwarding-permission-mapper
という名前の simple-permission-mapper
を追加します。
-
anonymous
ユーザーのパーミッションマッピングこのユーザーにパーミッションがなく、匿名ユーザーがログインできなくなります。 -
theserver1
ユーザーのパーミッションマッピング。このユーザーには、*
というRunAsPrincipalPermission
パーミッションが割り当てられ、このユーザーに任意のアイデンティティーとして実行するグローバルパーミッションが付与されます。必要に応じて、特定のアイデンティティーにパーミッションを制限できます。 - その他のすべてのユーザーのパーミッションマッピング。
例: 簡単なパーミッションマッパーを作成する管理 CLI コマンド
/subsystem=elytron/permission-set=run-as-principal-permission:add(permissions=[{class-name="org.wildfly.security.auth.permission.RunAsPrincipalPermission",target-name="*"}]) /subsystem=elytron/simple-permission-mapper=auth-forwarding-permission-mapper:add(permission-mappings=[{principals=["anonymous"]},{principals=["theserver1"],permission-sets=[{permission-set=login-permission},{permission-set=default-permissions},{permission-set=run-as-principal-permission}]},{match-all=true,permission-sets=[{permission-set=login-permission},{permission-set=default-permissions}]}]
このコマンドは、以下の simple-permission-mapper
設定を elytron
サブシステムに追加します。
例: 簡単なパーミッションマッパー設定
<mappers> <simple-permission-mapper name="auth-forwarding-permission-mapper"> <permission-mapping> <principal name="anonymous"/> <!-- No permissions: Deny any permission to anonymous! --> </permission-mapping> <permission-mapping> <principal name="theserver1"/> <permission-set name="login-permission"/> <permission-set name="default-permissions"/> <permission-set name="run-as-principal-permission"/> </permission-mapping> <permission-mapping match-all="true"> <permission-set name="login-permission"/> <permission-set name="default-permissions"/> </permission-mapping> </simple-permission-mapper> </mappers> <permission-sets> <permission-set name="login-permission"> <permission class-name="org.wildfly.security.auth.permission.LoginPermission"/> </permission-set> <permission-set name="default-permissions"> <permission class-name="org.wildfly.extension.batch.jberet.deployment.BatchPermission" module="org.wildfly.extension.batch.jberet" target-name="*"/> <permission class-name="org.wildfly.transaction.client.RemoteTransactionPermission" module="org.wildfly.transaction.client"/> <permission class-name="org.jboss.ejb.client.RemoteEJBPermission" module="org.jboss.ejb-client"/> </permission-set> <permission-set name="run-as-principal-permission"> <permission class-name="org.wildfly.security.auth.permission.RunAsPrincipalPermission" target-name="*"/> </permission-set> </permission-sets>
Login-permission
および default-permissions
パーミッションセットはすでにデフォルト設定に存在します。
承認の転送後にプリンシパルトランスフォーマーが使用される場合、これらのトランスフォーマーは認証と承認プリンシパルの両方に適用されます。
3.2.3. プリンシパルユーザー名の大文字小文字を変更する ケースプリンシパルトランスフォーマー
の作成
elytron
サブシステムには、case-principal-transformer
のプリンシパルトランスフォーマーがあります。case-principal-transformer を使用して、プリンシパルのユーザー名を大文字または小文字のいずれかに変更できます。
case-principal-transformer
主なトランスフォーマーには、デフォルトで true
に設定されている upper-case
属性が含まれています。
case-principal-transformer
の使用例として、認証メカニズムを使用してプリンシパルをセキュリティーレルムにマッピングしている場合を見ていきます。レルムマッパーは、マッピングされたプリンシパルを操作して、セキュリティーレルムを特定し、そのアイデンティティの 1 つをロードします。認証メカニズムは、アイデンティティをポストレルムマッピングステージと最終的なプリンシパル変換ステージに渡します。その後、認証メカニズムは、認証目的で ID を検証します。case-principal-transformer
プリンシパルトランスフォーマーを使用して、マッピングされたプリンシパルの文字の大文字/小文字の形式を変換できます。
手順の例では、セキュリティードメインのコンテキストで case-principal-transformer
を使用しています。プリンシパルトランスフォーマーは、以下の認証ポリシーとインラインで使用することもできます。
-
http-authentication-factory
-
sasl-authentication-factory
-
ssl-context
-
aggregate-realm
手順
elytron
サブシステムにcase-principal-transformer
を追加し、ユーザー名に大文字または小文字のどちらを使用するか選択します。トランスフォーマーのユーザー名を大文字に変更するには、デフォルトの
upper-case
属性値を変更しないでください。elytron
サブシステムに、デフォルトのupper-case
属性設定を定義して、<transformer_name>
を追加する例/subsystem=elytron/case-principal-transformer=<transformer_name>:add(upper-case="true")
また、コマンド構文を短縮して、デフォルトの
upper-case
属性値を使用することもできます。/subsystem=elytron/case-principal-transformer=<transformer_name>:add()
トランスフォーマーのユーザー名を小文字に変更するには、
upper-case
属性をfalse
に設定します。upper-case
属性をfalse
に設定してelytron
サブシステムに追加した<transformer_name>
の例。/subsystem=elytron/case-principal-transformer=<transformer_name>:add(upper-case="false")
オプション:
elytron
サブシステムを使用して、プリンシパルトランスフォーマーを設定します。次の例では、elytron
サブシステムが提供するデフォルトのApplication Domain
設定にプリンシパルトランスフォーマーを設定しています。Elytron は、デフォルトのApplication Domain
設定をpre-realm-principal-transformer
に適用します。/subsystem=elytron/security-domain=ApplicationDomain:write-attribute(name=pre-realm-principal-transformer,value=<transformer_name>)
注記レルムマッパーでのセキュリティーレルムの特定後に、
Application Domain
設定を使用するpost-realm-principal-transformer
を設定できます。
関連情報
-
upper-case
属性については、表 A.26case-principal-transformer
属性を参照してください。
3.2.4. セキュリティーアイデンティティーの認証情報の取得
HTTP クライアントなど、発信呼び出しで使用するアイデンティティー認証情報の取得が必要となる場合があります。以下の例は、セキュリティー認証情報をプログラムで取得する方法を示しています。
import org.wildfly.security.auth.server.IdentityCredentials; import org.wildfly.security.auth.server.SecurityDomain; import org.wildfly.security.auth.server.SecurityIdentity; import org.wildfly.security.credential.PasswordCredential; import org.wildfly.security.password.interfaces.ClearPassword; SecurityIdentity securityIdentity = null; ClearPassword password = null; // Obtain the SecurityDomain for the current deployment. // The calling code requires the // org.wildfly.security.permission.ElytronPermission("getSecurityDomain") permission // if running with a security manager. SecurityDomain securityDomain = SecurityDomain.getCurrent(); if (securityDomain != null) { // Obtain the current security identity from the security domain. // This always returns an identity, but it could be the representation // of the anonymous identity if no authenticated identity is available. securityIdentity = securityDomain.getCurrentSecurityIdentity(); // The private credentials can be accessed to obtain any credentials delegated to the identity. // The calling code requires the // org.wildfly.security.permission.ElytronPermission("getPrivateCredentials") // permission if running with a security manager. IdentityCredentials credentials = securityIdentity.getPrivateCredentials(); if (credentials.contains(PasswordCredential.class)) { password = credentials.getCredential(PasswordCredential.class).getPassword(ClearPassword.class); } }
3.2.5. セキュリティー アイデンティティーの伝搬をサポートするメカニズム
以下の SASL メカニズムは、セキュリティー アイデンティティーの伝搬に対応しています。
-
PLAIN
-
OAUTHBEARER
-
GSSAPI
-
GS2-KRB5
以下の HTTP メカニズムは、セキュリティーアイデンティティーの伝搬に対応しています。
-
FORM
1 -
BASIC
-
BEARER_TOKEN
-
SPNEGO
1 FORM
認証は、Web ブラウザーでは自動的に処理されません。このため、HA クラスターで実行するときに FORM
認証を使用する Web アプリケーションでアイデンティティー伝搬を使用することはできません。BASIC
や SPNEGO
などの他のメカニズムは、HA クラスター環境でのアイデンティティー伝搬に対応しています。