@@ -18,9 +18,16 @@

import static org.wildfly.extension.elytron.ElytronDescriptionConstants.ALGORITHM;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.AUTOFLUSH;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.BCRYPT_MAPPER;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.FILE_AUDIT_LOG;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.HASH_ENCODING;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.JDBC_REALM;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.MODULAR_CRYPT_MAPPER;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.PERIODIC_ROTATING_FILE_AUDIT_LOG;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.SALTED_SIMPLE_DIGEST_MAPPER;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.SALT_ENCODING;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.SCRAM_MAPPER;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.SIMPLE_DIGEST_MAPPER;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.SIZE_ROTATING_FILE_AUDIT_LOG;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.SYNCHRONIZED;
import static org.wildfly.extension.elytron.ElytronExtension.ELYTRON_1_2_0;
@@ -31,9 +38,11 @@
import static org.wildfly.extension.elytron.ElytronExtension.ELYTRON_6_0_0;
import static org.wildfly.extension.elytron.ElytronExtension.ELYTRON_7_0_0;
import static org.wildfly.extension.elytron.JdbcRealmDefinition.PrincipalQueryAttributes.PRINCIPAL_QUERIES;
import static org.wildfly.extension.elytron.JdbcRealmDefinition.PrincipalQueryAttributes.PRINCIPAL_QUERY;
import static org.wildfly.extension.elytron._private.ElytronSubsystemMessages.ROOT_LOGGER;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.jboss.as.controller.ModelVersion;
@@ -87,6 +96,22 @@ public void registerTransformers(SubsystemTransformerRegistration registration)
private static void from7(ChainedTransformationDescriptionBuilder chainedBuilder) {
ResourceTransformationDescriptionBuilder builder = chainedBuilder.createBuilder(ELYTRON_7_0_0, ELYTRON_6_0_0);

Map<String, RejectAttributeChecker> keyMapperChecker = new HashMap<>();
keyMapperChecker.put(HASH_ENCODING, RejectAttributeChecker.DEFINED);
keyMapperChecker.put(SALT_ENCODING, RejectAttributeChecker.DEFINED);

Map<String, RejectAttributeChecker> principalQueryCheckers = new HashMap<>();
principalQueryCheckers.put(BCRYPT_MAPPER, new RejectAttributeChecker.ObjectFieldsRejectAttributeChecker(keyMapperChecker));
principalQueryCheckers.put(SALTED_SIMPLE_DIGEST_MAPPER, new RejectAttributeChecker.ObjectFieldsRejectAttributeChecker(keyMapperChecker));
principalQueryCheckers.put(SIMPLE_DIGEST_MAPPER, new RejectAttributeChecker.ObjectFieldsRejectAttributeChecker(keyMapperChecker));
principalQueryCheckers.put(SCRAM_MAPPER, new RejectAttributeChecker.ObjectFieldsRejectAttributeChecker(keyMapperChecker));
principalQueryCheckers.put(MODULAR_CRYPT_MAPPER, RejectAttributeChecker.DEFINED);

builder.addChildResource(PathElement.pathElement(JDBC_REALM))
.getAttributeBuilder()
.addRejectCheck(new RejectAttributeChecker.ListRejectAttributeChecker(
new RejectAttributeChecker.ObjectFieldsRejectAttributeChecker(principalQueryCheckers)
), PRINCIPAL_QUERY);
}

