Skip to content
Closed
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ target
.project
.settings
.classpath

dependency-reduced-pom.xml
1 change: 1 addition & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This software includes third party software subject to the following licenses:
Apache Commons Lang under Apache License, Version 2.0
Apache HttpClient under Apache License, Version 2.0
Apache HttpCore under Apache License, Version 2.0
Digipost Certificate Validator under The Apache Software License, Version 2.0
istack common utility code runtime under Eclipse Distribution License - v 1.0
Jakarta Activation under EDL 1.0
Jakarta Activation API jar under EDL 1.0
Expand Down
57 changes: 52 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@
<artifactId>signature-api-specification-jaxb</artifactId>
<version>${signature.api.version}</version>
</dependency>
<dependency>
<groupId>no.digipost</groupId>
<artifactId>certificate-validator</artifactId>
<version>2.3</version>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
Expand Down Expand Up @@ -205,11 +216,6 @@
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/certificates</directory>
<filtering>false</filtering>
<targetPath>no/digipost/signature/client/certificates</targetPath>
</resource>
</resources>
<pluginManagement>
<plugins>
Expand Down Expand Up @@ -269,6 +275,37 @@
</parameter>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<!--
Version 3.2.2 introduces a warning about target/classes being a directory when minimizing the resulting JAR,
and warning is still present in v3.2.4, so keeping the version on 3.2.1 until https://github.com/apache/maven-shade-plugin/pull/83
is hopefully resolved. Judging by the discussion, it is not happening anytime soon.
-->
<version>3.2.1</version>
<configuration>
<minimizeJar>true</minimizeJar>
<artifactSet>
<includes>
<include>no.digipost:certificate-validator</include>
</includes>
</artifactSet>
<filters>
<filter>
<artifact>no.digipost.*</artifact>
<excludes>
<exclude>META-INF/*.MF</exclude>
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>no.digipost.security</pattern>
<shadedPattern>no.digipost.signature.client.core.internal.security.certificate_validator</shadedPattern>
</relocation>
</relocations>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
Expand Down Expand Up @@ -363,6 +400,16 @@
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Expand Down
Binary file removed src/main/certificates/prod/BPClass3CA3.cer
Binary file not shown.
Binary file removed src/main/certificates/prod/BPClass3RootCA.cer
Binary file not shown.
Binary file removed src/main/certificates/prod/commfides_ca.cer
Binary file not shown.
Binary file removed src/main/certificates/prod/commfides_root_ca.cer
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed src/main/certificates/test/commfides_test_ca.cer
Binary file not shown.
Binary file not shown.
33 changes: 0 additions & 33 deletions src/main/certificates/test/digipost_test_root_ca.pem

This file was deleted.

32 changes: 18 additions & 14 deletions src/main/java/no/digipost/signature/client/Certificates.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package no.digipost.signature.client;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;
Expand All @@ -11,32 +10,37 @@ public enum Certificates {
TEST(
"test/Buypass_Class_3_Test4_CA_3.cer",
"test/Buypass_Class_3_Test4_Root_CA.cer",

"test/BPCl3CaG2HTBS.cer",
"test/BPCl3CaG2STBS.cer",
"test/BPCl3RootCaG2HT.cer",
"test/BPCl3RootCaG2ST.cer",

"test/commfides_test_ca.cer",
"test/commfides_test_root_ca.cer",
"test/digipost_test_root_ca.pem"

"test/digipost_test_root_ca.cert.pem"

),
PRODUCTION(
"prod/BPClass3CA3.cer",
"prod/BPClass3RootCA.cer",

"prod/BPCl3CaG2HTBS.cer",
"prod/BPCl3CaG2STBS.cer",
"prod/BPCl3RootCaG2HT.cer",
"prod/BPCl3RootCaG2ST.cer",

"prod/commfides_ca.cer",
"prod/commfides_root_ca.cer"
);

final List<String> certificatePaths;

Certificates(String ... certificatePaths) {
this.certificatePaths = Stream.of(certificatePaths).map(FullCertificateClassPathUri.instance).collect(toList());
this.certificatePaths = Stream.of(certificatePaths)
.map("classpath:/certificates/"::concat)
.collect(toList());
}
}


final class FullCertificateClassPathUri implements Function<String, String> {
static final FullCertificateClassPathUri instance = new FullCertificateClassPathUri();

private static final String root = "/" + Certificates.class.getPackage().getName().replace('.', '/') + "/certificates/";

@Override
public String apply(String resourceName) {
return "classpath:" + root + resourceName;
}
}
60 changes: 43 additions & 17 deletions src/main/java/no/digipost/signature/client/ClientConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
import no.digipost.signature.client.core.exceptions.KeyException;
import no.digipost.signature.client.core.internal.http.AddRequestHeaderFilter;
import no.digipost.signature.client.core.internal.http.HttpIntegrationConfiguration;
import no.digipost.signature.client.core.internal.http.PostenEnterpriseCertificateStrategy;
import no.digipost.signature.client.core.internal.http.SignatureApiTrustStrategy;
import no.digipost.signature.client.core.internal.security.ProvidesCertificateResourcePaths;
import no.digipost.signature.client.core.internal.security.TrustStoreLoader;
import no.digipost.signature.client.core.internal.xml.JaxbMessageReaderWriterProvider;
import no.digipost.signature.client.security.CertificateChainValidation;
import no.digipost.signature.client.security.KeyStoreConfig;
import no.digipost.signature.client.security.OrganizationNumberValidation;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.ssl.PrivateKeyDetails;
import org.apache.http.ssl.PrivateKeyStrategy;
import org.apache.http.ssl.SSLContexts;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
Expand All @@ -28,8 +28,8 @@
import javax.ws.rs.core.Configurable;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.HttpHeaders;

import java.io.InputStream;
import java.net.Socket;
import java.net.URI;
import java.nio.file.Path;
import java.security.KeyManagementException;
Expand All @@ -39,7 +39,6 @@
import java.time.Clock;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Consumer;
Expand Down Expand Up @@ -89,21 +88,21 @@ public final class ClientConfiguration implements ProvidesCertificateResourcePat
private final Optional<Sender> sender;
private final URI signatureServiceRoot;
private final Iterable<DocumentBundleProcessor> documentBundleProcessors;
private final CertificateChainValidation serverCertificateValidation;
private final Clock clock;



private ClientConfiguration(
KeyStoreConfig keyStoreConfig, Configurable<? extends Configuration> jaxrsConfig,
Optional<Sender> sender, URI serviceRoot, Iterable<String> certificatePaths,
Iterable<DocumentBundleProcessor> documentBundleProcessors, Clock clock) {
Iterable<DocumentBundleProcessor> documentBundleProcessors, CertificateChainValidation serverCertificateValidation, Clock clock) {

this.keyStoreConfig = keyStoreConfig;
this.jaxrsConfig = jaxrsConfig;
this.sender = sender;
this.signatureServiceRoot = serviceRoot;
this.certificatePaths = certificatePaths;
this.documentBundleProcessors = documentBundleProcessors;
this.serverCertificateValidation = serverCertificateValidation;
this.clock = clock;
}

Expand Down Expand Up @@ -153,14 +152,9 @@ public Configuration getJaxrsConfiguration() {
@Override
public SSLContext getSSLContext() {
try {
return SSLContexts.custom()
.loadKeyMaterial(keyStoreConfig.keyStore, keyStoreConfig.privatekeyPassword.toCharArray(), new PrivateKeyStrategy() {
@Override
public String chooseAlias(Map<String, PrivateKeyDetails> aliases, Socket socket) {
return keyStoreConfig.alias;
}
})
.loadTrustMaterial(TrustStoreLoader.build(this), new PostenEnterpriseCertificateStrategy())
return SSLContexts.custom()
.loadKeyMaterial(keyStoreConfig.keyStore, keyStoreConfig.privatekeyPassword.toCharArray(), (aliases, socket) -> keyStoreConfig.alias)
.loadTrustMaterial(TrustStoreLoader.build(this), new SignatureApiTrustStrategy(serverCertificateValidation))
.build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
if (e instanceof UnrecoverableKeyException && "Given final block not properly padded".equals(e.getMessage())) {
Expand Down Expand Up @@ -194,6 +188,7 @@ public static class Builder {
private URI serviceRoot = ServiceUri.PRODUCTION.uri;
private Optional<Sender> globalSender = Optional.empty();
private Iterable<String> certificatePaths = Certificates.PRODUCTION.certificatePaths;
private CertificateChainValidation serverCertificateTrustStrategy = new OrganizationNumberValidation("984661185"); // Posten Norge AS organization number
private Optional<LoggingFeature> loggingFeature = Optional.empty();
private List<DocumentBundleProcessor> documentBundleProcessors = new ArrayList<>();
private Clock clock = Clock.systemDefaultZone();
Expand Down Expand Up @@ -350,6 +345,35 @@ public Builder customizeJaxRs(Consumer<? super Configurable<? extends Configurat
return this;
}


/**
* Override which organization number which is expected from the server's certificate.
* By default, this is the organization number of Posten Norge AS, and should <em>not</em>
* be overridden unless you have a specific need such as doing testing against your own
* stubbed implementation of the Posten signering API.
*
* @param serverOrganizationNumber the organization number expected in the server's enterprise certificate
*/
public Builder serverOrganizationNumber(String serverOrganizationNumber) {
return serverCertificateTrustStrategy(new OrganizationNumberValidation(serverOrganizationNumber));
}


