Skip to content

Commit

Permalink
[ELY-1996] [Community] SSLContext to support delegation to alternate …
Browse files Browse the repository at this point in the history
…instances based on peer information.
  • Loading branch information
Skyllarr committed Mar 18, 2024
1 parent b80aa6a commit 1f76fa0
Show file tree
Hide file tree
Showing 20 changed files with 1,775 additions and 2 deletions.
2 changes: 1 addition & 1 deletion ELY_Messages.txt
Expand Up @@ -126,7 +126,7 @@
24000 - 24999 wildfly-elytron-jose-jwk
25000 - 25999 wildfly-elytron-jose-jws
26000 - 26999 wildfly-elytron-jose-util
27000 - 27999
27000 - 27999 wildfly-elytron-dynamic-ssl
28000 - 28999
29000 - 29999
30000 - 30999
Expand Down
1 change: 0 additions & 1 deletion auth/client/pom.xml
Expand Up @@ -76,7 +76,6 @@
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-ssh-util</artifactId>
</dependency>

<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-annotations</artifactId>
Expand Down
Expand Up @@ -361,6 +361,10 @@ public <T, E extends Exception> T runAsSupplierEx(ExceptionSupplier<T, E> action
return runExFunction(ExceptionSupplier::get, action);
}

RuleNode<SecurityFactory<SSLContext>> getSslRules() {
return this.sslRules;
}

public ContextManager<AuthenticationContext> getInstanceContextManager() {
return getContextManager();
}
Expand Down
Expand Up @@ -30,7 +30,9 @@
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;

Expand Down Expand Up @@ -196,6 +198,46 @@ private static AuthenticationConfiguration initializeConfiguration(final URI uri
return configuration;
}

/**
* Get all SSL contexts configured for this authentication context.
*
* @param authenticationContext the authentication context to examine (must not be {@code null})
* @return List of all configured SSL contexts belonging to the provided authentication context
*/
public List<SSLContext> getConfiguredSSLContexts(AuthenticationContext authenticationContext) throws GeneralSecurityException {
List<SSLContext> sslContexts = new ArrayList<>();
if (authenticationContext == null) {
return sslContexts;
}
RuleNode<SecurityFactory<SSLContext>> node = authenticationContext.getSslRules();
while (node != null) {
sslContexts.add(node.getConfiguration().create());
node = node.getNext();
}
return sslContexts;
}

/**
* Get the default SSL context that should be used when no other rules match, or {@link SSLContext#getDefault()} if there is none configured.
*
* @param authenticationContext the authentication context to examine (must not be {@code null})
* @return the default SSL context configured if no other rules match
*/
public SSLContext getDefaultSSLContext(AuthenticationContext authenticationContext) throws GeneralSecurityException {
SSLContext defaultSSLContext = null;
if (authenticationContext == null) {
return SSLContext.getDefault();
}
RuleNode<SecurityFactory<SSLContext>> node = authenticationContext.getSslRules();
while (node != null) {
if (node.getRule().equals(MatchRule.ALL)) {
defaultSSLContext = node.getConfiguration().create();
}
node = node.getNext();
}
return defaultSSLContext == null ? SSLContext.getDefault() : defaultSSLContext;
}

/**
* Get the configured SSL context which matches ALL rules from provided AuthenticationContext, or {@link SSLContext#getDefault()} if there is none.
*
Expand Down
76 changes: 76 additions & 0 deletions dynamic-ssl/pom.xml
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-parent</artifactId>
<version>2.3.2.CR1-SNAPSHOT</version>
</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>wildfly-elytron-dynamic-ssl</artifactId>

<name>WildFly Elytron - Dynamic SSL</name>
<description>WildFly Security Dynamic SSL Implementation</description>
<dependencies>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-processor</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logmanager</groupId>
<artifactId>jboss-logmanager</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-client</artifactId>
</dependency>
<dependency>
<groupId>org.kohsuke.metainf-services</groupId>
<artifactId>metainf-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wildfly.common</groupId>
<artifactId>wildfly-common</artifactId>
<scope>compile</scope>
</dependency>

<!--test dependencies-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- Mock Web Server -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-netty</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wildfly.client</groupId>
<artifactId>wildfly-client-config</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,54 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2024 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.security.dynamic.ssl;

import javax.net.ssl.SSLContext;
import java.security.NoSuchAlgorithmException;

/**
* SSLContext that resolves which SSLContext to use based on peer's host and port information.
*
* @author <a href="mailto:dvilkola@redhat.com">Diana Krepinska</a>
*/
public final class DynamicSSLContext extends SSLContext {

private static SSLContext resolverSSLContext(DynamicSSLContextSPI dynamicSSLContextSPIImpl) throws NoSuchAlgorithmException, DynamicSSLContextException {
return dynamicSSLContextSPIImpl.getConfiguredDefault() == null ?
SSLContext.getDefault() : dynamicSSLContextSPIImpl.getConfiguredDefault();
}

/**
* This constructor uses ServiceLoader to find provider of DynamicSSLContextSPI on classpath.
*/
public DynamicSSLContext() throws NoSuchAlgorithmException {
// this does not use provider and protocol from DynamicSSLContextSPI implementation found on classpath
// to avoid this ServiceLoader.load would have to be called 3 times in separate static method
super(new DynamicSSLContextSpiImpl(), SSLContext.getDefault().getProvider(), SSLContext.getDefault().getProtocol());
}

/**
* This constructor uses received DynamicSSLContextSPI implementation or finds it on classpath if received is null.
*
* @param dynamicSSLContextSPIImpl DynamicSSLContextSPI implementation to use. If null then ServiceLoader is used to locate it on classpath.
*/
public DynamicSSLContext(DynamicSSLContextSPI dynamicSSLContextSPIImpl) throws NoSuchAlgorithmException, DynamicSSLContextException {
super(new DynamicSSLContextSpiImpl(dynamicSSLContextSPIImpl),
resolverSSLContext(dynamicSSLContextSPIImpl).getProvider(),
resolverSSLContext(dynamicSSLContextSPIImpl).getProtocol());
}
}
@@ -0,0 +1,42 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2024 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.security.dynamic.ssl;

