Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add an example to demonstrate how to configure OCSP stapling using TLS #212

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
322 changes: 322 additions & 0 deletions ocsp-stapling/README.md

Large diffs are not rendered by default.

85 changes: 85 additions & 0 deletions ocsp-stapling/configure-elytron.cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Batch script to configure Elytron for the example mutual TLS application on the WildFly server

# Start batching commands
batch


## Filesystem Realm and Security Domain ##
# Add a filesystem realm that resides in directory tlsFsRealmUsers inside the base configuration directory defined by jboss.server.config.dir property.
/subsystem=elytron/filesystem-realm=tlsFsRealm:add(path=tlsFsRealmUsers, relative-to=jboss.server.config.dir)

# Add the example identity
/subsystem=elytron/filesystem-realm=tlsFsRealm:add-identity(identity=example_user)

# Add the password for the example identity
/subsystem=elytron/filesystem-realm=tlsFsRealm:set-password(identity=example_user, clear={password=examplePwd1!})

# Add the guest role for the example identity
/subsystem=elytron/filesystem-realm=tlsFsRealm:add-identity-attribute(identity=example_user, name=Roles, value=[guest])

# Configure the security domain using the filesystem realm
/subsystem=elytron/security-domain=tlsFsSD:add(realms=[{realm=tlsFsRealm}],default-realm=tlsFsRealm,permission-mapper=default-permission-mapper)

# Add the security domain mapping to the EJB3 subsystem
/subsystem=ejb3/application-security-domain=tlsApp:add(security-domain=tlsFsSD)


## Server KeyStore and TrustStore ##
# Add the key store for the server in the base configuration directory
/subsystem=elytron/key-store=tlsKeyStore:add(path=server.keystore,relative-to=jboss.server.config.dir,credential-reference={clear-text=password})
/subsystem=elytron/key-store=tlsKeyStore:load()

# Run the batched commands to start the key store
run-batch

# Add the key manager to reference the key store
/subsystem=elytron/key-manager=tlsKM:add(key-store=tlsKeyStore,credential-reference={clear-text=password})

# Add the trust store for holding certificates in the base configuration directory
/subsystem=elytron/key-store=tlsTrustStore:add(path=tlsServer.truststore,relative-to=jboss.server.config.dir,credential-reference={clear-text=serverTrustSecret})
/subsystem=elytron/key-store=tlsTrustStore:import-certificate(alias=client,path=/PATH/TO/tlsClient.cer,credential-reference={clear-text=serverTrustSecret},trust-cacerts=true,validate=false)
/subsystem=elytron/key-store=tlsTrustStore:store()

# Run the batched commands to start the trust server
run-batch

# Start batching commands again
batch

# Import the client certificate into the trust store. Since the certificate is self-signed, it will not be validated
/subsystem=elytron/key-store=tlsTrustStore:import-certificate(alias=client,path=/PATH/TO/tlsClient.cer,credential-reference={clear-text=serverTrustSecret},trust-cacerts=true,validate=false)

# Store the trust store to file
/subsystem=elytron/key-store=tlsTrustStore:store()

# Configure the trust manager to reference the trust store
/subsystem=elytron/trust-manager=tlsTM:add(key-store=tlsTrustStore)

## TLS, SASL and Connector Configuration ##
# Add the server SSL/TLS context to reference the trust and key managers. This context requires client authentication for mutual TLS, and supports TLSv1.2 and TLSv1.3
/subsystem=elytron/server-ssl-context=tlsSSC:add(key-manager=tlsKM,protocols=["TLSv1.3","TLSv1.2"],cipher-suite-names=TLS_AES_128_GCM_SHA256,trust-manager=tlsTM,need-client-auth=true)
/subsystem=elytron/server-ssl-context=tlsSSC:write-attribute(name=ocsp-stapling, value={responder-uri=http://127.0.0.1:10000, response-timeout=5000, cache-size=256, cache-lifetime=3600, responder-override=true})

# Run the batched commands
run-batch

# Start batching commands again
batch

# Configure the https-listener to use Elytron's SSL/TLS context
/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=ssl-context,value=tlsSSC)

# Add the SASL authentication factory to use SCRAM-SHA-512-PLUS for channel binding, and the security domain
/subsystem=elytron/sasl-authentication-factory=tlsSASLFactory:add(sasl-server-factory=configured,security-domain=tlsFsSD,mechanism-configurations=[{mechanism-name=SCRAM-SHA-512-PLUS}])

# Add the remote HTTP connector using the HTTPS listener and SASL authentication factory
/subsystem=remoting/http-connector=tlsConnector:add(connector-ref=https,sasl-authentication-factory=tlsSASLFactory)

# Add the remote HTTPS connector to the ejb3 subsystem
/subsystem=ejb3/service=remote:write-attribute(name=connectors,value=[tlsConnector])

# Run the batched commands
run-batch

# Reload the server configuration
reload
49 changes: 49 additions & 0 deletions ocsp-stapling/openssl.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
dir = /PATH/TO/ocsp-stapling/demoCA

[ server ]
default_server = wildfly

[ wildfly ]
certificate = $dir/server.crt
database = $dir/index.txt
new_certs_dir = $dir/newcerts
private_key = $dir/server.keystore
serial = $dir/serial

default_crl_days = 365
default_days = 3650
default_md = sha256

policy = wildfly_policy
x509_extensions = v3_req

email_in_dn = no

[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
default_bits = 2048
default_md = sha256
default_keyfile = server.keystore
x509_extensions = v3_req

[ req_distinguished_name ]
commonName = wildfly
stateOrProvinceName = ON
countryName = CA
organizationName = elytron

[ wildfly_policy ]
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ v3_req ]
authorityInfoAccess = OCSP;URI:http://127.0.0.1:10000
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = OCSPSigning
96 changes: 96 additions & 0 deletions ocsp-stapling/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wildfly.security.examples</groupId>
<artifactId>ocsp-stapling-tls</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<version.org.wildfly.plugins.wildfly-maven-plugins>2.0.2.Final</version.org.wildfly.plugins.wildfly-maven-plugins>
<version.org.apache.maven.plugins.maven-ejb-plugins>3.2.1</version.org.apache.maven.plugins.maven-ejb-plugins>
<version.wildfly>33.0.0.Final-SNAPSHOT</version.wildfly>
<version.org.codehaus.mojo.exec-maven-plugin>3.0.0</version.org.codehaus.mojo.exec-maven-plugin>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.wildfly.bom</groupId>
<artifactId>wildfly-ee-with-tools</artifactId>
<scope>import</scope>
<type>pom</type>
<version>${version.wildfly}</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<type>pom</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron</artifactId>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>10.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>${version.org.wildfly.plugins.wildfly-maven-plugins}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>${version.org.apache.maven.plugins.maven-ejb-plugins}</version>
<configuration>
<ejbVersion>${version.org.apache.maven.plugins.maven-ejb-plugins}</ejbVersion>
<generateClient>true</generateClient>
</configuration>
</plugin>
<!-- Add the Maven exec plug-in to allow us to run a Java program via Maven -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>${version.org.codehaus.mojo.exec-maven-plugin}</version>
<configuration>
<executable>java</executable>
<workingDirectory>${project.build.directory}/exec-working-directory</workingDirectory>
<arguments>
<!-- automatically creates the classpath using all project dependencies,
also adding the project build directory -->
<argument>-classpath</argument>
<classpath/>
<argument>org.wildfly.security.examples.RemoteClient</argument>
</arguments>
</configuration>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
86 changes: 86 additions & 0 deletions ocsp-stapling/restore-configuration.cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Batch script to restore the WildFly configuration that was modified to run the quickstart

# Start batching commands
batch


## tls and Connector Configuration ##
# Restore the remote connector for the ejb3 subsystem
/subsystem=ejb3/service=remote:write-attribute(name=connectors,value=[http-remoting-connector])

# Remove the remote HTTP connector
/subsystem=remoting/http-connector=tlsConnector:remove()

# Remove the SASL authentication factory
/subsystem=elytron/sasl-authentication-factory=tlsSASLFactory:remove()

# Restore the original the SSL/TLS context
/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=ssl-context,value=applicationSSC)

