diff options
author | Martin Polden <mpolden@mpolden.no> | 2019-09-20 14:41:33 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2019-09-20 15:08:41 +0200 |
commit | e9caf7649d7bb235cdec15cb9593b9a0eac29c28 (patch) | |
tree | e309ed7d52d46c145127ac2999e7782f7f8c8c1a /athenz-identity-provider-service | |
parent | eb50e5195dab5662a5a9011c0b7ca69ecf8b64c4 (diff) |
Implement helper class for creating certificates
Diffstat (limited to 'athenz-identity-provider-service')
2 files changed, 90 insertions, 0 deletions
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/Certificates.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/Certificates.java new file mode 100644 index 00000000000..6d121657a40 --- /dev/null +++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/Certificates.java @@ -0,0 +1,57 @@ +// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.ca; + +import com.yahoo.security.Pkcs10Csr; +import com.yahoo.security.SubjectAlternativeName; +import com.yahoo.security.X509CertificateBuilder; + +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.time.Clock; +import java.time.Duration; +import java.util.Objects; + +import static com.yahoo.security.SignatureAlgorithm.SHA256_WITH_ECDSA; +import static com.yahoo.security.SubjectAlternativeName.Type.DNS_NAME; + +/** + * Helper class for creating {@link X509Certificate}s. + * + * @author mpolden + */ +public class Certificates { + + private static final Duration CERTIFICATE_TTL = Duration.ofDays(30); + + private final Clock clock; + + public Certificates(Clock clock) { + this.clock = Objects.requireNonNull(clock, "clock must be non-null"); + } + + /** Create a new certificate from csr signed by the given CA private key */ + public X509Certificate create(Pkcs10Csr csr, X509Certificate caCertificate, PrivateKey caPrivateKey) { + var x500principal = caCertificate.getSubjectX500Principal(); + var now = clock.instant(); + var notBefore = now.minus(Duration.ofHours(1)); + var notAfter = now.plus(CERTIFICATE_TTL); + return X509CertificateBuilder.fromCsr(csr, + x500principal, + notBefore, + notAfter, + caPrivateKey, + SHA256_WITH_ECDSA, + X509CertificateBuilder.generateRandomSerialNumber()) + .build(); + } + + /** Returns the DNS name field from Subject Alternative Names in given csr */ + public static String extractDnsName(Pkcs10Csr csr) { + return csr.getSubjectAlternativeNames().stream() + .filter(san -> san.getType() == DNS_NAME) + .map(SubjectAlternativeName::getValue) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("DNS name not found in CSR")); + } + +} diff --git a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/ca/CertificatesTest.java b/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/ca/CertificatesTest.java new file mode 100644 index 00000000000..4e306d9a70e --- /dev/null +++ b/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/ca/CertificatesTest.java @@ -0,0 +1,33 @@ +// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.ca; + +import com.yahoo.security.KeyAlgorithm; +import com.yahoo.security.KeyUtils; +import com.yahoo.test.ManualClock; +import org.junit.Test; + +import java.time.Duration; + +import static java.time.temporal.ChronoUnit.SECONDS; +import static org.junit.Assert.assertEquals; + +/** + * @author mpolden + */ +public class CertificatesTest { + + @Test + public void expiry() { + var clock = new ManualClock(); + var certificates = new Certificates(clock); + var csr = CertificateTester.createCsr(); + var keyPair = KeyUtils.generateKeypair(KeyAlgorithm.EC, 256); + var caCertificate = CertificateTester.createCertificate("CA", keyPair); + var certificate = certificates.create(csr, caCertificate, keyPair.getPrivate()); + var now = clock.instant(); + + assertEquals(now.minus(Duration.ofHours(1)).truncatedTo(SECONDS), certificate.getNotBefore().toInstant()); + assertEquals(now.plus(Duration.ofDays(30)).truncatedTo(SECONDS), certificate.getNotAfter().toInstant()); + } + +} |