Search in sources :

Example 1 with CertificateData

use of org.carapaceproxy.configstore.CertificateData in project carapaceproxy by diennea.

the class CertificatesTest method testUploadTypedCertificatesWithDaysBeforeRenewal.

@Test
@Parameters({ "acme", "manual" })
public void testUploadTypedCertificatesWithDaysBeforeRenewal(String type) throws Exception {
    configureAndStartServer();
    int port = server.getLocalPort();
    DynamicCertificatesManager dynCertsMan = server.getDynamicCertificatesManager();
    KeyPair endUserKeyPair = KeyPairUtils.createKeyPair(DEFAULT_KEYPAIRS_SIZE);
    Certificate[] chain = generateSampleChain(endUserKeyPair, false);
    byte[] chainData = createKeystore(chain, endUserKeyPair.getPrivate());
    try (RawHttpClient client = new RawHttpClient("localhost", DEFAULT_ADMIN_PORT)) {
        // Create
        HttpResponse resp = uploadCertificate("localhost2", "type=" + type + "&daysbeforerenewal=10", chainData, client, credentials);
        if (type.equals("manual")) {
            assertTrue(resp.getBodyString().contains("ERROR: param 'daysbeforerenewal' available for type 'acme' only"));
        } else {
            CertificateData data = dynCertsMan.getCertificateDataForDomain("localhost2");
            assertNotNull(data);
            assertEquals(10, data.getDaysBeforeRenewal());
        }
        // negative value
        resp = uploadCertificate("localhost-negative", "type=" + type + "&daysbeforerenewal=-10", chainData, client, credentials);
        if (type.equals("manual")) {
            assertTrue(resp.getBodyString().contains("ERROR: param 'daysbeforerenewal' available for type 'acme' only"));
        } else {
            assertTrue(resp.getBodyString().contains("ERROR: param 'daysbeforerenewal' has to be a positive number"));
        }
        // default value
        uploadCertificate("localhost-default", "type=" + type, chainData, client, credentials);
        CertificateData data = dynCertsMan.getCertificateDataForDomain("localhost-default");
        assertNotNull(data);
        assertEquals(type.equals("manual") ? 0 : DEFAULT_DAYS_BEFORE_RENEWAL, data.getDaysBeforeRenewal());
        // Update
        uploadCertificate("localhost2", "type=" + type + "&daysbeforerenewal=45", chainData, client, credentials);
        if (type.equals("manual")) {
            assertTrue(resp.getBodyString().contains("ERROR: param 'daysbeforerenewal' available for type 'acme' only"));
        } else {
            data = dynCertsMan.getCertificateDataForDomain("localhost2");
            assertNotNull(data);
            assertEquals(45, data.getDaysBeforeRenewal());
        }
        // negative value
        resp = uploadCertificate("localhost2", "type=" + type + "&daysbeforerenewal=-10", chainData, client, credentials);
        if (type.equals("manual")) {
            assertTrue(resp.getBodyString().contains("ERROR: param 'daysbeforerenewal' available for type 'acme' only"));
        } else {
            assertTrue(resp.getBodyString().contains("ERROR: param 'daysbeforerenewal' has to be a positive number"));
        }
        // default value
        uploadCertificate("localhost2", "type=" + type, chainData, client, credentials);
        data = dynCertsMan.getCertificateDataForDomain("localhost2");
        assertNotNull(data);
        assertEquals(type.equals("manual") ? 0 : DEFAULT_DAYS_BEFORE_RENEWAL, data.getDaysBeforeRenewal());
        // changing the type (acme <-> manual)
        String other = type.equals("manual") ? "acme" : "manual";
        uploadCertificate("localhost2", "type=" + other, chainData, client, credentials);
        data = dynCertsMan.getCertificateDataForDomain("localhost2");
        assertNotNull(data);
        assertEquals(other.equals("manual") ? 0 : DEFAULT_DAYS_BEFORE_RENEWAL, data.getDaysBeforeRenewal());
        SSLCertificateConfiguration config = server.getCurrentConfiguration().getCertificates().get("localhost2");
        assertEquals(other.equals("manual") ? 0 : DEFAULT_DAYS_BEFORE_RENEWAL, config.getDaysBeforeRenewal());
        // checking for "certificate.X.daysbeforerenewal" property delete
        ConfigurationStore store = server.getDynamicConfigurationStore();
        assertEquals(other.equals("acme"), store.anyPropertyMatches((k, v) -> {
            if (k.matches("certificate\\.[0-9]+\\.hostname") && v.equals("localhost2")) {
                return store.getProperty(k.replace("hostname", "daysbeforerenewal"), null) != null;
            }
            return false;
        }));
    }
}
Also used : RawHttpClient(org.carapaceproxy.utils.RawHttpClient) X509Certificate(java.security.cert.X509Certificate) KeyPair(java.security.KeyPair) Arrays(java.util.Arrays) OcspStaplingManager(org.carapaceproxy.server.certificates.ocsp.OcspStaplingManager) SubjectPublicKeyInfo(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo) Date(java.util.Date) ConfigurationStore(org.carapaceproxy.configstore.ConfigurationStore) CertificatesUtils.createKeystore(org.carapaceproxy.utils.CertificatesUtils.createKeystore) Order(org.shredzone.acme4j.Order) UseAdminServer(org.carapaceproxy.api.UseAdminServer) JUnitParamsRunner(junitparams.JUnitParamsRunner) WireMock.aResponse(com.github.tomakehurst.wiremock.client.WireMock.aResponse) RawHttpClient(org.carapaceproxy.utils.RawHttpClient) BasicOCSPRespBuilder(org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder) List(java.util.List) Base64(java.util.Base64) Certificate(java.security.cert.Certificate) JcaX509CertificateHolder(org.bouncycastle.cert.jcajce.JcaX509CertificateHolder) Assert.assertFalse(org.junit.Assert.assertFalse) OCSPRespBuilder(org.bouncycastle.cert.ocsp.OCSPRespBuilder) Login(org.shredzone.acme4j.Login) ExtendedSSLSession(javax.net.ssl.ExtendedSSLSession) Mockito.mock(org.mockito.Mockito.mock) Parameters(junitparams.Parameters) KeyPairUtils(org.shredzone.acme4j.util.KeyPairUtils) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) Whitebox(org.powermock.reflect.Whitebox) X509CertificateHolder(org.bouncycastle.cert.X509CertificateHolder) HttpResponse(org.carapaceproxy.utils.RawHttpClient.HttpResponse) CertificatesUtils(org.carapaceproxy.utils.CertificatesUtils) CertificatesTestUtils.uploadCertificate(org.carapaceproxy.utils.CertificatesTestUtils.uploadCertificate) JcaContentSignerBuilder(org.bouncycastle.operator.jcajce.JcaContentSignerBuilder) RunWith(org.junit.runner.RunWith) BcDigestCalculatorProvider(org.bouncycastle.operator.bc.BcDigestCalculatorProvider) WireMockRule(com.github.tomakehurst.wiremock.junit.WireMockRule) CertificateID(org.bouncycastle.cert.ocsp.CertificateID) DEFAULT_KEYPAIRS_SIZE(org.carapaceproxy.server.certificates.DynamicCertificatesManager.DEFAULT_KEYPAIRS_SIZE) CertificateData(org.carapaceproxy.configstore.CertificateData) CertificatesTestUtils.generateSampleChain(org.carapaceproxy.utils.CertificatesTestUtils.generateSampleChain) HttpTestUtils(org.carapaceproxy.utils.HttpTestUtils) SSLCertificateConfiguration(org.carapaceproxy.server.config.SSLCertificateConfiguration) WireMock.get(com.github.tomakehurst.wiremock.client.WireMock.get) Properties(java.util.Properties) CertificateStatus(org.bouncycastle.cert.ocsp.CertificateStatus) TestUtils(org.carapaceproxy.utils.TestUtils) Assert.assertNotNull(org.junit.Assert.assertNotNull) VALID(org.shredzone.acme4j.Status.VALID) OCSPResp(org.bouncycastle.cert.ocsp.OCSPResp) Assert.assertTrue(org.junit.Assert.assertTrue) DEFAULT_ADMIN_PORT(org.carapaceproxy.api.UseAdminServer.DEFAULT_ADMIN_PORT) Test(org.junit.Test) Mockito.when(org.mockito.Mockito.when) CertificateException(java.security.cert.CertificateException) BasicOCSPResp(org.bouncycastle.cert.ocsp.BasicOCSPResp) Rule(org.junit.Rule) DigestCalculatorProvider(org.bouncycastle.operator.DigestCalculatorProvider) WireMock.stubFor(com.github.tomakehurst.wiremock.client.WireMock.stubFor) WireMock.urlEqualTo(com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo) DEFAULT_DAYS_BEFORE_RENEWAL(org.carapaceproxy.server.certificates.DynamicCertificatesManager.DEFAULT_DAYS_BEFORE_RENEWAL) Assert.assertEquals(org.junit.Assert.assertEquals) KeyPair(java.security.KeyPair) ConfigurationStore(org.carapaceproxy.configstore.ConfigurationStore) HttpResponse(org.carapaceproxy.utils.RawHttpClient.HttpResponse) SSLCertificateConfiguration(org.carapaceproxy.server.config.SSLCertificateConfiguration) CertificateData(org.carapaceproxy.configstore.CertificateData) X509Certificate(java.security.cert.X509Certificate) Certificate(java.security.cert.Certificate) CertificatesTestUtils.uploadCertificate(org.carapaceproxy.utils.CertificatesTestUtils.uploadCertificate) Parameters(junitparams.Parameters) Test(org.junit.Test)