/**
* Exception to indicate a failure related to the DynamicSSLContext.
*
* @author <a href="mailto:dvilkola@redhat.com">Diana Krepinska</a>
*/
public class DynamicSSLContextException extends Exception {
private static final long serialVersionUID = 894798122053539237L;

public DynamicSSLContextException() {
}

public DynamicSSLContextException(String msg) {
super(msg);
}

public DynamicSSLContextException(String message, Throwable cause) {
super(message, cause);
}

public DynamicSSLContextException(Throwable cause) {
super(cause);
}
}
@@ -0,0 +1,90 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2024 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.security.dynamic.ssl;

import org.kohsuke.MetaInfServices;
import org.wildfly.common.Assert;
import org.wildfly.security.auth.client.AuthenticationContext;
import org.wildfly.security.auth.client.AuthenticationContextConfigurationClient;

import javax.net.ssl.SSLContext;
import java.net.URI;
import java.security.AccessController;
import java.security.GeneralSecurityException;
import java.security.PrivilegedAction;
import java.util.List;

/**
* Elytron client implementation of DynamicSSLContextSPI. It uses configuration from either provided instance of AuthenticationContext
* or from current AuthenticationContext if a configuration was not provided.
*
* @author <a href="mailto:dvilkola@redhat.com">Diana Krepinska (Vilkolakova)</a>
*/
@MetaInfServices(value = DynamicSSLContextSPI.class)
public class DynamicSSLContextImpl implements DynamicSSLContextSPI {

private final AuthenticationContextConfigurationClient AUTH_CONTEXT_CLIENT =
AccessController.doPrivileged((PrivilegedAction<AuthenticationContextConfigurationClient>) AuthenticationContextConfigurationClient::new);
private AuthenticationContext authenticationContext;
private SSLContext configuredDefaultSSLContext;
private List<SSLContext> configuredSSLContexts;

public DynamicSSLContextImpl() throws GeneralSecurityException {
}

public DynamicSSLContextImpl(AuthenticationContext authenticationContext) throws GeneralSecurityException {
Assert.assertNotNull("authenticationContext");
this.authenticationContext = authenticationContext;
this.configuredSSLContexts = AUTH_CONTEXT_CLIENT.getConfiguredSSLContexts(authenticationContext);
this.configuredDefaultSSLContext = AUTH_CONTEXT_CLIENT.getDefaultSSLContext(authenticationContext);
}

@Override
public SSLContext getConfiguredDefault() throws DynamicSSLContextException {
if (this.configuredDefaultSSLContext != null) {
return this.configuredDefaultSSLContext;
}
try {
return AUTH_CONTEXT_CLIENT.getDefaultSSLContext(AuthenticationContext.captureCurrent());
} catch (GeneralSecurityException e) {
throw ElytronMessages.log.cannotObtainDefaultSSLContext(e);
}
}

@Override
public List<SSLContext> getConfiguredSSLContexts() throws DynamicSSLContextException {
if (this.configuredSSLContexts != null) {
return this.configuredSSLContexts;
}
try {
return AUTH_CONTEXT_CLIENT.getConfiguredSSLContexts(AuthenticationContext.captureCurrent());
} catch (GeneralSecurityException e) {
throw ElytronMessages.log.cannotObtainConfiguredSSLContexts(e);
}
}

@Override
public SSLContext getSSLContext(URI uri) throws DynamicSSLContextException {
try {
return AUTH_CONTEXT_CLIENT.getSSLContext(uri, authenticationContext == null ? AuthenticationContext.captureCurrent() : authenticationContext);
} catch (GeneralSecurityException e) {
throw ElytronMessages.log.cannotObtainSSLContextForGivenURI(e);
}
}
}

0 comments on commit 1f76fa0

Please sign in to comment.