# Remove the server SSL/TLS context
/subsystem=elytron/server-ssl-context=tlsSSC:undefine-attribute(name=ocsp-stapling)
/subsystem=elytron/server-ssl-context=tlsSSC:remove()


## Server KeyStore and TrustStore ##
# Remove the trust manager
/subsystem=elytron/trust-manager=tlsTM:remove()

# Remove the client certificate from the trust store
/subsystem=elytron/key-store=tlsTrustStore:remove-alias(alias=client)

# Store the updated trust store state to the trust store file
/subsystem=elytron/key-store=tlsTrustStore:store()

# Run batched commands
run-batch

# Start batching commands again
batch

# Remove the trust store from the server
/subsystem=elytron/key-store=tlsTrustStore:remove()

# Remove the key manager
/subsystem=elytron/key-manager=tlsKM:remove()

# Remove the server key pair from the key store
/subsystem=elytron/key-store=tlsKeyStore:remove-alias(alias=localhost)

# Store the updated trust store state to the key store file
/subsystem=elytron/key-store=tlsKeyStore:store()

# Run batched commands
run-batch

# Start batching commands again
batch

# Remove the key store for the server
/subsystem=elytron/key-store=tlsKeyStore:remove()


## Filesystem Realm and Security Domain ##
# Remove the security domain mapping from the ejb3 subsystem
/subsystem=ejb3/application-security-domain=tlsApp:remove()

# Remove the security domain from the filesystem realm
/subsystem=elytron/security-domain=tlsFsSD:remove()

# Remove the example identity
/subsystem=elytron/filesystem-realm=tlsFsRealm:remove-identity(identity=example_user)

# Run batched commands
run-batch

# Start batching commands again
batch

# Remove the filesystem realm
/subsystem=elytron/filesystem-realm=tlsFsRealm:remove()

# Run batched commands
run-batch

# Reload the server configuration
reload
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2024 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.security.examples;

import jakarta.ejb.EJBAccessException;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.util.Hashtable;

/**
* The remote client responsible for making invoking the intermediate bean to demonstrate security context propagation
* in EJB to remote EJB calls.
*
* @author <a href="mailto:[email protected]">Stefan Guilhen</a>
*/
public class RemoteClient {

public static void main(String[] args) throws Exception {

final Hashtable<String, String> jndiProperties = new Hashtable<>();
jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
jndiProperties.put(Context.PROVIDER_URL, "remote+https://localhost:8443");
final Context context = new InitialContext(jndiProperties);

final String moduleName = "ocsp-stapling-tls";
final String beanName = SecuredEJB.class.getSimpleName();
final String interfaceName = SecuredEJBMutualTLS.class.getName();
SecuredEJBMutualTLS beanReference = (SecuredEJBMutualTLS) context.lookup("ejb:/" + moduleName + "/"
+ beanName + "!" + interfaceName);

System.out.println("\n\n\n* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\n");
System.out.println("Successfully called secured bean, caller principal " + beanReference.getSecurityInfo());
boolean hasAdminPermission = false;
try {
hasAdminPermission = beanReference.administrativeMethod();
} catch (EJBAccessException ignored) {}
System.out.println("\nPrincipal has admin permission: " + hasAdminPermission);
System.out.println("\n\n* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\n\n");
}
}
Loading