Example 2 with CertificateData

use of org.carapaceproxy.configstore.CertificateData in project carapaceproxy by diennea.

the class DynamicCertificatesManagerTest method testWidlcardCertificateStateManagement.

@Test
// E) challenge failed -> record deleted
@Parameters({ "challenge_creation_failed", "challenge_check_limit_expired", "challenge_ready", "challenge_verified", "challenge_failed" })
public void testWidlcardCertificateStateManagement(String runCase) throws Exception {
    System.setProperty("carapace.acme.dnschallengereachabilitycheck.limit", "2");
    // ACME mocking
    ACMEClient ac = mock(ACMEClient.class);
    Order o = mock(Order.class);
    when(o.getLocation()).thenReturn(new URL("https://localhost/index"));
    Login login = mock(Login.class);
    when(login.bindOrder(any())).thenReturn(o);
    when(ac.getLogin()).thenReturn(login);
    when(ac.createOrderForDomain(any())).thenReturn(o);
    Session session = mock(Session.class);
    Connection conn = mock(Connection.class);
    when(conn.readJsonResponse()).thenReturn(JSON.parse("{\"url\": \"https://localhost/index\", \"type\": \"dns-01\"}"));
    when(session.connect()).thenReturn(conn);
    when(login.getSession()).thenReturn(session);
    when(login.getKeyPair()).thenReturn(KeyPairUtils.createKeyPair(DEFAULT_KEYPAIRS_SIZE));
    Dns01Challenge c = mock(Dns01Challenge.class);
    when(c.getDigest()).thenReturn("");
    when(c.getJSON()).thenReturn(JSON.parse("{\"url\": \"https://localhost/index\", \"type\": \"dns-01\", \"token\": \"mytoken\"}"));
    when(ac.getChallengeForOrder(any(), eq(true))).thenReturn(c);
    when(ac.checkResponseForChallenge(any())).thenReturn(runCase.equals("challenge_failed") ? INVALID : VALID);
    KeyPair keyPair = KeyPairUtils.createKeyPair(DEFAULT_KEYPAIRS_SIZE);
    Certificate cert = mock(Certificate.class);
    X509Certificate _cert = (X509Certificate) generateSampleChain(keyPair, false)[0];
    when(cert.getCertificateChain()).thenReturn(Arrays.asList(_cert));
    when(ac.fetchCertificateForOrder(any())).thenReturn(cert);
    HttpProxyServer parent = mock(HttpProxyServer.class);
    when(parent.getListeners()).thenReturn(mock(Listeners.class));
    DynamicCertificatesManager man = new DynamicCertificatesManager(parent);
    man.attachGroupMembershipHandler(new NullGroupMembershipHandler());
    Whitebox.setInternalState(man, ac);
    // Route53Cliente mocking
    man.initAWSClient("access", "secret");
    Route53Client r53Client = mock(Route53Client.class);
    when(r53Client.createDnsChallengeForDomain(any(), any())).thenReturn(!runCase.startsWith("challenge_creation_failed"));
    when(r53Client.isDnsChallengeForDomainAvailable(any(), any())).thenReturn(!(runCase.equals("challenge_creation_failed_n_reboot") || runCase.equals("challenge_check_limit_expired")));
    Whitebox.setInternalState(man, r53Client);
    // Store mocking
    ConfigurationStore store = mock(ConfigurationStore.class);
    when(store.loadKeyPairForDomain(anyString())).thenReturn(keyPair);
    // certificate to order
    String domain = "*.localhost";
    CertificateData cd1 = new CertificateData(domain, "", "", WAITING, "", "");
    when(store.loadCertificateForDomain(eq(domain))).thenReturn(cd1);
    man.setConfigurationStore(store);
    // Manager setup
    Properties props = new Properties();
    props.setProperty("certificate.1.hostname", domain);
    props.setProperty("certificate.1.mode", "acme");
    props.setProperty("certificate.1.daysbeforerenewal", "0");
    props.setProperty("dynamiccertificatesmanager.domainschecker.ipaddresses", "127.0.0.1, 0:0:0:0:0:0:0:1");
    ConfigurationStore configStore = new PropertiesConfigurationStore(props);
    RuntimeServerConfiguration conf = new RuntimeServerConfiguration();
    conf.configure(configStore);
    man.reloadConfiguration(conf);
    CertificateData certData = man.getCertificateDataForDomain(domain);
    assertThat(certData.isWildcard(), is(true));
    // at every run the certificate has to be saved to the db (whether not AVAILABLE).
    int saveCounter = 0;
    // WAITING
    assertCertificateState(domain, WAITING, man);
    man.run();
    verify(store, times(++saveCounter)).saveCertificate(any());
    if (runCase.equals("challenge_creation_failed")) {
        // WAITING
        assertCertificateState(domain, WAITING, man);
    } else {
        // DNS_CHALLENGE_WAIT
        assertCertificateState(domain, DNS_CHALLENGE_WAIT, man);
        man.run();
        verify(store, times(++saveCounter)).saveCertificate(any());
        if (runCase.equals("challenge_check_limit_expired")) {
            assertCertificateState(domain, DNS_CHALLENGE_WAIT, man);
            man.run();
            verify(store, times(++saveCounter)).saveCertificate(any());
            assertCertificateState(domain, REQUEST_FAILED, man);
            // check dns-challenge-record deleted
            verify(r53Client, times(1)).deleteDnsChallengeForDomain(any(), any());
        } else {
            // VERIFYING
            assertCertificateState(domain, VERIFYING, man);
            man.run();
            verify(store, times(++saveCounter)).saveCertificate(any());
            if (runCase.equals("challenge_failed")) {
                // REQUEST_FAILED
                assertCertificateState(domain, REQUEST_FAILED, man);
                // check dns-challenge-record deleted
                verify(r53Client, times(1)).deleteDnsChallengeForDomain(any(), any());
            } else if (runCase.equals("challenge_verified")) {
                // VERIFIED
                assertCertificateState(domain, VERIFIED, man);
                // check dns-challenge-record deleted
                verify(r53Client, times(1)).deleteDnsChallengeForDomain(any(), any());
            }
        }
    }
}
Also used : Order(org.shredzone.acme4j.Order) KeyPair(java.security.KeyPair) HttpProxyServer(org.carapaceproxy.core.HttpProxyServer) PropertiesConfigurationStore(org.carapaceproxy.configstore.PropertiesConfigurationStore) ConfigurationStore(org.carapaceproxy.configstore.ConfigurationStore) PropertiesConfigurationStore(org.carapaceproxy.configstore.PropertiesConfigurationStore) RuntimeServerConfiguration(org.carapaceproxy.core.RuntimeServerConfiguration) Connection(org.shredzone.acme4j.connector.Connection) Login(org.shredzone.acme4j.Login) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Properties(java.util.Properties) URL(java.net.URL) X509Certificate(java.security.cert.X509Certificate) Listeners(org.carapaceproxy.core.Listeners) CertificateData(org.carapaceproxy.configstore.CertificateData) Dns01Challenge(org.shredzone.acme4j.challenge.Dns01Challenge) NullGroupMembershipHandler(org.carapaceproxy.cluster.impl.NullGroupMembershipHandler) Session(org.shredzone.acme4j.Session) X509Certificate(java.security.cert.X509Certificate) Certificate(org.shredzone.acme4j.Certificate) Parameters(junitparams.Parameters) Test(org.junit.Test)