private static void from6(ChainedTransformationDescriptionBuilder chainedBuilder) {
@@ -97,7 +122,6 @@ private static void from6(ChainedTransformationDescriptionBuilder chainedBuilder
.end();
}


private static void from5(ChainedTransformationDescriptionBuilder chainedBuilder) {
ResourceTransformationDescriptionBuilder builder = chainedBuilder.createBuilder(ELYTRON_5_0_0, ELYTRON_4_0_0);
builder.getAttributeBuilder()

Large diffs are not rendered by default.

@@ -50,9 +50,13 @@
.addAttributes(RealmDefinitions.IDENTITY_REALM_ATTRIBUTES)
.setUseElementsForGroups(false)
.build();
@Deprecated
private final PersistentResourceXMLDescription jdbcRealmParser = builder(PathElement.pathElement(ElytronDescriptionConstants.JDBC_REALM), null)
.addAttribute(PrincipalQueryAttributes.PRINCIPAL_QUERIES, AttributeParser.UNWRAPPED_OBJECT_LIST_PARSER, AttributeMarshaller.UNWRAPPED_OBJECT_LIST_MARSHALLER)
.build();
private final PersistentResourceXMLDescription jdbcRealmParser_7_0 = builder(PathElement.pathElement(ElytronDescriptionConstants.JDBC_REALM), null)
.addAttribute(PrincipalQueryAttributes.PRINCIPAL_QUERIES_7_0, AttributeParser.UNWRAPPED_OBJECT_LIST_PARSER, AttributeMarshaller.UNWRAPPED_OBJECT_LIST_MARSHALLER)
.build();
private final PersistentResourceXMLDescription keyStoreRealmParser = builder(PathElement.pathElement(ElytronDescriptionConstants.KEY_STORE_REALM), null)
.addAttribute(KeyStoreRealmDefinition.KEYSTORE)
.build();
@@ -89,6 +93,19 @@
.addChild(cachingRealmParser)
.build();

final PersistentResourceXMLDescription realmParser_7_0 = decorator(ElytronDescriptionConstants.SECURITY_REALMS)
.addChild(aggregateRealmParser)
.addChild(customRealmParser)
.addChild(customModifiableRealmParser)
.addChild(identityRealmParser)
.addChild(jdbcRealmParser_7_0)
.addChild(keyStoreRealmParser)
.addChild(propertiesRealmParser)
.addChild(ldapRealmParser)
.addChild(fileSystemRealmDescription)
.addChild(tokenRealmParser)
.addChild(cachingRealmParser)
.build();

RealmParser() {

@@ -674,12 +674,15 @@ elytron.jdbc-realm.principal-query.algorithm=The algorithm for a specific passwo
elytron.jdbc-realm.principal-query.password-index=The column index from an authentication query that represents the user's password.
elytron.jdbc-realm.principal-query.salt-index=The column index from an authentication query that represents the password's salt, if supported.
elytron.jdbc-realm.principal-query.iteration-count-index=The column index from an authentication query that represents the password's iteration count, if supported.
elytron.jdbc-realm.principal-query.hash-encoding=The encoding of the user's password hash.
elytron.jdbc-realm.principal-query.salt-encoding=The encoding of the password's salt.
# Password Mapper Complex Attributes
elytron.jdbc-realm.principal-query.clear-password-mapper=A key mapper that maps a column returned from a SQL query to a Clear Password key type.
elytron.jdbc-realm.principal-query.bcrypt-mapper=A key mapper that maps a column returned from a SQL query to a Bcrypt key type.
elytron.jdbc-realm.principal-query.salted-simple-digest-mapper=A key mapper that maps a column returned from a SQL query to a Salted Simple Digest key type.
elytron.jdbc-realm.principal-query.simple-digest-mapper=A key mapper that maps a column returned from a SQL query to a Simple Digest key type.
elytron.jdbc-realm.principal-query.scram-mapper=A key mapper that maps a column returned from a SQL query to a Scram key type.
elytron.jdbc-realm.principal-query.modular-crypt-mapper=A key mapper that maps a column returned from a SQL query to a Modular Crypt key type.
# Attribute Mapping Attributes
elytron.jdbc-realm.principal-query.attribute-mapping=The attribute mappings defined for this resource.
elytron.jdbc-realm.principal-query.index=The column index from a query that representing the mapped attribute.
@@ -1121,6 +1121,7 @@
<xs:element name="simple-digest-mapper" type="simpleDigestMapperType" minOccurs="0"/>
<xs:element name="salted-simple-digest-mapper" type="saltedSimpleDigestMapperType" minOccurs="0"/>
<xs:element name="scram-mapper" type="scramMapperType" minOccurs="0"/>
<xs:element name="modular-crypt-mapper" type="modularCryptMapperType" minOccurs="0"/>
<xs:element name="attribute-mapping" type="jdbcAttributeMappingType" minOccurs="0"/>
</xs:all>
<xs:attribute name="sql" type="xs:string" use="required">
@@ -1234,6 +1235,32 @@
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="hash-encoding" default="base64">
<xs:annotation>
<xs:documentation>
The encoding of the password hash.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="base64"/>
<xs:enumeration value="hex"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="salt-encoding" default="base64">
<xs:annotation>
<xs:documentation>
The encoding of the password salt.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="base64"/>
<xs:enumeration value="hex"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>

<xs:complexType name="saltedSimpleDigestMapperType">
@@ -1287,6 +1314,32 @@
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="hash-encoding" default="base64">
<xs:annotation>
<xs:documentation>
The encoding of the password hash.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="base64" />
<xs:enumeration value="hex" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="salt-encoding" default="base64">
<xs:annotation>
<xs:documentation>
The encoding of the password salt.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="base64" />
<xs:enumeration value="hex" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>

<xs:complexType name="simpleDigestMapperType">
@@ -1324,6 +1377,19 @@
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="hash-encoding" default="base64">
<xs:annotation>
<xs:documentation>
The encoding of the password hash.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="base64" />
<xs:enumeration value="hex" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>

<xs:complexType name="scramMapperType">
@@ -1383,6 +1449,52 @@
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="hash-encoding" default="base64">
<xs:annotation>
<xs:documentation>
The encoding of the password hash.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="base64" />
<xs:enumeration value="hex" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="salt-encoding" default="base64">
<xs:annotation>
<xs:documentation>
The encoding of the password salt.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="base64" />
<xs:enumeration value="hex" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>

<xs:complexType name="modularCryptMapperType">
<xs:annotation>
<xs:documentation>
A key mapper that maps a column returned from a SQL query to a Modular Crypt key type.
</xs:documentation>
</xs:annotation>
<xs:attribute name="password-index" use="required">
<xs:annotation>
<xs:documentation>
The column index from an authentication query that represents the user password in Modular Crypt Format.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:int">
<xs:minInclusive value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>

<xs:complexType name="keyStoreRealmType">
@@ -16,9 +16,11 @@

package org.wildfly.extension.elytron;

import static org.jboss.as.model.test.FailedOperationTransformationConfig.REJECTED_RESOURCE;
import static org.jboss.as.model.test.ModelTestControllerVersion.EAP_7_1_0;
import static org.jboss.as.model.test.ModelTestControllerVersion.EAP_7_2_0;
import static org.junit.Assert.assertTrue;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.JDBC_REALM;

import java.io.IOException;
import java.util.List;
@@ -111,6 +113,14 @@ public void testRejectingTransformersEAP720() throws Exception {
)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PathElement.pathElement(ElytronDescriptionConstants.SERVER_SSL_SNI_CONTEXT)),
FailedOperationTransformationConfig.REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PathElement.pathElement(JDBC_REALM, "JdbcBcryptHashHex")), REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PathElement.pathElement(JDBC_REALM, "JdbcBcryptSaltHex")), REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PathElement.pathElement(JDBC_REALM, "JdbcSaltedSimpleDigestHashHex")), REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PathElement.pathElement(JDBC_REALM, "JdbcSaltedSimpleDigestSaltHex")), REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PathElement.pathElement(JDBC_REALM, "JdbcSimpleDigestHashHex")), REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PathElement.pathElement(JDBC_REALM, "JdbcScramHashHex")), REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PathElement.pathElement(JDBC_REALM, "JdbcScramSaltHex")), REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PathElement.pathElement(JDBC_REALM, "JdbcModularCrypt")), REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PathElement.pathElement(ElytronDescriptionConstants.TOKEN_REALM, "SslTokenRealm")),
FailedOperationTransformationConfig.REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PathElement.pathElement(ElytronDescriptionConstants.TOKEN_REALM, "KeyMapTokenRealm")),
@@ -48,6 +48,19 @@
<scram-mapper algorithm="scram-sha-512" password-index="1" salt-index="2" iteration-count-index="10000"/>
</principal-query>
</jdbc-realm>
<jdbc-realm name="JdbcRealm">
<principal-query sql="SELECT role, password, salt, ic FROM User WHERE username = ?" data-source="ExampleDS">
<attribute-mapping>
<attribute index="1" to="role"/>
</attribute-mapping>
<clear-password-mapper password-index="2"/>
<bcrypt-mapper password-index="2" salt-index="3" iteration-count-index="4" hash-encoding="hex" salt-encoding="hex"/>
<salted-simple-digest-mapper password-index="2" salt-index="3" algorithm="password-salt-digest-sha-1" hash-encoding="hex" salt-encoding="hex"/>
<simple-digest-mapper password-index="2" hash-encoding="hex" algorithm="simple-digest-sha-1"/>
<scram-mapper password-index="2" salt-index="3" iteration-count-index="4" hash-encoding="hex" salt-encoding="hex" algorithm="scram-sha-1"/>
<modular-crypt-mapper password-index="2"/>
</principal-query>
</jdbc-realm>
<properties-realm name="PropRealm">
<users-properties path="users-hashed.properties" relative-to="jboss.server.config.dir"/>
</properties-realm>
@@ -22,7 +22,7 @@
<mappers>
<simple-permission-mapper name="SimplePermissionMapperLegacy" mapping-mode="and">
<permission-mapping match-all="true">
<permission class-name="a.b.MyPermission" />
<permission class-name="java.security.AllPermission" />
</permission-mapping>
</simple-permission-mapper>
<simple-permission-mapper name="SimplePermissionMapper" mapping-mode="and">
@@ -37,10 +37,10 @@
</mappers>
<permission-sets>
<permission-set name="my-permission">
<permission class-name="a.b.MyPermission" />
<permission class-name="java.io.FilePermission" target-name="/tmp" action="read,write" />
</permission-set>
<permission-set name="user-permissions">
<permission class-name="a.b.UserPermission" />
<permission class-name="java.io.FilePermission" target-name="/home" action="read" />
</permission-set>
</permission-sets>
<policy name="elytron-a">
@@ -16,6 +16,46 @@
<size-rotating-file-audit-log name="audit6" path="target/audit.log" format="JSON" max-backup-index="5" rotate-on-boot="true" rotate-size="5" suffix="y-M-d" synchronized="false" autoflush="true" />
</audit-logging>
<security-realms>
<jdbc-realm name="JdbcBcryptHashHex">
<principal-query sql="SELECT role, password, salt, ic FROM User WHERE username = ?" data-source="ExampleDS">
<bcrypt-mapper password-index="2" salt-index="3" iteration-count-index="4" hash-encoding="hex"/>
</principal-query>
</jdbc-realm>
<jdbc-realm name="JdbcBcryptSaltHex">
<principal-query sql="SELECT role, password, salt, ic FROM User WHERE username = ?" data-source="ExampleDS">
<bcrypt-mapper password-index="2" salt-index="3" iteration-count-index="4" salt-encoding="hex"/>
</principal-query>
</jdbc-realm>
<jdbc-realm name="JdbcSaltedSimpleDigestHashHex">
<principal-query sql="SELECT role, password, salt, ic FROM User WHERE username = ?" data-source="ExampleDS">
<salted-simple-digest-mapper password-index="2" salt-index="3" algorithm="password-salt-digest-sha-1" hash-encoding="hex"/>
</principal-query>
</jdbc-realm>
<jdbc-realm name="JdbcSaltedSimpleDigestSaltHex">
<principal-query sql="SELECT role, password, salt, ic FROM User WHERE username = ?" data-source="ExampleDS">
<salted-simple-digest-mapper password-index="2" salt-index="3" algorithm="password-salt-digest-sha-1" salt-encoding="hex"/>
</principal-query>
</jdbc-realm>
<jdbc-realm name="JdbcSimpleDigestHashHex">
<principal-query sql="SELECT role, password, salt, ic FROM User WHERE username = ?" data-source="ExampleDS">
<simple-digest-mapper password-index="2" hash-encoding="hex" algorithm="simple-digest-sha-1"/>
</principal-query>
</jdbc-realm>
<jdbc-realm name="JdbcScramHashHex">
<principal-query sql="SELECT role, password, salt, ic FROM User WHERE username = ?" data-source="ExampleDS">
<scram-mapper password-index="2" salt-index="3" iteration-count-index="4" hash-encoding="hex" algorithm="scram-sha-1"/>
</principal-query>
</jdbc-realm>
<jdbc-realm name="JdbcScramSaltHex">
<principal-query sql="SELECT role, password, salt, ic FROM User WHERE username = ?" data-source="ExampleDS">
<scram-mapper password-index="2" salt-index="3" iteration-count-index="4" salt-encoding="hex" algorithm="scram-sha-1"/>
</principal-query>
</jdbc-realm>
<jdbc-realm name="JdbcModularCrypt">
<principal-query sql="SELECT role, password, salt, ic FROM User WHERE username = ?" data-source="ExampleDS">
<modular-crypt-mapper password-index="2"/>
</principal-query>
</jdbc-realm>
<token-realm name="SslTokenRealm">
<jwt host-name-verification-policy="ANY" client-ssl-context="ClientContext"/>
</token-realm>
@@ -50,8 +50,13 @@ public LogContext getLogContext() {
}

