aboutsummaryrefslogtreecommitdiffstats
path: root/vespa-feed-client/src/test/java/ai/vespa/feed/client/impl/SslContextBuilderTest.java
blob: 28687ee78c02980aedeb764bede9e7aaa1494509 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package ai.vespa.feed.client.impl;

import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.util.io.pem.PemObject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import javax.net.ssl.SSLContext;
import javax.security.auth.x500.X500Principal;
import java.io.BufferedWriter;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.ECGenParameterSpec;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;

import static org.junit.jupiter.api.Assertions.assertEquals;

/**
 * @author bjorncs
 */
class SslContextBuilderTest {

    private static Path certificateFile;
    private static Path privateKeyFile;

    @BeforeAll
    static void createPemFiles(@TempDir Path tempDirectory) throws GeneralSecurityException, OperatorCreationException, IOException {
        KeyPair keypair = createKeypair();
        X509Certificate certificate = createCertificate(keypair);
        certificateFile = tempDirectory.resolve("cert.pem");
        privateKeyFile = tempDirectory.resolve("key.pem");
        writePem(certificateFile, "CERTIFICATE", certificate.getEncoded());
        writePem(privateKeyFile, "PRIVATE KEY", keypair.getPrivate().getEncoded());
    }

    @Test
    void successfully_constructs_sslcontext_from_pem_files() {
        SSLContext sslContext = Assertions.assertDoesNotThrow(() ->
                new SslContextBuilder()
                        .withCaCertificates(certificateFile)
                        .withCertificateAndKey(certificateFile, privateKeyFile)
                        .build());
        assertEquals("TLSv1.3", sslContext.getProtocol());
    }

    @Test
    void successfully_constructs_sslcontext_when_no_builder_parameter_given() {
        SSLContext sslContext = Assertions.assertDoesNotThrow(() -> new SslContextBuilder().build());
        assertEquals("TLSv1.3", sslContext.getProtocol());
    }

    @Test
    void successfully_constructs_sslcontext_with_only_certificate_file() {
        SSLContext sslContext = Assertions.assertDoesNotThrow(() ->
                new SslContextBuilder()
                        .withCertificateAndKey(certificateFile, privateKeyFile)
                        .build());
        assertEquals("TLSv1.3", sslContext.getProtocol());
    }

    @Test
    void successfully_constructs_sslcontext_with_only_ca_certificate_file() {
        SSLContext sslContext = Assertions.assertDoesNotThrow(() ->
                new SslContextBuilder()
                        .withCaCertificates(certificateFile)
                        .build());
        assertEquals("TLSv1.3", sslContext.getProtocol());
    }

    private static void writePem(Path file, String type, byte[] asn1DerEncodedObject) throws IOException {
        try (BufferedWriter fileWriter = Files.newBufferedWriter(file);
             JcaPEMWriter pemWriter = new JcaPEMWriter(fileWriter)) {
            pemWriter.writeObject(new PemObject(type, asn1DerEncodedObject));
            pemWriter.flush();
        }
    }

    private static KeyPair createKeypair() throws GeneralSecurityException {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", SslContextBuilder.bcProvider);
        generator.initialize(new ECGenParameterSpec("prime256v1"));
        return generator.generateKeyPair();
    }

    private static X509Certificate createCertificate(KeyPair keypair) throws OperatorCreationException, CertificateException {
        JcaX509v3CertificateBuilder jcaCertBuilder = new JcaX509v3CertificateBuilder(
                new X500Principal("CN=localhost"), BigInteger.ONE, Date.from(Instant.EPOCH),
                Date.from(Instant.EPOCH.plus(100_000, ChronoUnit.DAYS)), new X500Principal("CN=localhost"), keypair.getPublic());
        ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256withECDSA")
                .setProvider(SslContextBuilder.bcProvider)
                .build(keypair.getPrivate());
        return new JcaX509CertificateConverter()
                .setProvider(SslContextBuilder.bcProvider)
                .getCertificate(jcaCertBuilder.build(contentSigner));
    }

}