Example 3 with CertificateData

use of org.carapaceproxy.configstore.CertificateData in project carapaceproxy by diennea.

the class StartAPIServerTest method testCertificates.

@Test
public void testCertificates() throws Exception {
    final String dynDomain = "dynamic.test.tld";
    Properties properties = new Properties(HTTP_ADMIN_SERVER_CONFIG);
    KeyPair endUserKeyPair = KeyPairUtils.createKeyPair(DEFAULT_KEYPAIRS_SIZE);
    Certificate[] originalChain = generateSampleChain(endUserKeyPair, false);
    X509Certificate certificate = (X509Certificate) originalChain[0];
    String serialNumber1 = certificate.getSerialNumber().toString(16).toUpperCase();
    String expiringDate1 = certificate.getNotAfter().toString();
    byte[] keystoreData = createKeystore(originalChain, endUserKeyPair.getPrivate());
    File mock1 = tmpFolder.newFile("mock1.p12");
    Files.write(mock1.toPath(), keystoreData);
    properties.put("certificate.1.hostname", "localhost");
    properties.put("certificate.1.file", mock1.getAbsolutePath());
    properties.put("certificate.1.password", KEYSTORE_PW);
    endUserKeyPair = KeyPairUtils.createKeyPair(DEFAULT_KEYPAIRS_SIZE);
    originalChain = generateSampleChain(endUserKeyPair, true);
    certificate = (X509Certificate) originalChain[0];
    String serialNumber2 = certificate.getSerialNumber().toString(16).toUpperCase();
    String expiringDate2 = certificate.getNotAfter().toString();
    keystoreData = createKeystore(originalChain, endUserKeyPair.getPrivate());
    File mock2 = tmpFolder.newFile("mock2.p12");
    Files.write(mock2.toPath(), keystoreData);
    properties.put("certificate.2.hostname", "127.0.0.1");
    properties.put("certificate.2.file", mock2.getAbsolutePath());
    properties.put("certificate.2.password", KEYSTORE_PW);
    // Acme certificate
    properties.put("certificate.3.hostname", dynDomain);
    properties.put("certificate.3.mode", "acme");
    startServer(properties);
    DynamicCertificatesManager man = server.getDynamicCertificatesManager();
    // need to explicitly add 'cause DynamicCertificatesManager never run
    ConfigurationStore store = server.getDynamicConfigurationStore();
    endUserKeyPair = KeyPairUtils.createKeyPair(DEFAULT_KEYPAIRS_SIZE);
    originalChain = generateSampleChain(endUserKeyPair, false);
    certificate = (X509Certificate) originalChain[0];
    String serialNumber = certificate.getSerialNumber().toString(16).toUpperCase();
    String expiringDate = certificate.getNotAfter().toString();
    String dynChain = Base64.getEncoder().encodeToString(createKeystore(originalChain, endUserKeyPair.getPrivate()));
    store.saveCertificate(new CertificateData(dynDomain, "", dynChain, WAITING, "", ""));
    // this reloads certificates from the store
    man.setStateOfCertificate(dynDomain, WAITING);
    // Static certificates
    try (RawHttpClient client = new RawHttpClient("localhost", 8761)) {
        // full list request
        RawHttpClient.HttpResponse response = client.get("/api/certificates", credentials);
        String json = response.getBodyString();
        assertThat(json, containsString("localhost"));
        assertThat(json, containsString("\"mode\":\"static\""));
        assertThat(json, containsString("\"dynamic\":false"));
        assertThat(json, containsString("\"status\":\"available\""));
        assertThat(json, containsString("\"sslCertificateFile\":\"" + mock1.getAbsolutePath() + "\""));
        assertThat(json, containsString("\"serialNumber\":\"" + serialNumber1 + "\""));
        assertThat(json, containsString("\"expiringDate\":\"" + expiringDate1 + "\""));
        assertThat(json, containsString("127.0.0.1"));
        assertThat(json, containsString("\"mode\":\"static\""));
        assertThat(json, containsString("\"dynamic\":false"));
        assertThat(json, containsString("\"status\":\"expired\""));
        assertThat(json, containsString("\"sslCertificateFile\":\"" + mock2.getAbsolutePath() + "\""));
        assertThat(json, containsString("\"serialNumber\":\"" + serialNumber2 + "\""));
        assertThat(json, containsString("\"expiringDate\":\"" + expiringDate2 + "\""));
        // single cert request to /{certId}
        response = client.get("/api/certificates/127.0.0.1", credentials);
        json = response.getBodyString();
        assertThat(json, not(containsString("localhost")));
        assertThat(json, containsString("\"mode\":\"static\""));
        assertThat(json, containsString("\"dynamic\":false"));
        assertThat(json, containsString("\"status\":\"expired\""));
        assertThat(json, containsString("\"sslCertificateFile\":\"" + mock2.getAbsolutePath() + "\""));
        assertThat(json, containsString("\"serialNumber\":\"" + serialNumber2 + "\""));
        assertThat(json, containsString("\"expiringDate\":\"" + expiringDate2 + "\""));
    }
    // Acme certificate
    try (RawHttpClient client = new RawHttpClient("localhost", 8761)) {
        // full list request
        RawHttpClient.HttpResponse response = client.get("/api/certificates", credentials);
        String json = response.getBodyString();
        assertThat(json, containsString(dynDomain));
        assertThat(json, containsString("\"mode\":\"acme\""));
        assertThat(json, containsString("\"dynamic\":true"));
        assertThat(json, containsString("\"status\":\"waiting\""));
        assertThat(json, containsString("\"serialNumber\":\"" + serialNumber + "\""));
        assertThat(json, containsString("\"expiringDate\":\"" + expiringDate + "\""));
        // single cert request to /{certId}
        response = client.get("/api/certificates/" + dynDomain, credentials);
        json = response.getBodyString();
        assertThat(json, containsString(dynDomain));
        assertThat(json, containsString("\"mode\":\"acme\""));
        assertThat(json, containsString("\"dynamic\":true"));
        assertThat(json, containsString("\"status\":\"waiting\""));
        assertThat(json, containsString("\"serialNumber\":\"" + serialNumber + "\""));
        assertThat(json, containsString("\"expiringDate\":\"" + expiringDate + "\""));
        // Changing dynamic certificate state
        for (DynamicCertificateState state : DynamicCertificateState.values()) {
            man.setStateOfCertificate(dynDomain, state);
            response = client.get("/api/certificates", credentials);
            json = response.getBodyString();
            assertThat(json, containsString(dynDomain));
            assertThat(json, containsString("\"mode\":\"acme\""));
            assertThat(json, containsString("\"dynamic\":true"));
            assertThat(json, containsString("\"status\":\"" + certificateStateToString(state) + "\""));
            response = client.get("/api/certificates/" + dynDomain, credentials);
            json = response.getBodyString();
            assertThat(json, containsString(dynDomain));
            assertThat(json, containsString("\"mode\":\"acme\""));
            assertThat(json, containsString("\"dynamic\":true"));
            assertThat(json, containsString("\"status\":\"" + certificateStateToString(state) + "\""));
        }
        // Downloading
        CertificateData cert = store.loadCertificateForDomain(dynDomain);
        byte[] newKeystore = createKeystore(generateSampleChain(endUserKeyPair, false), KeyPairUtils.createKeyPair(DEFAULT_KEYPAIRS_SIZE).getPrivate());
        cert.setChain(Base64.getEncoder().encodeToString(newKeystore));
        store.saveCertificate(cert);
        man.setStateOfCertificate(dynDomain, DynamicCertificateState.AVAILABLE);
        response = client.get("/api/certificates/" + dynDomain + "/download", credentials);
        assertTrue(Arrays.equals(newKeystore, response.getBody()));
    }
    // Manual certificate
    try (RawHttpClient client = new RawHttpClient("localhost", 8761)) {
        String manualDomain = "manual.test.tld";
        int certsCount = server.getCurrentConfiguration().getCertificates().size();
        // Uploading trash-stuff
        RawHttpClient.HttpResponse resp = uploadCertificate(manualDomain, null, "fake-chain".getBytes(), client, credentials);
        String s = resp.getBodyString();
        assertTrue(s.contains("ERROR"));
        // Uploading real certificate
        endUserKeyPair = KeyPairUtils.createKeyPair(DEFAULT_KEYPAIRS_SIZE);
        originalChain = generateSampleChain(endUserKeyPair, false);
        certificate = (X509Certificate) originalChain[0];
        serialNumber = certificate.getSerialNumber().toString(16).toUpperCase();
        expiringDate = certificate.getNotAfter().toString();
        byte[] chain1 = createKeystore(originalChain, endUserKeyPair.getPrivate());
        resp = uploadCertificate(manualDomain, null, chain1, client, credentials);
        s = resp.getBodyString();
        assertTrue(s.contains("SUCCESS"));
        int certsCount2 = server.getCurrentConfiguration().getCertificates().size();
        assertEquals(certsCount + 1, certsCount2);
        // full list request
        RawHttpClient.HttpResponse response = client.get("/api/certificates", credentials);
        String json = response.getBodyString();
        assertThat(json, containsString(manualDomain));
        assertThat(json, containsString("\"mode\":\"manual\""));
        assertThat(json, containsString("\"dynamic\":true"));
        assertThat(json, containsString("\"status\":\"available\""));
        assertThat(json, containsString("\"serialNumber\":\"" + serialNumber + "\""));
        assertThat(json, containsString("\"expiringDate\":\"" + expiringDate + "\""));
        // single cert request to /{certId}
        response = client.get("/api/certificates/" + manualDomain, credentials);
        json = response.getBodyString();
        assertThat(json, containsString(manualDomain));
        assertThat(json, containsString("\"mode\":\"manual\""));
        assertThat(json, containsString("\"dynamic\":true"));
        assertThat(json, containsString("\"status\":\"available\""));
        assertThat(json, containsString("\"serialNumber\":\"" + serialNumber + "\""));
        assertThat(json, containsString("\"expiringDate\":\"" + expiringDate + "\""));
        // Downloading
        response = client.get("/api/certificates/" + manualDomain + "/download", credentials);
        assertTrue(Arrays.equals(chain1, response.getBody()));
        // Certificate updating
        // Uploading
        endUserKeyPair = KeyPairUtils.createKeyPair(DEFAULT_KEYPAIRS_SIZE);
        originalChain = generateSampleChain(endUserKeyPair, true);
        certificate = (X509Certificate) originalChain[0];
        serialNumber = certificate.getSerialNumber().toString(16).toUpperCase();
        expiringDate = certificate.getNotAfter().toString();
        byte[] chain2 = createKeystore(originalChain, endUserKeyPair.getPrivate());
        assertFalse(Arrays.equals(chain1, chain2));
        resp = uploadCertificate(manualDomain, null, chain2, client, credentials);
        s = resp.getBodyString();
        assertTrue(s.contains("SUCCESS"));
        // check properties (certificate) not duplicated
        int certsCount3 = server.getCurrentConfiguration().getCertificates().size();
        assertEquals(certsCount2, certsCount3);
        // full list request
        response = client.get("/api/certificates", credentials);
        json = response.getBodyString();
        assertThat(json, containsString(manualDomain));
        assertThat(json, containsString("\"mode\":\"manual\""));
        assertThat(json, containsString("\"dynamic\":true"));
        assertThat(json, containsString("\"status\":\"expired\""));
        assertThat(json, containsString("\"serialNumber\":\"" + serialNumber + "\""));
        assertThat(json, containsString("\"expiringDate\":\"" + expiringDate + "\""));
        // single cert request to /{certId}
        response = client.get("/api/certificates/" + manualDomain, credentials);
        json = response.getBodyString();
        assertThat(json, containsString(manualDomain));
        assertThat(json, containsString("\"mode\":\"manual\""));
        assertThat(json, containsString("\"dynamic\":true"));
        assertThat(json, containsString("\"status\":\"expired\""));
        assertThat(json, containsString("\"serialNumber\":\"" + serialNumber + "\""));
        assertThat(json, containsString("\"expiringDate\":\"" + expiringDate + "\""));
        // Downloading
        response = client.get("/api/certificates/" + manualDomain + "/download", credentials);
        assertTrue(Arrays.equals(chain2, response.getBody()));
    }
}
Also used : RawHttpClient(org.carapaceproxy.utils.RawHttpClient) DynamicCertificateState(org.carapaceproxy.server.certificates.DynamicCertificateState) KeyPair(java.security.KeyPair) DynamicCertificatesManager(org.carapaceproxy.server.certificates.DynamicCertificatesManager) ConfigurationStore(org.carapaceproxy.configstore.ConfigurationStore) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) APIUtils.certificateStateToString(org.carapaceproxy.utils.APIUtils.certificateStateToString) Properties(java.util.Properties) X509Certificate(java.security.cert.X509Certificate) CertificateData(org.carapaceproxy.configstore.CertificateData) File(java.io.File) X509Certificate(java.security.cert.X509Certificate) CertificatesTestUtils.uploadCertificate(org.carapaceproxy.utils.CertificatesTestUtils.uploadCertificate) Certificate(java.security.cert.Certificate) Test(org.junit.Test)