WildFlyLogContextSelectorImpl(final LogContextSelector defaultLogContextSelector) {
// There is not a way to reset the LogContextSelector after a reload. If the current selector is already a
// WildFlyLogContextSelectorImpl we should use the system default selector. This avoids possibly wrapping the
// same log context several times. It should also work with the embedded CLI selector as the commands handle
// setting and resetting the contexts.
final LogContextSelector dft = (defaultLogContextSelector instanceof WildFlyLogContextSelectorImpl ? LogContext.DEFAULT_LOG_CONTEXT_SELECTOR : defaultLogContextSelector);
counter = new AtomicInteger(0);
contextSelector = new ClassLoaderLogContextSelector(defaultLogContextSelector, true);
contextSelector = new ClassLoaderLogContextSelector(dft, true);
threadLocalContextSelector = new ThreadLocalLogContextSelector(contextSelector);
}

@@ -26,7 +26,7 @@
<parent>
<groupId>org.jboss</groupId>
<artifactId>jboss-parent</artifactId>
<version>29</version>
<version>35</version>
</parent>

<groupId>org.wildfly.core</groupId>
@@ -108,14 +108,11 @@
</surefire.system.args>
<test.level>INFO</test.level>

<!-- use older version of checkstyle as otherwise lots of checks fail -->
<version.checkstyle>6.8</version.checkstyle>

<!-- Non-default maven plugin versions and configuration -->
<version.jacoco.plugin>0.8.0</version.jacoco.plugin>
<version.org.jboss.galleon>4.0.0.Alpha1</version.org.jboss.galleon>
<version.org.wildfly.build-tools>1.2.10.Final</version.org.wildfly.build-tools>
<version.org.wildfly.checkstyle-config>1.0.5.Final</version.org.wildfly.checkstyle-config>
<version.org.wildfly.checkstyle-config>1.0.8.Final</version.org.wildfly.checkstyle-config>
<version.org.wildfly.galleon-plugins>4.0.0.Alpha4</version.org.wildfly.galleon-plugins>
<!-- wildfly plugin-->
<version.org.wildfly.plugin>1.2.1.Final</version.org.wildfly.plugin>
@@ -159,8 +159,7 @@ private static KdcServer createKdcServer(CreateKdcServer createKdcServer, Direct

}

private static Transport createTransport( CreateTransport transportBuilder, int startPort )
{
private static Transport createTransport( CreateTransport transportBuilder, int startPort ) {
String protocol = transportBuilder.protocol();
int port = transportBuilder.port();
int nbThreads = transportBuilder.nbThreads();