Skip to content

Commit

Permalink
[WFCORE-5101] [Community] SSLContext to support delegation to alterna…
Browse files Browse the repository at this point in the history
…te instancesbased on peer information.
  • Loading branch information
Skyllarr committed Mar 20, 2024
1 parent d7de0dd commit e562b79
Show file tree
Hide file tree
Showing 19 changed files with 430 additions and 10 deletions.
4 changes: 4 additions & 0 deletions core-feature-pack/common/pom.xml
Expand Up @@ -322,6 +322,10 @@
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-digest</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-dynamic-ssl</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-encryption</artifactId>
Expand Down
Expand Up @@ -34,6 +34,7 @@
<artifact name="${org.wildfly.security:wildfly-elytron-credential-source-impl}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-credential-store}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-digest}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-dynamic-ssl}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-encryption}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http}"/>
<artifact name="${org.wildfly.security:wildfly-elytron-http-basic}"/>
Expand Down
5 changes: 5 additions & 0 deletions elytron/pom.xml
Expand Up @@ -64,6 +64,11 @@
<artifactId>wildfly-elytron-auth</artifactId>
</dependency>

<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-dynamic-ssl</artifactId>
</dependency>

<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-realm-jdbc</artifactId>
Expand Down
Expand Up @@ -15,6 +15,7 @@
import static org.wildfly.extension.elytron.Capabilities.SECURITY_DOMAIN_CAPABILITY;
import static org.wildfly.extension.elytron.Capabilities.SECURITY_FACTORY_CREDENTIAL_CAPABILITY;
import static org.wildfly.extension.elytron.Capabilities.SSL_CONTEXT_CAPABILITY;
import static org.wildfly.extension.elytron.ElytronDefinition.commonRequirements;
import static org.wildfly.extension.elytron._private.ElytronSubsystemMessages.ROOT_LOGGER;

import java.util.HashMap;
Expand Down Expand Up @@ -42,6 +43,8 @@
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceTarget;
import org.jboss.msc.value.InjectedValue;
import org.wildfly.common.function.ExceptionSupplier;
import org.wildfly.extension.elytron.TrivialService.ValueSupplier;
Expand Down Expand Up @@ -491,6 +494,17 @@ protected ValueSupplier<AuthenticationContext> getValueSupplier(ServiceBuilder<A
return () -> finalContext.apply(parentSupplier.get());
}

@Override
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
commonRequirements(installService(context, model)).setInitialMode(ServiceController.Mode.ON_DEMAND).install();
}

ServiceBuilder<AuthenticationContext> installService(OperationContext context, ModelNode model) throws OperationFailedException {
ServiceTarget serviceTarget = context.getCapabilityServiceTarget();
ServiceBuilder<?> serviceBuilder = context.getCapabilityServiceTarget().addCapability(AUTHENTICATION_CONTEXT_RUNTIME_CAPABILITY);
TrivialService<AuthenticationContext> authenticationContextTrivialService = new TrivialService<AuthenticationContext>(getValueSupplier((ServiceBuilder<AuthenticationContext>) serviceBuilder, context, model));
return serviceTarget.addService(AUTHENTICATION_CONTEXT_RUNTIME_CAPABILITY.getCapabilityServiceName(context.getCurrentAddressValue()), authenticationContextTrivialService);
}
};

