aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/endpointcertificates/EndpointCertificateManagerTest.java
blob: 3f8e91dec582a03628ae9e1cbd664a570c26743d (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
package com.yahoo.vespa.hosted.controller.endpointcertificates;

import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.security.KeyAlgorithm;
import com.yahoo.security.KeyUtils;
import com.yahoo.security.SignatureAlgorithm;
import com.yahoo.security.X509CertificateBuilder;
import com.yahoo.security.X509CertificateUtils;
import com.yahoo.vespa.flags.Flags;
import com.yahoo.vespa.flags.InMemoryFlagSource;
import com.yahoo.vespa.hosted.controller.Instance;
import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCertificateMock;
import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCertificateMetadata;
import com.yahoo.vespa.hosted.controller.integration.SecretStoreMock;
import com.yahoo.vespa.hosted.controller.integration.ZoneRegistryMock;
import com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb;
import org.junit.Before;
import org.junit.Test;

import javax.security.auth.x500.X500Principal;
import java.security.KeyPair;
import java.security.cert.X509Certificate;
import java.time.Clock;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Optional;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
 * @author andreer
 */
public class EndpointCertificateManagerTest {

    private final SecretStoreMock secretStore = new SecretStoreMock();
    private final ZoneRegistryMock zoneRegistryMock = new ZoneRegistryMock(SystemName.main);
    private final MockCuratorDb mockCuratorDb = new MockCuratorDb();
    private final EndpointCertificateMock endpointCertificateMock = new EndpointCertificateMock();
    private final InMemoryFlagSource inMemoryFlagSource = new InMemoryFlagSource();
    private final Clock clock = Clock.systemUTC();
    private final EndpointCertificateManager endpointCertificateManager = new EndpointCertificateManager(zoneRegistryMock, mockCuratorDb, secretStore, endpointCertificateMock, clock, inMemoryFlagSource);

    private static final KeyPair testKeyPair = KeyUtils.generateKeypair(KeyAlgorithm.EC, 192);
    private static final X509Certificate testCertificate = X509CertificateBuilder
            .fromKeypair(
                    testKeyPair,
                    new X500Principal("CN=test"),
                    Instant.now(), Instant.now().plus(5, ChronoUnit.MINUTES),
                    SignatureAlgorithm.SHA256_WITH_ECDSA,
                    X509CertificateBuilder.generateRandomSerialNumber())
            .addSubjectAlternativeName("vt2ktgkqme5zlnp4tj4ttyor7fj3v7q5o.vespa.oath.cloud")
            .addSubjectAlternativeName("default.default.global.vespa.oath.cloud")
            .addSubjectAlternativeName("*.default.default.global.vespa.oath.cloud")
            .addSubjectAlternativeName("default.default.us-east-1.test.vespa.oath.cloud")
            .addSubjectAlternativeName("*.default.default.us-east-1.test.vespa.oath.cloud")
            .build();

    private final Instance testInstance = new Instance(ApplicationId.defaultId());
    private final String testKeyName = "testKeyName";
    private final String testCertName = "testCertName";
    private ZoneId testZone;

    @Before
    public void setUp() {
        zoneRegistryMock.exclusiveRoutingIn(zoneRegistryMock.zones().all().zones());
        testZone = zoneRegistryMock.zones().directlyRouted().zones().stream().findFirst().get().getId();
    }

    @Test
    public void provisions_new_certificate() {
        Optional<EndpointCertificateMetadata> endpointCertificateMetadata = endpointCertificateManager.getEndpointCertificateMetadata(testInstance, testZone);
        assertTrue(endpointCertificateMetadata.isPresent());
        assertTrue(endpointCertificateMetadata.get().keyName().matches("vespa.tls.default.default.*-key"));
        assertTrue(endpointCertificateMetadata.get().certName().matches("vespa.tls.default.default.*-cert"));
        assertEquals(0, endpointCertificateMetadata.get().version());
    }

    @Test
    public void reuses_stored_certificate_metadata() {
        mockCuratorDb.writeEndpointCertificateMetadata(testInstance.id(), new EndpointCertificateMetadata(testKeyName, testCertName, 7));
        Optional<EndpointCertificateMetadata> endpointCertificateMetadata = endpointCertificateManager.getEndpointCertificateMetadata(testInstance, testZone);
        assertTrue(endpointCertificateMetadata.isPresent());
        assertEquals(testKeyName, endpointCertificateMetadata.get().keyName());
        assertEquals(testCertName, endpointCertificateMetadata.get().certName());
        assertEquals(7, endpointCertificateMetadata.get().version());
    }

    @Test
    public void uses_refreshed_certificate_when_available_and_valid() {
        inMemoryFlagSource.withBooleanFlag(Flags.USE_REFRESHED_ENDPOINT_CERTIFICATE.id(), true);

        secretStore.setSecret(testKeyName, "secret-key", 7);
        secretStore.setSecret(testCertName, "cert", 7);
        secretStore.setSecret(testKeyName, KeyUtils.toPem(testKeyPair.getPrivate()), 8);
        secretStore.setSecret(testKeyName, KeyUtils.toPem(testKeyPair.getPrivate()), 9);
        secretStore.setSecret(testCertName, X509CertificateUtils.toPem(testCertificate)+X509CertificateUtils.toPem(testCertificate), 8);
        mockCuratorDb.writeEndpointCertificateMetadata(testInstance.id(), new EndpointCertificateMetadata(testKeyName, testCertName, 7));
        Optional<EndpointCertificateMetadata> endpointCertificateMetadata = endpointCertificateManager.getEndpointCertificateMetadata(testInstance, testZone);
        assertTrue(endpointCertificateMetadata.isPresent());
        assertEquals(testKeyName, endpointCertificateMetadata.get().keyName());
        assertEquals(testCertName, endpointCertificateMetadata.get().certName());
        assertEquals(8, endpointCertificateMetadata.get().version());
    }

}