/**
* Override the validation of the server's certificate. This method is mainly
* intended for tests if you need to override (or even disable) the default
* validation that the server identifies itself as "Posten Norge AS".
*
* Calling this method for a production deployment is probably <em>not</em> what you intend to do!
*
* @param certificateChainValidation the validation for the server's certificate
*/
public Builder serverCertificateTrustStrategy(CertificateChainValidation certificateChainValidation) {
LOG.warn("Overriding server certificate TrustStrategy! This should NOT be done for any integration with Posten signering.");
this.serverCertificateTrustStrategy = certificateChainValidation;
return this;
}

/**
* Allows for overriding which {@link Clock} is used to convert between Java and XML,
* may be useful for e.g. automated tests.
Expand All @@ -368,7 +392,9 @@ public ClientConfiguration build() {
jaxrsConfig.register(JaxbMessageReaderWriterProvider.class);
jaxrsConfig.register(new AddRequestHeaderFilter(USER_AGENT, createUserAgentString()));
this.loggingFeature.ifPresent(jaxrsConfig::register);
return new ClientConfiguration(keyStoreConfig, jaxrsConfig, globalSender, serviceRoot, certificatePaths, documentBundleProcessors, clock);
return new ClientConfiguration(
keyStoreConfig, jaxrsConfig, globalSender, serviceRoot, certificatePaths,
documentBundleProcessors, serverCertificateTrustStrategy, clock);
}

String createUserAgentString() {
Expand Down

This file was deleted.

Loading