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 メカニズムは、セキュリティーアイデンティティーの伝搬に対応しています。
-
FORM1 -
BASIC -
BEARER_TOKEN -
SPNEGO
1 FORM 認証は、Web ブラウザーでは自動的に処理されません。このため、HA クラスターで実行するときに FORM 認証を使用する Web アプリケーションでアイデンティティー伝搬を使用することはできません。BASIC や SPNEGO などの他のメカニズムは、HA クラスター環境でのアイデンティティー伝搬に対応しています。