Example 4 with CertificateData

use of org.carapaceproxy.configstore.CertificateData in project carapaceproxy by diennea.

the class DynamicCertificatesManager method certificatesLifecycle.

private void certificatesLifecycle() {
    boolean flushCache = false;
    List<CertificateData> _certificates = certificates.entrySet().stream().filter(e -> !e.getValue().isManual()).sorted((e1, e2) -> e1.getKey().compareTo(e2.getKey())).map(e -> e.getValue()).collect(Collectors.toList());
    for (CertificateData cert : _certificates) {
        boolean updateCertificate = true;
        final String domain = cert.getDomain();
        try {
            switch(cert.getState()) {
                // certificate waiting to be issues/renew
                case WAITING:
                case DOMAIN_UNREACHABLE:
                    {
                        // certificate domain reported as unreachable for issuing/renewing
                        LOG.log(Level.INFO, "WAITING for certificate issuing process start for domain: {0}.", domain);
                        if (cert.isWildcard() || checkDomain(domain)) {
                            Order order = createOrderForCertificate(cert);
                            createChallengeForCertificateOrder(cert, order);
                        } else {
                            cert.setState(DOMAIN_UNREACHABLE);
                        }
                        break;
                    }
                case DNS_CHALLENGE_WAIT:
                    {
                        // waiting for full dns propagation
                        LOG.log(Level.INFO, "DNS CHALLENGE WAITING for domain {0}.", domain);
                        Dns01Challenge pendingChallenge = (Dns01Challenge) getChallengeFromCertificate(cert);
                        checkDnsChallengeReachabilityForCertificate(pendingChallenge, cert);
                        break;
                    }
                case VERIFYING:
                    {
                        // challenge verification by LE pending
                        LOG.log(Level.INFO, "VERIFYING certificate for domain {0}.", domain);
                        Challenge pendingChallenge = getChallengeFromCertificate(cert);
                        checkChallengeResponseForCertificate(pendingChallenge, cert);
                        break;
                    }
                case VERIFIED:
                    {
                        // challenge succeded
                        LOG.log(Level.INFO, "Certificate for domain {0} VERIFIED.", domain);
                        Order pendingOrder = acmeClient.getLogin().bindOrder(new URL(cert.getPendingOrderLocation()));
                        if (pendingOrder.getStatus() != Status.VALID) {
                            // whether the order is already valid we have to skip finalization
                            try {
                                KeyPair keys = loadOrCreateKeyPairForDomain(domain);
                                acmeClient.orderCertificate(pendingOrder, keys);
                            } catch (AcmeException ex) {
                                // order finalization failed
                                LOG.log(Level.SEVERE, "Certificate order finalization for domain {0} FAILED.", domain);
                                cert.setState(REQUEST_FAILED);
                                break;
                            }
                        }
                        cert.setState(ORDERING);
                        break;
                    }
                case ORDERING:
                    {
                        // certificate ordering
                        LOG.log(Level.INFO, "ORDERING certificate for domain {0}.", domain);
                        Order order = acmeClient.getLogin().bindOrder(new URL(cert.getPendingOrderLocation()));
                        Status status = acmeClient.checkResponseForOrder(order);
                        if (status == Status.VALID) {
                            List<X509Certificate> certificateChain = acmeClient.fetchCertificateForOrder(order).getCertificateChain();
                            PrivateKey key = loadOrCreateKeyPairForDomain(domain).getPrivate();
                            String chain = base64EncodeCertificateChain(certificateChain.toArray(new Certificate[0]), key);
                            cert.setChain(chain);
                            cert.setState(AVAILABLE);
                            LOG.log(Level.INFO, "Certificate issuing for domain: {0} SUCCEED. Certificate AVAILABLE.", domain);
                        } else if (status == Status.INVALID) {
                            cert.setState(REQUEST_FAILED);
                        }
                        break;
                    }
                case REQUEST_FAILED:
                    {
                        // challenge/order failed
                        LOG.log(Level.INFO, "Certificate issuing for domain: {0} current status is FAILED, setting status=WAITING again.", domain);
                        cert.setState(WAITING);
                        break;
                    }
                case AVAILABLE:
                    {
                        // certificate saved/available/not expired
                        if (isCertificateExpired(cert.getExpiringDate(), cert.getDaysBeforeRenewal())) {
                            cert.setState(EXPIRED);
                        } else {
                            updateCertificate = false;
                        }
                        break;
                    }
                case EXPIRED:
                    {
                        // certificate expired
                        LOG.log(Level.INFO, "Certificate for domain: {0} EXPIRED.", domain);
                        cert.setState(WAITING);
                        break;
                    }
                default:
                    throw new IllegalStateException();
            }
            if (updateCertificate) {
                LOG.log(Level.INFO, "Save certificate request status for domain {0}", domain);
                store.saveCertificate(cert);
                flushCache = true;
            }
        } catch (AcmeException | IOException | GeneralSecurityException | IllegalStateException ex) {
            LOG.log(Level.SEVERE, "Error while handling dynamic certificate for domain " + domain, ex);
        }
    }
    if (flushCache) {
        groupMembershipHandler.fireEvent(EVENT_CERTIFICATES_STATE_CHANGED);
        // remember that events  are not delivered to the local JVM
        reloadCertificatesFromDB();
    }
}
Also used : X509Certificate(java.security.cert.X509Certificate) KeyPair(java.security.KeyPair) DOMAIN_UNREACHABLE(org.carapaceproxy.server.certificates.DynamicCertificateState.DOMAIN_UNREACHABLE) ScheduledFuture(java.util.concurrent.ScheduledFuture) CertificatesUtils.readChainFromKeystore(org.carapaceproxy.utils.CertificatesUtils.readChainFromKeystore) Http01Challenge(org.shredzone.acme4j.challenge.Http01Challenge) URL(java.net.URL) VERIFIED(org.carapaceproxy.server.certificates.DynamicCertificateState.VERIFIED) ConfigurationStore(org.carapaceproxy.configstore.ConfigurationStore) ConfigurationNotValidException(org.carapaceproxy.server.config.ConfigurationNotValidException) Order(org.shredzone.acme4j.Order) InetAddress(java.net.InetAddress) GeneralSecurityException(java.security.GeneralSecurityException) Challenge(org.shredzone.acme4j.challenge.Challenge) Map(java.util.Map) RuntimeServerConfiguration(org.carapaceproxy.core.RuntimeServerConfiguration) MANUAL(org.carapaceproxy.server.config.SSLCertificateConfiguration.CertificateMode.MANUAL) VERIFYING(org.carapaceproxy.server.certificates.DynamicCertificateState.VERIFYING) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) Logger(java.util.logging.Logger) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) List(java.util.List) Base64(java.util.Base64) Certificate(java.security.cert.Certificate) PrivateKey(java.security.PrivateKey) HttpProxyServer(org.carapaceproxy.core.HttpProxyServer) Entry(java.util.Map.Entry) KeyPairUtils(org.shredzone.acme4j.util.KeyPairUtils) ThreadFactoryBuilder(org.glassfish.jersey.internal.guava.ThreadFactoryBuilder) EXPIRED(org.carapaceproxy.server.certificates.DynamicCertificateState.EXPIRED) Level(java.util.logging.Level) CertificatesUtils.isCertificateExpired(org.carapaceproxy.utils.CertificatesUtils.isCertificateExpired) Status(org.shredzone.acme4j.Status) JSON(org.shredzone.acme4j.toolbox.JSON) CertificateData(org.carapaceproxy.configstore.CertificateData) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) REQUEST_FAILED(org.carapaceproxy.server.certificates.DynamicCertificateState.REQUEST_FAILED) SSLCertificateConfiguration(org.carapaceproxy.server.config.SSLCertificateConfiguration) DNS_CHALLENGE_WAIT(org.carapaceproxy.server.certificates.DynamicCertificateState.DNS_CHALLENGE_WAIT) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) ORDERING(org.carapaceproxy.server.certificates.DynamicCertificateState.ORDERING) WAITING(org.carapaceproxy.server.certificates.DynamicCertificateState.WAITING) TimeUnit(java.util.concurrent.TimeUnit) ConfigurationStoreUtils.base64EncodeCertificateChain(org.carapaceproxy.configstore.ConfigurationStoreUtils.base64EncodeCertificateChain) GroupMembershipHandler(org.carapaceproxy.cluster.GroupMembershipHandler) Dns01Challenge(org.shredzone.acme4j.challenge.Dns01Challenge) AVAILABLE(org.carapaceproxy.server.certificates.DynamicCertificateState.AVAILABLE) AcmeException(org.shredzone.acme4j.exception.AcmeException) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Order(org.shredzone.acme4j.Order) Status(org.shredzone.acme4j.Status) KeyPair(java.security.KeyPair) PrivateKey(java.security.PrivateKey) AcmeException(org.shredzone.acme4j.exception.AcmeException) GeneralSecurityException(java.security.GeneralSecurityException) IOException(java.io.IOException) URL(java.net.URL) Http01Challenge(org.shredzone.acme4j.challenge.Http01Challenge) Challenge(org.shredzone.acme4j.challenge.Challenge) Dns01Challenge(org.shredzone.acme4j.challenge.Dns01Challenge) CertificateData(org.carapaceproxy.configstore.CertificateData) Dns01Challenge(org.shredzone.acme4j.challenge.Dns01Challenge) List(java.util.List)

