Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ELY-2711] Add support for encrypted expressions in the wildfly-config.xml #2084

Draft
wants to merge 9 commits into
base: 2.x
Choose a base branch
from
Draft
2 changes: 1 addition & 1 deletion auth/client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-processor</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,23 @@ public AuthenticationConfiguration usePassword(Password password) {
return password == null ? useCredentials(filtered) : useCredentials(filtered).useCredential(new PasswordCredential(password));
}

// /**
// * Create a new configuration which is the same as this configuration, but which uses the given encrypted
// * password to authenticate. The current encryption client configuration is loaded and is used to decrypt
// * the encrypted password. If one does not exist, appropriate exception is thrown.
// *
// * @param encryptedPassword the password to use
// * @return the new configuration
// */
// public AuthenticationConfiguration decryptAndUsePassword(String encryptedPassword) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is here temporarily and will be uncommented if we decide to add support for programmatic configuration with encrypted expressions.

// EncryptionClientContext ctx = EncryptionClientContext.captureCurrent();
// if (ctx.encryptionClientConfiguration == null) {
// throw new EncryptedExpressionResolutionException("No encryption client configuration available");
// }
// String password = ctx.encryptionClientConfiguration.encryptedExpressionResolver.resolveExpression(encryptedPassword, ctx.encryptionClientConfiguration);
// return usePassword(password == null ? null : ClearPassword.createRaw(ClearPassword.ALGORITHM_CLEAR, password.toCharArray()));
// }

