diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/AcmeAccountService.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/AcmeAccountService.java index c5ef158..d686c50 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/AcmeAccountService.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/AcmeAccountService.java @@ -25,15 +25,16 @@ import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.util.List; -import java.util.function.Supplier; import org.jboss.as.controller.OperationContext; import org.jboss.as.controller.OperationFailedException; -import org.jboss.msc.Service; +import org.jboss.msc.inject.Injector; +import org.jboss.msc.service.Service; import org.jboss.msc.service.ServiceRegistry; import org.jboss.msc.service.StartContext; import org.jboss.msc.service.StartException; import org.jboss.msc.service.StopContext; +import org.jboss.msc.value.InjectedValue; import org.wildfly.common.function.ExceptionSupplier; import org.wildfly.security.credential.source.CredentialSource; import org.wildfly.security.x500.cert.acme.AcmeAccount; @@ -44,10 +45,10 @@ * * @author Farah Juma */ -class AcmeAccountService implements Service { +class AcmeAccountService implements Service { - private Supplier keyStoreSupplier; - private ExceptionSupplier credentialSourceSupplier; + private final InjectedValue keyStoreInjector = new InjectedValue<>(); + private final InjectedValue> credentialSourceSupplierInjector = new InjectedValue<>(); private final String certificateAuthorityName; private final List contactUrlsList; private final String alias; @@ -67,7 +68,7 @@ public void start(StartContext startContext) throws StartException { final ServiceRegistry serviceRegistry = startContext.getController().getServiceContainer(); final ModifiableKeyStoreService keyStoreService = CertificateAuthorityAccountDefinition.getModifiableKeyStoreService(serviceRegistry, keyStoreName); char[] keyPassword = resolveKeyPassword((KeyStoreService) keyStoreService); - KeyStore keyStore = keyStoreSupplier.get(); + KeyStore keyStore = keyStoreInjector.getValue(); CertificateAuthority certificateAuthority; if (certificateAuthorityName.equalsIgnoreCase(CertificateAuthority.LETS_ENCRYPT.getName())) { certificateAuthority = CertificateAuthority.LETS_ENCRYPT; @@ -112,21 +113,22 @@ public void stop(StopContext stopContext) { acmeAccount = null; } + @Override public AcmeAccount getValue() throws IllegalStateException, IllegalArgumentException { return acmeAccount; } - void setKeyStoreSupplier(Supplier keyStoreSupplier) { - this.keyStoreSupplier = keyStoreSupplier; + Injector getKeyStoreInjector() { + return keyStoreInjector; } - void setCredentialSourceSupplier(ExceptionSupplier credentialSourceSupplier) { - this.credentialSourceSupplier = credentialSourceSupplier; + Injector> getCredentialSourceSupplierInjector() { + return credentialSourceSupplierInjector; } char[] resolveKeyPassword(KeyStoreService keyStoreService) throws RuntimeException { try { - return keyStoreService.resolveKeyPassword(credentialSourceSupplier); + return keyStoreService.resolveKeyPassword(credentialSourceSupplierInjector.getOptionalValue()); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/AggregateComponentService.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/AggregateComponentService.java index 4277865..a72026b 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/AggregateComponentService.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/AggregateComponentService.java @@ -25,6 +25,7 @@ import org.jboss.msc.inject.Injector; import org.jboss.msc.service.Service; import org.jboss.msc.service.StartContext; +import org.jboss.msc.service.StartException; import org.jboss.msc.service.StopContext; import org.jboss.msc.value.InjectedValue; @@ -38,7 +39,7 @@ class AggregateComponentService implements Service { private final Class aggregationType; private final Function aggregator; - private List> injections = new ArrayList<>(); + private List> injections = new ArrayList>(); private T aggregation; @@ -52,7 +53,7 @@ class AggregateComponentService implements Service { */ @SuppressWarnings("unchecked") @Override - public void start(StartContext context) { + public void start(StartContext context) throws StartException { ArrayList toAggregate = new ArrayList<>(injections.size()); for (InjectedValue current : injections) { toAggregate.add(current.getValue()); diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthorityAccountDefinition.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthorityAccountDefinition.java index 7606d3e..2bdb468 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthorityAccountDefinition.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthorityAccountDefinition.java @@ -27,11 +27,11 @@ import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.CERTIFICATE_AUTHORITY_RUNTIME_CAPABILITY; import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.KEY_STORE_CAPABILITY; import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.KEY_STORE_RUNTIME_CAPABILITY; +import static org.wildfly.extension.elytron.tls.subsystem.ElytronTlsExtension.getRequiredService; +import static org.wildfly.extension.elytron.tls.subsystem.ElytronTlsExtension.isServerOrHostController; import static org.wildfly.extension.elytron.tls.subsystem.ElytronTlsSubsystemDefinition.commonRequirements; import static org.wildfly.extension.elytron.tls.subsystem.FileAttributeDefinitions.PATH; import static org.wildfly.extension.elytron.tls.subsystem.FileAttributeDefinitions.RELATIVE_TO; -import static org.wildfly.extension.elytron.tls.subsystem.ElytronTlsExtension.getRequiredService; -import static org.wildfly.extension.elytron.tls.subsystem.ElytronTlsExtension.isServerOrHostController; import static org.wildfly.extension.elytron.tls.subsystem._private.ElytronTLSLogger.LOGGER; import java.security.KeyStore; @@ -60,7 +60,6 @@ import org.jboss.as.controller.registry.OperationEntry; import org.jboss.as.controller.registry.Resource; import org.jboss.as.controller.security.CredentialReference; -import org.jboss.as.domain.http.server.ConsoleAvailabilityService.LogAdminConsole; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.jboss.msc.service.ServiceBuilder; @@ -228,19 +227,16 @@ protected void performRuntime(OperationContext context, ModelNode operation, Res ServiceTarget serviceTarget = context.getServiceTarget(); RuntimeCapability certificateAuthorityAccountRuntimeCapability = CERTIFICATE_AUTHORITY_ACCOUNT_RUNTIME_CAPABILITY.fromBaseCapability(context.getCurrentAddressValue()); ServiceName acmeAccountServiceName = certificateAuthorityAccountRuntimeCapability.getCapabilityServiceName(AcmeAccount.class); - ServiceBuilder acmeAccountServiceBuilder = (ServiceBuilder) serviceTarget.addService(acmeAccountServiceName).setInitialMode(ServiceController.Mode.ACTIVE); - - acmeAccountService.setCredentialSourceSupplier(credentialSourceSupplier); + ServiceBuilder acmeAccountServiceBuilder = serviceTarget.addService(acmeAccountServiceName, acmeAccountService).setInitialMode(ServiceController.Mode.ACTIVE); + acmeAccountService.getCredentialSourceSupplierInjector().inject(credentialSourceSupplier); - String keyStoreCapabilityName = RuntimeCapability.buildDynamicCapabilityName(KEY_STORE_CAPABILITY, finalKeyStoreName); - ServiceName keyStoreServiceName = context.getCapabilityServiceName(keyStoreCapabilityName, KeyStore.class); - acmeAccountService.setKeyStoreSupplier(acmeAccountServiceBuilder.requires(keyStoreServiceName)); - + String keyStoreCapabilityName = RuntimeCapability.buildDynamicCapabilityName(KEY_STORE_CAPABILITY, keyStoreName); + acmeAccountServiceBuilder.addDependency(context.getCapabilityServiceName(keyStoreCapabilityName, KeyStore.class), KeyStore.class, acmeAccountService.getKeyStoreInjector()); if (certificateAuthorityName.equalsIgnoreCase(CertificateAuthority.LETS_ENCRYPT.getName())) { - commonRequirements(acmeAccountServiceBuilder, true, true).install(); + commonRequirements(acmeAccountServiceBuilder).install(); } else { acmeAccountServiceBuilder.requires(CERTIFICATE_AUTHORITY_RUNTIME_CAPABILITY.getCapabilityServiceName(certificateAuthorityName)); - commonRequirements(acmeAccountServiceBuilder, true, true).install(); + commonRequirements(acmeAccountServiceBuilder).install(); } } diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthorityDefinition.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthorityDefinition.java index 704c9c6..5c20fcf 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthorityDefinition.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthorityDefinition.java @@ -18,6 +18,14 @@ package org.wildfly.extension.elytron.tls.subsystem; +import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.CERTIFICATE_AUTHORITY_RUNTIME_CAPABILITY; +import static org.wildfly.extension.elytron.tls.subsystem.ElytronTlsExtension.getRequiredService; +import static org.wildfly.extension.elytron.tls.subsystem.ElytronTlsSubsystemDefinition.commonRequirements; +import static org.wildfly.extension.elytron.tls.subsystem._private.ElytronTLSLogger.LOGGER; + +import java.net.MalformedURLException; +import java.net.URL; + import org.jboss.as.controller.AbstractAddStepHandler; import org.jboss.as.controller.AttributeDefinition; import org.jboss.as.controller.OperationContext; @@ -34,21 +42,14 @@ import org.jboss.as.controller.registry.OperationEntry; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; +import org.jboss.msc.service.Service; import org.jboss.msc.service.ServiceBuilder; import org.jboss.msc.service.ServiceController; +import org.jboss.msc.service.ServiceController.Mode; import org.jboss.msc.service.ServiceName; import org.jboss.msc.service.ServiceRegistry; import org.jboss.msc.service.ServiceTarget; import org.wildfly.security.x500.cert.acme.CertificateAuthority; -import org.jboss.msc.service.ServiceController.Mode; - -import java.net.MalformedURLException; -import java.net.URL; - -import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.CERTIFICATE_AUTHORITY_RUNTIME_CAPABILITY; -import static org.wildfly.extension.elytron.tls.subsystem.ElytronTlsSubsystemDefinition.commonRequirements; -import static org.wildfly.extension.elytron.tls.subsystem.ElytronTlsExtension.getRequiredService; -import static org.wildfly.extension.elytron.tls.subsystem._private.ElytronTLSLogger.LOGGER; /** * A {@link ResourceDefinition} for a single certificate authority. @@ -124,7 +125,7 @@ protected void performRuntime(OperationContext context, ModelNode operation, Mod if (certificateAuthorityName.equalsIgnoreCase(CertificateAuthority.LETS_ENCRYPT.getName())) { throw LOGGER.letsEncryptNameNotAllowed(); } - commonRequirements(installService(context, model), true, true).setInitialMode(Mode.ACTIVE).install(); + commonRequirements(installService(context, model)).setInitialMode(Mode.ACTIVE).install(); } ServiceBuilder installService(OperationContext context, ModelNode model) { @@ -143,7 +144,7 @@ protected TrivialService.ValueSupplier getValueSupplier(Op } } - static org.jboss.msc.service.Service getCertificateAuthorityService(ServiceRegistry serviceRegistry, String certificateAuthorityName) { + static Service getCertificateAuthorityService(ServiceRegistry serviceRegistry, String certificateAuthorityName) { RuntimeCapability runtimeCapability = CERTIFICATE_AUTHORITY_RUNTIME_CAPABILITY.fromBaseCapability(certificateAuthorityName); ServiceName serviceName = runtimeCapability.getCapabilityServiceName(); ServiceController serviceContainer = getRequiredService(serviceRegistry, serviceName, CertificateAuthority.class); diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CredentialStoreResourceDefinition.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CredentialStoreResourceDefinition.java index 9202be7..bb403a6 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CredentialStoreResourceDefinition.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/CredentialStoreResourceDefinition.java @@ -18,7 +18,6 @@ package org.wildfly.extension.elytron.tls.subsystem; -import static org.jboss.as.controller.AbstractControllerService.PATH_MANAGER_CAPABILITY; import static org.jboss.as.controller.security.CredentialReference.getCredentialSource; import static org.jboss.as.controller.security.CredentialReference.handleCredentialReferenceUpdate; import static org.jboss.as.controller.security.CredentialReference.rollbackCredentialStoreUpdate; @@ -70,6 +69,7 @@ import org.jboss.as.controller.registry.OperationEntry; import org.jboss.as.controller.registry.Resource; import org.jboss.as.controller.security.CredentialReference; +import org.jboss.as.controller.services.path.PathManagerService; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.jboss.msc.service.ServiceName; @@ -455,11 +455,12 @@ protected void resolveRuntime(ModelNode model, OperationContext context) throws protected ExceptionSupplier prepareServiceSupplier(OperationContext context, CapabilityServiceBuilder serviceBuilder) throws OperationFailedException { + final Supplier pathManager; if (relativeTo != null) { - pathManagerSupplier = serviceBuilder.requires(PATH_MANAGER_CAPABILITY.getCapabilityServiceName()); + pathManager = serviceBuilder.requires(PathManagerService.SERVICE_NAME); serviceBuilder.requires(pathName(relativeTo)); } else { - pathManagerSupplier = null; + pathManager = null; } final Supplier providerSupplier; @@ -498,7 +499,7 @@ public CredentialStore get() throws StartException { PathResolver pathResolver = pathResolver(); pathResolver.path(location); if (relativeTo != null) { - pathResolver.relativeTo(relativeTo, pathManagerSupplier.get()); + pathResolver.relativeTo(relativeTo, pathManager.get()); } File resolved = pathResolver.resolve(); pathResolver.clear(); diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/DefaultSSLContextService.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/DefaultSSLContextService.java index e404c8a..b86e8d0 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/DefaultSSLContextService.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/DefaultSSLContextService.java @@ -16,8 +16,11 @@ package org.wildfly.extension.elytron.tls.subsystem; +import static org.wildfly.extension.elytron.tls.subsystem.ElytronTlsSubsystemDefinition.RESTORE_DEFAULT_SSL_CONTEXT; import static org.wildfly.extension.elytron.tls.subsystem.SecurityActions.doPrivileged; +import static org.wildfly.extension.elytron.tls.subsystem._private.ElytronTLSLogger.LOGGER; +import java.security.NoSuchAlgorithmException; import java.security.PrivilegedAction; import java.util.function.Consumer; import java.util.function.Supplier; @@ -30,7 +33,6 @@ import org.jboss.msc.service.StartException; import org.jboss.msc.service.StopContext; - /** * A simple {@link Service} to take an {@link SSLContext} and register it as the process wide default. * @@ -40,7 +42,7 @@ class DefaultSSLContextService implements Service { static final ServiceName SERVICE_NAME = ElytronTlsExtension.BASE_SERVICE_NAME.append(Constants.SSL_CONTEXT_REGISTRATION); - //private static final boolean RESTORE_SSL_CONTEXT = doPrivileged((PrivilegedAction) () -> Boolean.getBoolean(RESTORE_DEFAULT_SSL_CONTEXT)); + private static final boolean RESTORE_SSL_CONTEXT = doPrivileged((PrivilegedAction) () -> Boolean.getBoolean(RESTORE_DEFAULT_SSL_CONTEXT)); private final Supplier defaultSSLContextSupplier; private final Consumer valueConsumer; @@ -64,7 +66,6 @@ public void start(StartContext context) throws StartException { public void stop(StopContext context) { // We can't set the default back to 'null' as that would cause a NullPointerException. // For the purpose of testing we may want to restore the default. - /* if (RESTORE_SSL_CONTEXT) { try { final SSLContext defaultSSLContext = SSLContext.getInstance("Default"); @@ -75,7 +76,7 @@ public void stop(StopContext context) { } catch (NoSuchAlgorithmException e) { LOGGER.debug(e); } - }*/ + } } } diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronDoohickey.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronDoohickey.java index 9d59a1a..99522c9 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronDoohickey.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronDoohickey.java @@ -26,7 +26,6 @@ import java.util.Iterator; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Supplier; import org.jboss.as.controller.CapabilityServiceBuilder; import org.jboss.as.controller.OperationContext; @@ -48,9 +47,12 @@ */ abstract class ElytronDoohickey implements ExceptionFunction { - private static final Supplier> CALL_STACK_SUPPLIER = ArrayDeque::new; - - private static final ThreadLocal> CALL_STACK = ThreadLocal.withInitial(CALL_STACK_SUPPLIER); + private static final ThreadLocal> CALL_STACK = new ThreadLocal() { + @Override + protected Deque initialValue() { + return new ArrayDeque<>(); + } + }; /* * As each Thread tracks the addresses of the relevent resources we could likely implement some form of @@ -63,7 +65,6 @@ abstract class ElytronDoohickey implements ExceptionFunction serviceValueSupplier; - protected volatile Supplier pathManagerSupplier; private volatile T value; @@ -164,9 +165,8 @@ protected File resolveRelativeToImmediately(String path, String relativeTo, Oper PathResolver pathResolver = pathResolver(); pathResolver.path(path); if (relativeTo != null) { -// PathManager pathManager = (PathManager) foreignContext.getServiceRegistry(false) -// .getRequiredService(PATH_MANAGER_CAPABILITY.getCapabilityServiceName()).getValue(); - PathManager pathManager = pathManagerSupplier.get(); + PathManager pathManager = (PathManager) foreignContext.getServiceRegistry(false) + .getRequiredService(PathManagerService.SERVICE_NAME).getValue(); pathResolver.relativeTo(relativeTo, pathManager); } File resolved = pathResolver.resolve(); diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystemDefinition.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystemDefinition.java index 943bb8c..12bac9f 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystemDefinition.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystemDefinition.java @@ -17,11 +17,10 @@ package org.wildfly.extension.elytron.tls.subsystem; import static org.jboss.as.controller.OperationContext.Stage.RUNTIME; -import static org.jboss.as.server.deployment.Phase.DEPENDENCIES; -import static org.jboss.as.server.deployment.Phase.STRUCTURE; -import static org.jboss.as.server.deployment.Phase.STRUCTURE_ELYTRON_EXPRESSION_RESOLVER; import static org.jboss.as.server.deployment.Phase.CONFIGURE_DEFAULT_SSL_CONTEXT; import static org.jboss.as.server.deployment.Phase.CONFIGURE_MODULE; +import static org.jboss.as.server.deployment.Phase.DEPENDENCIES; +import static org.jboss.as.server.deployment.Phase.STRUCTURE; import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.ELYTRON_TLS_RUNTIME_CAPABILITY; import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.PROVIDERS_CAPABILITY; import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.SSL_CONTEXT_CAPABILITY; @@ -44,6 +43,7 @@ import org.jboss.as.controller.AttributeMarshaller; import org.jboss.as.controller.AttributeParser; import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationContext.AttachmentKey; import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.OperationStepHandler; import org.jboss.as.controller.PersistentResourceDefinition; @@ -61,7 +61,7 @@ import org.jboss.as.server.DeploymentProcessorTarget; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; -import org.jboss.msc.Service; +import org.jboss.msc.service.Service; import org.jboss.msc.service.ServiceBuilder; import org.jboss.msc.service.ServiceController; import org.jboss.msc.service.ServiceController.Mode; @@ -71,17 +71,27 @@ import org.wildfly.extension.elytron.tls.subsystem._private.ElytronTLSLogger; import org.wildfly.extension.elytron.tls.subsystem.deployment.DependencyProcessor; import org.wildfly.extension.elytron.tls.subsystem.expression.DeploymentExpressionResolverProcessor; +import org.wildfly.security.Version; /** + * Top level {@link PersistentResourceDefinition} for the Elytron TLS subsystem. + * * @author Kabir Khan * @author Cameron Rodriguez */ public class ElytronTlsSubsystemDefinition extends PersistentResourceDefinition { + /** + * System property which if set to {@code true} will cause the JVM wide default {@link SSLContext} to be restored when the subsystem shuts down. + * + * This property is only for use by test cases. + */ + static final String RESTORE_DEFAULT_SSL_CONTEXT = ElytronTlsSubsystemDefinition.class.getPackage().getName() + ".restore-default-ssl-context"; + static final PropertiesAttributeDefinition SECURITY_PROPERTIES = new PropertiesAttributeDefinition.Builder(Constants.SECURITY_PROPERTIES, true) .build(); - private static final OperationContext.AttachmentKey SECURITY_PROPERTY_SERVICE_KEY = OperationContext.AttachmentKey.create(SecurityPropertyService.class); + private static final AttachmentKey SECURITY_PROPERTY_SERVICE_KEY = AttachmentKey.create(SecurityPropertyService.class); static final SimpleAttributeDefinition DEFAULT_SSL_CONTEXT = new SimpleAttributeDefinitionBuilder(Constants.DEFAULT_SSL_CONTEXT, ModelType.STRING, true) @@ -183,9 +193,11 @@ protected void revertUpdateToRuntime(OperationContext context, ModelNode operati @Override public void registerAdditionalRuntimePackages(ManagementResourceRegistration resourceRegistration) { - super.registerAdditionalRuntimePackages(resourceRegistration); } + static ServiceBuilder commonRequirements(ServiceBuilder serviceBuilder) { + return commonRequirements(serviceBuilder, true, true); + } static ServiceBuilder commonRequirements(ServiceBuilder serviceBuilder, boolean dependOnProperties, boolean dependOnProviderRegistration) { if (dependOnProperties) serviceBuilder.requires(SecurityPropertyService.SERVICE_NAME); @@ -193,11 +205,10 @@ static ServiceBuilder commonRequirements(ServiceBuilder serviceBuilder return serviceBuilder; } - private static void installService(ServiceName serviceName, Service service, ServiceTarget serviceTarget) { - serviceTarget.addService(serviceName) - .setInstance(service) - .setInitialMode(Mode.ACTIVE) - .install(); + private static void installService(ServiceName serviceName, Service service, ServiceTarget serviceTarget) { + serviceTarget.addService(serviceName, service) + .setInitialMode(Mode.ACTIVE) + .install(); } private static SecurityPropertyService uninstallSecurityPropertyService(OperationContext context) { @@ -207,7 +218,7 @@ private static SecurityPropertyService uninstallSecurityPropertyService(Operatio if (service != null) { Object serviceImplementation = service.getService(); context.removeService(service); - if (serviceImplementation instanceof SecurityPropertyService) { + if (serviceImplementation != null && serviceImplementation instanceof SecurityPropertyService) { return (SecurityPropertyService) serviceImplementation; } } @@ -221,9 +232,15 @@ private ElytronTlsAdd() { super(INITIAL_PROVIDERS, FINAL_PROVIDERS, DISALLOWED_PROVIDERS, SECURITY_PROPERTIES, DEFAULT_SSL_CONTEXT); } + @Override + protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException { + Version.getVersion(); + super.populateModel(operation, model); + } + @Override protected void performBoottime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException { - Map securityProperties = SECURITY_PROPERTIES.unwrap(context, model); + Map securityProperties = SECURITY_PROPERTIES.unwrap(context, model); final String defaultSSLContext = DEFAULT_SSL_CONTEXT.resolveModelAttribute(context, model).asStringOrNull(); ServiceTarget target = context.getServiceTarget(); @@ -231,20 +248,21 @@ protected void performBoottime(OperationContext context, ModelNode operation, Mo List disallowedProviders = DISALLOWED_PROVIDERS.unwrap(context, operation); ProviderRegistrationService prs = new ProviderRegistrationService(disallowedProviders); - ServiceBuilder builder = target.addService(ProviderRegistrationService.SERVICE_NAME) - .setInstance(prs) - .setInitialMode(Mode.ACTIVE); + ServiceBuilder builder = target.addService(ProviderRegistrationService.SERVICE_NAME, prs) + .setInitialMode(Mode.ACTIVE); String initialProviders = INITIAL_PROVIDERS.resolveModelAttribute(context, model).asStringOrNull(); if (initialProviders != null) { - builder.requires( - context.getCapabilityServiceName(PROVIDERS_CAPABILITY, initialProviders, Provider[].class)); + builder.addDependency( + context.getCapabilityServiceName(PROVIDERS_CAPABILITY, initialProviders, Provider[].class), + Provider[].class, prs.getInitialProivders()); } String finalProviders = FINAL_PROVIDERS.resolveModelAttribute(context, model).asStringOrNull(); if (finalProviders != null) { - builder.requires( - context.getCapabilityServiceName(PROVIDERS_CAPABILITY, finalProviders, Provider[].class)); + builder.addDependency( + context.getCapabilityServiceName(PROVIDERS_CAPABILITY, finalProviders, Provider[].class), + Provider[].class, prs.getFinalProviders()); } builder.install(); @@ -260,7 +278,7 @@ protected void performBoottime(OperationContext context, ModelNode operation, Mo serviceBuilder.setInstance(defaultSSLContextService).install(); } - if(context.isNormalServer()){ + if (context.isNormalServer()) { context.addStep(new AbstractDeploymentChainStep() { @Override public void execute(DeploymentProcessorTarget processorTarget) { @@ -293,11 +311,11 @@ protected boolean requiresRuntime(final OperationContext context) { private static class ElytronTlsRemove extends AbstractRemoveStepHandler implements ElytronOperationStepHandler { private ElytronTlsRemove() { - super(); + super(ELYTRON_TLS_RUNTIME_CAPABILITY); } @Override - protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) { + protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException { if (context.isResourceServiceRestartAllowed()) { SecurityPropertyService securityPropertyService = uninstallSecurityPropertyService(context); if (securityPropertyService != null) { diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystemParser_1_0.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystemParser_1_0.java index d2fc720..2975896 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystemParser_1_0.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystemParser_1_0.java @@ -75,11 +75,11 @@ String getNameSpace() { PersistentResourceXMLDescription getTlsParser() { return PersistentResourceXMLDescription.decorator(TLS) - .addChild(getServerSSLContextParser()) - .addChild(getClientSSLContextParser()) .addChild(getKeyStoreParser()) .addChild(getKeyManagerParser()) .addChild(getTrustManagerParser()) + .addChild(getServerSSLContextParser()) + .addChild(getClientSSLContextParser()) .addChild(getCertificateAuthorityParser()) .addChild(getCertificateAuthorityAccountParser()) .build(); @@ -88,16 +88,16 @@ PersistentResourceXMLDescription getTlsParser() { @Override public PersistentResourceXMLDescription getParserDescription() { return PersistentResourceXMLDescription.builder(ElytronTlsExtension.SUBSYSTEM_PATH, getNameSpace()) - .addAttribute(ElytronTlsSubsystemDefinition.SECURITY_PROPERTIES, - new AttributeParsers.PropertiesParser(null, SECURITY_PROPERTY, true), - new AttributeMarshallers.PropertiesAttributeMarshaller(null, SECURITY_PROPERTY, true)) .addAttribute(ElytronTlsSubsystemDefinition.INITIAL_PROVIDERS) .addAttribute(ElytronTlsSubsystemDefinition.FINAL_PROVIDERS) .addAttribute(ElytronTlsSubsystemDefinition.DISALLOWED_PROVIDERS) + .addAttribute(ElytronTlsSubsystemDefinition.SECURITY_PROPERTIES, + new AttributeParsers.PropertiesParser(null, SECURITY_PROPERTY, true), + new AttributeMarshallers.PropertiesAttributeMarshaller(null, SECURITY_PROPERTY, true)) .addAttribute(ElytronTlsSubsystemDefinition.DEFAULT_SSL_CONTEXT) + .addChild(getProviderParser()) .addChild(getTlsParser()) .addChild(getCredentialStoresParser()) - .addChild(getProviderParser()) .addChild(getExpressionResolverParser()) .build(); } diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyManagerAttributeDefinition.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyManagerAttributeDefinition.java deleted file mode 100644 index 41dd136..0000000 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyManagerAttributeDefinition.java +++ /dev/null @@ -1,27 +0,0 @@ - /* - * Copyright 2022 Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.wildfly.extension.elytron.tls.subsystem; - -import org.jboss.as.controller.ObjectTypeAttributeDefinition; - -public class KeyManagerAttributeDefinition extends ObjectTypeAttributeDefinition { - - protected KeyManagerAttributeDefinition(Builder builder) { - super(builder); - } - -} diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreDefinition.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreDefinition.java index 9a6e4f9..43ee449 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreDefinition.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreDefinition.java @@ -18,7 +18,6 @@ package org.wildfly.extension.elytron.tls.subsystem; -import static org.jboss.as.controller.AbstractControllerService.PATH_MANAGER_CAPABILITY; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP; import static org.jboss.as.controller.security.CredentialReference.handleCredentialReferenceUpdate; import static org.jboss.as.controller.security.CredentialReference.rollbackCredentialStoreUpdate; @@ -62,6 +61,8 @@ import org.jboss.as.controller.registry.OperationEntry; import org.jboss.as.controller.registry.Resource; 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.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.jboss.msc.service.ServiceBuilder; @@ -267,10 +268,9 @@ protected void performRuntime(OperationContext context, ModelNode operation, Res ServiceTarget serviceTarget = context.getServiceTarget(); RuntimeCapability runtimeCapability = KEY_STORE_RUNTIME_CAPABILITY.fromBaseCapability(context.getCurrentAddressValue()); ServiceName serviceName = runtimeCapability.getCapabilityServiceName(KeyStore.class); - ServiceBuilder serviceBuilder = (ServiceBuilder) serviceTarget.addService(serviceName).setInitialMode(Mode.ACTIVE); + ServiceBuilder serviceBuilder = serviceTarget.addService(serviceName, keyStoreService).setInitialMode(Mode.ACTIVE); - keyStoreService.setPathManagerSupplier(serviceBuilder.requires( - PATH_MANAGER_CAPABILITY.getCapabilityServiceName())); + serviceBuilder.addDependency(PathManagerService.SERVICE_NAME, PathManager.class, keyStoreService.getPathManagerInjector()); if (relativeTo != null) { serviceBuilder.requires(pathName(relativeTo)); } @@ -278,13 +278,13 @@ protected void performRuntime(OperationContext context, ModelNode operation, Res if (providers != null) { String providersCapabilityName = RuntimeCapability.buildDynamicCapabilityName(PROVIDERS_CAPABILITY, providers); ServiceName providerLoaderServiceName = context.getCapabilityServiceName(providersCapabilityName, Provider[].class); - keyStoreService.setProvidersSupplier(serviceBuilder.requires(providerLoaderServiceName)); + serviceBuilder.addDependency(providerLoaderServiceName, Provider[].class, keyStoreService.getProvidersInjector()); } - keyStoreService.setCredentialSourceSupplier(CredentialReference.getCredentialSourceSupplier( - context, CREDENTIAL_REFERENCE, model, serviceBuilder)); + keyStoreService.getCredentialSourceSupplierInjector() + .inject(CredentialReference.getCredentialSourceSupplier(context, KeyStoreDefinition.CREDENTIAL_REFERENCE, model, serviceBuilder)); - commonRequirements(serviceBuilder, true, true).install(); + commonRequirements(serviceBuilder).install(); } @Override diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreParser.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreParser.java index f9d0fa3..9c81878 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreParser.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreParser.java @@ -27,14 +27,14 @@ class KeyStoreParser { final PersistentResourceXMLDescription keyStoreParser_1_0 = PersistentResourceXMLDescription.builder(PathElement.pathElement(KEY_STORE)) .setXmlWrapperElement(KEY_STORES) - .addAttribute(KeyStoreDefinition.CREDENTIAL_REFERENCE) .addAttribute(KeyStoreDefinition.TYPE) - .addAttribute(FileAttributeDefinitions.PATH) - .addAttribute(FileAttributeDefinitions.RELATIVE_TO) - .addAttribute(KeyStoreDefinition.ALIAS_FILTER) - .addAttribute(KeyStoreDefinition.PROVIDERS) .addAttribute(KeyStoreDefinition.PROVIDER_NAME) + .addAttribute(KeyStoreDefinition.PROVIDERS) + .addAttribute(KeyStoreDefinition.CREDENTIAL_REFERENCE) + .addAttribute(KeyStoreDefinition.ALIAS_FILTER) .addAttribute(KeyStoreDefinition.REQUIRED) + .addAttribute(FileAttributeDefinitions.PATH) + .addAttribute(FileAttributeDefinitions.RELATIVE_TO) .addAttribute(CredentialReference.getAttributeDefinition()) .build(); } diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreService.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreService.java index f9f69a5..5441083 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreService.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoreService.java @@ -47,10 +47,12 @@ import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.services.path.PathManager; import org.jboss.logging.Logger; -import org.jboss.msc.Service; +import org.jboss.msc.inject.Injector; +import org.jboss.msc.service.Service; import org.jboss.msc.service.StartContext; import org.jboss.msc.service.StartException; import org.jboss.msc.service.StopContext; +import org.jboss.msc.value.InjectedValue; import org.wildfly.common.function.ExceptionSupplier; import org.wildfly.common.iteration.ByteIterator; import org.wildfly.extension.elytron.tls.subsystem.FileAttributeDefinitions.PathResolver; @@ -87,9 +89,9 @@ class KeyStoreService implements ModifiableKeyStoreService { private final boolean required; private final String aliasFilter; - private Supplier pathManagerSupplier; - private Supplier providersSupplier; - private ExceptionSupplier credentialSourceSupplier; + private final InjectedValue pathManager = new InjectedValue<>(); + private final InjectedValue providers = new InjectedValue<>(); + private final InjectedValue> credentialSourceSupplier = new InjectedValue<>(); private PathResolver pathResolver; private File resolvedPath; @@ -160,7 +162,7 @@ public void start(StartContext startContext) throws StartException { if (type != null) { keyStore.load(is, password); } else { - Provider[] resolvedProviders = providersSupplier.get(); + Provider[] resolvedProviders = providers.getOptionalValue(); if (resolvedProviders == null) { resolvedProviders = Security.getProviders(); } @@ -200,9 +202,9 @@ public void start(StartContext startContext) throws StartException { } private Provider resolveProvider() throws StartException { - Provider[] candidates = providersSupplier.get(); - Supplier resolveProvidersSupplier = () -> candidates == null ? Security.getProviders() : candidates; - Provider identified = findProvider(resolveProvidersSupplier, provider, KeyStore.class, type); + Provider[] candidates = providers.getOptionalValue(); + Supplier providersSupplier = () -> candidates == null ? Security.getProviders() : candidates; + Provider identified = findProvider(providersSupplier, provider, KeyStore.class, type); if (identified == null) { throw LOGGER.noSuitableProvider(type); } @@ -249,6 +251,7 @@ public void stop(StopContext stopContext) { } } + @Override public KeyStore getValue() throws IllegalStateException, IllegalArgumentException { return unmodifiableKeyStore; } @@ -257,16 +260,16 @@ public KeyStore getModifiableValue() { return trackingKeyStore; } - void setPathManagerSupplier(Supplier pathManagerSupplier) { - this.pathManagerSupplier = pathManagerSupplier; + Injector getPathManagerInjector() { + return pathManager; } - void setProvidersSupplier(Supplier providersSupplier) { - this.providersSupplier = providersSupplier; + Injector getProvidersInjector() { + return providers; } - void setCredentialSourceSupplier(ExceptionSupplier credentialSourceSupplier) { - this.credentialSourceSupplier = credentialSourceSupplier; + Injector> getCredentialSourceSupplierInjector() { + return credentialSourceSupplier; } String getResolvedAbsolutePath() { @@ -336,7 +339,8 @@ char[] resolveKeyPassword(final ExceptionSupplier k } private char[] resolvePassword() throws Exception { - CredentialSource cs = credentialSourceSupplier != null ? credentialSourceSupplier.get() : null; + ExceptionSupplier sourceSupplier = credentialSourceSupplier.getValue(); + CredentialSource cs = sourceSupplier != null ? sourceSupplier.get() : null; String path = resolvedPath != null ? resolvedPath.getPath() : "null"; if (cs == null) throw LOGGER.keyStorePasswordCannotBeResolved(path); PasswordCredential credential = cs.getCredential(PasswordCredential.class); @@ -350,7 +354,7 @@ private char[] resolvePassword() throws Exception { File getResolvedPath(PathResolver pathResolver, String path, String relativeTo) { pathResolver.path(path); if (relativeTo != null) { - pathResolver.relativeTo(relativeTo, pathManagerSupplier.get()); + pathResolver.relativeTo(relativeTo, pathManager.getValue()); } return pathResolver.resolve(); } diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ManagerParsers.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ManagerParsers.java index d0c8917..3713190 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ManagerParsers.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ManagerParsers.java @@ -33,10 +33,10 @@ class ManagerParsers { .addAttribute(SSLContextDefinitions.KEY_STORE) // .addAttribute(SSLContextDefinitions.KEY_STORE_OBJECT) .addAttribute(SSLContextDefinitions.ALIAS_FILTER) - .addAttribute(SSLContextDefinitions.PROVIDER_NAME) .addAttribute(SSLContextDefinitions.PROVIDERS) - .addAttribute(SSLContextDefinitions.GENERATE_SELF_SIGNED_CERTIFICATE_HOST) // new + .addAttribute(SSLContextDefinitions.PROVIDER_NAME) .addAttribute(CredentialReference.getAttributeDefinition()) + .addAttribute(SSLContextDefinitions.GENERATE_SELF_SIGNED_CERTIFICATE_HOST) // new .build(); final PersistentResourceXMLDescription trustManagerParser_1_0 = PersistentResourceXMLDescription.builder(PathElement.pathElement(TRUST_MANAGER)) diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ModifiableKeyStoreService.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ModifiableKeyStoreService.java index fd94757..fcc079b 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ModifiableKeyStoreService.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ModifiableKeyStoreService.java @@ -20,14 +20,14 @@ import java.security.KeyStore; -import org.jboss.msc.Service; +import org.jboss.msc.service.Service; /** * An interface for KeyStore services, which provide modifiable KeyStore. * * @author Jan Kalina */ -interface ModifiableKeyStoreService extends Service { +interface ModifiableKeyStoreService extends Service { KeyStore getModifiableValue(); diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ProviderDefinitions.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ProviderDefinitions.java index 1cd5d96..0005450 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ProviderDefinitions.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ProviderDefinitions.java @@ -18,7 +18,6 @@ package org.wildfly.extension.elytron.tls.subsystem; -import static org.jboss.as.controller.AbstractControllerService.PATH_MANAGER_CAPABILITY; import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.PROVIDERS_API_CAPABILITY; import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.PROVIDERS_RUNTIME_CAPABILITY; import static org.wildfly.extension.elytron.tls.subsystem.ClassLoadingAttributeDefinitions.CLASS_NAMES; @@ -64,6 +63,7 @@ import org.jboss.as.controller.SimpleAttributeDefinition; import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; import org.jboss.as.controller.SimpleMapAttributeDefinition; +import org.jboss.as.controller.services.path.PathManagerService; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.jboss.modules.Module; @@ -165,11 +165,12 @@ protected void resolveRuntime(ModelNode model, OperationContext context) throws @Override protected ExceptionSupplier prepareServiceSupplier(OperationContext context, CapabilityServiceBuilder serviceBuilder) throws OperationFailedException { + final Supplier pathManager; if (properties == null && relativeTo != null) { - pathManagerSupplier = serviceBuilder.requires(PATH_MANAGER_CAPABILITY.getCapabilityServiceName()); + pathManager = serviceBuilder.requires(PathManagerService.SERVICE_NAME); serviceBuilder.requires(pathName(relativeTo)); } else { - pathManagerSupplier = null; + pathManager = null; } return new ExceptionSupplier() { @@ -180,8 +181,8 @@ public Provider[] get() throws StartException { if (properties == null && relativeTo != null) { PathResolver pathResolver = pathResolver(); pathResolver.path(path); - if (relativeTo != null && pathManagerSupplier != null) { - pathResolver.relativeTo(relativeTo, pathManagerSupplier.get()); + if (relativeTo != null) { + pathResolver.relativeTo(relativeTo, pathManager.get()); } resolved = pathResolver.resolve(); pathResolver.clear(); diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ProviderRegistrationService.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ProviderRegistrationService.java index 3f5f533..6b79b5a 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ProviderRegistrationService.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/ProviderRegistrationService.java @@ -27,10 +27,11 @@ import java.util.Iterator; import java.util.Set; -import org.jboss.msc.Service; import org.jboss.msc.inject.Injector; +import org.jboss.msc.service.Service; import org.jboss.msc.service.ServiceName; import org.jboss.msc.service.StartContext; +import org.jboss.msc.service.StartException; import org.jboss.msc.service.StopContext; import org.jboss.msc.value.InjectedValue; @@ -39,7 +40,7 @@ * * @author Darran Lofthouse */ -class ProviderRegistrationService implements Service { +class ProviderRegistrationService implements Service { static final ServiceName SERVICE_NAME = ElytronTlsExtension.BASE_SERVICE_NAME.append(Constants.PROVIDER_REGISTRATION); @@ -54,7 +55,7 @@ class ProviderRegistrationService implements Service { } @Override - public void start(StartContext context) { + public void start(StartContext context) throws StartException { SecurityActions.doPrivileged((PrivilegedAction) () -> { for (String s : providersToRemove) { Security.removeProvider(s); @@ -109,4 +110,9 @@ Injector getInitialProivders() { Injector getFinalProviders() { return finalProviders; } + + @Override + public Void getValue() throws IllegalStateException, IllegalArgumentException { + return null; + } } diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SSLContextDefinitions.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SSLContextDefinitions.java index d0f428e..0148492 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SSLContextDefinitions.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SSLContextDefinitions.java @@ -16,7 +16,6 @@ package org.wildfly.extension.elytron.tls.subsystem; -import static org.jboss.as.controller.AbstractControllerService.PATH_MANAGER_CAPABILITY; 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; @@ -33,9 +32,6 @@ import static org.wildfly.extension.elytron.tls.subsystem.FileAttributeDefinitions.PATH; import static org.wildfly.extension.elytron.tls.subsystem.FileAttributeDefinitions.RELATIVE_TO; import static org.wildfly.extension.elytron.tls.subsystem.FileAttributeDefinitions.pathName; -import static org.wildfly.extension.elytron.tls.subsystem.FileAttributeDefinitions.pathResolver; -import static org.wildfly.extension.elytron.tls.subsystem.TrivialResourceDefinition.Builder; -import static org.wildfly.extension.elytron.tls.subsystem.TrivialService.ValueSupplier; import static org.wildfly.extension.elytron.tls.subsystem._private.ElytronTLSLogger.LOGGER; import java.io.File; @@ -51,7 +47,6 @@ import java.security.Principal; import java.security.PrivateKey; import java.security.Provider; -import java.security.Security; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; @@ -61,7 +56,6 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; @@ -75,6 +69,8 @@ import org.jboss.as.controller.AbstractAddStepHandler; import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.MapAttributeDefinition; +import org.jboss.as.controller.ModelVersion; import org.jboss.as.controller.ObjectListAttributeDefinition; import org.jboss.as.controller.ObjectTypeAttributeDefinition; import org.jboss.as.controller.OperationContext; @@ -84,6 +80,7 @@ import org.jboss.as.controller.ResourceDefinition; import org.jboss.as.controller.SimpleAttributeDefinition; import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; +import org.jboss.as.controller.SimpleMapAttributeDefinition; import org.jboss.as.controller.SimpleOperationDefinitionBuilder; import org.jboss.as.controller.StringListAttributeDefinition; import org.jboss.as.controller.capability.RuntimeCapability; @@ -95,6 +92,7 @@ import org.jboss.as.controller.registry.Resource; 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.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.jboss.msc.service.ServiceBuilder; @@ -103,24 +101,24 @@ import org.jboss.msc.service.ServiceName; import org.jboss.msc.service.ServiceRegistry; import org.jboss.msc.service.StartException; +import org.jboss.msc.value.InjectedValue; import org.wildfly.common.function.ExceptionSupplier; -import org.wildfly.security.EmptyProvider; +import org.wildfly.extension.elytron.tls.subsystem.TrivialResourceDefinition.Builder; +import org.wildfly.extension.elytron.tls.subsystem.TrivialService.ValueSupplier; import org.wildfly.security.credential.PasswordCredential; import org.wildfly.security.credential.source.CredentialSource; import org.wildfly.security.keystore.AliasFilter; -import org.wildfly.security.keystore.AtomicLoadKeyStore; import org.wildfly.security.keystore.FilteringKeyStore; -import org.wildfly.security.keystore.KeyStoreUtil; import org.wildfly.security.password.interfaces.ClearPassword; -import org.wildfly.security.provider.util.ProviderUtil; import org.wildfly.security.ssl.CipherSuiteSelector; import org.wildfly.security.ssl.DomainlessSSLContextBuilder; import org.wildfly.security.ssl.Protocol; import org.wildfly.security.ssl.ProtocolSelector; import org.wildfly.security.ssl.X509RevocationTrustManager; - /** + * Definitions for resources used to configure SSLContexts. + * * @author Cameron Rodriguez */ public class SSLContextDefinitions { @@ -220,6 +218,14 @@ public class SSLContextDefinitions { .setRestartAllServices() .build(); + @Deprecated + static final SimpleAttributeDefinition MAXIMUM_CERT_PATH_CRL = new SimpleAttributeDefinitionBuilder(Constants.MAXIMUM_CERT_PATH, ModelType.INT, true) + .setDeprecated(ModelVersion.create(8)) + .setValidator(new IntRangeValidator(1)) + .setAllowExpression(true) + .setRestartAllServices() + .build(); + static final SimpleAttributeDefinition GENERATE_SELF_SIGNED_CERTIFICATE_HOST = new SimpleAttributeDefinitionBuilder(Constants.GENERATE_SELF_SIGNED_CERTIFICATE_HOST, ModelType.STRING, true) .setMinSize(1) .setAllowExpression(true) @@ -439,21 +445,22 @@ public class SSLContextDefinitions { /* SSL Context definitions */ - static final SimpleAttributeDefinition DEFAULT_SSL_CONTEXT = new SimpleAttributeDefinitionBuilder(Constants.DEFAULT_SSL_CONTEXT, ModelType.STRING) + static final SimpleAttributeDefinition DEFAULT_SSL_CONTEXT = new SimpleAttributeDefinitionBuilder(Constants.DEFAULT_SSL_CONTEXT, ModelType.STRING) .setRequired(true) .setCapabilityReference(SSL_CONTEXT_CAPABILITY) .setRestartAllServices() .build(); -// static final MapAttributeDefinition HOST_CONTEXT_MAP = new SimpleMapAttributeDefinition.Builder(Constants.HOST_CONTEXT_MAP, ModelType.STRING, true) -// .setMinSize(0) -// .setMapValidator(new HostContextMapValidator()) -// .setCapabilityReference(SSL_CONTEXT_CAPABILITY) -// .setAllowExpression(false) -// .setRestartAllServices() -// .build(); + static final MapAttributeDefinition HOST_CONTEXT_MAP = new SimpleMapAttributeDefinition.Builder(Constants.HOST_CONTEXT_MAP, ModelType.STRING, true) + .setMinSize(0) + .setCapabilityReference(SSL_CONTEXT_CAPABILITY) + .setMapValidator(new Validators.HostContextMapValidator()) + .setAllowExpression(false) + .setRestartAllServices() + .build(); + + /* Runtime Attributes */ - /** Runtime Attributes */ private static final SimpleAttributeDefinition ACTIVE_SESSION_COUNT = new SimpleAttributeDefinitionBuilder(Constants.ACTIVE_SESSION_COUNT, ModelType.INT) .setStorageRuntime() .build(); @@ -484,32 +491,36 @@ protected ValueSupplier getValueSupplier(ServiceBuilder final String providerName = PROVIDER_NAME.resolveModelAttribute(context, model).asStringOrNull(); final String providersName = providersKMDefinition.resolveModelAttribute(context, model).asStringOrNull(); - Supplier providersSupplier = addRequirement(PROVIDERS_CAPABILITY, Provider[].class, serviceBuilder, - context, providersName); - Supplier pathManagerSupplier = serviceBuilder.requires(PATH_MANAGER_CAPABILITY.getCapabilityServiceName()); + final InjectedValue providersInjector = new InjectedValue<>(); + if (providersName != null) { + serviceBuilder.addDependency(context.getCapabilityServiceName( + buildDynamicCapabilityName(PROVIDERS_CAPABILITY, providersName), Provider[].class), + Provider[].class, providersInjector); + } // final ModelNode keyStoreObject = keystoreKMObjectDefinition.resolveModelAttribute(context, model); final String keyStoreName = keystoreKMDefinition.resolveModelAttribute(context, model).asStringOrNull(); final ModifiableKeyStoreService keyStoreService = getModifiableKeyStoreService(context, keyStoreName); - ExceptionSupplier keyStoreSupplier; + final InjectedValue keyStoreInjector = new InjectedValue<>(); - /* if (keyStoreName != null) { - if (keyStoreObject != null) { - throw LOGGER.multipleKeystoreDefinitions(); - } - keyStoreSupplier = new SSLContextExceptionSupplier<>(KEY_STORE_CAPABILITY, KeyStore.class, serviceBuilder, context, keyStoreName); - } else { - if (keyStoreObject == null) { - LOGGER.missingKeyStoreDefinition(); - } - keyStoreSupplier = createKeyStore(serviceBuilder, context, keyStoreObject, pathManagerSupplier, providersSupplier); - } */ - keyStoreSupplier = new SSLContextExceptionSupplier<>(KEY_STORE_CAPABILITY, KeyStore.class, serviceBuilder, context, keyStoreName); + if (keyStoreName != null) { + /* if (keyStoreObject.isDefined()) { + throw LOGGER.multipleKeyStoreDefinitions(); + } */ + serviceBuilder.addDependency(context.getCapabilityServiceName( + buildDynamicCapabilityName(KEY_STORE_CAPABILITY, keyStoreName), KeyStore.class), + KeyStore.class, keyStoreInjector); + /* } else { + if (!keyStoreObject.isDefined()) { + LOGGER.missingKeyStoreDefinition(); + } + keyStoreInjector = createKeyStore(serviceBuilder, context, keyStoreObject, providersInjector); */ + } final String algorithm = algorithmName != null ? algorithmName : KeyManagerFactory.getDefaultAlgorithm(); DelegatingKeyManager delegatingKeyManager = new DelegatingKeyManager(); return () -> { - Provider[] providers = providersSupplier.get(); + Provider[] providers = providersInjector.getOptionalValue(); KeyManagerFactory keyManagerFactory = null; if (providers != null) { for (Provider current : providers) { @@ -533,7 +544,7 @@ protected ValueSupplier getValueSupplier(ServiceBuilder } } - KeyStore keyStore = keyStoreSupplier.get(); + KeyStore keyStore = keyStoreInjector.getOptionalValue(); char[] password; try { CredentialSource cs = credentialSourceSupplier.get(); @@ -577,22 +588,6 @@ protected ValueSupplier getValueSupplier(ServiceBuilder protected void rollbackRuntime(OperationContext context, final ModelNode operation, final Resource resource) { rollbackCredentialStoreUpdate(credentialReferenceDefinition, context, resource); } - - class SSLContextExceptionSupplier implements ExceptionSupplier { - private final Supplier supplier; - private final ExceptionSupplier exceptionSupplier; - - SSLContextExceptionSupplier (String baseName, Class type, ServiceBuilder serviceBuilder, - OperationContext context, String dynamicModelElement) { - this.supplier = addRequirement(baseName, type, serviceBuilder, context, dynamicModelElement); - this.exceptionSupplier = this.supplier::get; - } - - @Override - public T get() throws E { - return exceptionSupplier.get(); - } - } }; final ServiceUtil KEY_MANAGER_UTIL = ServiceUtil.newInstance(KEY_MANAGER_RUNTIME_CAPABILITY, Constants.KEY_MANAGER, KeyManager.class); @@ -621,41 +616,45 @@ protected ValueSupplier getValueSupplier(ServiceBuilder providersSupplier = addRequirement(PROVIDERS_CAPABILITY, Provider[].class, serviceBuilder, - context, providersName); - Supplier pathManagerSupplier = serviceBuilder.requires(PATH_MANAGER_CAPABILITY.getCapabilityServiceName()); + final InjectedValue providersInjector = new InjectedValue<>(); + if (providerLoader != null) { + serviceBuilder.addDependency(context.getCapabilityServiceName( + buildDynamicCapabilityName(PROVIDERS_CAPABILITY, providerLoader), Provider[].class), + Provider[].class, providersInjector); + } // final ModelNode keyStoreObject = keystoreTMObjectDefinition.resolveModelAttribute(context, model); - final String keyStoreName = keystoreTMDefinition.resolveModelAttribute(context, model).asStringOrNull(); - final ExceptionSupplier keyStoreSupplier; + final InjectedValue keyStoreInjector = new InjectedValue<>(); - /* if (keyStoreName != null) { - if (keyStoreObject != null) { - throw LOGGER.multipleKeystoreDefinitions(); - } - keyStoreSupplier = new SSLContextExceptionSupplier<>(KEY_STORE_CAPABILITY, KeyStore.class, serviceBuilder, context, keyStoreName); - } else { - if (keyStoreObject == null) { + if (keyStoreName != null) { + /* if (keyStoreObject.isDefined()) { + throw LOGGER.multipleKeyStoreDefinitions(); + } */ + serviceBuilder.addDependency(context.getCapabilityServiceName( + buildDynamicCapabilityName(KEY_STORE_CAPABILITY, keyStoreName), KeyStore.class), + KeyStore.class, keyStoreInjector); + /* } else { + if (!keyStoreObject.isDefined()) { LOGGER.missingKeyStoreDefinition(); } - keyStoreSupplier = createKeyStore(serviceBuilder, context, keyStoreObject, pathManagerSupplier, providersSupplier); - } */ - keyStoreSupplier = new SSLContextExceptionSupplier<>(KEY_STORE_CAPABILITY, KeyStore.class, serviceBuilder, context, keyStoreName); + keyStoreInjector = createKeyStore(serviceBuilder, context, keyStoreObject, providersInjector); */ + } final String algorithm = algorithmName != null ? algorithmName : TrustManagerFactory.getDefaultAlgorithm(); if (model.hasDefined(CERTIFICATE_REVOCATION_LIST.getName()) || model.hasDefined(OCSP.getName()) || model.hasDefined(CERTIFICATE_REVOCATION_LISTS.getName())) { - return createX509RevocationTrustManager(serviceBuilder, context, model, algorithm, providerName, providersSupplier, keyStoreSupplier, aliasFilter); + return createX509RevocationTrustManager(serviceBuilder, context, model, algorithm, providerName, providersInjector, keyStoreInjector, aliasFilter); } DelegatingTrustManager delegatingTrustManager = new DelegatingTrustManager(); return () -> { - Provider[] providers = providersSupplier.get(); + Provider[] providers = providersInjector.getOptionalValue(); TrustManagerFactory trustManagerFactory = createTrustManagerFactory(providers, providerName, algorithm); - KeyStore keyStore = keyStoreSupplier.get(); + KeyStore keyStore = keyStoreInjector.getOptionalValue(); try { if (aliasFilter != null) { @@ -669,7 +668,7 @@ protected ValueSupplier getValueSupplier(ServiceBuilder getValueSupplier(ServiceBuilder createX509RevocationTrustManager(ServiceBuilder serviceBuilder, OperationContext context, - ModelNode model, String algorithm, String providerName, Supplier providersSupplier, - ExceptionSupplier keyStoreSupplier, String aliasFilter) throws OperationFailedException { - + ModelNode model, String algorithm, String providerName, InjectedValue providersInjector, + InjectedValue keyStoreInjector, String aliasFilter) throws OperationFailedException { ModelNode crlNode = CERTIFICATE_REVOCATION_LIST.resolveModelAttribute(context, model); ModelNode ocspNode = OCSP.resolveModelAttribute(context, model); ModelNode multipleCrlsNode = CERTIFICATE_REVOCATION_LISTS.resolveModelAttribute(context, model); @@ -696,9 +694,20 @@ private ValueSupplier createX509RevocationTrustManager(ServiceBuil boolean onlyLeafCert = ONLY_LEAF_CERT.resolveModelAttribute(context, model).asBoolean(); Integer maxCertPath = MAXIMUM_CERT_PATH.resolveModelAttribute(context, model).asIntOrNull(); + //BW compatibility, max cert path is now in trust-manager + @Deprecated + Integer crlCertPath = MAXIMUM_CERT_PATH_CRL.resolveModelAttribute(context, crlNode).asIntOrNull(); + if (crlCertPath != null) { + LOGGER.warn("maximum-cert-path in certificate-revocation-list is for legacy support. Please use only the one in trust-manager!"); + if (maxCertPath != null) { + throw LOGGER.multipleMaximumCertPathDefinitions(); + } + maxCertPath = crlCertPath; + } + String crlPath = null; String crlRelativeTo = null; - Supplier pathManagerSupplier = serviceBuilder.requires(PATH_MANAGER_CAPABILITY.getCapabilityServiceName()); + InjectedValue pathManagerInjector = new InjectedValue<>(); List crlFiles = new ArrayList<>(); if (crlNode.isDefined()) { @@ -707,20 +716,23 @@ private ValueSupplier createX509RevocationTrustManager(ServiceBuil if (crlPath != null) { if (crlRelativeTo != null) { + serviceBuilder.addDependency(PathManagerService.SERVICE_NAME, PathManager.class, pathManagerInjector); serviceBuilder.requires(pathName(crlRelativeTo)); } - crlFiles.add(new CrlFile(crlPath, crlRelativeTo, pathManagerSupplier)); + crlFiles.add(new CrlFile(crlPath, crlRelativeTo, pathManagerInjector)); } } else if (multipleCrlsNode.isDefined()) { // certificate-revocation-lists and certificate-revocation-list are mutually exclusive for (ModelNode crl : multipleCrlsNode.asList()) { crlPath = PATH.resolveModelAttribute(context, crl).asStringOrNull(); crlRelativeTo = RELATIVE_TO.resolveModelAttribute(context, crl).asStringOrNull(); + pathManagerInjector = new InjectedValue<>(); if (crlPath != null) { if (crlRelativeTo != null) { + serviceBuilder.addDependency(PathManagerService.SERVICE_NAME, PathManager.class, pathManagerInjector); serviceBuilder.requires(pathName(crlRelativeTo)); } - crlFiles.add(new CrlFile(crlPath, crlRelativeTo, pathManagerSupplier)); + crlFiles.add(new CrlFile(crlPath, crlRelativeTo, pathManagerInjector)); } } } @@ -730,9 +742,13 @@ private ValueSupplier createX509RevocationTrustManager(ServiceBuil String responderCertAlias = RESPONDER_CERTIFICATE.resolveModelAttribute(context, ocspNode).asStringOrNull(); String responderKeystore = RESPONDER_KEYSTORE.resolveModelAttribute(context, ocspNode).asStringOrNull(); - final ExceptionSupplier responderStoreSupplier = responderKeystore != null - ? new SSLContextExceptionSupplier<>(KEY_STORE_CAPABILITY, KeyStore.class, serviceBuilder, context, responderKeystore) - : keyStoreSupplier; + final InjectedValue responderStoreInjector = responderKeystore != null ? new InjectedValue<>() : keyStoreInjector; + + if (responderKeystore != null) { + serviceBuilder.addDependency(context.getCapabilityServiceName( + buildDynamicCapabilityName(KEY_STORE_CAPABILITY, responderKeystore), KeyStore.class), + KeyStore.class, responderStoreInjector); + } URI responderUri; try { @@ -765,8 +781,8 @@ private ValueSupplier createX509RevocationTrustManager(ServiceBuil } final List finalCrlFiles = crlFiles; return () -> { - TrustManagerFactory trustManagerFactory = createTrustManagerFactory(providersSupplier.get(), providerName, algorithm); - KeyStore keyStore = keyStoreSupplier.get(); + TrustManagerFactory trustManagerFactory = createTrustManagerFactory(providersInjector.getOptionalValue(), providerName, algorithm); + KeyStore keyStore = keyStoreInjector.getOptionalValue(); if (aliasFilter != null) { try { @@ -777,7 +793,7 @@ private ValueSupplier createX509RevocationTrustManager(ServiceBuil } if (responderCertAlias != null) { - KeyStore responderStore = responderStoreSupplier.get(); + KeyStore responderStore = responderStoreInjector.getOptionalValue(); try { builder.setOcspResponderCert((X509Certificate) responderStore.getCertificate(responderCertAlias)); } catch (KeyStoreException e) { @@ -801,7 +817,7 @@ private List getCrlStreams(List crlFiles) throws StartExce List crlStreams = new ArrayList<>(); for (CrlFile crl : crlFiles) { try { - crlStreams.add(new FileInputStream(resolveFileLocation(crl.getCrlPath(), crl.getRelativeTo(), crl.getPathManagerSupplier()))); + crlStreams.add(new FileInputStream(resolveFileLocation(crl.getCrlPath(), crl.getRelativeTo(), crl.getPathManagerInjector()))); } catch (FileNotFoundException e) { throw LOGGER.unableToAccessCRL(e); } @@ -866,10 +882,10 @@ public X509Certificate[] getAcceptedIssuers() { }; } - private File resolveFileLocation(String path, String relativeTo, Supplier pathManagerSupplier) { + private File resolveFileLocation(String path, String relativeTo, InjectedValue pathManagerInjector) { final File resolvedPath; if (relativeTo != null) { - PathManager pathManager = pathManagerSupplier.get(); + PathManager pathManager = pathManagerInjector.getValue(); resolvedPath = new File(pathManager.resolveRelativePathEntry(path, relativeTo)); } else { resolvedPath = new File(path); @@ -901,22 +917,6 @@ private TrustManagerFactory createTrustManagerFactory(Provider[] providers, Stri throw new StartException(e); } } - - class SSLContextExceptionSupplier implements ExceptionSupplier { - private final Supplier supplier; - private final ExceptionSupplier exceptionSupplier; - - SSLContextExceptionSupplier (String baseName, Class type, ServiceBuilder serviceBuilder, - OperationContext context, String dynamicModelElement) { - this.supplier = addRequirement(baseName, type, serviceBuilder, context, dynamicModelElement); - this.exceptionSupplier = this.supplier::get; - } - - @Override - public T get() throws E { - return exceptionSupplier.get(); - } - } }; ResourceDescriptionResolver resolver = ElytronTlsExtension.getResourceDescriptionResolver(Constants.TRUST_MANAGER); @@ -930,22 +930,21 @@ public T get() throws E { .addOperation(new SimpleOperationDefinitionBuilder(Constants.RELOAD_CERTIFICATE_REVOCATION_LIST, resolver) .setRuntimeOnly() .build(), new ElytronRuntimeOnlyHandler() { - - @Override - protected void executeRuntimeStep(OperationContext context, ModelNode operation) throws OperationFailedException { - ServiceName serviceName = TRUST_MANAGER_RUNTIME_CAPABILITY.fromBaseCapability(context.getCurrentAddressValue()).getCapabilityServiceName(); - ServiceController serviceContainer = getRequiredService(context.getServiceRegistry(true), serviceName, TrustManager.class); - State serviceState; - if ((serviceState = serviceContainer.getState()) != State.UP) { - throw LOGGER.requiredServiceNotUp(serviceName, serviceState); - } - TrustManager trustManager = serviceContainer.getValue(); - if (! (trustManager instanceof ReloadableX509ExtendedTrustManager)) { - throw LOGGER.unableToReloadCRLNotReloadable(); - } - ((ReloadableX509ExtendedTrustManager) trustManager).reload(); - } - }) + @Override + protected void executeRuntimeStep(OperationContext context, ModelNode operation) throws OperationFailedException { + ServiceName serviceName = TRUST_MANAGER_RUNTIME_CAPABILITY.fromBaseCapability(context.getCurrentAddressValue()).getCapabilityServiceName(); + ServiceController serviceContainer = getRequiredService(context.getServiceRegistry(true), serviceName, TrustManager.class); + State serviceState; + if ((serviceState = serviceContainer.getState()) != State.UP) { + throw LOGGER.requiredServiceNotUp(serviceName, serviceState); + } + TrustManager trustManager = serviceContainer.getValue(); + if (! (trustManager instanceof ReloadableX509ExtendedTrustManager)) { + throw LOGGER.unableToReloadCRLNotReloadable(); + } + ((ReloadableX509ExtendedTrustManager) trustManager).reload(); + } + }) .addOperation(new SimpleOperationDefinitionBuilder(Constants.INIT, RESOURCE_RESOLVER) .setRuntimeOnly() .build(), init(TRUST_MANAGER_UTIL)) @@ -1008,44 +1007,44 @@ static ResourceDefinition getClientSSLContextDefinition(boolean serverOrHostCont @Override protected ValueSupplier getValueSupplier(ServiceBuilder serviceBuilder, OperationContext context, ModelNode model) throws OperationFailedException { final String providerName = PROVIDER_NAME.resolveModelAttribute(context, model).asStringOrNull(); - final String providersName = providersDefinition.resolveModelAttribute(context, model).asStringOrNull(); final List protocols = PROTOCOLS.unwrap(context, model); final String cipherSuiteFilter = CIPHER_SUITE_FILTER.resolveModelAttribute(context, model).asString(); final String cipherSuiteNames = CIPHER_SUITE_NAMES.resolveModelAttribute(context, model).asStringOrNull(); - Supplier providersSupplier = addRequirement(PROVIDERS_CAPABILITY, Provider[].class, serviceBuilder, - context, providersName); - Supplier pathManagerSupplier = serviceBuilder.requires(PATH_MANAGER_CAPABILITY.getCapabilityServiceName()); - SSLContextExceptionSupplier keyManagerSupplier; - SSLContextExceptionSupplier trustManagerSupplier; + final InjectedValue providersInjector = addSSLContextDependency(PROVIDERS_CAPABILITY, providersDefinition, Provider[].class, serviceBuilder, context, model); + final InjectedValue keyManagerInjector = addSSLContextDependency(KEY_MANAGER_CAPABILITY, KEY_MANAGER, KeyManager.class, serviceBuilder, context, model); + final InjectedValue trustManagerInjector = addSSLContextDependency(TRUST_MANAGER_CAPABILITY, TRUST_MANAGER, TrustManager.class, serviceBuilder, context, model);; + // final ModelNode keyManagerObject = KEY_MANAGER_OBJECT.resolveModelAttribute(context, model); + // final ModelNode trustManagerObject = TRUST_MANAGER_OBJECT.resolveModelAttribute(context, model); - final String keyManagerName = KEY_MANAGER.resolveModelAttribute(context, model).asStringOrNull(); - /* final ModelNode keyManagerObject = KEY_MANAGER_OBJECT.resolveModelAttribute(context, model); - if (keyManagerObject.isDefined()) { - keyManagerSupplier = (SSLContextExceptionSupplier) createKeyManager(serviceBuilder, context, keyManagerObject, pathManagerSupplier, providersSupplier); + /* if (keyManagerName != null) { + if (keyManagerObject.isDefined()) { + throw LOGGER.multipleKeyManagerDefinitions(); + } + keyManagerInjector = addSSLContextDependency(KEY_MANAGER_CAPABILITY, KEY_MANAGER, KeyManager.class, serviceBuilder, context, model); } else { // Use reference - keyManagerSupplier = new SSLContextExceptionSupplier<>(KEY_MANAGER_CAPABILITY, KeyManager.class, serviceBuilder, - context, keyManagerName); - } */ - keyManagerSupplier = new SSLContextExceptionSupplier<>(KEY_MANAGER_CAPABILITY, KeyManager.class, serviceBuilder, context, keyManagerName); + if (!keyManagerObject.isDefined()) { + LOGGER.missingKeyManagerDefinition(); + } + keyManagerInjector = createKeyManager(serviceBuilder, context, keyManagerObject, providersInjector); + } - final String trustManagerName = TRUST_MANAGER.resolveModelAttribute(context, model).asStringOrNull(); - /* final ModelNode trustManagerObject = TRUST_MANAGER_OBJECT.resolveModelAttribute(context, model); - if (trustManagerObject.isDefined()) { - trustManagerSupplier = (SSLContextExceptionSupplier) createTrustManager(serviceBuilder, context, trustManagerObject, pathManagerSupplier, providersSupplier); + if (trustManagerName != null) { + if (trustManagerObject.isDefined()) { + throw LOGGER.multipleTrustManagerDefinitions(); + } + trustManagerInjector = addSSLContextDependency(TRUST_MANAGER_CAPABILITY, TRUST_MANAGER, TrustManager.class, serviceBuilder, context, model); } else { - trustManagerSupplier = new SSLContextExceptionSupplier<>(TRUST_MANAGER_CAPABILITY, TrustManager.class, serviceBuilder, - context, trustManagerName); + if (!trustManagerObject.isDefined()) { + LOGGER.missingTrustManagerDefinition(); + } + trustManagerInjector = createTrustManager(serviceBuilder, context, trustManagerObject, providersInjector); } */ - trustManagerSupplier = new SSLContextExceptionSupplier<>(TRUST_MANAGER_CAPABILITY, TrustManager.class, serviceBuilder, context, trustManagerName); - - final SSLContextExceptionSupplier finalKeyManagerSupplier = keyManagerSupplier; - final SSLContextExceptionSupplier finalTrustManagerSupplier = trustManagerSupplier; return () -> { - X509ExtendedKeyManager keyManager = getX509KeyManager(finalKeyManagerSupplier.get()); - X509ExtendedTrustManager trustManager = getX509TrustManager(finalTrustManagerSupplier.get()); - Provider[] providers = filterProviders(providersSupplier.get(), providerName); + X509ExtendedKeyManager keyManager = getX509KeyManager(keyManagerInjector.getOptionalValue()); + X509ExtendedTrustManager trustManager = getX509TrustManager(trustManagerInjector.getOptionalValue()); + Provider[] providers = filterProviders(providersInjector.getOptionalValue(), providerName); DomainlessSSLContextBuilder builder = new DomainlessSSLContextBuilder(); if (keyManager != null) builder.setKeyManager(keyManager); @@ -1103,8 +1102,6 @@ protected void installedForResource(ServiceController serviceControl static ResourceDefinition getServerSSLContextDefinition(boolean serverOrHostController) { - final ObjectTypeAttributeDefinition credentialReferenceDefinition = CredentialReference.getAttributeDefinition(true); - final SimpleAttributeDefinition providersDefinition = new SimpleAttributeDefinitionBuilder(PROVIDERS) .setCapabilityReference(PROVIDERS_CAPABILITY, SSL_CONTEXT_CAPABILITY) .setRestartAllServices() @@ -1120,16 +1117,14 @@ static ResourceDefinition getServerSSLContextDefinition(boolean serverOrHostCont providersDefinition, WANT_CLIENT_AUTH, NEED_CLIENT_AUTH, AUTHENTICATION_OPTIONAL, USE_CIPHER_SUITES_ORDER, MAXIMUM_SESSION_CACHE_SIZE, SESSION_TIMEOUT, WRAP}; - AbstractAddStepHandler add = new TrivialAddHandler(SSLContext.class, ServiceController.Mode.ACTIVE, ServiceController.Mode.PASSIVE, attributes, SSL_CONTEXT_RUNTIME_CAPABILITY) { @Override protected ValueSupplier getValueSupplier(ServiceBuilder serviceBuilder, - OperationContext context, ModelNode model) throws OperationFailedException { + OperationContext context, ModelNode model) throws OperationFailedException { final String providerName = PROVIDER_NAME.resolveModelAttribute(context, model).asStringOrNull(); - final String providersName = PROVIDERS.resolveModelAttribute(context, model).asStringOrNull(); final List protocols = PROTOCOLS.unwrap(context, model); final String cipherSuiteFilter = CIPHER_SUITE_FILTER.resolveModelAttribute(context, model).asString(); // has default value, can't be null final String cipherSuiteNames = CIPHER_SUITE_NAMES.resolveModelAttribute(context, model).asStringOrNull(); // doesn't have a default value yet since we are disabling TLS 1.3 by default @@ -1140,40 +1135,41 @@ protected ValueSupplier getValueSupplier(ServiceBuilder final int maximumSessionCacheSize = MAXIMUM_SESSION_CACHE_SIZE.resolveModelAttribute(context, model).asInt(); final int sessionTimeout = SESSION_TIMEOUT.resolveModelAttribute(context, model).asInt(); final boolean wrap = WRAP.resolveModelAttribute(context, model).asBoolean(); - - Supplier providersSupplier = addRequirement(PROVIDERS_CAPABILITY, Provider[].class, serviceBuilder, - context, providersName); - Supplier pathManagerSupplier = serviceBuilder.requires(PATH_MANAGER_CAPABILITY.getCapabilityServiceName()); - SSLContextExceptionSupplier keyManagerSupplier; - SSLContextExceptionSupplier trustManagerSupplier; - - final String keyManagerName = keyManagerDefinition.resolveModelAttribute(context, model).asStringOrNull(); - /* final ModelNode keyManagerObject = KEY_MANAGER_OBJECT.resolveModelAttribute(context, model); - if (keyManagerObject.isDefined()) { - keyManagerSupplier = (SSLContextExceptionSupplier) createKeyManager(serviceBuilder, context, keyManagerObject, pathManagerSupplier, providersSupplier); + + final InjectedValue providersInjector = addSSLContextDependency(PROVIDERS_CAPABILITY, providersDefinition, Provider[].class, serviceBuilder, context, model); + InjectedValue keyManagerInjector = addSSLContextDependency(KEY_MANAGER_CAPABILITY, KEY_MANAGER, KeyManager.class, serviceBuilder, context, model); + InjectedValue trustManagerInjector = addSSLContextDependency(TRUST_MANAGER_CAPABILITY, TRUST_MANAGER, TrustManager.class, serviceBuilder, context, model);; + // final ModelNode keyManagerObject = KEY_MANAGER_OBJECT.resolveModelAttribute(context, model); + // final ModelNode trustManagerObject = TRUST_MANAGER_OBJECT.resolveModelAttribute(context, model); + + /* if (keyManagerName != null) { + if (keyManagerObject.isDefined()) { + throw LOGGER.multipleKeyManagerDefinitions(); + } + keyManagerInjector = addSSLContextDependency(KEY_MANAGER_CAPABILITY, KEY_MANAGER, KeyManager.class, serviceBuilder, context, model); } else { // Use reference - keyManagerSupplier = new SSLContextExceptionSupplier<>(KEY_MANAGER_CAPABILITY, KeyManager.class, serviceBuilder, - context, keyManagerName); - } */ - keyManagerSupplier = new SSLContextExceptionSupplier<>(KEY_MANAGER_CAPABILITY, KeyManager.class, serviceBuilder, context, keyManagerName); - - final String trustManagerName = TRUST_MANAGER.resolveModelAttribute(context, model).asStringOrNull(); - /* final ModelNode trustManagerObject = TRUST_MANAGER_OBJECT.resolveModelAttribute(context, model); - if (trustManagerObject.isDefined()) { - trustManagerSupplier = (SSLContextExceptionSupplier) createTrustManager(serviceBuilder, context, keyManagerObject, pathManagerSupplier, providersSupplier); + if (!keyManagerObject.isDefined()) { + throw LOGGER.missingKeyManagerDefinition(); + } + keyManagerInjector = createKeyManager(serviceBuilder, context, keyManagerObject, providersInjector); + } + + if (trustManagerName != null) { + if (trustManagerObject.isDefined()) { + throw LOGGER.multipleTrustManagerDefinitions(); + } + trustManagerInjector = addSSLContextDependency(TRUST_MANAGER_CAPABILITY, TRUST_MANAGER, TrustManager.class, serviceBuilder, context, model); } else { - trustManagerSupplier = new SSLContextExceptionSupplier<>(TRUST_MANAGER_CAPABILITY, TrustManager.class, serviceBuilder, - context, trustManagerName); + if (!keyManagerObject.isDefined()) { + throw LOGGER.missingKeyManagerDefinition(); + } + trustManagerInjector = createTrustManager(serviceBuilder, context, keyManagerObject, providersInjector); } */ - trustManagerSupplier = new SSLContextExceptionSupplier<>(TRUST_MANAGER_CAPABILITY, TrustManager.class, serviceBuilder, context, trustManagerName); - - final SSLContextExceptionSupplier finalKeyManagerSupplier = keyManagerSupplier; - final SSLContextExceptionSupplier finalTrustManagerSupplier = trustManagerSupplier; return () -> { - X509ExtendedKeyManager keyManager = getX509KeyManager(finalKeyManagerSupplier.get()); - X509ExtendedTrustManager trustManager = getX509TrustManager(finalTrustManagerSupplier.get()); - Provider[] providers = filterProviders(providersSupplier.get(), providerName); + X509ExtendedKeyManager keyManager = getX509KeyManager(keyManagerInjector.getOptionalValue()); + X509ExtendedTrustManager trustManager = getX509TrustManager(trustManagerInjector.getOptionalValue()); + Provider[] providers = filterProviders(providersInjector.getOptionalValue(), providerName); DomainlessSSLContextBuilder builder = new DomainlessSSLContextBuilder(); if (keyManager != null) builder.setKeyManager(keyManager); @@ -1234,75 +1230,122 @@ protected void installedForResource(ServiceController serviceControl return createSSLContextDefinition(Constants.SERVER_SSL_CONTEXT, true, add, attributes, serverOrHostController); } + // TODO: Add SNI + /* static ResourceDefinition getServerSNISSLContextDefinition() { - private static ExceptionSupplier createTrustManager(ServiceBuilder serviceBuilder, OperationContext context, ModelNode model, - Supplier pathManager, - Supplier providersSupplier) throws OperationFailedException { - final String algorithmName = ALGORITHM.resolveModelAttribute(context, model).asStringOrNull(); - final String aliasFilter = ALIAS_FILTER.resolveModelAttribute(context, model).asStringOrNull(); - final String providerName = PROVIDER_NAME.resolveModelAttribute(context, model).asStringOrNull(); - - final ModelNode keyStoreObject = keystoreTMObjectDefinition.resolveModelAttribute(context, model); - final String keyStoreName = keystoreTMDefinition.resolveModelAttribute(context, model).asStringOrNull(); - ExceptionSupplier keyStoreSupplier; + AttributeDefinition[] attributes = new AttributeDefinition[] { DEFAULT_SSL_CONTEXT, HOST_CONTEXT_MAP }; - if (keyStoreName != null) { - if (keyStoreObject != null) { - throw LOGGER.multipleKeystoreDefinitions(); - } - keyStoreSupplier = new SSLContextExceptionSupplier<>(KEY_STORE_CAPABILITY, KeyStore.class, serviceBuilder, context, keyStoreName); - } else { - if (keyStoreObject == null) { - throw LOGGER.missingKeyStoreDefinition(); - } - keyStoreSupplier = createKeyStore(serviceBuilder, context, keyStoreObject, pathManager, providersSupplier); - } + AbstractAddStepHandler add = new TrivialAddHandler(SSLContext.class, attributes, SSL_CONTEXT_RUNTIME_CAPABILITY) { - final String algorithm = algorithmName != null ? algorithmName : TrustManagerFactory.getDefaultAlgorithm(); + @Override + protected ValueSupplier getValueSupplier(ServiceBuilder serviceBuilder, + OperationContext context, ModelNode model) throws OperationFailedException { - if (model.hasDefined(CERTIFICATE_REVOCATION_LIST.getName()) || model.hasDefined(OCSP.getName()) || model.hasDefined(CERTIFICATE_REVOCATION_LISTS.getName())) { - return createX509RevocationTrustManager(serviceBuilder, context, model, algorithm, providerName, keyStoreSupplier, aliasFilter, pathManager); - } + final InjectedValue defaultContext = new InjectedValue<>(); - DelegatingTrustManager delegatingTrustManager = new DelegatingTrustManager(); - return () -> { - Provider[] providers = providersSupplier.get(); - - TrustManagerFactory trustManagerFactory = createTrustManagerFactory(providers, providerName, algorithm); - KeyStore keyStore = keyStoreSupplier.get(); + ModelNode defaultContextName = DEFAULT_SSL_CONTEXT.resolveModelAttribute(context, model); + serviceBuilder.addDependency(SSL_CONTEXT_RUNTIME_CAPABILITY.getCapabilityServiceName(defaultContextName.asString()), SSLContext.class, defaultContext); - try { - if (aliasFilter != null) { - keyStore = FilteringKeyStore.filteringKeyStore(keyStore, AliasFilter.fromString(aliasFilter)); - } + ModelNode hostContextMap = HOST_CONTEXT_MAP.resolveModelAttribute(context, model); - if (LOGGER.isTraceEnabled()) { - LOGGER.tracef( - "TrustManager supplying: providers = %s provider = %s algorithm = %s trustManagerFactory = %s keyStoreName = %s keyStore = %s aliasFilter = %s keyStoreSize = %d", - Arrays.toString(providers), providerName, algorithm, trustManagerFactory, keyStoreName, keyStore, aliasFilter, keyStore.size() - ); - } - - trustManagerFactory.init(keyStoreSupplier.get()); - } catch (Exception e) { - throw new StartException(e); - } + Set keys; + if (hostContextMap.isDefined() && !(keys = hostContextMap.keys()).isEmpty()) { + final Map> sslContextMap = new HashMap<>(keys.size()); + for (String host : keys) { + String sslContextName = hostContextMap.require(host).asString(); + final InjectedValue injector = new InjectedValue<>(); + serviceBuilder.addDependency(SSL_CONTEXT_RUNTIME_CAPABILITY.getCapabilityServiceName(sslContextName), SSLContext.class, injector); + sslContextMap.put(host, injector); + } - TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); - for (TrustManager trustManager : trustManagers) { - if (trustManager instanceof X509ExtendedTrustManager) { - delegatingTrustManager.setTrustManager((X509ExtendedTrustManager) trustManager); - return delegatingTrustManager; - } - } - throw LOGGER.noTypeFound(X509ExtendedKeyManager.class.getSimpleName()); + return () -> { + SNIContextMatcher.Builder builder = new SNIContextMatcher.Builder(); + for(Map.Entry> e : sslContextMap.entrySet()) { + builder.addMatch(e.getKey(), e.getValue().getValue()); + } + return new SNISSLContext(builder + .setDefaultContext(defaultContext.getValue()) + .build()); + }; + return () -> defaultContext.getValue(); }; + + Builder builder = TrivialResourceDefinition.builder() + .setPathKey(ElytronDescriptionConstants.SERVER_SSL_SNI_CONTEXT) + .setAddHandler(add) + .setAttributes(attributes) + .setRuntimeCapabilities(SSL_CONTEXT_RUNTIME_CAPABILITY); + return builder.build(); + } */ + + private static ExceptionSupplier createTrustManager(ServiceBuilder serviceBuilder, OperationContext context, ModelNode model, + InjectedValue providersInjector) throws OperationFailedException { + final String algorithmName = ALGORITHM.resolveModelAttribute(context, model).asStringOrNull(); + final String aliasFilter = ALIAS_FILTER.resolveModelAttribute(context, model).asStringOrNull(); + final String providerName = PROVIDER_NAME.resolveModelAttribute(context, model).asStringOrNull(); + + // final ModelNode keyStoreObject = keystoreTMObjectDefinition.resolveModelAttribute(context, model); + final String keyStoreName = keystoreTMDefinition.resolveModelAttribute(context, model).asStringOrNull(); + InjectedValue keyStoreInjector = new InjectedValue<>(); + + if (keyStoreName != null) { + /* if (keyStoreObject.isDefined()) { + throw LOGGER.multipleKeyStoreDefinitions(); + } */ + serviceBuilder.addDependency(context.getCapabilityServiceName( + buildDynamicCapabilityName(KEY_STORE_CAPABILITY, keyStoreName), KeyStore.class), + KeyStore.class, keyStoreInjector); + /* } else { + if (!keyStoreObject.isDefined()) { + LOGGER.missingKeyStoreDefinition(); + } + keyStoreInjector = createKeyStore(serviceBuilder, context, keyStoreObject, providersInjector); */ + } + + final String algorithm = algorithmName != null ? algorithmName : TrustManagerFactory.getDefaultAlgorithm(); + + if (model.hasDefined(CERTIFICATE_REVOCATION_LIST.getName()) || model.hasDefined(OCSP.getName()) || model.hasDefined(CERTIFICATE_REVOCATION_LISTS.getName())) { + return createX509RevocationTrustManager(serviceBuilder, context, model, algorithm, providerName, providersInjector, keyStoreInjector, aliasFilter); + } + + DelegatingTrustManager delegatingTrustManager = new DelegatingTrustManager(); + return () -> { + Provider[] providers = providersInjector.getOptionalValue(); + + TrustManagerFactory trustManagerFactory = createTrustManagerFactory(providers, providerName, algorithm); + KeyStore keyStore = keyStoreInjector.getOptionalValue(); + + try { + if (aliasFilter != null) { + keyStore = FilteringKeyStore.filteringKeyStore(keyStore, AliasFilter.fromString(aliasFilter)); + } + + if (LOGGER.isTraceEnabled()) { + LOGGER.tracef( + "TrustManager supplying: providers = %s provider = %s algorithm = %s trustManagerFactory = %s keyStoreName = %s keyStore = %s aliasFilter = %s keyStoreSize = %d", + Arrays.toString(providers), providerName, algorithm, trustManagerFactory, keyStoreName, keyStore, aliasFilter, keyStore.size() + ); + } + + trustManagerFactory.init(keyStoreInjector.getOptionalValue()); + } catch (Exception e) { + throw new StartException(e); + } + + TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); + for (TrustManager trustManager : trustManagers) { + if (trustManager instanceof X509ExtendedTrustManager) { + delegatingTrustManager.setTrustManager((X509ExtendedTrustManager) trustManager); + return delegatingTrustManager; + } + } + throw LOGGER.noTypeFound(X509ExtendedKeyManager.class.getSimpleName()); + }; } private static ExceptionSupplier createX509RevocationTrustManager(ServiceBuilder serviceBuilder, OperationContext context, - ModelNode model, String algorithm, String providerName, ExceptionSupplier keyStoreSupplier, - String aliasFilter, Supplier pathManager) throws OperationFailedException { - + ModelNode model, String algorithm, String providerName, InjectedValue providersInjector, + InjectedValue keyStoreInjector, String aliasFilter) throws OperationFailedException { ModelNode crlNode = CERTIFICATE_REVOCATION_LIST.resolveModelAttribute(context, model); ModelNode ocspNode = OCSP.resolveModelAttribute(context, model); ModelNode multipleCrlsNode = CERTIFICATE_REVOCATION_LISTS.resolveModelAttribute(context, model); @@ -1310,8 +1353,20 @@ private static ExceptionSupplier createX509RevocationTr boolean onlyLeafCert = ONLY_LEAF_CERT.resolveModelAttribute(context, model).asBoolean(); Integer maxCertPath = MAXIMUM_CERT_PATH.resolveModelAttribute(context, model).asIntOrNull(); + //BW compatibility, max cert path is now in trust-manager + @Deprecated + Integer crlCertPath = MAXIMUM_CERT_PATH_CRL.resolveModelAttribute(context, crlNode).asIntOrNull(); + if (crlCertPath != null) { + LOGGER.warn("maximum-cert-path in certificate-revocation-list is for legacy support. Please use only the one in trust-manager!"); + if (maxCertPath != null) { + throw LOGGER.multipleMaximumCertPathDefinitions(); + } + maxCertPath = crlCertPath; + } + String crlPath; String crlRelativeTo; + InjectedValue pathManagerInjector = new InjectedValue<>(); List crlFiles = new ArrayList<>(); if (crlNode.isDefined()) { @@ -1319,14 +1374,24 @@ private static ExceptionSupplier createX509RevocationTr crlRelativeTo = RELATIVE_TO.resolveModelAttribute(context, crlNode).asStringOrNull(); if (crlPath != null) { - crlFiles.add(new CrlFile(crlPath, crlRelativeTo, pathManager)); + if (crlRelativeTo != null) { + serviceBuilder.addDependency(PathManagerService.SERVICE_NAME, PathManager.class, pathManagerInjector); + serviceBuilder.requires(pathName(crlRelativeTo)); + } + crlFiles.add(new CrlFile(crlPath, crlRelativeTo, pathManagerInjector)); } } else if (multipleCrlsNode.isDefined()) { + // certificate-revocation-lists and certificate-revocation-list are mutually exclusive for (ModelNode crl : multipleCrlsNode.asList()) { crlPath = PATH.resolveModelAttribute(context, crl).asStringOrNull(); crlRelativeTo = RELATIVE_TO.resolveModelAttribute(context, crl).asStringOrNull(); + pathManagerInjector = new InjectedValue<>(); if (crlPath != null) { - crlFiles.add(new CrlFile(crlPath, crlRelativeTo, pathManager)); + if (crlRelativeTo != null) { + serviceBuilder.addDependency(PathManagerService.SERVICE_NAME, PathManager.class, pathManagerInjector); + serviceBuilder.requires(pathName(crlRelativeTo)); + } + crlFiles.add(new CrlFile(crlPath, crlRelativeTo, pathManagerInjector)); } } } @@ -1334,11 +1399,15 @@ private static ExceptionSupplier createX509RevocationTr boolean preferCrls = PREFER_CRLS.resolveModelAttribute(context, ocspNode).asBoolean(false); String responder = RESPONDER.resolveModelAttribute(context, ocspNode).asStringOrNull(); String responderCertAlias = RESPONDER_CERTIFICATE.resolveModelAttribute(context, ocspNode).asStringOrNull(); - String responderKeystoreName = RESPONDER_KEYSTORE.resolveModelAttribute(context, ocspNode).asStringOrNull(); + String responderKeystore = RESPONDER_KEYSTORE.resolveModelAttribute(context, ocspNode).asStringOrNull(); - final ExceptionSupplier responderStoreSupplier = (responderKeystoreName != null) - ? new SSLContextExceptionSupplier<>(KEY_STORE_CAPABILITY, KeyStore.class, serviceBuilder, context, responderKeystoreName) - : keyStoreSupplier; + final InjectedValue responderStoreInjector = responderKeystore != null ? new InjectedValue<>() : keyStoreInjector; + + if (responderKeystore != null) { + serviceBuilder.addDependency(context.getCapabilityServiceName( + buildDynamicCapabilityName(KEY_STORE_CAPABILITY, responderKeystore), KeyStore.class), + KeyStore.class, responderStoreInjector); + } URI responderUri; try { @@ -1371,8 +1440,8 @@ private static ExceptionSupplier createX509RevocationTr } final List finalCrlFiles = crlFiles; return () -> { - TrustManagerFactory trustManagerFactory = createTrustManagerFactory(Security.getProviders(), providerName, algorithm); - KeyStore keyStore = keyStoreSupplier.get(); + TrustManagerFactory trustManagerFactory = createTrustManagerFactory(providersInjector.getOptionalValue(), providerName, algorithm); + KeyStore keyStore = keyStoreInjector.getOptionalValue(); if (aliasFilter != null) { try { @@ -1383,7 +1452,7 @@ private static ExceptionSupplier createX509RevocationTr } if (responderCertAlias != null) { - KeyStore responderStore = responderStoreSupplier.get(); + KeyStore responderStore = responderStoreInjector.getOptionalValue(); try { builder.setOcspResponderCert((X509Certificate) responderStore.getCertificate(responderCertAlias)); } catch (KeyStoreException e) { @@ -1407,7 +1476,7 @@ private static List getCrlStreams(List crlFiles) throws St List crlStreams = new ArrayList<>(); for (CrlFile crl : crlFiles) { try { - crlStreams.add(new FileInputStream(resolveFileLocation(crl.getCrlPath(), crl.getRelativeTo(), crl.getPathManagerSupplier()))); + crlStreams.add(new FileInputStream(resolveFileLocation(crl.getCrlPath(), crl.getRelativeTo(), crl.getPathManagerInjector()))); } catch (FileNotFoundException e) { throw LOGGER.unableToAccessCRL(e); } @@ -1415,10 +1484,10 @@ private static List getCrlStreams(List crlFiles) throws St return crlStreams; } - private static File resolveFileLocation(String path, String relativeTo, Supplier pathManagerSupplier) { + private static File resolveFileLocation(String path, String relativeTo, InjectedValue pathManagerInjector) { final File resolvedPath; if (relativeTo != null) { - PathManager pathManager = pathManagerSupplier.get(); + PathManager pathManager = pathManagerInjector.getValue(); resolvedPath = new File(pathManager.resolveRelativePathEntry(path, relativeTo)); } else { resolvedPath = new File(path); @@ -1504,35 +1573,36 @@ public X509Certificate[] getAcceptedIssuers() { } private static ExceptionSupplier createKeyManager(ServiceBuilder serviceBuilder, OperationContext context, - ModelNode model, Supplier pathManagerSupplier, - Supplier providersSupplier) throws OperationFailedException { + ModelNode model, InjectedValue providersInjector) throws OperationFailedException { final ExceptionSupplier credentialSourceSupplier = CredentialReference.getCredentialSourceSupplier(context, CREDENTIAL_REFERENCE, model, serviceBuilder); final String algorithmName = ALGORITHM.resolveModelAttribute(context, model).asStringOrNull(); final String aliasFilter = ALIAS_FILTER.resolveModelAttribute(context, model).asStringOrNull(); final String generateSelfSignedCertificateHost = GENERATE_SELF_SIGNED_CERTIFICATE_HOST.resolveModelAttribute(context, model).asStringOrNull(); final String providerName = PROVIDER_NAME.resolveModelAttribute(context, model).asStringOrNull(); - final ModelNode keyStoreObject = keystoreKMObjectDefinition.resolveModelAttribute(context, model); + // final ModelNode keyStoreObject = keystoreKMObjectDefinition.resolveModelAttribute(context, model); final String keyStoreName = keystoreKMDefinition.resolveModelAttribute(context, model).asStringOrNull(); final ModifiableKeyStoreService keyStoreService = getModifiableKeyStoreService(context, keyStoreName); - ExceptionSupplier keyStoreSupplier; + InjectedValue keyStoreInjector = new InjectedValue<>(); if (keyStoreName != null) { - if (keyStoreObject != null) { - throw LOGGER.multipleKeystoreDefinitions(); - } - keyStoreSupplier = new SSLContextExceptionSupplier<>(KEY_STORE_CAPABILITY, KeyStore.class, serviceBuilder, context, keyStoreName); - } else { - if (keyStoreObject == null) { + /* if (keyStoreObject.isDefined()) { + throw LOGGER.multipleKeyStoreDefinitions(); + } */ + serviceBuilder.addDependency(context.getCapabilityServiceName( + buildDynamicCapabilityName(KEY_STORE_CAPABILITY, keyStoreName), KeyStore.class), + KeyStore.class, keyStoreInjector); + /* } else { + if (!keyStoreObject.isDefined()) { throw LOGGER.missingKeyStoreDefinition(); } - keyStoreSupplier = createKeyStore(serviceBuilder, context, keyStoreObject, pathManagerSupplier, providersSupplier); + keyStoreInjector = createKeyStore(serviceBuilder, context, keyStoreObject, providersInjector); */ } final String algorithm = algorithmName == null ? algorithmName : KeyManagerFactory.getDefaultAlgorithm(); DelegatingKeyManager delegatingKeyManager = new DelegatingKeyManager(); return () -> { - Provider[] providers = providersSupplier.get(); + Provider[] providers = providersInjector.getOptionalValue(); KeyManagerFactory keyManagerFactory = null; if (providers != null) { for (Provider current : providers) { @@ -1554,14 +1624,15 @@ private static ExceptionSupplier createKeyManager(Service } } - KeyStore keyStore = keyStoreSupplier.get(); + KeyStore keyStore = keyStoreInjector.getOptionalValue(); char[] password; try { CredentialSource cs = credentialSourceSupplier.get(); if (cs != null) { password = cs.getCredential(PasswordCredential.class).getPassword(ClearPassword.class).getPassword(); } else { - throw new StartException(LOGGER.keyStorePasswordCannotBeResolved(keyStoreName == null ? keyStoreObject.asStringOrNull() : keyStoreName)); + // throw new StartException(LOGGER.keyStorePasswordCannotBeResolved(keyStoreName == null ? keyStoreObject.asStringOrNull() : keyStoreName)); + throw new StartException(LOGGER.keyStorePasswordCannotBeResolved(keyStoreName)); } if (LOGGER.isTraceEnabled()) { LOGGER.tracef( @@ -1621,7 +1692,14 @@ private static X509ExtendedKeyManager getX509KeyManager(KeyManager keyManager) t return null; } if (keyManager instanceof X509ExtendedKeyManager) { - return (X509ExtendedKeyManager) keyManager; + X509ExtendedKeyManager x509KeyManager = (X509ExtendedKeyManager) keyManager; + // TODO: add FIPS + /* if (x509KeyManager instanceof DelegatingKeyManager && IS_FIPS.getAsBoolean()) { + LOGGER.trace("FIPS enabled on JVM, unwrapping KeyManager"); + // If FIPS is enabled unwrap the KeyManager + x509KeyManager = ((DelegatingKeyManager) x509KeyManager).delegating.get(); + } */ + return x509KeyManager; } throw LOGGER.invalidTypeInjected(X509ExtendedKeyManager.class.getSimpleName()); } @@ -1734,13 +1812,18 @@ private static X509ExtendedTrustManager getX509TrustManager(TrustManager trustMa if (trustManager == null) { return null; } - if (trustManager instanceof X509ExtendedTrustManager) { - return (X509ExtendedTrustManager) trustManager; + if (trustManager instanceof X509ExtendedKeyManager) { + X509ExtendedTrustManager x509TrustManager = (X509ExtendedTrustManager) trustManager; + // TODO: add FIPS + /* if (x509TrustManager instanceof DelegatingTrustManager && IS_FIPS.getAsBoolean()) { + ROOT_LOGGER.trace("FIPS enabled on JVM, unwrapping TrustManager"); + x509TrustManager = ((DelegatingTrustManager)x509TrustManager).delegating.get(); + } */ + return x509TrustManager; } throw LOGGER.invalidTypeInjected(X509ExtendedTrustManager.class.getSimpleName()); } - private abstract static class ReloadableX509ExtendedTrustManager extends X509ExtendedTrustManager { abstract void reload(); } @@ -1838,121 +1921,47 @@ public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEn } } + //TODO: correctly implement creating new key stores private static ExceptionSupplier createKeyStore(ServiceBuilder serviceBuilder, OperationContext context, - ModelNode model, Supplier pathManager, - Supplier providersSupplier) throws OperationFailedException { - final String providerName = PROVIDER_NAME.resolveModelAttribute(context, model).asStringOrNull(); - final String type = TYPE.resolveModelAttribute(context, model).asStringOrNull(); - final String aliasFilter = ALIAS_FILTER.resolveModelAttribute(context, model).asStringOrNull(); - final String path = PATH.resolveModelAttribute(context, model).asStringOrNull(); - final String relativeTo = RELATIVE_TO.resolveModelAttribute(context, model).asStringOrNull(); - final boolean required = REQUIRED.resolveModelAttribute(context, model).asBoolean(false); - final ExceptionSupplier credentialSourceSupplier = CredentialReference.getCredentialSourceSupplier(context, CREDENTIAL_REFERENCE, model, serviceBuilder); - - return () -> { - AtomicLoadKeyStore keyStore = null; - FileAttributeDefinitions.PathResolver pathResolver; - File resolvedPath = null; - Provider provider = null; - - if (type != null) { - provider = resolveProviders(providerName, KeyStore.class, type, providersSupplier.get()); - keyStore = AtomicLoadKeyStore.newInstance(type, provider); - } - - if (path != null) { - pathResolver = pathResolver(); - pathResolver.path(path); - if (relativeTo != null) { - pathResolver.relativeTo(relativeTo, pathManager.get()); - } - resolvedPath = pathResolver.resolve(); - } + ModelNode model, InjectedValue providersInjector) throws OperationFailedException { return null; } - if (resolvedPath != null && ! resolvedPath.exists()) { - if (required) { - if (type == null) { - throw LOGGER.nonexistingKeyStoreMissingType(); - } else { - throw LOGGER.keyStoreFileNotExists(resolvedPath.getAbsolutePath()); - } - } else { - LOGGER.keyStoreFileNotExistsButIgnored(resolvedPath.getAbsolutePath()); - } - } - - try (FileInputStream is = (resolvedPath != null && resolvedPath.exists()) ? new FileInputStream(resolvedPath) : null) { - CredentialSource cs = credentialSourceSupplier != null ? credentialSourceSupplier.get() : null; - if (cs == null) { - throw LOGGER.keyStorePasswordCannotBeResolved(path); - } - PasswordCredential credential = cs.getCredential(PasswordCredential.class); - if (credential == null) { - throw LOGGER.keyStorePasswordCannotBeResolved(path); - } - ClearPassword clearPassword = credential.getPassword(ClearPassword.class); - if (clearPassword == null) { - throw LOGGER.keyStorePasswordCannotBeResolved(path); - } - - char[] password = clearPassword.getPassword(); - - LOGGER.tracef( - "starting: type = %s provider = %s path = %s resolvedPath = %s password = %b aliasFilter = %s", - type, provider, path, resolvedPath, password != null, aliasFilter - ); - - if (is != null) { - if (type != null) { - keyStore.load(is, password); - } else { - Provider[] resolvedProviders = providersSupplier.get(); - Provider[] finalProviders = resolvedProviders == null ? Security.getProviders() : resolvedProviders; - KeyStore detected = KeyStoreUtil.loadKeyStore(() -> finalProviders, providerName, is, resolvedPath.getPath(), password); - - if (detected == null) { - throw LOGGER.unableToDetectKeyStore(resolvedPath.getPath()); - } - - keyStore = AtomicLoadKeyStore.atomize(detected); - } - } else { - if (keyStore == null) { - String defaultType = KeyStore.getDefaultType(); - LOGGER.debugf("KeyStore: provider = %s path = %s resolvedPath = %s password = %b aliasFilter = %s does not exist. New keystore of %s type will be created.", - provider, path, resolvedPath, password != null, aliasFilter, defaultType - ); - keyStore = AtomicLoadKeyStore.newInstance(defaultType); - } - - synchronized (EmptyProvider.getInstance()) { - keyStore.load(null, password); - } - } - } - return keyStore; - }; + // Derives dynamic name from provided attribute + private static InjectedValue addSSLContextDependency(String baseName, SimpleAttributeDefinition attribute, + Class type, ServiceBuilder serviceBuilder, OperationContext context, ModelNode model) throws OperationFailedException { + String dynamicNameElement = attribute.resolveModelAttribute(context, model).asStringOrNull(); + InjectedValue injectedValue = new InjectedValue<>(); + if (dynamicNameElement != null) { + serviceBuilder.addDependency(context.getCapabilityServiceName( + buildDynamicCapabilityName(baseName, dynamicNameElement), type), + type, injectedValue); + } + return injectedValue; } - private static Provider resolveProviders(String name, Class type, String alg, Provider[] candidates) throws StartException { - Supplier resolveProvidersSupplier = () -> candidates == null ? Security.getProviders() : candidates; - Provider provider = ProviderUtil.findProvider(resolveProvidersSupplier, name, type, alg); - if (provider == null) { - throw LOGGER.noSuitableProvider(alg); + private static InjectedValue addKeyManagerDependency(String baseName, SimpleAttributeDefinition attribute, + Class type, ServiceBuilder serviceBuilder, OperationContext context, ModelNode model) throws OperationFailedException { + String dynamicNameElement = attribute.resolveModelAttribute(context, model).asStringOrNull(); + InjectedValue injectedValue = new InjectedValue<>(); + + if (dynamicNameElement != null) { + serviceBuilder.addDependency(context.getCapabilityServiceName( + buildDynamicCapabilityName(baseName, dynamicNameElement), type), + type, injectedValue); } - return provider; + return injectedValue; } - // Derives dynamic name from provided attribute - private static Supplier addRequirement(String baseName, Class type, ServiceBuilder serviceBuilder, - OperationContext context, String dynamicNameElement) { - Supplier supplier = () -> null; + private static InjectedValue addTrustManagerDependency(String baseName, SimpleAttributeDefinition attribute, + Class type, ServiceBuilder serviceBuilder, OperationContext context, ModelNode model) throws OperationFailedException { + String dynamicNameElement = attribute.resolveModelAttribute(context, model).asStringOrNull(); + InjectedValue injectedValue = new InjectedValue<>(); if (dynamicNameElement != null) { - supplier = serviceBuilder.requires(context.getCapabilityServiceName( - buildDynamicCapabilityName(baseName, dynamicNameElement), type)); + serviceBuilder.addDependency(context.getCapabilityServiceName( + buildDynamicCapabilityName(baseName, dynamicNameElement), type), + type, injectedValue); } - return supplier; + return injectedValue; } private static Provider[] filterProviders(Provider[] all, String provider) { @@ -1966,25 +1975,6 @@ private static Provider[] filterProviders(Provider[] all, String provider) { return list.toArray(new Provider[0]); } - /** - * A supplier that throws exceptions, and can be constructed from {@link ServiceBuilder} or {@link ExceptionSupplier}. - */ - private static class SSLContextExceptionSupplier implements ExceptionSupplier { - private final Supplier supplier; - private final ExceptionSupplier exceptionSupplier; - - SSLContextExceptionSupplier (String baseName, Class type, ServiceBuilder serviceBuilder, - OperationContext context, String dynamicModelElement) { - this.supplier = addRequirement(baseName, type, serviceBuilder, context, dynamicModelElement); - this.exceptionSupplier = this.supplier::get; - } - - @Override - public T get() throws E { - return exceptionSupplier.get(); - } - } - abstract static class SSLContextRuntimeHandler extends ElytronRuntimeOnlyHandler { @Override protected void executeRuntimeStep(OperationContext context, ModelNode operation) throws OperationFailedException { @@ -2004,6 +1994,31 @@ protected void executeRuntimeStep(OperationContext context, ModelNode operation) protected abstract ServiceUtil getSSLContextServiceUtil(); } + // TODO: add FIPS + /* private static BooleanSupplier getFipsSupplier() { + try { + final Class providerClazz = SSLDefinitions.class.getClassLoader().loadClass("com.sun.net.ssl.internal.ssl.Provider"); + final Method isFipsMethod = providerClazz.getMethod("isFIPS", new Class[0]); + + Object isFips; + try { + isFips = isFipsMethod.invoke(null, new Object[0]); + if ((isFips instanceof Boolean)) { + return () -> (boolean) isFips; + } else { + return () -> false; + } + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + LOGGER.trace("Unable to invoke com.sun.net.ssl.internal.ssl.Provider.isFIPS() method.", e); + return () -> false; + } + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) { + LOGGER.trace("Unable to find com.sun.net.ssl.internal.ssl.Provider.isFIPS() method.", e); + } + + return () -> new SecureRandom().getProvider().getName().toLowerCase().contains("fips"); + } */ + static ModifiableKeyStoreService getModifiableKeyStoreService(OperationContext context, String keyStoreName) { ServiceRegistry serviceRegistry = context.getServiceRegistry(true); RuntimeCapability runtimeCapability = KEY_STORE_RUNTIME_CAPABILITY.fromBaseCapability(keyStoreName); @@ -2012,15 +2027,19 @@ static ModifiableKeyStoreService getModifiableKeyStoreService(OperationContext c return (ModifiableKeyStoreService) serviceContainer.getService(); } + /** + * CrlFile contains the necessary information to create a + * CRL File Input Stream + */ static class CrlFile { private final String crlPath; private final String relativeTo; - private final Supplier pathManagerSupplier; + private final InjectedValue pathManagerInjector; - public CrlFile(final String crlPath, final String relativeTo, Supplier pathManagerSupplier) { + public CrlFile(final String crlPath, final String relativeTo, InjectedValue pathManagerInjector) { this.crlPath = crlPath; this.relativeTo = relativeTo; - this.pathManagerSupplier = pathManagerSupplier; + this.pathManagerInjector = pathManagerInjector; } public String getCrlPath() { @@ -2031,8 +2050,8 @@ public String getRelativeTo() { return relativeTo; } - public Supplier getPathManagerSupplier() { - return pathManagerSupplier; + public InjectedValue getPathManagerInjector() { + return pathManagerInjector; } } diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecretKeyCredentialStoreDefinition.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecretKeyCredentialStoreDefinition.java index 01bc163..ac839c1 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecretKeyCredentialStoreDefinition.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecretKeyCredentialStoreDefinition.java @@ -16,7 +16,6 @@ package org.wildfly.extension.elytron.tls.subsystem; -import static org.jboss.as.controller.AbstractControllerService.PATH_MANAGER_CAPABILITY; import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.CREDENTIAL_STORE_API_CAPABILITY; import static org.wildfly.extension.elytron.tls.subsystem.Capabilities.CREDENTIAL_STORE_RUNTIME_CAPABILITY; import static org.wildfly.extension.elytron.tls.subsystem.ElytronTlsExtension.isServerOrHostController; @@ -30,6 +29,7 @@ import java.security.GeneralSecurityException; import java.util.HashMap; import java.util.Map; +import java.util.function.Supplier; import javax.crypto.SecretKey; @@ -49,6 +49,7 @@ import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver; import org.jboss.as.controller.registry.ManagementResourceRegistration; import org.jboss.as.controller.registry.OperationEntry; +import org.jboss.as.controller.services.path.PathManagerService; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.jboss.msc.service.StartException; @@ -236,13 +237,14 @@ protected void resolveRuntime(ModelNode model, OperationContext context) throws @Override protected ExceptionSupplier prepareServiceSupplier(OperationContext context, - CapabilityServiceBuilder serviceBuilder) { + CapabilityServiceBuilder serviceBuilder) { + final Supplier pathManager; if (relativeTo != null) { - pathManagerSupplier = serviceBuilder.requires(PATH_MANAGER_CAPABILITY.getCapabilityServiceName()); + pathManager = serviceBuilder.requires(PathManagerService.SERVICE_NAME); serviceBuilder.requires(pathName(relativeTo)); } else { - pathManagerSupplier = null; + pathManager = null; } return new ExceptionSupplier() { @@ -253,7 +255,7 @@ public CredentialStore get() throws StartException { PathResolver pathResolver = pathResolver(); pathResolver.path(path); if (relativeTo != null) { - pathResolver.relativeTo(relativeTo, pathManagerSupplier.get()); + pathResolver.relativeTo(relativeTo, pathManager.get()); } File resolved = pathResolver.resolve(); pathResolver.clear(); diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecurityPropertiesWriteHandler.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecurityPropertiesWriteHandler.java index 423ecc9..416509e 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecurityPropertiesWriteHandler.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecurityPropertiesWriteHandler.java @@ -32,7 +32,7 @@ /** * @author Tomaz Cerar (c) 2017 Red Hat Inc. */ -class SecurityPropertiesWriteHandler extends AbstractWriteAttributeHandler{ +class SecurityPropertiesWriteHandler extends AbstractWriteAttributeHandler { private final PropertiesAttributeDefinition securityProperties; SecurityPropertiesWriteHandler(PropertiesAttributeDefinition attributeDefinition) { @@ -64,7 +64,7 @@ private static void removeProperty(OperationContext context, String name) { } @Override - protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode resolvedValue, ModelNode currentValue, HandbackHolder handbackHolder) throws OperationFailedException { + protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode resolvedValue, ModelNode currentValue, HandbackHolder handbackHolder) throws OperationFailedException { Map newProps = securityProperties.unwrap(context, resolvedValue); Map oldProps = securityProperties.unwrap(context, currentValue); setProperties(context, newProps, oldProps); @@ -92,7 +92,7 @@ private void setProperties(final OperationContext context, Map n } @Override - protected void revertUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode valueToRestore, ModelNode valueToRevert, Void handback) throws OperationFailedException { + protected void revertUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode valueToRestore, ModelNode valueToRevert, Object handback) throws OperationFailedException { Map newProps = securityProperties.unwrap(context, valueToRestore); Map oldProps = securityProperties.unwrap(context, valueToRevert); setProperties(context, newProps, oldProps); diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecurityPropertyService.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecurityPropertyService.java index c06a0f9..77a0073 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecurityPropertyService.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SecurityPropertyService.java @@ -27,7 +27,7 @@ import java.util.Map; import java.util.Properties; -import org.jboss.msc.Service; +import org.jboss.msc.service.Service; import org.jboss.msc.service.ServiceName; import org.jboss.msc.service.StartContext; import org.jboss.msc.service.StartException; @@ -41,7 +41,7 @@ * * @author Darran Lofthouse */ -class SecurityPropertyService implements Service { +class SecurityPropertyService implements Service { static final ServiceName SERVICE_NAME = ElytronTlsExtension.BASE_SERVICE_NAME.append(Constants.SECURITY_PROPERTIES); @@ -86,6 +86,11 @@ public synchronized void stop(StopContext context) { started = false; } + @Override + public Void getValue() throws IllegalStateException, IllegalArgumentException { + return null; + } + private void restoreProperty(String name, String restorationValue) { if (restorationValue == null) { try { diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/TrivialService.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/TrivialService.java index 85dc497..43a4f68 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/TrivialService.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/TrivialService.java @@ -58,11 +58,7 @@ void setValueSupplier(ValueSupplier valueSupplier) { @Override public void start(StartContext context) throws StartException { - try { - value = checkNotNullParam("valueSupplier", valueSupplier).get(); - } catch (Exception e) { - throw new StartException(e); - } + value = checkNotNullParam("valueSupplier", valueSupplier).get(); if (valueConsumer != null) { valueConsumer.accept(value); } @@ -86,7 +82,7 @@ public T getValue() throws IllegalStateException, IllegalArgumentException { @FunctionalInterface interface ValueSupplier { - T get() throws Exception; + T get() throws StartException; default void dispose() {} diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/TrustManagerBuilder.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/TrustManagerBuilder.java deleted file mode 100644 index 9c4310b..0000000 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/TrustManagerBuilder.java +++ /dev/null @@ -1,51 +0,0 @@ - /* - * Copyright 2022 Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.wildfly.extension.elytron.tls.subsystem; - -import java.security.KeyStore; - -import javax.net.ssl.TrustManager; - -import org.wildfly.common.function.ExceptionSupplier; - -public class TrustManagerBuilder { - private ExceptionSupplier keyStoreSupplier; - private String keyStoreReferenceName; - private String aliasFilter; - private String algorithm; - private int maximumCertPath; - private boolean onlyLeafCert; - private boolean softFail; - private String providerName; - - private String ocspResponder; - private boolean preferCrls; - private String responderCertificate; - private ExceptionSupplier responderKeyStore; - - - public TrustManagerBuilder() { - - } - - public TrustManager build() { - - - return null; - } - -} diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/Validators.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/Validators.java index 9040f6a..7c81eba 100644 --- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/Validators.java +++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/Validators.java @@ -18,8 +18,12 @@ import static org.wildfly.extension.elytron.tls.subsystem._private.ElytronTLSLogger.LOGGER; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.operations.validation.ModelTypeValidator; +import org.jboss.as.controller.operations.validation.ParameterValidator; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.wildfly.security.ssl.CipherSuiteSelector; @@ -63,4 +67,31 @@ public void validateParameter(String parameterName, ModelNode value) throws Oper } } } + + static class HostContextMapValidator implements ParameterValidator { + // Hostnames can contain ASCII letters a-z (case-insensitive), digits 0-9, hyphens and dots. + // This pattern allows also [,],*,? characters to make regular expressions possible. Non-escaped dot represents any character, escaped dot is delimeter. + static Pattern hostnameRegexPattern = Pattern.compile("[0-9a-zA-Z\\[.*]" + // first character can be digit, letter, left square bracket, non-escaped dot or asterisk + "([0-9a-zA-Z*.\\[\\]?^-]" + // any combination of digits, letters, asterisks, non-escaped dots, square brackets, question marks, hyphens and carets + "|" + // OR + "(? nodes = assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT).asList(); assertEquals(2, nodes.size()); operation = new ModelNode(); operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store","ModifiedKeyStore"); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store","ModifiedKeyStore"); operation.get(ClientConstants.OP).set(Constants.REMOVE_ALIAS); operation.get(Constants.ALIAS).set("ca"); assertSuccess(services.executeOperation(operation)); operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store","ModifiedKeyStore"); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store","ModifiedKeyStore"); operation.get(ClientConstants.OP).set(Constants.READ_ALIASES); nodes = assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT).asList(); assertEquals(1, nodes.size()); operation = new ModelNode(); // remove keystore operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store","ModifiedKeyStore"); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store","ModifiedKeyStore"); operation.get(ClientConstants.OP).set(ClientConstants.REMOVE_OPERATION); assertSuccess(services.executeOperation(operation)); } @@ -439,7 +439,7 @@ public void testKeystoreReadVerbose() throws Exception { ModelNode operation = new ModelNode(); // add keystore operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store", "ModifiedKeyStore"); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", "ModifiedKeyStore"); operation.get(ClientConstants.OP).set(ClientConstants.ADD); operation.get(Constants.PATH).set(resources + "/firefly-copy.keystore"); operation.get(Constants.TYPE).set("JKS"); @@ -447,7 +447,7 @@ public void testKeystoreReadVerbose() throws Exception { assertSuccess(services.executeOperation(operation)); operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store","ModifiedKeyStore"); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store","ModifiedKeyStore"); operation.get(ClientConstants.OP).set(Constants.READ_ALIASES); List nodes = assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT).asList(); assertEquals(2, nodes.size()); @@ -459,7 +459,7 @@ public void testKeystoreReadVerbose() throws Exception { validateRecursiveReadAliases(false); operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store","ModifiedKeyStore"); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store","ModifiedKeyStore"); operation.get(ClientConstants.OP).set(Constants.READ_ALIAS); operation.get(Constants.ALIAS).set("firefly"); operation.get(Constants.VERBOSE).set(false); @@ -468,7 +468,7 @@ public void testKeystoreReadVerbose() throws Exception { private void validateRecursiveReadAliases(final boolean verbose) { ModelNode operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store","ModifiedKeyStore"); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store","ModifiedKeyStore"); operation.get(ClientConstants.OP).set(Constants.READ_ALIASES); operation.get(Constants.VERBOSE).set(verbose); operation.get(Constants.RECURSIVE).set(true); @@ -490,7 +490,7 @@ private void validateRecursiveReadAliases(final boolean verbose) { } final ModelNode readOperation = new ModelNode(); - readOperation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store","ModifiedKeyStore"); + readOperation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store","ModifiedKeyStore"); readOperation.get(ClientConstants.OP).set(Constants.READ_ALIAS); readOperation.get(Constants.VERBOSE).set(verbose); readOperation.get(Constants.ALIAS).set(alias); @@ -539,25 +539,6 @@ public void testFilteringKeystoreService() throws Exception { assertFalse(keyStore.isCertificateEntry("ca")); } - @Test - public void testFilteringKeystoreCli() throws Exception { - ModelNode operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add(Constants.FILTERING_KEY_STORE,"FilteringKeyStore"); - operation.get(ClientConstants.OP).set(Constants.READ_ALIASES); - List nodes = assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT).asList(); - assertEquals(1, nodes.size()); - assertEquals("firefly", nodes.get(0).asString()); - - operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add(Constants.FILTERING_KEY_STORE,"FilteringKeyStore"); - operation.get(ClientConstants.OP).set(Constants.READ_ALIAS); - operation.get(Constants.ALIAS).set("firefly"); - ModelNode firefly = assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT); - assertEquals("firefly", firefly.get(Constants.ALIAS).asString()); - assertEquals(KeyStore.PrivateKeyEntry.class.getSimpleName(), firefly.get(Constants.ENTRY_TYPE).asString()); - assertTrue(firefly.get(Constants.CERTIFICATE_CHAIN).isDefined()); - } - @Test public void testAutomaticKeystoreService() throws Exception { ServiceName serviceName = Capabilities.KEY_STORE_RUNTIME_CAPABILITY.getCapabilityServiceName("AutomaticKeystore"); @@ -584,17 +565,17 @@ public void testAutomaticKeystoreService() throws Exception { @Test public void testAutomaticKeystoreCli() throws Exception { ModelNode operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron"); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls"); operation.get(ClientConstants.OP).set("read-resource"); System.out.println(services.executeOperation(operation).get(ClientConstants.RESULT).asString()); operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add(Constants.KEY_STORE,"AutomaticKeystore"); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add(Constants.KEY_STORE,"AutomaticKeystore"); operation.get(ClientConstants.OP).set(Constants.READ_ALIASES); List nodes = assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT).asList(); assertEquals(2, nodes.size()); operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add(Constants.KEY_STORE,"AutomaticKeystore"); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add(Constants.KEY_STORE,"AutomaticKeystore"); operation.get(ClientConstants.OP).set(Constants.READ_ALIAS); operation.get(Constants.ALIAS).set("firefly"); ModelNode firefly = assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT); @@ -603,7 +584,7 @@ public void testAutomaticKeystoreCli() throws Exception { assertTrue(firefly.get(Constants.CERTIFICATE_CHAIN).isDefined()); operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add(Constants.KEY_STORE,"AutomaticKeystore"); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add(Constants.KEY_STORE,"AutomaticKeystore"); operation.get(ClientConstants.OP).set(Constants.READ_ALIAS); operation.get(Constants.ALIAS).set("ca"); ModelNode ca = assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT); @@ -1319,7 +1300,7 @@ private void addKeyStore(String keyStoreFile, String keyStoreName, String keySto Files.copy(resources.resolve(keyStoreFile), resources.resolve("test-copy.keystore"), java.nio.file.StandardCopyOption.REPLACE_EXISTING); ModelNode operation = new ModelNode(); operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store", keyStoreName); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", keyStoreName); operation.get(ClientConstants.OP).set(ClientConstants.ADD); operation.get(Constants.PATH).set(resources + "/test-copy.keystore"); operation.get(Constants.TYPE).set("JKS"); @@ -1337,7 +1318,7 @@ private void addOriginalKeyStore() throws Exception { Files.copy(resources.resolve("test-original.keystore"), resources.resolve("test-copy.keystore"), java.nio.file.StandardCopyOption.REPLACE_EXISTING); ModelNode operation = new ModelNode(); operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store", KEYSTORE_NAME); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", KEYSTORE_NAME); operation.get(ClientConstants.OP).set(ClientConstants.ADD); operation.get(Constants.PATH).set(resources + "/test-copy.keystore"); operation.get(Constants.TYPE).set("JKS"); @@ -1347,14 +1328,14 @@ private void addOriginalKeyStore() throws Exception { private List readAliases() { ModelNode operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store", KEYSTORE_NAME); + operation.get(ClientConstants.OP_ADDR).add("subsystem","`elytron-tls").add("key-store", KEYSTORE_NAME); operation.get(ClientConstants.OP).set(Constants.READ_ALIASES); return assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT).asList(); } private ModelNode readAlias(String aliasName) { ModelNode operation = new ModelNode(); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store", KEYSTORE_NAME); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", KEYSTORE_NAME); operation.get(ClientConstants.OP).set(Constants.READ_ALIAS); operation.get(Constants.ALIAS).set(aliasName); ModelNode alias = assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT); @@ -1377,7 +1358,7 @@ private void removeKeyStore() { private void removeKeyStore(String keyStoreName) { ModelNode operation = new ModelNode(); operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store", keyStoreName); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", keyStoreName); operation.get(ClientConstants.OP).set(ClientConstants.REMOVE_OPERATION); assertSuccess(services.executeOperation(operation)); } @@ -1389,7 +1370,7 @@ private ModelNode getAddKeyStoreUsingNonExistingFileOperation(boolean required, ModelNode operation = new ModelNode(); operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("key-store", KEYSTORE_NAME); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", KEYSTORE_NAME); operation.get(ClientConstants.OP).set(ClientConstants.ADD); operation.get(Constants.PATH).set(resources + nonExistentFileName); operation.get(Constants.TYPE).set("JKS"); @@ -1433,7 +1414,7 @@ private void removeCertificateAuthority() { private void removeCertificateAuthorityAccount() { ModelNode operation = new ModelNode(); operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE); - operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add("certificate-authority-account", CERTIFICATE_AUTHORITY_ACCOUNT_NAME); + operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls`").add("certificate-authority-account", CERTIFICATE_AUTHORITY_ACCOUNT_NAME); operation.get(ClientConstants.OP).set(ClientConstants.REMOVE_OPERATION); assertSuccess(services.executeOperation(operation)); } diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/account.keystore b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/account.keystore new file mode 100644 index 0000000..cc62266 Binary files /dev/null and b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/account.keystore differ diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/test-original.keystore b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/test-original.keystore new file mode 100644 index 0000000..d6f215c Binary files /dev/null and b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/test-original.keystore differ diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-ibm.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-ibm.xml index da99b62..448656a 100644 --- a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-ibm.xml +++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-ibm.xml @@ -4,14 +4,6 @@ - - - - - - - - @@ -151,4 +143,12 @@ trust-manager="CaTrustManager" providers="ManagerProviderLoader"/> + + + + + + + + diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-oracle13plus.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-oracle13plus.xml index b6e5d8c..df5b0b1 100644 --- a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-oracle13plus.xml +++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-oracle13plus.xml @@ -4,14 +4,6 @@ - - - - - - - - @@ -155,4 +147,12 @@ trust-manager="CaTrustManager" providers="ManagerProviderLoader"/> + + + + + + + + diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-sun.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-sun.xml index 49fa533..928a3c4 100644 --- a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-sun.xml +++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-sun.xml @@ -4,14 +4,6 @@ - - - - - - - - @@ -155,4 +147,12 @@ trust-manager="CaTrustManager" providers="ManagerProviderLoader"/> + + + + + + + + diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls.xml index 304c3fe..cacb7cc 100644 --- a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls.xml +++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls.xml @@ -2,27 +2,6 @@ - - - - - - - - - - - - - - - - - - - @@ -102,6 +81,27 @@ provider-name="first" /> + + + + + + + + + + + + + + + + + + +