Example 5 with CertificateData

use of org.carapaceproxy.configstore.CertificateData in project carapaceproxy by diennea.

the class HttpProxyServer method updateDynamicCertificateForDomain.

public void updateDynamicCertificateForDomain(CertificateData cert) throws Exception {
    // Certificate saving on db
    dynamicConfigurationStore.saveCertificate(cert);
    // Configuration updating
    Properties props = dynamicConfigurationStore.asProperties(null);
    boolean newCertificate = !dynamicConfigurationStore.anyPropertyMatches((k, v) -> {
        if (k.matches("certificate\\.[0-9]+\\.hostname") && v.equals(cert.getDomain())) {
            // updating existing certificate
            performUpdate(props, k, cert);
            return true;
        }
        return false;
    });
    if (newCertificate) {
        performCreate(props, cert);
    }
    // Configuration reloading
    applyDynamicConfigurationFromAPI(new PropertiesConfigurationStore(props));
}
Also used : ServletContextHandler(org.eclipse.jetty.servlet.ServletContextHandler) MeterFilter(io.micrometer.core.instrument.config.MeterFilter) ForceHeadersAPIRequestsFilter(org.carapaceproxy.api.ForceHeadersAPIRequestsFilter) SslConnectionFactory(org.eclipse.jetty.server.SslConnectionFactory) WebAppContext(org.eclipse.jetty.webapp.WebAppContext) OcspStaplingManager(org.carapaceproxy.server.certificates.ocsp.OcspStaplingManager) PropertiesConfigurationStore(org.carapaceproxy.configstore.PropertiesConfigurationStore) PROPERTY_PEER_ADMIN_SERVER_PORT(org.carapaceproxy.cluster.impl.ZooKeeperGroupMembershipHandler.PROPERTY_PEER_ADMIN_SERVER_PORT) ContextHandlerCollection(org.eclipse.jetty.server.handler.ContextHandlerCollection) ConfigurationStore(org.carapaceproxy.configstore.ConfigurationStore) ConfigurationNotValidException(org.carapaceproxy.server.config.ConfigurationNotValidException) Metrics(io.micrometer.core.instrument.Metrics) InetAddress(java.net.InetAddress) NCSARequestLog(org.eclipse.jetty.server.NCSARequestLog) CONNECTION_PROVIDER_PREFIX(reactor.netty.Metrics.CONNECTION_PROVIDER_PREFIX) Map(java.util.Map) PROPERTY_PEER_ADMIN_SERVER_HTTPS_PORT(org.carapaceproxy.cluster.impl.ZooKeeperGroupMembershipHandler.PROPERTY_PEER_ADMIN_SERVER_HTTPS_PORT) Server(org.eclipse.jetty.server.Server) EnumSet(java.util.EnumSet) UserRealm(org.carapaceproxy.user.UserRealm) HttpServlet(javax.servlet.http.HttpServlet) HerdDBConfigurationStore(org.carapaceproxy.configstore.HerdDBConfigurationStore) ServletHolder(org.eclipse.jetty.servlet.ServletHolder) ServletContainer(org.glassfish.jersey.servlet.ServletContainer) KeyStore(java.security.KeyStore) EndpointKey(org.carapaceproxy.client.EndpointKey) Logger(java.util.logging.Logger) JAXRS_APPLICATION_CLASS(org.glassfish.jersey.servlet.ServletProperties.JAXRS_APPLICATION_CLASS) InvocationTargetException(java.lang.reflect.InvocationTargetException) IDLE_CONNECTIONS(reactor.netty.Metrics.IDLE_CONNECTIONS) Objects(java.util.Objects) List(java.util.List) NetworkListenerConfiguration(org.carapaceproxy.server.config.NetworkListenerConfiguration) PrometheusRenameFilter(io.micrometer.prometheus.PrometheusRenameFilter) TOTAL_CONNECTIONS(reactor.netty.Metrics.TOTAL_CONNECTIONS) ApplicationConfig(org.carapaceproxy.api.ApplicationConfig) HttpConnectionFactory(org.eclipse.jetty.server.HttpConnectionFactory) BackendConfiguration(org.carapaceproxy.server.config.BackendConfiguration) ConfigurationChangeInProgressException(org.carapaceproxy.server.config.ConfigurationChangeInProgressException) Setter(lombok.Setter) ZooKeeperGroupMembershipHandler(org.carapaceproxy.cluster.impl.ZooKeeperGroupMembershipHandler) PrometheusMetricsProvider(org.apache.bookkeeper.stats.prometheus.PrometheusMetricsProvider) NullGroupMembershipHandler(org.carapaceproxy.cluster.impl.NullGroupMembershipHandler) Getter(lombok.Getter) SslContextFactory(org.eclipse.jetty.util.ssl.SslContextFactory) REMOTE_ADDRESS(reactor.netty.Metrics.REMOTE_ADDRESS) HashMap(java.util.HashMap) NAME(reactor.netty.Metrics.NAME) ConfigurationException(javax.naming.ConfigurationException) ArrayList(java.util.ArrayList) Level(java.util.logging.Level) RequestFilterFactory.buildRequestFilter(org.carapaceproxy.server.filters.RequestFilterFactory.buildRequestFilter) RequestFilterConfiguration(org.carapaceproxy.server.config.RequestFilterConfiguration) SecureRequestCustomizer(org.eclipse.jetty.server.SecureRequestCustomizer) HttpServletRequest(javax.servlet.http.HttpServletRequest) PROPERTY_PEER_ADMIN_SERVER_HOST(org.carapaceproxy.cluster.impl.ZooKeeperGroupMembershipHandler.PROPERTY_PEER_ADMIN_SERVER_HOST) HttpConfiguration(org.eclipse.jetty.server.HttpConfiguration) ACTIVE_CONNECTIONS(reactor.netty.Metrics.ACTIVE_CONNECTIONS) CertificateData(org.carapaceproxy.configstore.CertificateData) org.apache.bookkeeper.stats(org.apache.bookkeeper.stats) ContentsCache(org.carapaceproxy.server.cache.ContentsCache) PENDING_CONNECTIONS(reactor.netty.Metrics.PENDING_CONNECTIONS) SSLCertificateConfiguration(org.carapaceproxy.server.config.SSLCertificateConfiguration) PropertiesConfiguration(org.apache.commons.configuration.PropertiesConfiguration) OutputStream(java.io.OutputStream) DynamicCertificatesManager(org.carapaceproxy.server.certificates.DynamicCertificatesManager) Properties(java.util.Properties) ReentrantLock(java.util.concurrent.locks.ReentrantLock) MetricsServlet(io.prometheus.client.exporter.MetricsServlet) HttpServletResponse(javax.servlet.http.HttpServletResponse) Meter(io.micrometer.core.instrument.Meter) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) AuthAPIRequestsFilter(org.carapaceproxy.api.AuthAPIRequestsFilter) UnknownHostException(java.net.UnknownHostException) File(java.io.File) Measurement(io.micrometer.core.instrument.Measurement) EndpointMapper(org.carapaceproxy.server.mapper.EndpointMapper) RequestLogHandler(org.eclipse.jetty.server.handler.RequestLogHandler) GroupMembershipHandler(org.carapaceproxy.cluster.GroupMembershipHandler) SimpleUserRealm(org.carapaceproxy.user.SimpleUserRealm) ServerConnector(org.eclipse.jetty.server.ServerConnector) BackendHealthManager(org.carapaceproxy.server.backends.BackendHealthManager) PrometheusMeterRegistry(io.micrometer.prometheus.PrometheusMeterRegistry) Data(lombok.Data) DispatcherType(javax.servlet.DispatcherType) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Collections(java.util.Collections) PrometheusConfig(io.micrometer.prometheus.PrometheusConfig) PropertiesConfigurationStore(org.carapaceproxy.configstore.PropertiesConfigurationStore) Properties(java.util.Properties)