/**
* Create a new configuration which is the same as this configuration, but which uses the given password to authenticate.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@
import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
import static org.wildfly.common.Assert.checkMinimumParameter;
import static org.wildfly.common.Assert.checkNotNullParam;
import static org.wildfly.security.util.XMLParserUtils.isSet;
import static org.wildfly.security.util.XMLParserUtils.setBit;
import static org.wildfly.security.util.XMLParserUtils.checkAttributeNamespace;
import static org.wildfly.security.util.XMLParserUtils.requireNoAttributes;
import static org.wildfly.security.util.XMLParserUtils.requireSingleAttribute;
import static org.wildfly.security.util.XMLParserUtils.requireSingleURIAttribute;
import static org.wildfly.security.util.XMLParserUtils.missingAttribute;
import static org.wildfly.security.util.XMLParserUtils.andThenOp;
import static org.wildfly.security.auth.client._private.ElytronMessages.xmlLog;
import static org.wildfly.security.provider.util.ProviderUtil.INSTALLED_PROVIDERS;
import static org.wildfly.security.provider.util.ProviderUtil.findProvider;
Expand Down Expand Up @@ -74,6 +82,7 @@

import org.ietf.jgss.GSSException;
import org.ietf.jgss.Oid;
import org.jboss.modules.ModuleLoadException;
import org.wildfly.client.config.ClientConfiguration;
import org.wildfly.client.config.ConfigXMLParseException;
import org.wildfly.client.config.ConfigurationXMLStreamReader;
Expand Down Expand Up @@ -105,6 +114,7 @@
import org.wildfly.security.credential.source.impl.LocalKerberosCredentialSource;
import org.wildfly.security.credential.source.OAuth2CredentialSource;
import org.wildfly.security.credential.store.CredentialStore;
import org.wildfly.security.credential.store.CredentialStoreFactory;
import org.wildfly.security.keystore.AliasFilter;
import org.wildfly.security.keystore.FilteringKeyStore;
import org.wildfly.security.keystore.KeyStoreUtil;
Expand All @@ -130,6 +140,7 @@
import org.wildfly.security.ssl.SSLContextBuilder;
import org.wildfly.security.ssl.X509RevocationTrustManager;
import org.wildfly.security.ssh.util.SshUtil;
import org.wildfly.security.util.ModuleLoader;

/**
* A parser for the Elytron XML schema.
Expand Down Expand Up @@ -222,7 +233,7 @@ public static SecurityFactory<AuthenticationContext> parseAuthenticationClientCo
final ClientConfiguration clientConfiguration = ClientConfiguration.getInstance(uri);
if (clientConfiguration != null) try (final ConfigurationXMLStreamReader streamReader = clientConfiguration.readConfiguration(KNOWN_NAMESPACES.keySet())) {
if (streamReader != null) {
xmlLog.tracef("Parsig configuration from %s for namespace %s", streamReader.getUri(), streamReader.getNamespaceURI());
xmlLog.tracef("Parsing configuration from %s for namespace %s", streamReader.getUri(), streamReader.getNamespaceURI());
return parseAuthenticationClientConfiguration(streamReader);
} else {
if (xmlLog.isTraceEnabled()) {
Expand Down Expand Up @@ -1219,7 +1230,12 @@ static void parseAuthenticationConfigurationType(ConfigurationXMLStreamReader re
if (isSet(foundBits, 12)) throw reader.unexpectedElement();
foundBits = setBit(foundBits, 12);
final String moduleName = parseModuleRefType(reader);
final ClassLoader classLoader = (moduleName == null) ? ElytronXmlParser.class.getClassLoader() : ModuleLoader.getClassLoaderFromModule(reader, moduleName);
final ClassLoader classLoader;
try {
classLoader = (moduleName == null) ? ElytronXmlParser.class.getClassLoader() : ModuleLoader.getClassLoaderFromModule(moduleName);
} catch (ModuleLoadException e){
throw xmlLog.xmlNoModuleFound(reader, e, moduleName);
}
configuration = andThenOp(configuration, parentConfig -> parentConfig.useSaslClientFactory(new ServiceLoaderSaslClientFactory(classLoader)));
break;
}
Expand Down Expand Up @@ -1275,9 +1291,14 @@ static Supplier<Provider[]> parseProvidersType(ConfigurationXMLStreamReader read
if (isSet(foundBits, 2)) throw reader.unexpectedElement();
foundBits = setBit(foundBits, 2);
final String moduleName = parseModuleRefType(reader);
Supplier<Provider[]> serviceLoaderSupplier = (moduleName == null) ?
ELYTRON_PROVIDER_SUPPLIER :
new ProviderServiceLoaderSupplier(ModuleLoader.getClassLoaderFromModule(reader, moduleName));
Supplier<Provider[]> serviceLoaderSupplier;
try {
serviceLoaderSupplier = (moduleName == null) ?
ELYTRON_PROVIDER_SUPPLIER :
new ProviderServiceLoaderSupplier(ModuleLoader.getClassLoaderFromModule(moduleName));
} catch (ModuleLoadException e) {
throw xmlLog.xmlNoModuleFound(reader, e, moduleName);
}
providerSupplier = providerSupplier == null ? serviceLoaderSupplier : ProviderUtil.aggregate(providerSupplier, serviceLoaderSupplier);
break;
}
Expand Down Expand Up @@ -1432,18 +1453,6 @@ private static MatchRule parseMatchAbstractType(final MatchRule rule, final Conf
return name == null && authority == null ? rule : rule.matchAbstractType(name, authority);
}

private static boolean isSet(int var, int bit) {
return (var & 1 << bit) != 0;
}

private static int setBit(int var, int bit) {
return var | 1 << bit;
}

private static <T, E extends Exception> ExceptionUnaryOperator<T, E> andThenOp(ExceptionUnaryOperator<T, E> first, ExceptionUnaryOperator<T, E> second) {
return t -> second.apply(first.apply(t));
}

private static ExceptionSupplier<CredentialSource, ConfigXMLParseException> parseCredentialsType(final ConfigurationXMLStreamReader reader, final Version xmlVersion, final Map<String, ExceptionSupplier<KeyStore, ConfigXMLParseException>> keyStoresMap, final Map<String, ExceptionSupplier<CredentialStore, ConfigXMLParseException>> credentialStoresMap, Supplier<Provider[]> providers) throws ConfigXMLParseException {
ExceptionUnaryOperator<CredentialSource, ConfigXMLParseException> function = parent -> CredentialSource.NONE;
requireNoAttributes(reader);
Expand Down Expand Up @@ -2378,7 +2387,8 @@ private static void parseCredentialStoreType(ConfigurationXMLStreamReader reader
}
} else if (tag == END_ELEMENT) {
if (!credentialStoresMap.containsKey(name)) {
ExceptionSupplier<CredentialStore, ConfigXMLParseException> credentialStoreSecurityFactory = new CredentialStoreFactory(name, type, attributesMap, provider, location, credentialSourceSupplier, providersSupplier);
ExceptionSupplier<CredentialStore, ConfigXMLParseException> credentialStoreSecurityFactory;
credentialStoreSecurityFactory = new CredentialStoreFactory(name, type, attributesMap, provider, location, credentialSourceSupplier, providersSupplier);
credentialStoresMap.put(name, credentialStoreSecurityFactory);
} else {
throw xmlLog.duplicateCredentialStoreName(reader, name);
Expand Down Expand Up @@ -2579,7 +2589,12 @@ static ExceptionSupplier<InputStream, IOException> parseResourceType(Configurati
throw reader.unexpectedElement();
} else if (tag == END_ELEMENT) {
final String resourceName = name;
final ClassLoader classLoader = module != null ? ModuleLoader.getClassLoaderFromModule(reader, module) : Thread.currentThread().getContextClassLoader();
final ClassLoader classLoader;
try {
classLoader = module != null ? ModuleLoader.getClassLoaderFromModule(module) : Thread.currentThread().getContextClassLoader();
} catch (ModuleLoadException e) {
throw xmlLog.xmlNoModuleFound(reader, e, module);
}
return () -> {
ClassLoader actualClassLoader = classLoader != null ? classLoader : ElytronXmlParser.class.getClassLoader();
final InputStream stream = actualClassLoader.getResourceAsStream(resourceName);
Expand Down Expand Up @@ -2850,6 +2865,11 @@ static ProtocolSelector parseProtocolSelectorNamesType(ConfigurationXMLStreamRea
return selector;
}


static ConfigXMLParseException invalidPortNumber(final ConfigurationXMLStreamReader reader, final int index) throws ConfigXMLParseException {
return xmlLog.xmlInvalidPortNumber(reader, reader.getAttributeValueResolved(index), reader.getAttributeLocalName(index), reader.getName());
}

/**
* Parse an XML element of type {@code module-ref-type} from an XML reader.
*
Expand Down Expand Up @@ -3499,51 +3519,6 @@ private static void checkElementNamespace(final ConfigurationXMLStreamReader rea
}
}

private static void checkAttributeNamespace(final ConfigurationXMLStreamReader reader, final int idx) throws ConfigXMLParseException {
final String attributeNamespace = reader.getAttributeNamespace(idx);
if (attributeNamespace != null && ! attributeNamespace.isEmpty()) {
throw reader.unexpectedAttribute(idx);
}
}

private static void requireNoAttributes(final ConfigurationXMLStreamReader reader) throws ConfigXMLParseException {
final int attributeCount = reader.getAttributeCount();
if (attributeCount > 0) {
throw reader.unexpectedAttribute(0);
}
}

private static String requireSingleAttribute(final ConfigurationXMLStreamReader reader, final String attributeName) throws ConfigXMLParseException {
return requireSingleAttribute(reader, attributeName, (ExceptionSupplier<String, ConfigXMLParseException>) () -> reader.getAttributeValueResolved(0));
}

private static URI requireSingleURIAttribute(final ConfigurationXMLStreamReader reader, final String attributeName) throws ConfigXMLParseException {
return requireSingleAttribute(reader, attributeName, () -> reader.getURIAttributeValueResolved(0));
}

private static <A> A requireSingleAttribute(final ConfigurationXMLStreamReader reader, final String attributeName, ExceptionSupplier<A, ConfigXMLParseException> attributeFunction) throws ConfigXMLParseException {
final int attributeCount = reader.getAttributeCount();
if (attributeCount < 1) {
throw reader.missingRequiredAttribute("", attributeName);
}
checkAttributeNamespace(reader, 0);
if (! reader.getAttributeLocalName(0).equals(attributeName)) {
throw reader.unexpectedAttribute(0);
}
if (attributeCount > 1) {
throw reader.unexpectedAttribute(1);
}
return attributeFunction.get();
}

private static ConfigXMLParseException missingAttribute(final ConfigurationXMLStreamReader reader, final String name) {
return reader.missingRequiredAttribute(null, name);
}

private static ConfigXMLParseException invalidPortNumber(final ConfigurationXMLStreamReader reader, final int index) throws ConfigXMLParseException {
return xmlLog.xmlInvalidPortNumber(reader, reader.getAttributeValueResolved(index), reader.getAttributeLocalName(index), reader.getName());
}

static final class KeyStoreCreateFactory implements ExceptionSupplier<KeyStore, ConfigXMLParseException> {
private final String providerName;
private final Supplier<Provider[]> providers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.wildfly.security.auth.client;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ public interface ElytronMessages extends BasicLogger {

@Message(id = 1001, value = "No module found for identifier \"%s\"")
ConfigXMLParseException xmlNoModuleFound(@Param XMLStreamReader reader, @Cause Exception e,
String moduleIdentifier);
String moduleIdentifier);

@Message(id = 1002, value = "Invalid port number \"%s\" specified for attribute \"%s\" of element \"%s\"; expected a numerical value between 1 and 65535 (inclusive)")
ConfigXMLParseException xmlInvalidPortNumber(@Param XMLStreamReader reader, String attributeValue,
String attributeName, QName elementName);
String attributeName, QName elementName);

@Message(id = 1028, value = "Invalid port number \"%d\"")
IllegalArgumentException invalidPortNumber(int port);
Expand Down Expand Up @@ -117,7 +117,7 @@ ConfigXMLParseException xmlInvalidPortNumber(@Param XMLStreamReader reader, Stri

@Message(id = 1134, value = "Duplicate authentication configuration name \"%s\"")
ConfigXMLParseException xmlDuplicateAuthenticationConfigurationName(String name,
@Param ConfigurationXMLStreamReader reader);
@Param ConfigurationXMLStreamReader reader);

@Message(id = 1135, value = "Failed to load keystore data")
ConfigXMLParseException xmlFailedToLoadKeyStoreData(@Param Location location, @Cause Throwable cause);
Expand All @@ -127,14 +127,14 @@ ConfigXMLParseException xmlDuplicateAuthenticationConfigurationName(String name,

@Message(id = 1137, value = "Invalid key store entry type for alias \"%s\" (expected %s, got %s)")
ConfigXMLParseException xmlInvalidKeyStoreEntryType(@Param Location location, String alias, Class<?> expectedClass,
Class<?> actualClass);
Class<?> actualClass);

@Message(id = 1139, value = "Failed to create credential store")
ConfigXMLParseException xmlFailedToCreateCredentialStore(@Param Location location, @Cause Throwable cause);

@Message(id = 1140, value = "Wrong PEM content type; expected %s, actually was %s")
ConfigXMLParseException xmlWrongPemType(@Param ConfigurationXMLStreamReader reader, Class<?> expected,
Class<?> actual);
Class<?> actual);

@Message(id = 1141, value = "No PEM content found")
ConfigXMLParseException xmlNoPemContent(@Param ConfigurationXMLStreamReader reader);
Expand All @@ -150,11 +150,11 @@ ConfigXMLParseException xmlWrongPemType(@Param ConfigurationXMLStreamReader read

@Message(id = 1163, value = "Mechanism OID conversion from string \"%s\" failed")
ConfigXMLParseException xmlGssMechanismOidConversionFailed(@Param XMLStreamReader reader, String mechanismOid,
@Cause Throwable cause);
@Cause Throwable cause);

@Message(id = 1164, value = "Unable to identify provider name=%s, for service type=%s, algorithm=%s")
ConfigXMLParseException xmlUnableToIdentifyProvider(@Param Location location, String providerName,
String serviceType, String algorithm);
String serviceType, String algorithm);

@LogMessage(level = WARN)
@Message(id = 1166, value = "%2$s: Element \"%1$s\" is deprecated")
Expand Down Expand Up @@ -213,4 +213,5 @@ ConfigXMLParseException xmlUnableToIdentifyProvider(@Param Location location, St

@Message(id = 14008, value = "WildFlyElytronClientDefaultSSLContextProvider could not obtain client default SSLContext")
NoSuchAlgorithmException couldNotObtainClientDefaultSSLContext();

}
Binary file added auth/client/src/test/resources/mycredstore.cs
Binary file not shown.
4 changes: 4 additions & 0 deletions credential/store/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
<description>WildFly Security Credential Store SPIs and implementaions</description>

<dependencies>
<dependency>
<groupId>org.wildfly.client</groupId>
<artifactId>wildfly-client-config</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-asn1</artifactId>
Expand Down
Loading
Loading