return new TrivialResourceDefinition(ElytronDescriptionConstants.AUTHENTICATION_CONTEXT, add, attributes,
Expand Down
Expand Up @@ -294,6 +294,7 @@ public void registerChildren(ManagementResourceRegistration resourceRegistration
resourceRegistration.registerSubModel(SSLDefinitions.getServerSNISSLContextDefinition());
resourceRegistration.registerSubModel(new CertificateAuthorityDefinition());
resourceRegistration.registerSubModel(new CertificateAuthorityAccountDefinition());
resourceRegistration.registerSubModel(SSLDefinitions.getDynamicClientSSLContextDefinition());

// Credential Store Block
resourceRegistration.registerSubModel(new CredentialStoreResourceDefinition());
Expand Down
Expand Up @@ -173,6 +173,8 @@ interface ElytronDescriptionConstants {
String DISTINGUISHED_NAME = "distinguished-name";
String DISTRIBUTED_REALM = "distributed-realm";
String DOMAIN_NAMES = "domain-names";
String DYNAMIC_CLIENT_SSL_CONTEXT = "dynamic-client-ssl-context";
String DYNAMIC_CLIENT_SSL_CONTEXTS = "dynamic-client-ssl-contexts";

String ELYTRON_SECURITY = "elytron-security";
String ENABLE_CONNECTION_POOLING = "enable-connection-pooling";
Expand Down
Expand Up @@ -26,6 +26,7 @@
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.PERMISSION_SETS;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.SECURITY_PROPERTY;
import static org.wildfly.extension.elytron.PermissionMapperDefinitions.PERMISSIONS;
import static org.wildfly.extension.elytron.SSLDefinitions.getDynamicClientSSLContextDefinition;

/**
* Enumeration of elytron subsystem schema versions.
Expand Down Expand Up @@ -191,7 +192,9 @@ private void addCredentialStoreParser(PersistentResourceXMLDescription.Persisten

private void addTlsParser(PersistentResourceXMLDescription.PersistentResourceXMLBuilder builder) {
TlsParser tlsParser = new TlsParser();
if (this.since(ElytronSubsystemSchema.VERSION_14_0)) {
if (this.since(ElytronSubsystemSchema.VERSION_18_0_COMMUNITY) && this.enables(getDynamicClientSSLContextDefinition())) {
builder.addChild(tlsParser.tlsParserCommunity_18_0);
} else if (this.since(ElytronSubsystemSchema.VERSION_14_0)) {
builder.addChild(tlsParser.tlsParser_14_0);
} else if (this.since(ElytronSubsystemSchema.VERSION_12_0)) {
builder.addChild(tlsParser.tlsParser_12_0);
Expand Down
Expand Up @@ -170,6 +170,8 @@ private static void from18(ChainedTransformationDescriptionBuilder chainedBuilde
.setDiscard(DiscardAttributeChecker.UNDEFINED, EMIT_EVENTS)
.addRejectCheck(new RejectAttributeChecker.SimpleRejectAttributeChecker(ModelNode.TRUE), IGNORE_UNAVAILABLE_REALMS)
.addRejectCheck(RejectAttributeChecker.DEFINED, EMIT_EVENTS);
builder.rejectChildResource(PathElement.pathElement(ElytronDescriptionConstants.DYNAMIC_CLIENT_SSL_CONTEXTS));
builder.rejectChildResource(PathElement.pathElement(ElytronDescriptionConstants.DYNAMIC_CLIENT_SSL_CONTEXT));
}

private static void from17(ChainedTransformationDescriptionBuilder chainedBuilder) {
Expand Down
Expand Up @@ -21,6 +21,7 @@
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceController.State;
import org.wildfly.common.iteration.ByteIterator;
import org.wildfly.security.dynamic.ssl.DynamicSSLContext;

/**
* A {@link Resource} to represent a server-ssl-context/client-ssl-context, the majority is actually model
Expand Down Expand Up @@ -129,6 +130,9 @@ public Resource clone() {
*/
private boolean hasActiveSessions() {
final SSLContext sslContext = getSSLContext(sslContextServiceController);
if (sslContext instanceof DynamicSSLContext) {
return false;
}
if (sslContext == null) return false;
SSLSessionContext sslSessionContext = server ? sslContext.getServerSessionContext() : sslContext.getClientSessionContext();
return sslSessionContext.getIds().hasMoreElements();
Expand Down
Expand Up @@ -8,6 +8,7 @@
import static org.jboss.as.controller.capability.RuntimeCapability.buildDynamicCapabilityName;
import static org.jboss.as.controller.security.CredentialReference.handleCredentialReferenceUpdate;
import static org.jboss.as.controller.security.CredentialReference.rollbackCredentialStoreUpdate;
import static org.wildfly.extension.elytron.Capabilities.AUTHENTICATION_CONTEXT_CAPABILITY;
import static org.wildfly.extension.elytron.Capabilities.KEY_MANAGER_CAPABILITY;
import static org.wildfly.extension.elytron.Capabilities.KEY_MANAGER_RUNTIME_CAPABILITY;
import static org.wildfly.extension.elytron.Capabilities.KEY_STORE_CAPABILITY;
Expand Down Expand Up @@ -56,6 +57,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

Expand Down Expand Up @@ -98,6 +100,7 @@
import org.jboss.as.controller.security.CredentialReference;
import org.jboss.as.controller.services.path.PathManager;
import org.jboss.as.controller.services.path.PathManagerService;
import org.jboss.as.version.Stability;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
import org.jboss.msc.service.ServiceBuilder;
Expand All @@ -112,12 +115,16 @@
import org.wildfly.extension.elytron.TrivialService.ValueSupplier;
import org.wildfly.extension.elytron._private.ElytronSubsystemMessages;
import org.wildfly.extension.elytron.capabilities.PrincipalTransformer;
import org.wildfly.security.auth.client.AuthenticationContext;
import org.wildfly.security.dynamic.ssl.DynamicSSLContextImpl;
import org.wildfly.security.auth.server.MechanismConfiguration;
import org.wildfly.security.auth.server.MechanismConfigurationSelector;
import org.wildfly.security.auth.server.RealmMapper;
import org.wildfly.security.auth.server.SecurityDomain;
import org.wildfly.security.credential.PasswordCredential;
import org.wildfly.security.credential.source.CredentialSource;
import org.wildfly.security.dynamic.ssl.DynamicSSLContext;
import org.wildfly.security.dynamic.ssl.DynamicSSLContextException;
import org.wildfly.security.keystore.AliasFilter;
import org.wildfly.security.keystore.FilteringKeyStore;
import org.wildfly.security.password.interfaces.ClearPassword;
Expand Down Expand Up @@ -147,6 +154,13 @@ class SSLDefinitions {
.setRestartAllServices()
.build();

static final SimpleAttributeDefinition AUTHENTICATION_CONTEXT_ATTRIBUTE = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.AUTHENTICATION_CONTEXT, ModelType.STRING, false)
.setMinSize(1)
.setRequired(true)
.setCapabilityReference(AUTHENTICATION_CONTEXT_CAPABILITY, SSL_CONTEXT_CAPABILITY)
.setRestartAllServices()
.build();

static final SimpleAttributeDefinition PROVIDER_NAME = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.PROVIDER_NAME, ModelType.STRING, true)
.setAllowExpression(true)
.setMinSize(1)
Expand Down Expand Up @@ -1208,11 +1222,17 @@ public X509Certificate[] getAcceptedIssuers() {
}

private static ResourceDefinition createSSLContextDefinition(String pathKey, boolean server, AbstractAddStepHandler addHandler, AttributeDefinition[] attributes, boolean serverOrHostController) {
return createSSLContextDefinition(pathKey, server, addHandler, attributes, serverOrHostController, Stability.DEFAULT);
}

private static ResourceDefinition createSSLContextDefinition(String pathKey, boolean server, AbstractAddStepHandler addHandler, AttributeDefinition[] attributes, boolean serverOrHostController, Stability stability) {

Builder builder = TrivialResourceDefinition.builder()
.setPathKey(pathKey)
.setAddHandler(addHandler)
.setAttributes(attributes)
.setRuntimeCapabilities(SSL_CONTEXT_RUNTIME_CAPABILITY);
.setRuntimeCapabilities(SSL_CONTEXT_RUNTIME_CAPABILITY)
.setStability(stability);

if (serverOrHostController) {
builder.addReadOnlyAttribute(ACTIVE_SESSION_COUNT, new SSLContextRuntimeHandler() {
Expand Down Expand Up @@ -1511,6 +1531,42 @@ protected void installedForResource(ServiceController<SSLContext> serviceControl
return createSSLContextDefinition(ElytronDescriptionConstants.CLIENT_SSL_CONTEXT, false, add, attributes, serverOrHostController);
}

static ResourceDefinition getDynamicClientSSLContextDefinition() {

AttributeDefinition[] attributes = new AttributeDefinition[]{AUTHENTICATION_CONTEXT_ATTRIBUTE};
AbstractAddStepHandler add = new TrivialAddHandler<SSLContext>(SSLContext.class, attributes, SSL_CONTEXT_RUNTIME_CAPABILITY) {
@Override
protected ValueSupplier<SSLContext> getValueSupplier(ServiceBuilder<SSLContext> serviceBuilder, OperationContext context, ModelNode model) throws OperationFailedException {
final String authenticationContextName = AUTHENTICATION_CONTEXT_ATTRIBUTE.resolveModelAttribute(context, model).asString();
String authenticationContextCapability = buildDynamicCapabilityName(AUTHENTICATION_CONTEXT_CAPABILITY, authenticationContextName);
ServiceName acServiceName = context.getCapabilityServiceName(authenticationContextCapability, AuthenticationContext.class);
Supplier<AuthenticationContext> authenticationContextSupplier = serviceBuilder.requires(acServiceName);

return () -> {
try {
return new DynamicSSLContext(new DynamicSSLContextImpl(authenticationContextSupplier.get()));
} catch (DynamicSSLContextException | GeneralSecurityException e) {
throw new RuntimeException(e);
}
};
}

@Override
protected Resource createResource(OperationContext context) {
SSLContextResource resource = new SSLContextResource(Resource.Factory.create(), false);
context.addResource(PathAddress.EMPTY_ADDRESS, resource);
return resource;
}

@Override
protected void installedForResource(ServiceController<SSLContext> serviceController, Resource resource) {
((SSLContextResource) resource).setSSLContextServiceController(serviceController);
}
};

return createSSLContextDefinition(ElytronDescriptionConstants.DYNAMIC_CLIENT_SSL_CONTEXT, false, add, attributes, false, Stability.COMMUNITY);
}

private static Provider[] filterProviders(Provider[] all, String provider) {
if (provider == null || all == null) return all;
List<Provider> list = new ArrayList<>();
Expand Down
22 changes: 22 additions & 0 deletions elytron/src/main/java/org/wildfly/extension/elytron/TlsParser.java
Expand Up @@ -13,6 +13,8 @@
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.CERTIFICATE_AUTHORITY_ACCOUNTS;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.CLIENT_SSL_CONTEXT;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.CLIENT_SSL_CONTEXTS;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.DYNAMIC_CLIENT_SSL_CONTEXT;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.DYNAMIC_CLIENT_SSL_CONTEXTS;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.FILTERING_KEY_STORE;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.HOST;
import static org.wildfly.extension.elytron.ElytronDescriptionConstants.SNI_MAPPING;
Expand Down Expand Up @@ -195,6 +197,10 @@ class TlsParser {
.addAttribute(SSLDefinitions.PROVIDERS)
.addAttribute(SSLDefinitions.PROVIDER_NAME);

private PersistentResourceXMLBuilder dynamicClientSslContextParser = PersistentResourceXMLDescription.builder(PathElement.pathElement(DYNAMIC_CLIENT_SSL_CONTEXT))
.setXmlWrapperElement(DYNAMIC_CLIENT_SSL_CONTEXTS)
.addAttribute(SSLDefinitions.AUTHENTICATION_CONTEXT_ATTRIBUTE);

private PersistentResourceXMLBuilder certificateAuthorityParser = PersistentResourceXMLDescription.builder(PathElement.pathElement(CERTIFICATE_AUTHORITY))
.setXmlWrapperElement(CERTIFICATE_AUTHORITIES)
.addAttribute(CertificateAuthorityDefinition.URL)
Expand Down Expand Up @@ -349,4 +355,20 @@ public void marshallSingleElement(AttributeDefinition attribute, ModelNode mappi
.addChild(certificateAuthorityAccountParser)
.addChild(serverSslSniContextParser)
.build();

final PersistentResourceXMLDescription tlsParserCommunity_18_0 = decorator(TLS)
.addChild(decorator(KEY_STORES)
.addChild(keyStoreParser)
.addChild(ldapKeyStoreParser)
.addChild(filteringKeyStoreParser)
)
.addChild(keyManagerParser_12_0)
.addChild(trustManagerParser_14_0)
.addChild(serverSslContextParser_9_0)
.addChild(clientSslContextParser_9_0)
.addChild(certificateAuthorityParser)
.addChild(certificateAuthorityAccountParser)
.addChild(serverSslSniContextParser)
.addChild(dynamicClientSslContextParser) // new
.build();
}

0 comments on commit e562b79

Please sign in to comment.