第16章 ログインモジュール
16.1. モジュールの使用 リンクのコピーリンクがクリップボードにコピーされました!
16.1.1. パスワードスタッキング リンクのコピーリンクがクリップボードにコピーされました!
password-stacking 属性を useFirstPass に設定する必要があります。パスワードスタッキング用に設定された以前のモジュールがユーザーを認証した場合、他のすべてのスタッキングモジュールはユーザーが認証されたとみなし、承認手順のロールのみを提供しようとします。
password-stacking オプションが useFirstPass に設定されている場合、このモジュールは最初にログインモジュールの共有状態マップにて、プロパティー名 javax.security.auth.login.name 配下の共有ユーザー名とjavax.security.auth.login.password 配下のパスワードを探します。
注記
例16.1 パスワードスタッキングの例
/subsystem=security/security-domain=pwdStack/authentication=classic/login-module=Ldap:add( \
code=Ldap, \
flag=required, \
module-options=[ \
("password-stacking"=>"useFirstPass"), \
... Ldap login module configuration
])
/subsystem=security/security-domain=pwdStack/authentication=classic/login-module=Database:add( \
code=Database, \
flag=required, \
module-options=[ \
("password-stacking"=>"useFirstPass"), \
... Database login module configuration
])
16.1.2. パスワードのハッシュ化 リンクのコピーリンクがクリップボードにコピーされました!
重要
例16.2 パスワードのハッシュ化
usersb64.properties ファイルに含まれ、認証されていないユーザーにプリンシパル名 nobody を割り当てるログインモジュールの設定になります。usersb64.properties ファイルはデプロイメントクラスパスの一部になります。
/subsystem=security/security-domain=testUsersRoles:add
/subsystem=security/security-domain=testUsersRoles/authentication=classic:add
/subsystem=security/security-domain=testUsersRoles/authentication=classic/login-module=UsersRoles:add( \
code=UsersRoles, \
flag=required, \
module-options=[ \
("usersProperties"=>"usersb64.properties"), \
("rolesProperties"=>"test-users-roles.properties"), \
("unauthenticatedIdentity"=>"nobody"), \
("hashAlgorithm"=>"SHA-256"), \
("hashEncoding"=>"base64") \
])
- hashAlgorithm
- パスワードをハッシュ化するために使用される
java.security.MessageDigestアルゴリズムの名前。デフォルトはないため、ハッシュ化を有効にするにはこのオプションを指定する必要があります。一般的な値はSHA-256、SHA-1、およびMD5です。 - hashEncoding
- 3 つのエンコーディング形式 (
base64、hex、またはrfc2617) の 1 つを指定する文字列です。デフォルトはbase64です。 - hashCharset
- クリアテキストのパスワードをバイトアレイに変換するために使用されるエンコーディング文字。デフォルトはプラットフォームのデフォルトエンコーディングです。
- hashUserPassword
- ユーザーが送信するパスワードに適用されるハッシュアルゴリズムを指定します。ハッシュ化されたユーザーパスワードは、パスワードのハッシュであることが想定されるログインモジュールの値と比較されます。デフォルトは
trueです。 - hashStorePassword
- サーバー側に保存されるパスワードに適用されるハッシュアルゴリズムを指定します。これは、ユーザーがユーザーパスワードのハッシュとサーバーからのリクエスト固有のトークンを送信して比較するダイジェスト認証に使用されます。サーバー側のハッシュを算出するために、ハッシュアルゴリズム (ダイジェスト認証の場合は
rfc2617) が使用されます。サーバー側のハッシュは、クライアントから送信されたハッシュ化された値と一致する必要があります。
org.jboss.security.auth.spi.Util クラスによって提供されます。以下の例は、base64 でエンコードされ MD5 でハッシュ化されたパスワードを生成します。
String hashedPassword = Util.createPasswordHash("SHA-256",
Util.BASE64_ENCODING, null, null, "password");
password が OpenSSL のダイジェスト関数へパイプ処理された後、base64 でエンコードされた形式に変換するために別の OpenSSL 関数へパイプ処理されます。
echo -n password | openssl dgst -sha256 -binary | openssl base64
XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg= で、両方の場合で同じになります。上記の例では、この値はセキュリティードメインで指定されたユーザーのプロパティーファイル usersb64.properties に保存される必要があります。
16.1.3. 非認証のアイデンティティー リンクのコピーリンクがクリップボードにコピーされました!
unauthenticatedIdentity は、関連する認証情報がない状態で作成されたリクエストへ特定のアイデンティティー (guest など) を割り当てるログインモジュール設定オプションです。このオプションを使用すると、保護されていないサーブレットは特定のロールを必要としない EJB 上でメソッドを呼び出しできます。このようなプリンシパルには関連するロールがなく、セキュアでない EJB やチェックされないパーミッション制約に関連する EJB メソッドへのみアクセスできます。
- unauthenticatedIdentity: 認証情報が含まれないリクエストへ割り当てられるプリンシパル名を定義します。
16.1.4. Ldap ログインモジュール リンクのコピーリンクがクリップボードにコピーされました!
Ldap ログインモジュールは LDAP (Lightweight Directory Access Protocol) サーバーに対して認証を行う LoginModule 実装です。JNDI (Java Naming and Directory Interface) LDAP プロバイダーを使用してアクセス可能な LDAP サーバーにユーザー名とクレデンシャルが保存される場合は、Ldap ログインモジュールを使用してください。
注記
AdvancedLdap ログインモジュールまたは AdvancedLdap ログインモジュールのみの使用を考慮してください。
- 識別名 (DN)
- LDAP (Lightweight Directory Access Protocol) では、識別名によってディレクトリーでオブジェクトが一意に識別されます。各識別名には他のオブジェクトとは異なる一意な名前と場所が必要で、これには属性と値のペア (AVP) を使用します。AVP は共通名や組織単位などの情報を定義します。これらの値を組み合わせることで、LDAP が必要とする一意な文字列が作成されます。
注記
- java.naming.factory.initial
InitialContextFactory実装クラス名。デフォルトは Sun LDAP プロバイダー実装com.sun.jndi.ldap.LdapCtxFactoryです。- java.naming.provider.url
- LDAP サーバーの LDAP URL。
- java.naming.security.authentication
- 使用するセキュリティープロトコルレベルです。使用可能な値は
none、simple、strongなどです。プロパティーが定義されていないと、挙動はサービスプロバイダーによって決定されます。 - java.naming.security.protocol
- セキュリティーアクセスに使用されるトランスポートプロトコル。この設定オプションをサービスプロバイダーのタイプ (例: SSL) に設定します。プロパティーが定義されてされていないと、挙動はサービスプロバイダーによって決定されます。
- java.naming.security.principal
- サービスに対する呼び出し元を認証するプリンシパルのアイデンティティーを指定します。これは、以下に示された他のプロパティーから構築されます。
- java.naming.security.credentials
- サービスに対する呼び出し元を認証するプリンシパルのクレデンシャルを指定します。クレデンシャルの可能な形式はハッシュ化されたパスワード、クリアテキストのパスワード、キー、または証明書です。プロパティーが定義されていないと、挙動はサービスプロバイダーによって決定されます。
注記
true に設定する必要があります。
InitialLdapContext を作成します。
InitialLdapContext インスタンスが作成されます)、roleAttributeName および uidAttributeName オプションの値に設定された検索属性で rolesCtxDN の場所を検索し、ユーザーのロールがクエリーされます。ロール名は、検索結果セットのロール属性で toString メソッドを呼び出して取得されます。
例16.3 LDAP ログインモジュールのセキュリティードメイン
/subsystem=security/security-domain=testLDAP:add(cache-type=default)
/subsystem=security/security-domain=testLDAP/authentication=classic:add
/subsystem=security/security-domain=testLDAP/authentication=classic/login-module=Ldap:add( \
code=Ldap, \
flag=required, \
module-options=[ \
("java.naming.factory.initial"=>"com.sun.jndi.ldap.LdapCtxFactory"), \
("java.naming.provider.url"=>"ldap://ldaphost.jboss.org:1389/"), \
("java.naming.security.authentication"=>"simple"), \
("principalDNPrefix"=>"uid="), \
("principalDNSuffix"=>",ou=People,dc=jboss,dc=org"), \
("rolesCtxDN"=>"ou=Roles,dc=jboss,dc=org"), \
("uidAttributeID"=>"member"), \
("matchOnUserDN"=>true), \
("roleAttributeID"=>"cn"), \
("roleAttributeIsDN"=>false) \
])
java.naming.factory.initial、java.naming.factory.url、および java.naming.security オプションは以下の条件を示します。
- Sun LDAP JNDI プロバイダー実装が使用されます。
- LDAP サーバーは、ポート 1389 のホスト
ldaphost.jboss.orgにあります。 - LDAP サーバーへの接続には LDAP の単純な認証メソッドが使用されます。
jsmith が uid=jsmith,ou=People,dc=jboss,dc=org へマップされます。
注記
userPassword 属性 (この例では theduke) を使用して LDAP サーバーがユーザーを認証することを想定します。ほとんどの LDAP サーバーはこのように動作しますが、ご使用の LDAP サーバーの認証処理がこれとは異なる場合は、本番環境の要件に従って LDAP を設定する必要があります。
rolesCtxDN のサブツリー検索が実行され、承認の基になるロールが読み出されます。matchOnUserDN が true の場合、ユーザーの完全な DN を基に検索が実行されます。true でない場合は、入力された実際のユーザー名を基にして検索が実行されます。この例では、ou=Roles,dc=jboss,dc=org 配下の uid=jsmith,ou=People,dc=jboss,dc=org と等しい member 属性を持つエントリーに対して検索が行われ、ロールエントリー配下の cn=JBossAdmin が見つかります。
cn になります。返される値は JBossAdmin で、ユーザー jsmith が JBossAdmin ロールに割り当てられます。
- LDAP データ変換形式 (LDIF)
- LDAP ディレクトリーの内容や更新リクエストを表すために使用されるプレーンテキストのデータ変換形式です。ディレクトリーの内容は 各オブジェクトまたは更新リクエストが 1 つのレコードとして示されます。内容は追加、変更、削除、および名前変更リクエストで構成されます。
例16.4 LDIF ファイルの例
dn: dc=jboss,dc=org
objectclass: top
objectclass: dcObject
objectclass: organization
dc: jboss
o: JBoss
dn: ou=People,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: People
dn: uid=jsmith,ou=People,dc=jboss,dc=org
objectclass: top
objectclass: uidObject
objectclass: person
uid: jsmith
cn: John
sn: Smith
userPassword: theduke
dn: ou=Roles,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: Roles
dn: cn=JBossAdmin,ou=Roles,dc=jboss,dc=org
objectclass: top
objectclass: groupOfNames
cn: JBossAdmin
member: uid=jsmith,ou=People,dc=jboss,dc=org
description: the JBossAdmin group
16.1.5. LdapExtended ログインモジュール リンクのコピーリンクがクリップボードにコピーされました!
- 識別名 (DN)
- LDAP (Lightweight Directory Access Protocol) では、識別名によってディレクトリーでオブジェクトが一意に識別されます。各識別名には他のオブジェクトとは異なる一意な名前と場所が必要で、これには属性と値のペア (AVP) を使用します。AVP は共通名や組織単位などの情報を定義します。これらの値を組み合わせることで、LDAP が必要とする一意な文字列が作成されます。
org.jboss.security.auth.spi.LdapExtLoginModule) はバインドするユーザーと関連するロールを検索します。ロールクエリーは再帰的に DN をたどり、階層的なロール構成を移動します。
- Context.INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial"
- Context.SECURITY_PROTOCOL = "java.naming.security.protocol"
- Context.PROVIDER_URL = "java.naming.provider.url"
- Context.SECURITY_AUTHENTICATION = "java.naming.security.authentication"
- Context.REFERRAL = "java.naming.referral"
- 初期の LDAP サーバーのバインドは bindDN および bindCredential プロパティーを使用して認証されます。bindDN は、ユーザーとロールの baseCtxDN および rolesCtxDN ツリーを検索する権限を持つユーザーです。認証する user DN は、baseFilter プロパティーによって指定されたフィルターを使用してクエリーされます。
- 結果となる userDN は、InitialLdapContext 環境 Context.SECURITY_PRINCIPAL として userDN を使用して LDAP サーバーにバインドすることで認証されます。Context.SECURITY_CREDENTIALS プロパティーは、コールバックハンドラーにより取得された文字列パスワードに設定されます。
- これに成功すると、rolesCtxDN、roleAttributeID、roleAttributeIsDN、roleNameAttributeID、および roleFilter オプションを使用して関連するユーザーロールがクエリーされます。
図16.1 LDAP 構成の例
例16.5 LDAP 設定例 2
version: 1
dn: o=example2,dc=jboss,dc=org
objectClass: top
objectClass: organization
o: example2
dn: ou=People,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: People
dn: uid=jduke,ou=People,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: uidObject
objectClass: person
objectClass: inetOrgPerson
cn: Java Duke
employeeNumber: judke-123
sn: Duke
uid: jduke
userPassword:: dGhlZHVrZQ==
dn: uid=jduke2,ou=People,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: uidObject
objectClass: person
objectClass: inetOrgPerson
cn: Java Duke2
employeeNumber: judke2-123
sn: Duke2
uid: jduke2
userPassword:: dGhlZHVrZTI=
dn: ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: Roles
dn: uid=jduke,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupUserEx
memberOf: cn=Echo,ou=Roles,o=example2,dc=jboss,dc=org
memberOf: cn=TheDuke,ou=Roles,o=example2,dc=jboss,dc=org
uid: jduke
dn: uid=jduke2,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupUserEx
memberOf: cn=Echo2,ou=Roles,o=example2,dc=jboss,dc=org
memberOf: cn=TheDuke2,ou=Roles,o=example2,dc=jboss,dc=org
uid: jduke2
dn: cn=Echo,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: Echo
description: the echo role
member: uid=jduke,ou=People,dc=jboss,dc=org
dn: cn=TheDuke,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: TheDuke
description: the duke role
member: uid=jduke,ou=People,o=example2,dc=jboss,dc=org
dn: cn=Echo2,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: Echo2
description: the Echo2 role
member: uid=jduke2,ou=People,dc=jboss,dc=org
dn: cn=TheDuke2,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: TheDuke2
description: the duke2 role
member: uid=jduke2,ou=People,o=example2,dc=jboss,dc=org
dn: cn=JBossAdmin,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: JBossAdmin
description: the JBossAdmin group
member: uid=jduke,ou=People,dc=jboss,dc=org
/subsystem=security/security-domain=testLdapExample2/authentication=classic/login-module=LdapExtended:add( \
code=LdapExtended, \
flag=required, \
module-options=[ \
("java.naming.factory.initial"=>"com.sun.jndi.ldap.LdapCtxFactory"), \
("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"), \
("java.naming.security.authentication"=>"simple"), \
("bindDN"=>"cn=Root,dc=jboss,dc=org"), \
("bindCredential"=>"secret1"), \
("baseCtxDN"=>"ou=People,o=example2,dc=jboss,dc=org"), \
("baseFilter"=>"(uid={0})"), \
("rolesCtxDN"=>"ou=Roles,o=example2,dc=jboss,dc=org"), \
("roleFilter"=>"(uid={0})"), \
("roleAttributeIsDN"=>"true"), \
("roleAttributeID"=>"memberOf"), \
("roleNameAttributeID"=>"cn") \
])
例16.6 LDAP 設定例 3
dn: o=example3,dc=jboss,dc=org
objectclass: top
objectclass: organization
o: example3
dn: ou=People,o=example3,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: People
dn: uid=jduke,ou=People,o=example3,dc=jboss,dc=org
objectclass: top
objectclass: uidObject
objectclass: person
objectClass: inetOrgPerson
uid: jduke
employeeNumber: judke-123
cn: Java Duke
sn: Duke
userPassword: theduke
dn: ou=Roles,o=example3,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: Roles
dn: uid=jduke,ou=Roles,o=example3,dc=jboss,dc=org
objectClass: top
objectClass: groupUserEx
memberOf: cn=Echo,ou=Roles,o=example3,dc=jboss,dc=org
memberOf: cn=TheDuke,ou=Roles,o=example3,dc=jboss,dc=org
uid: jduke
dn: cn=Echo,ou=Roles,o=example3,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: Echo
description: the JBossAdmin group
member: uid=jduke,ou=People,o=example3,dc=jboss,dc=org
dn: cn=TheDuke,ou=Roles,o=example3,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: TheDuke
member: uid=jduke,ou=People,o=example3,dc=jboss,dc=org
/subsystem=security/security-domain=testLdapExample3/authentication=classic/login-module=LdapExtended:add( \
code=LdapExtended, \
flag=required, \
module-options=[ \
("java.naming.factory.initial"=>"com.sun.jndi.ldap.LdapCtxFactory"), \
("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"), \
("java.naming.security.authentication"=>"simple"), \
("bindDN"=>"cn=Root,dc=jboss,dc=org"), \
("bindCredential"=>"secret1"), \
("baseCtxDN"=>"ou=People,o=example3,dc=jboss,dc=org"), \
("baseFilter"=>"(cn={0})"), \
("rolesCtxDN"=>"ou=Roles,o=example3,dc=jboss,dc=org"), \
("roleFilter"=>"(member={1})"), \
("roleAttributeID"=>"cn") \
])
例16.7 LDAP 設定例 4
dn: o=example4,dc=jboss,dc=org
objectclass: top
objectclass: organization
o: example4
dn: ou=People,o=example4,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: People
dn: uid=jduke,ou=People,o=example4,dc=jboss,dc=org
objectClass: top
objectClass: uidObject
objectClass: person
objectClass: inetOrgPerson
cn: Java Duke
employeeNumber: jduke-123
sn: Duke
uid: jduke
userPassword:: dGhlZHVrZQ==
dn: ou=Roles,o=example4,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: Roles
dn: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: RG1
member: cn=empty
dn: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: RG2
member: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
member: uid=jduke,ou=People,o=example4,dc=jboss,dc=org
dn: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: RG3
member: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
dn: cn=R1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R1
member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
dn: cn=R2,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R2
member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
dn: cn=R3,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R3
member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
dn: cn=R4,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R4
member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
dn: cn=R5,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R5
member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
member: uid=jduke,ou=People,o=example4,dc=jboss,dc=org
/subsystem=security/security-domain=testLdapExample4/authentication=classic/login-module=LdapExtended:add( \
code=LdapExtended, \
flag=required, \
module-options=[ \
("java.naming.factory.initial"=>"com.sun.jndi.ldap.LdapCtxFactory"), \
("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"), \
("java.naming.security.authentication"=>"simple"), \
("bindDN"=>"cn=Root,dc=jboss,dc=org"), \
("bindCredential"=>"secret1"), \
("baseCtxDN"=>"ou=People,o=example4,dc=jboss,dc=org"), \
("baseFilter"=>"(cn={0})"), \
("rolesCtxDN"=>"ou=Roles,o=example4,dc=jboss,dc=org"), \
("roleFilter"=>"(member={1})"), \
("roleRecursion"=>"1"), \
("roleAttributeID"=>"memberOf") \
])
例16.8 デフォルトの Active Directory 設定
/subsystem=security/security-domain=AD_Default/authentication=classic/login-module=LdapExtended:add( \
code=LdapExtended, \
flag=required, \
module-options=[ \
("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"), \
("bindDN"=>"JBOSS\searchuser"), \
("bindCredential"=>"password"), \
("baseCtxDN"=>"CN=Users,DC=jboss,DC=org"), \
("baseFilter"=>"(sAMAccountName={0})"), \
("rolesCtxDN"=>"CN=Users,DC=jboss,DC=org"), \
("roleFilter"=>"(sAMAccountName={0})"), \
("roleAttributeID"=>"memberOf"), \
("roleAttributeIsDN"=>"true"), \
("roleNameAttributeID"=>"cn"), \
("searchScope"=>"ONELEVEL_SCOPE"), \
("allowEmptyPasswords"=>"false") \
])
例16.9 再帰的なロールの Active Directory 設定
/subsystem=security/security-domain=AD_Recursive/authentication=classic/login-module=LdapExtended:add( \
code=LdapExtended, \
flag=required, \
module-options=[ \
("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"), \
("java.naming.referral"=>"follow"), \
("bindDN"=>"JBOSS\searchuser"), \
("bindCredential"=>"password"), \
("baseCtxDN"=>"CN=Users,DC=jboss,DC=org"), \
("baseFilter"=>"(sAMAccountName={0})"), \
("rolesCtxDN"=>"CN=Users,DC=jboss,DC=org"), \
("roleFilter"=>"(member={1})"), \
("roleAttributeID"=>"cn"), \
("roleAttributeIsDN"=>"false"), \
("roleRecursion"=>"2"), \
("searchScope"=>"ONELEVEL_SCOPE"), \
("allowEmptyPasswords"=>"false") \
])
16.1.6. UsersRoles ログインモジュール リンクのコピーリンクがクリップボードにコピーされました!
UsersRoles ログインモジュールは、Java プロパティーファイルからロードされた複数のユーザーおよびユーザーロールをサポートする簡単なログインモジュールです。デフォルトのユーザー名対パスワードマッピングのファイル名は users.properties で、デフォルトのユーザー名対ロールマッピングのファイル名は roles.properties です。
WAR アーカイブの WEB-INF/classes フォルダー内) やサーバークラスパスのディレクトリー内に置くことができます。このログインモジュールの主な目的は、アプリケーションでデプロイされたプロパティーファイルを使用して複数のユーザーやロールのセキュリティー設定を簡単にテストすることです。
例16.10 UserRoles ログインモジュール
/subsystem=security/security-domain=ejb3-sampleapp/authentication=classic/login-module=UsersRoles:add( \
code=UsersRoles, \
flag=required, \
module-options=[ \
("usersProperties"=>"ejb3-sampleapp-users.properties"), \
("rolesProperties"=>"ejb3-sampleapp-roles.properties") \
])
ejb3-sampleapp-users.properties ファイルは各ユーザーエントリーが個別の行で示される username=password 形式を使用します。
username1=password1
username2=password2
...
ejb3-sampleapp-roles.properties ファイルは、グループ名の値を任意で用いて username=role1,role2, というパターンを使用します。例を以下に示します。
username1=role1,role2,...
username1.RoleGroup1=role3,role4,...
username2=role1,role3,...
ejb3-sampleapp-roles.properties の user name.XXX というプロパティー名のパターンは、ユーザー名ロールをロールの特定の名前を持つグループへ割り当てるために使用されます。プロパティー名の XXX 部分はグループ名になります。user name=... は user name.Roles=... の省略形です。Roles グループ名は JBossAuthorizationManager が想定する、ユーザーの権限を定義するロールが含まれる標準名です。
jduke と同等の定義になります。
jduke=TheDuke,AnimatedCharacter
jduke.Roles=TheDuke,AnimatedCharacter
16.1.7. Database ログインモジュール リンクのコピーリンクがクリップボードにコピーされました!
Database ログインモジュールは、認証とロールマッピングをサポートする JDBC (Java Database Connectivity) ベースのログインモジュールです。ユーザー名、パスワード、およびロールの情報がリレーショナルデータベースに保存される場合は、このログインモジュールを使用します。
注記
Database ログインモジュールは、以下の 2 つの論理テーブルを基にします。
Table Principals(PrincipalID text, Password text)
Table Roles(PrincipalID text, Role text, RoleGroup text)
Principals テーブルは、ユーザーの PrincipalID を有効なパスワードに関連付けます。Roles テーブルは、ユーザーの PrincipalID をロールセットに関連付けます。ユーザー権限に使用されるロールは、RoleGroup 列の値が Roles である行に含まれる必要があります。
java.sql.ResultSet の論理構成が前述の Principals および Roles テーブルと同じであることです。結果は列インデックスを基にアクセスされるため、テーブルおよび列の実際の名前は関係ありません。
Principals と Roles の 2 つのテーブルを持つデータベースについて考えてみてください。以下のステートメントは以下のデータをテーブルに追加します。
Principalsテーブル内のPasswordがechomanのPrincipalIDjavaRolesテーブル内のRolesRoleGroupにあるEchoという名前のロールを持つPrincipalIDjavaRolesテーブル内のCallerPrincipalRoleGroupにあるcaller_javaという名前のロールを持つPrincipalIDjava
INSERT INTO Principals VALUES('java', 'echoman')
INSERT INTO Roles VALUES('java', 'Echo', 'Roles')
INSERT INTO Roles VALUES('java', 'caller_java', 'CallerPrincipal')
Database login module ログインモジュールの設定例は、次のように構築できます。
CREATE TABLE Users(username VARCHAR(64) PRIMARY KEY, passwd VARCHAR(64))
CREATE TABLE UserRoles(username VARCHAR(64), role VARCHAR(32))
/subsystem=security/security-domain=testDB/authentication=classic/login-module=Database:add( \
code=Database, \
flag=required, \
module-options=[ \
("dsJndiName"=>"java:/MyDatabaseDS"), \
("principalsQuery"=>"select passwd from Users where username=?"), \
("rolesQuery"=>"select role, 'Roles' from UserRoles where username=?") \
])
16.1.8. Certificate ログインモジュール リンクのコピーリンクがクリップボードにコピーされました!
Certificate ログインモジュールは X509 証明書を基にユーザーを認証します。このログインモジュールの典型的なユースケースが Web 層の CLIENT-CERT 認証です。
CertRolesLoginModule および DatabaseCertLoginModule は、動作を拡張してプロパティーファイルまたはデータベースから承認ロールを取得します。
Certificate ログインモジュールオプションの詳細は「含まれる認証モジュール」を参照してください。
Certificate ログインモジュールは、ユーザーの検証に KeyStore を必要とします。これは、以下の設定 (一部分) が示すとおり、リンクされたセキュリティードメインの JSSE 設定から取得されます。
/subsystem=security/security-domain=trust-domain:add
/subsystem=security/security-domain=trust-domain/jsse=classic:add( \
truststore={ \
password=>pass1234, \
url=>/home/jbosseap/trusted-clients.jks \
})
/subsystem=security/security-domain=testCert:add
/subsystem=security/security-domain=testCert/authentication=classic:add
/subsystem=security/security-domain=testCert/authentication=classic/login-module=Certificate:add( \
code=Certificate, \
flag=required, \
module-options=[ \
("securityDomain"=>"trust-domain"), \
])
手順16.1 証明書およびロールベース承認を用いた Web アプリケーションのセキュア化
user-app.war などの Web アプリケーションをセキュアにする方法を説明します。この例では、認証と承認に CertificateRoles ログインモジュールが使用されます。trusted-clients.keystore および app-roles.properties には、クライアント証明書に関連するプリンシパルへマップするエントリーが必要になります。
リソースおよびロールの宣言
web.xmlを変更し、認証および承認に使用される許可されたロールおよびセキュリティードメインとともにセキュア化されるリソースを宣言します。<?xml version="1.0" encoding="UTF-8"?> <web-app 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_3_0.xsd" version="3.0"> <security-constraint> <web-resource-collection> <web-resource-name>Protect App</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>Admin</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>CLIENT-CERT</auth-method> <realm-name>Secured area</realm-name> </login-config> <security-role> <role-name>Admin</role-name> </security-role> </web-app>セキュリティードメインの指定
jboss-web.xmlファイルで、必要なセキュリティードメインを指定します。<jboss-web> <security-domain>app-sec-domain</security-domain> </jboss-web>ログインモジュールの設定
管理 CLI を使用して、指定したapp-sec-domainドメインのログインモジュール設定を定義します。[ /subsystem=security/security-domain=trust-domain:add /subsystem=security/security-domain=trust-domain/jsse=classic:add( \ truststore={ \ password=>pass1234, \ url=>/home/jbosseap/trusted-clients.jks \ }) /subsystem=security/security-domain=app-sec-domain:add /subsystem=security/security-domain=app-sec-domain/authentication=classic:add /subsystem=security/security-domain=app-sec-domain/authentication=classic/login-module=CertificateRoles:add( \ code=CertificateRoles, \ flag=required, \ module-options=[ \ ("securityDomain"=>"trust-domain"), \ ("rolesProperties"=>"app-roles.properties") \ ])
例16.11 証明書の例
[conf]$ keytool -printcert -file valid-client-cert.crt
Owner: CN=valid-client, OU=Security QE, OU=JBoss, O=Red Hat, C=CZ
Issuer: CN=EAP Certification Authority, OU=Security QE, OU=JBoss, O=Red Hat, C=CZ
Serial number: 2
Valid from: Mon Mar 24 18:21:55 CET 2014 until: Tue Mar 24 18:21:55 CET 2015
Certificate fingerprints:
MD5: 0C:54:AE:6E:29:ED:E4:EF:46:B5:14:30:F2:E0:2A:CB
SHA1: D6:FB:19:E7:11:28:6C:DE:01:F2:92:2F:22:EF:BB:5D:BF:73:25:3D
SHA256: CD:B7:B1:72:A3:02:42:55:A3:1C:30:E1:A6:F0:20:B0:2C:0F:23:4F:7A:8E:2F:2D:FA:AF:55:3E:A7:9B:2B:F4
Signature algorithm name: SHA1withRSA
Version: 3
trusted-clients.keystore は、例16.11「証明書の例」 の証明書が CN=valid-client, OU=Security QE, OU=JBoss, O=Red Hat, C=CZ のエイリアスと保存されることを要件とすることがあります。app-roles.properties には同じエントリーが存在する必要があります。DN には通常は区切り文字として使用される文字が含まれているため、以下のようにバックスラッシュ (\) を使用して区切り文字をエスケープする必要があります。
# A sample app-roles.properties file
CN\=valid-client,\ OU\=Security\ QE,\ OU\=JBoss,\ O\=Red\ Hat,\ C\=CZ
16.1.9. Identity ログインモジュール リンクのコピーリンクがクリップボードにコピーされました!
Identity ログインモジュールは、ハードコードされたユーザー名をモジュールに対して認証されたサブジェクトに関連付ける簡単なログインモジュールです。このモジュールは、principal オプションによって指定された名前を使用して SimplePrincipal インスタンスを作成します。
注記
jduke という名前のプリンシパルとして認証し、TheDuke および AnimatedCharacter というロール名を割り当てます。
/subsystem=security/security-domain=testIdentity:add
/subsystem=security/security-domain=testIdentity/authentication=classic:add
/subsystem=security/security-domain=testIdentity/authentication=classic/login-module=Identity:add( \
code=Identity, \
flag=required, \
module-options=[ \
("principal"=>"jduke"), \
("roles"=>"TheDuke,AnimatedCharacter") \
])
16.1.10. RunAs ログインモジュール リンクのコピーリンクがクリップボードにコピーされました!
RunAs ログインモジュールはヘルパーモジュールで、認証のログイン段階の間に run as ロールをスタックへプッシュし、コミットまたはアボート段階で run as ロールをスタックからポップします。
RunAs ロールを必要とするログインモジュールを確立する前に RunAs ログインモジュールを設定する必要があります。
16.1.10.1. RunAsIdentity の作成 リンクのコピーリンクがクリップボードにコピーされました!
javax.security.auth.Subject インスタンスまたは org.jboss.security.RunAsIdentity インスタンスのいずれかによって示されます。これらのクラスは、アイデンティティーとアイデンティティーが持つロールのリストを示す 1 つ以上のプリンシパルを保存します。javax.security.auth.Subject の場合は、クレデンシャルのリストも保存されます。
ejb-jar.xml デプロイメント記述子の <assembly-descriptor> セクションには、ユーザーがさまざまな EJB メソッドへアクセスするために必要な 1 つ以上のロールを指定します。これらのリストを比較すると、EJB メソッドへアクセスするために必要なロールの 1 つをユーザーが持っているかどうかが分かります。
例16.12 org.jboss.security.RunAsIdentity の作成
ejb-jar.xml ファイルには、<session> 要素の子として定義された <run-as> ロールを持つ <security-identity> 要素を指定します。
<session>
...
<security-identity>
<run-as>
<role-name>Admin</role-name>
</run-as>
</security-identity>
...
</session>
Admin の RunAsIdentity ロールを作成する必要があることを意味します。
Admin ロールのプリンシパルに名前と付けるには、jboss-ejb3.xml ファイルで <run-as-principal> 要素を定義します。
<jboss:ejb-jar
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns:s="urn:security:1.1"
version="3.1" impl-version="2.0">
<assembly-descriptor>
<s:security>
<ejb-name>WhoAmIBean</ejb-name>
<s:run-as-principal>John</s:run-as-principal>
</s:security>
</assembly-descriptor>
</jboss:ejb-jar>
ejb-jar.xml ファイルの <security-identity> 要素と jboss-ejb3.xml ファイルの <security> 要素はデプロイメント時点で解析されます。<run-as> ロール名および <run-as-principal> 名は org.jboss.metadata.ejb.spec.SecurityIdentityMetaData クラスに保存されます。
例16.13 RunAsIdentity への複数ロールの割り当て
jboss-ejb3.xml デプロイメント記述子の <assembly-descriptor> 要素グループでロールをプリンシパルへマップすると、追加のロールを RunAsIdentity へ割り当てできます。
<jboss:ejb-jar xmlns:sr="urn:security-role"
...>
<assembly-descriptor>
...
<sr:security-role>
<sr:role-name>Support</sr:role-name>
<sr:principal-name>John</sr:principal-name>
<sr:principal-name>Jill</sr:principal-name>
<sr:principal-name>Tony</sr:principal-name>
</sr:security-role>
</assembly-descriptor>
</jboss:ejb-jar>
John の <run-as-principal> が作成されました。この例の設定は、Support ロールを追加して Admin ロールを拡張します。新しいロールには、追加のプリンシパルと最初に定義されたプリンシパル John が含まれます。
ejb-jar.xml および jboss-ejb3.xml ファイルの <security-role> 要素はデプロイ時に解析されます。<role-name> および <principal-name> データは org.jboss.metadata.ejb.spec.SecurityIdentityMetaData クラスに保存されます。
16.1.11. Client ログインモジュール リンクのコピーリンクがクリップボードにコピーされました!
Client ログインモジュール (org.jboss.security.ClientLoginModule) は、呼び出し側のアイデンティティーとクレデンシャルを確立するときに JBoss クライアントによって使用される LoginModule の実装です。このモジュールは、新しい SecurityContext を作成してプリンシパルとクレデンシャルを割り当て、SecurityContext を ThreadLocal セキュリティーコンテキストに設定します。
Client ログインモジュールは、クライアントが現在のスレッドの呼び出し側を確立するために唯一サポートされるメカニズムです。スタンドアロンクライアントアプリケーションとサーバー環境 (EAP セキュリティーサブシステムを透過的に使用するよう設定されていないセキュリティー環境で JBoss EJB クライアントとして動作する) の両方は Client ログインモジュールを使用する必要があります。
Client ログインモジュールの他に別のログインモジュールを設定する必要があります。
16.1.12. SPNEGO ログインモジュール リンクのコピーリンクがクリップボードにコピーされました!
SPNEGO ログインモジュール (org.jboss.security.negotiation.spnego.SPNEGOLoginModule) は、KDC を用いて呼び出し側のアイデンティティーとクレデンシャルを確立する LoginModule の実装です。モジュールは JBoss Negotiation プロジェクトの一部で、SPNEGO (Simple and Protected GSSAPI Negotiation メカニズム) を実装します。AdvancedLdap ログインモジュールを用いてチェーンされた設定でこの認証を使用すると、LDAP サーバーとの連携を可能にできます。
SPNEGO または AdvancedLdap ログインモジュールを使用するには、META-INF/jboss-deployment-structure.xml デプロイメント記述子ファイルを編集し、手作業で依存関係を追加する必要があります。
例16.14 JBoss Negotiation モジュールを依存関係として追加
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.jboss.security.negotiation" />
</dependencies>
</deployment>
</jboss-deployment-structure>
16.1.13. RoleMapping ログインモジュール リンクのコピーリンクがクリップボードにコピーされました!
RoleMapping ログインモジュールは、認証プロセスの最終結果であるロールを 1 つ以上の宣言的ロールへマップすることをサポートします。たとえば、ユーザー「A」は「ldapAdmin」および「testAdmin」ロールを持ち、アクセスのために web.xml または ejb-jar.xml ファイルに定義された宣言的ロールは admin であると認証プロセスによって判断された場合、このモジュールは admin ロールをユーザー A にマップします。
RoleMapping ログインモジュールオプションの詳細は「含まれる認証モジュール」を参照してください。
RoleMapping ログインモジュールはログインモジュール設定の任意のモジュールであると定義する必要があります。これにより、以前マップされたロールのマッピングが変更されます。
例16.15 マップされたロールの定義
/subsystem=security/security-domain=test-domain-2/:add
/subsystem=security/security-domain=test-domain-2/authentication=classic:add
/subsystem=security/security-domain=test-domain-2/authentication=classic/login-module=test-2-lm/:add(\
flag=required,\
code=UsersRoles,\
module-options=[("usersProperties"=>"users.properties"),("rolesProperties"=>"roles.properties")]\
)
/subsystem=security/security-domain=test-domain-2/authentication=classic/login-module=test2-map/:add(\
flag=optional,\
code=RoleMapping,\
module-options=[("rolesProperties"=>"rolesMapping-roles.properties")]\
)
例16.16 マップされたロールを定義する推奨方法
/subsystem=security/security-domain=test-domain-2/:add
/subsystem=security/security-domain=test-domain-2/authentication=classic:add
/subsystem=security/security-domain=test-domain-2/authentication=classic/login-module=test-2-lm/:add(\
flag=required,\
code=UsersRoles,\
module-options=[("usersProperties"=>"users.properties"),("rolesProperties"=>"roles.properties")]\
)
/subsystem=security/security-domain=test-domain-2/mapping=classic/mapping-module=test2-map/:add(\
code=PropertiesRoles,type=role,\
module-options=[("rolesProperties"=>"rolesMapping-roles.properties")]\
)
例16.17 RoleMappingLoginModule によって使用されるプロパティーファイル
ldapAdmin=admin, testAdmin
ldapAdmin ロールが含まれている場合、replaceRole プロパティーの値に応じて admin および testAdmin ロールが認証されたサブジェクトに追加されるか、認証されたサブジェクトの代替となります。
16.1.14. bindCredential モジュールオプション リンクのコピーリンクがクリップボードにコピーされました!
bindCredential モジュールオプションは、DN のクレデンシャルを保存するために使用され、複数のログインおよびマッピングモジュールによって使用されます。パスワードを取得する方法は複数あります。
- 管理 CLI コマンドのプレーンテキスト。
bindCredentialモジュールのパスワードは、("bindCredential"=>"secret1")のように管理 CLI コマンドにてプレーンテキストで提供されることがあります。セキュリティー上の理由で、このパスワードは JBoss EAP の vault メカニズムを使用して暗号化する必要があります。- 外部コマンドの使用。
- 外部コマンドの出力からパスワードを入手するには、
{EXT}...形式を使用します (...は外部コマンドに置き換えます)。コマンド出力の最初の行がパスワードとして使用されます。パフォーマンスを改善するため、{EXTC[:expiration_in_millis]}の亜種は指定のミリ秒の間パスワードをキャッシュします。デフォルトでは、キャッシュされたパスワードは失効しません。0(ゼロ) が値として指定された場合、キャッシュされたクレデンシャルは失効しません。EXTCの亜種はLdapExtendedログインモジュールのみによってサポートされます。
例16.18 外部コマンドからのパスワードの取得
{EXT}cat /mysecretpasswordfile
例16.19 外部ファイルからパスワードを取得し、500 ミリ秒間キャッシュする
{EXTC:500}cat /mysecretpasswordfile