Merge pull request #36 from maxlambrecht/master

Configuration, validation and logging improvements
This commit is contained in:
Max Lambrecht 2020-08-25 14:53:44 -03:00 committed by GitHub
commit 285545f704
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 193 additions and 65 deletions

View File

@ -26,26 +26,39 @@ X.509 and JWT SVIDs and bundles.
Download Download
-------- --------
The JARs can be downloaded from [Maven Central](https://search.maven.org/search?q=g:io.spiffe%20AND%20v:0.6.1). The JARs can be downloaded from [Maven Central](https://search.maven.org/search?q=g:io.spiffe%20AND%20v:0.6.2).
The dependencies can be added to `pom.xml`: The dependencies can be added to `pom.xml`
To import the `java-spiffe-provider` component:
```xml
<dependency>
<groupId>io.spiffe</groupId>
<artifactId>java-spiffe-provider</artifactId>
<version>0.6.2</version>
</dependency>
```
The `java-spiffe-provider` component imports the `java-spiffe-core` component.
To just import the `java-spiffe-core` component:
```xml ```xml
<dependency> <dependency>
<groupId>io.spiffe</groupId> <groupId>io.spiffe</groupId>
<artifactId>java-spiffe-core</artifactId> <artifactId>java-spiffe-core</artifactId>
<version>0.6.1</version> <version>0.6.2</version>
</dependency>
<dependency>
<groupId>io.spiffe</groupId>
<artifactId>java-spiffe-provider</artifactId>
<version>0.6.1</version>
</dependency> </dependency>
``` ```
Using Gradle: Using Gradle:
Import `java-spiffe-provider`:
```gradle ```gradle
implementation 'io.spiffe:java-spiffe-core:0.6.1' implementation group: 'io.spiffe', name: 'java-spiffe-provider', version: '0.6.2'
implementation 'io.spiffe:java-spiffe-provider:0.6.1' ```
Import `java-spiffe-core`:
```gradle
implementation group: 'io.spiffe', name: 'java-spiffe-core', version: '0.6.2'
``` ```
### MacOS Support ### MacOS Support
@ -55,14 +68,14 @@ Add to your `pom.xml`:
<dependency> <dependency>
<groupId>io.spiffe</groupId> <groupId>io.spiffe</groupId>
<artifactId>grpc-netty-macos</artifactId> <artifactId>grpc-netty-macos</artifactId>
<version>0.6.1</version> <version>0.6.2</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
``` ```
Using Gradle: Using Gradle:
```gradle ```gradle
runtimeOnly 'io.spiffe:grpc-netty-macos:0.6.1' runtimeOnly group: 'io.spiffe', name: 'grpc-netty-macos', version: '0.6.2'
``` ```
### Build the JARs ### Build the JARs

View File

@ -12,7 +12,7 @@ allprojects {
subprojects { subprojects {
group = 'io.spiffe' group = 'io.spiffe'
version = '0.6.1' version = '0.6.2'
ext { ext {
grpcVersion = '1.31.1' grpcVersion = '1.31.1'

View File

@ -6,6 +6,7 @@ import io.spiffe.exception.BundleNotFoundException;
import io.spiffe.internal.CertificateUtils; import io.spiffe.internal.CertificateUtils;
import io.spiffe.spiffeid.SpiffeId; import io.spiffe.spiffeid.SpiffeId;
import lombok.NonNull; import lombok.NonNull;
import lombok.extern.java.Log;
import lombok.val; import lombok.val;
import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException;
@ -18,6 +19,7 @@ import java.util.function.Supplier;
/** /**
* Provides methods to validate a chain of X.509 certificates using an X.509 bundle source. * Provides methods to validate a chain of X.509 certificates using an X.509 bundle source.
*/ */
@Log
public final class X509SvidValidator { public final class X509SvidValidator {
private X509SvidValidator() { private X509SvidValidator() {
@ -61,9 +63,16 @@ public final class X509SvidValidator {
@NonNull final Supplier<Set<SpiffeId>> acceptedSpiffeIdsSupplier) @NonNull final Supplier<Set<SpiffeId>> acceptedSpiffeIdsSupplier)
throws CertificateException { throws CertificateException {
val spiffeIdSet = acceptedSpiffeIdsSupplier.get(); val spiffeIdSet = acceptedSpiffeIdsSupplier.get();
if (spiffeIdSet.isEmpty()) {
String error = "The supplier of accepted SPIFFE IDs supplied an empty set";
log.warning(error);
throw new CertificateException(error);
}
val spiffeId = CertificateUtils.getSpiffeId(x509Certificate); val spiffeId = CertificateUtils.getSpiffeId(x509Certificate);
if (!spiffeIdSet.contains(spiffeId)) { if (!spiffeIdSet.contains(spiffeId)) {
final String error = "SPIFFE ID %s in X.509 certificate is not accepted"; val error = String.format("SPIFFE ID %s in X.509 certificate is not accepted", spiffeId);
log.warning(String.format("Client SPIFFE ID validation failed: %s", error));
throw new CertificateException(String.format(error, spiffeId)); throw new CertificateException(String.format(error, spiffeId));
} }
} }

View File

@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.function.Function; import java.util.function.Function;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors;
import static io.spiffe.workloadapi.internal.ThreadUtils.await; import static io.spiffe.workloadapi.internal.ThreadUtils.await;
@ -139,9 +140,8 @@ public final class DefaultX509Source implements X509Source {
* Returns the X.509 bundle for a given trust domain. * Returns the X.509 bundle for a given trust domain.
* *
* @return an instance of a {@link X509Bundle} * @return an instance of a {@link X509Bundle}
*
* @throws BundleNotFoundException is there is no bundle for the trust domain provided * @throws BundleNotFoundException is there is no bundle for the trust domain provided
* @throws IllegalStateException if the source is closed * @throws IllegalStateException if the source is closed
*/ */
@Override @Override
public X509Bundle getBundleForTrustDomain(@NonNull final TrustDomain trustDomain) throws BundleNotFoundException { public X509Bundle getBundleForTrustDomain(@NonNull final TrustDomain trustDomain) throws BundleNotFoundException {
@ -200,7 +200,8 @@ public final class DefaultX509Source implements X509Source {
workloadApiClient.watchX509Context(new Watcher<X509Context>() { workloadApiClient.watchX509Context(new Watcher<X509Context>() {
@Override @Override
public void onUpdate(final X509Context update) { public void onUpdate(final X509Context update) {
log.log(Level.INFO, "Received X509Context update"); String spiffeIds = update.getX509Svids().stream().map(s -> s.getSpiffeId().toString()).collect(Collectors.joining(", "));
log.log(Level.INFO, String.format("Received X509Context update: %s", spiffeIds));
setX509Context(update); setX509Context(update);
done.countDown(); done.countDown();
} }

View File

@ -81,7 +81,7 @@ public class X509SvidValidatorTest {
} }
@Test @Test
void checkSpiffeId_givenASpiffeIdInTheListOfAcceptedIds_doesntThrowException() throws IOException, CertificateException, URISyntaxException { void verifySpiffeId_givenASpiffeIdInTheListOfAcceptedIds_doesntThrowException() throws IOException, CertificateException, URISyntaxException {
val spiffeId1 = SpiffeId.parse("spiffe://example.org/test"); val spiffeId1 = SpiffeId.parse("spiffe://example.org/test");
val spiffeId2 = SpiffeId.parse("spiffe://example.org/test2"); val spiffeId2 = SpiffeId.parse("spiffe://example.org/test2");
@ -91,7 +91,7 @@ public class X509SvidValidatorTest {
} }
@Test @Test
void checkSpiffeId_givenASpiffeIdNotInTheListOfAcceptedIds_throwsCertificateException() throws IOException, CertificateException, URISyntaxException { void verifySpiffeId_givenASpiffeIdNotInTheListOfAcceptedIds_throwsCertificateException() throws IOException, CertificateException, URISyntaxException {
val spiffeId1 = SpiffeId.parse("spiffe://example.org/other1"); val spiffeId1 = SpiffeId.parse("spiffe://example.org/other1");
val spiffeId2 = SpiffeId.parse("spiffe://example.org/other2"); val spiffeId2 = SpiffeId.parse("spiffe://example.org/other2");
val spiffeIdSet = Sets.newHashSet(spiffeId1, spiffeId2); val spiffeIdSet = Sets.newHashSet(spiffeId1, spiffeId2);
@ -104,6 +104,17 @@ public class X509SvidValidatorTest {
} }
} }
@Test
void verifySpiffeId_givenAnEmptySupplier_throwsCertificateException() {
try {
X509SvidValidator.verifySpiffeId(leaf.getCertificate(), Collections::emptySet);
fail("Should have thrown CertificateException");
} catch (CertificateException e) {
assertEquals("The supplier of accepted SPIFFE IDs supplied an empty set", e.getMessage());
}
}
@Test @Test
void checkSpiffeId_nullX509Certificate_throwsNullPointerException() throws CertificateException { void checkSpiffeId_nullX509Certificate_throwsNullPointerException() throws CertificateException {
try { try {

View File

@ -10,11 +10,11 @@ The Helper automatically gets the SVID updates and stores them in the KeyStore a
On Linux: On Linux:
`java -jar java-spiffe-helper-0.6.1-linux-x86_64.jar -c helper.conf` `java -jar java-spiffe-helper-0.6.2-linux-x86_64.jar -c helper.conf`
On Mac OS: On Mac OS:
`java -jar java-spiffe-helper-0.6.1-osx-x86_64.jar -c helper.conf` `java -jar java-spiffe-helper-0.6.2-osx-x86_64.jar -c helper.conf`
(The jar can be found in `build/libs`, after running the gradle build) (The jar can be found in `build/libs`, after running the gradle build)

View File

@ -6,24 +6,23 @@ creating SSLContexts that are backed by the Workload API.
## Create an SSL Context backed by the Workload API ## Create an SSL Context backed by the Workload API
To create an SSL Context that uses a `X509Source` backed by the Workload API, having the environment variable To create an SSL Context that uses a `X509Source` backed by the Workload API, having the environment variable
` SPIFFE_ENDPOINT_SOCKET` defined with the Workload API endpoint address, and the `ssl.spiffe.accept` ` SPIFFE_ENDPOINT_SOCKET` defined with the Workload API endpoint address.
Security property defined in the `java.security` file containing the list of SPIFFE IDs that the current workload The `SSLContext` is configured with a set of SPIFFE IDs that the current workload
will trust for TLS connections: will trust for TLS connections:
``` ```
X509Source source = DefaultX509Source.newSource(); X509Source source = DefaultX509Source.newSource();
Supplier<Set<SpiffeId>> acceptedSpiffeIds = () -> Collections.singleton(SpiffeId.parse("spiffe://example.org/test"));
SslContextOptions options = SslContextOptions SslContextOptions options = SslContextOptions
.builder() .builder()
.x509Source(source) .x509Source(source)
.acceptedSpiffeIdsSupplier(acceptedSpiffeIds)
.build(); .build();
SSLContext sslContext = SpiffeSslContextFactory.getSslContext(options); SSLContext sslContext = SpiffeSslContextFactory.getSslContext(options);
``` ```
See [HttpsServer example](src/test/java/io/spiffe/provider/examples/mtls/HttpsServer.java). Alternatively, a different Workload API address can be used by passing it to the X509Source creation method.
Alternatively, a different Workload API address can be used by passing it to the X509Source creation method, and a
`Supplier` of a Set of accepted SPIFFE IDs can be provided as part of the `SslContextOptions`:
``` ```
X509SourceOptions sourceOptions = X509SourceOptions X509SourceOptions sourceOptions = X509SourceOptions
@ -32,12 +31,11 @@ Alternatively, a different Workload API address can be used by passing it to the
.build(); .build();
X509Source x509Source = DefaultX509Source.newSource(sourceOptions); X509Source x509Source = DefaultX509Source.newSource(sourceOptions);
Supplier<Set<SpiffeId>> acceptedSpiffeIds = () -> Collections.singleton(SpiffeId.parse("spiffe://example.org/test"));
Supplier<Set<SpiffeId>> spiffeIdSetSupplier = () -> Collections.singleton(SpiffeId.parse("spiffe://example.org/test"));
SslContextOptions sslContextOptions = SslContextOptions SslContextOptions sslContextOptions = SslContextOptions
.builder() .builder()
.acceptedSpiffeIdsSupplier(spiffeIdSetSupplier) .acceptedSpiffeIdsSupplier(acceptedSpiffeIds)
.x509Source(x509Source) .x509Source(x509Source)
.build(); .build();
@ -60,17 +58,19 @@ security.provider.<n>=<className>
This declares a provider, and specifies its preference order `n`. This declares a provider, and specifies its preference order `n`.
### Copy the JAR to the JVM extensions #### Java 8
For installing the JAR file containing the provider classes as a bundled extension in the java platform, For installing the JAR file containing the provider classes as a bundled extension in the java platform,
copy `build/libs/java-spiffe-provider-<version>-all-linux-x86_64.jar` to `<java-home>/jre/lib/ext`. copy `build/libs/java-spiffe-provider-<version>-all-linux-x86_64.jar` to `<java-home>/jre/lib/ext`.
In the case of testing the provider in Mac OS, the name of the jar will be `java-spiffe-provider-<version>-all-osx-x86_64.jar`. In the case of testing the provider in Mac OS, the name of the jar will be `java-spiffe-provider-<version>-all-osx-x86_64.jar`.
#### Register the SPIFFE Provider #### Java 9+
The `java-spiffe-provider` jar should be on the classpath.
### Extend `java.security` properties file
The master security properties file can be extended. Create a file `java.security` with the following content: The master security properties file can be extended. Create a file `java.security` with the following content:
``` ```
# Add the spiffe provider, change the <n> for the correct consecutive number # Add the spiffe provider, change the <n> for the correct consecutive number
security.provider.<n>=io.spiffe.provider.SpiffeProvider security.provider.<n>=io.spiffe.provider.SpiffeProvider
@ -120,7 +120,7 @@ in the `SslContextOptions`:
SslContextOptions sslContextOptions = SslContextOptions SslContextOptions sslContextOptions = SslContextOptions
.builder() .builder()
.x509Source(x509Source) .x509Source(x509Source)
.acceptAnySpiffeId(true) .acceptAnySpiffeId()
.build(); .build();
SSLContext sslContext = SpiffeSslContextFactory.getSslContext(sslContextOptions); SSLContext sslContext = SpiffeSslContextFactory.getSslContext(sslContextOptions);
@ -159,8 +159,8 @@ Prerequisite: Having the SPIFFE Provided configured through the `java.security`.
A `GRPC Server` using an SSL context backed by the Workload API: A `GRPC Server` using an SSL context backed by the Workload API:
``` ```
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(SpiffeProviderConstants.ALGORITHM, SpiffeProviderConstants.PROVIDER_NAME); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(SpiffeProviderConstants.ALGORITHM);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(SpiffeProviderConstants.ALGORITHM, SpiffeProviderConstants.PROVIDER_NAME); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(SpiffeProviderConstants.ALGORITHM);
SslContextBuilder sslContextBuilder = SslContextBuilder sslContextBuilder =
SslContextBuilder SslContextBuilder
@ -184,6 +184,8 @@ with a [X509Source instance](../java-spiffe-core/README.md#x509-source).
``` ```
// create a new X.509 source using the default socket endpoint address // create a new X.509 source using the default socket endpoint address
X509Source x509Source = DefaultX509Source.newSource(); X509Source x509Source = DefaultX509Source.newSource();
// KeyManager gets the X.509 cert and private key from the X.509 SVID source
KeyManager keyManager = new SpiffeKeyManager(x509Source); KeyManager keyManager = new SpiffeKeyManager(x509Source);
// TrustManager gets the X509Source and the supplier of the Set of accepted SPIFFE IDs. // TrustManager gets the X509Source and the supplier of the Set of accepted SPIFFE IDs.
@ -207,8 +209,11 @@ the GRPC SSL context, analogous to the config for the Server:
``` ```
X509Source x509Source = DefaultX509Source.newSource(); X509Source x509Source = DefaultX509Source.newSource();
KeyManager keyManager = new SpiffeKeyManager(x509Source); KeyManager keyManager = new SpiffeKeyManager(x509Source);
TrustManager trustManager = new SpiffeTrustManager(x509Source, () -> SpiffeIdUtils.toSetOfSpiffeIds("spiffe://example.org/workload-server", ','));
Supplier<Set<SpiffeId>> acceptedSpiffeIds = () -> SpiffeIdUtils.toSetOfSpiffeIds("spiffe://example.org/workload-server", ',');
TrustManager trustManager = new SpiffeTrustManager(x509Source, acceptedSpiffeIds);
SslContextBuilder sslContextBuilder = SslContextBuilder SslContextBuilder sslContextBuilder = SslContextBuilder
.forClient() .forClient()
@ -221,8 +226,13 @@ the GRPC SSL context, analogous to the config for the Server:
.build(); .build();
``` ```
## References ### Secure Socket Example:
See [HttpsServer example](src/test/java/io/spiffe/provider/examples/mtls/HttpsServer.java).
[How to Implement a Provider in the Java Cryptography Architecture](https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html) ## More information
[Java PKI Programmer's Guide](https://docs.oracle.com/javase/8/docs/technotes/guides/security/certpath/CertPathProgGuide.html) [Java Platform Security Developers Guide](https://docs.oracle.com/en/java/javase/14/security/)
[How to Implement a Provider in the Java Cryptography Architecture](https://docs.oracle.com/en/java/javase/14/security/howtoimplaprovider.html)
[Java PKI Programmer's Guide](https://docs.oracle.com/en/java/javase/14/security/java-pki-programmers-guide.html)

View File

@ -4,7 +4,6 @@ import io.spiffe.spiffeid.SpiffeId;
import io.spiffe.workloadapi.DefaultX509Source; import io.spiffe.workloadapi.DefaultX509Source;
import io.spiffe.workloadapi.X509Source; import io.spiffe.workloadapi.X509Source;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NonNull; import lombok.NonNull;
import lombok.Setter; import lombok.Setter;
@ -49,6 +48,11 @@ public final class SpiffeSslContextFactory {
throw new IllegalArgumentException("x509Source option cannot be null, an X.509 Source must be provided"); throw new IllegalArgumentException("x509Source option cannot be null, an X.509 Source must be provided");
} }
if (!options.acceptAnySpiffeId && options.acceptedSpiffeIdsSupplier == null) {
throw new IllegalArgumentException("SSL context should be configured either with a Supplier " +
"of accepted SPIFFE IDs or with acceptAnySpiffeId=true");
}
val sslContext = newSslContext(options); val sslContext = newSslContext(options);
val trustManagers = newTrustManager(options); val trustManagers = newTrustManager(options);
val keyManagers = new SpiffeKeyManagerFactory().engineGetKeyManagers(options.x509Source); val keyManagers = new SpiffeKeyManagerFactory().engineGetKeyManagers(options.x509Source);
@ -109,7 +113,6 @@ public final class SpiffeSslContextFactory {
@Setter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
private boolean acceptAnySpiffeId; private boolean acceptAnySpiffeId;
@Builder
public SslContextOptions( public SslContextOptions(
final String sslProtocol, final String sslProtocol,
final X509Source x509Source, final X509Source x509Source,
@ -120,5 +123,43 @@ public final class SpiffeSslContextFactory {
this.sslProtocol = sslProtocol; this.sslProtocol = sslProtocol;
this.acceptAnySpiffeId = acceptAnySpiffeId; this.acceptAnySpiffeId = acceptAnySpiffeId;
} }
public static SslContextOptionsBuilder builder() {
return new SslContextOptionsBuilder();
}
public static class SslContextOptionsBuilder {
private String sslProtocol;
private X509Source x509Source;
private Supplier<Set<SpiffeId>> acceptedSpiffeIdsSupplier;
private boolean acceptAnySpiffeId;
SslContextOptionsBuilder() {
}
public SslContextOptionsBuilder sslProtocol(String sslProtocol) {
this.sslProtocol = sslProtocol;
return this;
}
public SslContextOptionsBuilder x509Source(X509Source x509Source) {
this.x509Source = x509Source;
return this;
}
public SslContextOptionsBuilder acceptedSpiffeIdsSupplier(Supplier<Set<SpiffeId>> acceptedSpiffeIdsSupplier) {
this.acceptedSpiffeIdsSupplier = acceptedSpiffeIdsSupplier;
return this;
}
public SslContextOptionsBuilder acceptAnySpiffeId() {
this.acceptAnySpiffeId = true;
return this;
}
public SslContextOptions build() {
return new SslContextOptions(sslProtocol, x509Source, acceptedSpiffeIdsSupplier, acceptAnySpiffeId);
}
}
} }
} }

View File

@ -51,15 +51,15 @@ public final class SpiffeTrustManager extends X509ExtendedTrustManager {
* <p> * <p>
* Creates a {@link SpiffeTrustManager} with an X.509 bundle source used to provide the trusted bundles, * Creates a {@link SpiffeTrustManager} with an X.509 bundle source used to provide the trusted bundles,
* and a flag to indicate that any SPIFFE ID will be accepted. * and a flag to indicate that any SPIFFE ID will be accepted.
* <p>
* Any SPIFFE ID will be accepted during peer SVID validation.
* *
* @param x509BundleSource an implementation of a {@link BundleSource} * @param x509BundleSource an implementation of a {@link BundleSource}
* @param acceptAnySpiffeId a Supplier of a Set of accepted SPIFFE IDs.
*/ */
public SpiffeTrustManager(@NonNull final BundleSource<X509Bundle> x509BundleSource, public SpiffeTrustManager(@NonNull final BundleSource<X509Bundle> x509BundleSource) {
final boolean acceptAnySpiffeId) {
this.x509BundleSource = x509BundleSource; this.x509BundleSource = x509BundleSource;
this.acceptedSpiffeIdsSupplier = Collections::emptySet; this.acceptedSpiffeIdsSupplier = Collections::emptySet;
this.acceptAnySpiffeId = acceptAnySpiffeId; this.acceptAnySpiffeId = true;
} }
/** /**

View File

@ -70,7 +70,7 @@ public class SpiffeTrustManagerFactory extends TrustManagerFactorySpi {
final SpiffeTrustManager spiffeTrustManager; final SpiffeTrustManager spiffeTrustManager;
if (ACCEPT_ANY_SPIFFE_ID) { if (ACCEPT_ANY_SPIFFE_ID) {
spiffeTrustManager = new SpiffeTrustManager(x509Source, true); spiffeTrustManager = new SpiffeTrustManager(x509Source);
} else { } else {
spiffeTrustManager = new SpiffeTrustManager(x509Source, DEFAULT_SPIFFE_ID_SET_SUPPLIER); spiffeTrustManager = new SpiffeTrustManager(x509Source, DEFAULT_SPIFFE_ID_SET_SUPPLIER);
} }
@ -92,8 +92,7 @@ public class SpiffeTrustManagerFactory extends TrustManagerFactorySpi {
final SpiffeTrustManager spiffeTrustManager; final SpiffeTrustManager spiffeTrustManager;
if (ACCEPT_ANY_SPIFFE_ID) { if (ACCEPT_ANY_SPIFFE_ID) {
// make explicit that all SPIFFE IDs will be accepted spiffeTrustManager = new SpiffeTrustManager(x509BundleSource);
spiffeTrustManager = new SpiffeTrustManager(x509BundleSource, true);
} else { } else {
spiffeTrustManager = new SpiffeTrustManager(x509BundleSource, DEFAULT_SPIFFE_ID_SET_SUPPLIER); spiffeTrustManager = new SpiffeTrustManager(x509BundleSource, DEFAULT_SPIFFE_ID_SET_SUPPLIER);
} }
@ -108,7 +107,7 @@ public class SpiffeTrustManagerFactory extends TrustManagerFactorySpi {
* @return an instance of a {@link TrustManager} wrapped in an array. The actual type returned is {@link SpiffeTrustManager} * @return an instance of a {@link TrustManager} wrapped in an array. The actual type returned is {@link SpiffeTrustManager}
*/ */
public TrustManager[] engineGetTrustManagersAcceptAnySpiffeId(@NonNull final BundleSource<X509Bundle> x509BundleSource) { public TrustManager[] engineGetTrustManagersAcceptAnySpiffeId(@NonNull final BundleSource<X509Bundle> x509BundleSource) {
val spiffeTrustManager = new SpiffeTrustManager(x509BundleSource, true); val spiffeTrustManager = new SpiffeTrustManager(x509BundleSource);
return new TrustManager[]{spiffeTrustManager}; return new TrustManager[]{spiffeTrustManager};
} }

View File

@ -23,8 +23,12 @@ class SpiffeSslContextFactoryTest {
@Test @Test
void getSslContext_withX509Source() { void getSslContext_withX509Source() {
SpiffeSslContextFactory.SslContextOptions options = SpiffeSslContextFactory.SslContextOptions SpiffeSslContextFactory.SslContextOptions options =
.builder().x509Source(x509Source).build(); SpiffeSslContextFactory.SslContextOptions
.builder()
.x509Source(x509Source)
.acceptAnySpiffeId()
.build();
try { try {
assertNotNull(SpiffeSslContextFactory.getSslContext(options)); assertNotNull(SpiffeSslContextFactory.getSslContext(options));
} catch (NoSuchAlgorithmException | KeyManagementException e) { } catch (NoSuchAlgorithmException | KeyManagementException e) {
@ -34,8 +38,12 @@ class SpiffeSslContextFactoryTest {
@Test @Test
void getSslContext_withSupplierOfSpiffeIds() { void getSslContext_withSupplierOfSpiffeIds() {
SpiffeSslContextFactory.SslContextOptions options = SpiffeSslContextFactory.SslContextOptions SpiffeSslContextFactory.SslContextOptions options =
.builder().x509Source(x509Source).acceptedSpiffeIdsSupplier(Collections::emptySet).build(); SpiffeSslContextFactory.SslContextOptions
.builder()
.x509Source(x509Source)
.acceptedSpiffeIdsSupplier(Collections::emptySet)
.build();
try { try {
assertNotNull(SpiffeSslContextFactory.getSslContext(options)); assertNotNull(SpiffeSslContextFactory.getSslContext(options));
} catch (NoSuchAlgorithmException | KeyManagementException e) { } catch (NoSuchAlgorithmException | KeyManagementException e) {
@ -45,8 +53,12 @@ class SpiffeSslContextFactoryTest {
@Test @Test
void getSslContext_withAcceptAny() { void getSslContext_withAcceptAny() {
SpiffeSslContextFactory.SslContextOptions options = SpiffeSslContextFactory.SslContextOptions SpiffeSslContextFactory.SslContextOptions options =
.builder().x509Source(x509Source).acceptAnySpiffeId(true).build(); SpiffeSslContextFactory.SslContextOptions
.builder()
.x509Source(x509Source)
.acceptAnySpiffeId()
.build();
try { try {
assertNotNull(SpiffeSslContextFactory.getSslContext(options)); assertNotNull(SpiffeSslContextFactory.getSslContext(options));
} catch (NoSuchAlgorithmException | KeyManagementException e) { } catch (NoSuchAlgorithmException | KeyManagementException e) {
@ -56,8 +68,13 @@ class SpiffeSslContextFactoryTest {
@Test @Test
void getSslContext_withOtherSslProtocol() { void getSslContext_withOtherSslProtocol() {
SpiffeSslContextFactory.SslContextOptions options = SpiffeSslContextFactory.SslContextOptions SpiffeSslContextFactory.SslContextOptions options =
.builder().x509Source(x509Source).sslProtocol("TLSv1.1").build(); SpiffeSslContextFactory.SslContextOptions
.builder()
.x509Source(x509Source)
.acceptAnySpiffeId()
.sslProtocol("TLSv1.1")
.build();
try { try {
assertNotNull(SpiffeSslContextFactory.getSslContext(options)); assertNotNull(SpiffeSslContextFactory.getSslContext(options));
} catch (NoSuchAlgorithmException | KeyManagementException e) { } catch (NoSuchAlgorithmException | KeyManagementException e) {
@ -76,11 +93,33 @@ class SpiffeSslContextFactoryTest {
@Test @Test
void getSslContext_nullX509Source() throws KeyManagementException, NoSuchAlgorithmException { void getSslContext_nullX509Source() throws KeyManagementException, NoSuchAlgorithmException {
SpiffeSslContextFactory.SslContextOptions options = SpiffeSslContextFactory.SslContextOptions.builder().build(); SpiffeSslContextFactory.SslContextOptions options =
SpiffeSslContextFactory.SslContextOptions
.builder()
.acceptAnySpiffeId()
.build();
try { try {
SpiffeSslContextFactory.getSslContext(options); SpiffeSslContextFactory.getSslContext(options);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
assertEquals("x509Source option cannot be null, an X.509 Source must be provided", e.getMessage()); assertEquals("x509Source option cannot be null, an X.509 Source must be provided", e.getMessage());
} }
} }
@Test
void getSslContext_noSupplierAndAcceptAnyNotSet() {
SpiffeSslContextFactory.SslContextOptions options =
SpiffeSslContextFactory.SslContextOptions
.builder()
.x509Source(x509Source)
.build();
try {
SpiffeSslContextFactory.getSslContext(options);
fail();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
fail(e);
} catch (IllegalArgumentException e) {
assertEquals("SSL context should be configured either with a Supplier " +
"of accepted SPIFFE IDs or with acceptAnySpiffeId=true", e.getMessage());
}
}
} }

View File

@ -28,7 +28,12 @@ class SpiffeSslSocketFactoryTest {
@BeforeEach @BeforeEach
void setup() throws NoSuchAlgorithmException, KeyManagementException { void setup() throws NoSuchAlgorithmException, KeyManagementException {
X509SourceStub x509Source = new X509SourceStub(); X509SourceStub x509Source = new X509SourceStub();
SpiffeSslContextFactory.SslContextOptions options = SpiffeSslContextFactory.SslContextOptions.builder().x509Source(x509Source).build(); SpiffeSslContextFactory.SslContextOptions options =
SpiffeSslContextFactory.SslContextOptions
.builder()
.x509Source(x509Source)
.acceptAnySpiffeId()
.build();
spiffeSslSocketFactory = new SpiffeSslSocketFactory(options); spiffeSslSocketFactory = new SpiffeSslSocketFactory(options);
SSLContext sslContext = SpiffeSslContextFactory.getSslContext(options); SSLContext sslContext = SpiffeSslContextFactory.getSslContext(options);
socketFactory = sslContext.getSocketFactory(); socketFactory = sslContext.getSocketFactory();

View File

@ -75,7 +75,7 @@ public class SpiffeTrustManagerTest {
@Test @Test
void testCreateSpiffeTrustManager_nullSource() { void testCreateSpiffeTrustManager_nullSource() {
try { try {
new SpiffeTrustManager(null, true); new SpiffeTrustManager(null);
fail(); fail();
} catch (Exception e) { } catch (Exception e) {
assertEquals("x509BundleSource is marked non-null but is null", e.getMessage()); assertEquals("x509BundleSource is marked non-null but is null", e.getMessage());
@ -277,7 +277,7 @@ public class SpiffeTrustManagerTest {
acceptedSpiffeIds = Collections.singleton(SpiffeId.parse("spiffe://example.org/other")); acceptedSpiffeIds = Collections.singleton(SpiffeId.parse("spiffe://example.org/other"));
when(bundleSource.getBundleForTrustDomain(TrustDomain.of("example.org"))).thenReturn(bundleKnown); when(bundleSource.getBundleForTrustDomain(TrustDomain.of("example.org"))).thenReturn(bundleKnown);
spiffeTrustManager = new SpiffeTrustManager(bundleSource, true); spiffeTrustManager = new SpiffeTrustManager(bundleSource);
try { try {
spiffeTrustManager.checkClientTrusted(chain, ""); spiffeTrustManager.checkClientTrusted(chain, "");
@ -291,7 +291,7 @@ public class SpiffeTrustManagerTest {
acceptedSpiffeIds = Collections.singleton(SpiffeId.parse("spiffe://example.org/other")); acceptedSpiffeIds = Collections.singleton(SpiffeId.parse("spiffe://example.org/other"));
when(bundleSource.getBundleForTrustDomain(TrustDomain.of("example.org"))).thenReturn(bundleKnown); when(bundleSource.getBundleForTrustDomain(TrustDomain.of("example.org"))).thenReturn(bundleKnown);
spiffeTrustManager = new SpiffeTrustManager(bundleSource, true); spiffeTrustManager = new SpiffeTrustManager(bundleSource);
try { try {
spiffeTrustManager.checkClientTrusted(chain, ""); spiffeTrustManager.checkClientTrusted(chain, "");