Aggregations

CertificateData (org.carapaceproxy.configstore.CertificateData)17 X509Certificate (java.security.cert.X509Certificate)13 KeyPair (java.security.KeyPair)11 Test (org.junit.Test)10 Certificate (java.security.cert.Certificate)9 ConfigurationStore (org.carapaceproxy.configstore.ConfigurationStore)8 CertificatesTestUtils.uploadCertificate (org.carapaceproxy.utils.CertificatesTestUtils.uploadCertificate)7 RawHttpClient (org.carapaceproxy.utils.RawHttpClient)7 Properties (java.util.Properties)6 Order (org.shredzone.acme4j.Order)6 Parameters (junitparams.Parameters)5 HttpProxyServer (org.carapaceproxy.core.HttpProxyServer)5 Login (org.shredzone.acme4j.Login)5 URL (java.net.URL)4 NullGroupMembershipHandler (org.carapaceproxy.cluster.impl.NullGroupMembershipHandler)4 PropertiesConfigurationStore (org.carapaceproxy.configstore.PropertiesConfigurationStore)4 RuntimeServerConfiguration (org.carapaceproxy.core.RuntimeServerConfiguration)4 HttpResponse (org.carapaceproxy.utils.RawHttpClient.HttpResponse)4 IOException (java.io.IOException)3 GeneralSecurityException (java.security.GeneralSecurityException)3