diff --git a/carapace-server/src/main/java/org/carapaceproxy/api/CertificatesResource.java b/carapace-server/src/main/java/org/carapaceproxy/api/CertificatesResource.java index adc7d2bb6..ce72068c1 100644 --- a/carapace-server/src/main/java/org/carapaceproxy/api/CertificatesResource.java +++ b/carapace-server/src/main/java/org/carapaceproxy/api/CertificatesResource.java @@ -285,13 +285,11 @@ public Response uploadCertificate( String encodedData = ""; DynamicCertificateState state = WAITING; - boolean available = false; if (data != null && data.length > 0) { encodedData = Base64.getEncoder().encodeToString(data); - available = true; state = AVAILABLE; } - CertificateData cert = new CertificateData(domain, "", encodedData, state, "", "", available); + CertificateData cert = new CertificateData(domain, "", encodedData, state, "", ""); cert.setManual(MANUAL.equals(certType)); cert.setDaysBeforeRenewal(daysbeforerenewal != null ? daysbeforerenewal : DEFAULT_DAYS_BEFORE_RENEWAL); HttpProxyServer server = (HttpProxyServer) context.getAttribute("server"); diff --git a/carapace-server/src/main/java/org/carapaceproxy/configstore/CertificateData.java b/carapace-server/src/main/java/org/carapaceproxy/configstore/CertificateData.java index 631ad13a3..379b41973 100644 --- a/carapace-server/src/main/java/org/carapaceproxy/configstore/CertificateData.java +++ b/carapace-server/src/main/java/org/carapaceproxy/configstore/CertificateData.java @@ -38,7 +38,6 @@ public class CertificateData { private DynamicCertificateState state; private String pendingOrderLocation; private String pendingChallengeData; - private boolean available; // Data available at run-time only private boolean wildcard; @@ -46,14 +45,13 @@ public class CertificateData { private int daysBeforeRenewal; public CertificateData(String domain, String privateKey, String chain, DynamicCertificateState state, - String orderLocation, String challengeData, boolean available) { + String orderLocation, String challengeData) { this.domain = domain; this.privateKey = privateKey; this.chain = chain; this.state = state; this.pendingOrderLocation = orderLocation; this.pendingChallengeData = challengeData; - this.available = available; } public String getDomain() { @@ -80,10 +78,6 @@ public String getPendingChallengeData() { return pendingChallengeData; } - public boolean isAvailable() { - return available; - } - public void setDomain(String domain) { this.domain = domain; } @@ -100,10 +94,6 @@ public void setState(DynamicCertificateState state) { this.state = state; } - public void setAvailable(boolean available) { - this.available = available; - } - public void setPendingOrderLocation(String orderLocation) { this.pendingOrderLocation = orderLocation; } @@ -153,7 +143,6 @@ public int hashCode() { hash = 89 * hash + Objects.hashCode(this.state); hash = 89 * hash + Objects.hashCode(this.pendingOrderLocation); hash = 89 * hash + Objects.hashCode(this.pendingChallengeData); - hash = 89 * hash + (this.available ? 1 : 0); hash = 89 * hash + (this.manual ? 1 : 0); hash = 89 * hash + this.daysBeforeRenewal; return hash; @@ -171,9 +160,6 @@ public boolean equals(Object obj) { return false; } final CertificateData other = (CertificateData) obj; - if (this.available != other.available) { - return false; - } if (this.manual != other.manual) { return false; } @@ -203,7 +189,7 @@ public boolean equals(Object obj) { @Override public String toString() { - return "CertificateData{" + "domain=" + domain + ", state=" + state + ", available=" + available + ", manual=" + manual + '}'; + return "CertificateData{" + "domain=" + domain + ", state=" + state + ", manual=" + manual + '}'; } } diff --git a/carapace-server/src/main/java/org/carapaceproxy/configstore/HerdDBConfigurationStore.java b/carapace-server/src/main/java/org/carapaceproxy/configstore/HerdDBConfigurationStore.java index 5c37f095f..31eba7f72 100644 --- a/carapace-server/src/main/java/org/carapaceproxy/configstore/HerdDBConfigurationStore.java +++ b/carapace-server/src/main/java/org/carapaceproxy/configstore/HerdDBConfigurationStore.java @@ -1,21 +1,21 @@ /* - Licensed to Diennea S.r.l. under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. Diennea S.r.l. licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - + * Licensed to Diennea S.r.l. under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Diennea S.r.l. licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * */ package org.carapaceproxy.configstore; @@ -85,12 +85,12 @@ public class HerdDBConfigurationStore implements ConfigurationStore { private static final String DIGITAL_CERTIFICATES_TABLE_NAME = "digital_certificates"; private static final String CREATE_DIGITAL_CERTIFICATES_TABLE = "CREATE TABLE " + DIGITAL_CERTIFICATES_TABLE_NAME + "(domain string primary key, privateKey string, chain string, " - + "state string, pendingOrder string, pendingChallenge string, available tinyint)"; + + "state string, pendingOrder string, pendingChallenge string)"; private static final String SELECT_FROM_DIGITAL_CERTIFICATES_TABLE = "SELECT * from " + DIGITAL_CERTIFICATES_TABLE_NAME + " WHERE domain=?"; private static final String UPDATE_DIGITAL_CERTIFICATES_TABLE = "UPDATE " + DIGITAL_CERTIFICATES_TABLE_NAME - + " SET privateKey=?, chain=?, state=?, pendingOrder=?, pendingChallenge=?, available=? WHERE domain=?"; + + " SET privateKey=?, chain=?, state=?, pendingOrder=?, pendingChallenge=? WHERE domain=?"; private static final String INSERT_INTO_DIGITAL_CERTIFICATES_TABLE = "INSERT INTO " + DIGITAL_CERTIFICATES_TABLE_NAME - + "(domain, privateKey, chain, state, pendingOrder, pendingChallenge, available) values (?, ?, ?, ?, ?, ?, ?)"; + + "(domain, privateKey, chain, state, pendingOrder, pendingChallenge) values (?, ?, ?, ?, ?, ?)"; // Table for ACME challenge tokens private static final String ACME_CHALLENGE_TOKENS_TABLE_NAME = "acme_challenge_tokens"; @@ -380,15 +380,13 @@ public CertificateData loadCertificateForDomain(String domain) { String state = rs.getString(4); String pendingOrder = rs.getString(5); String pendigChallenge = rs.getString(6); - boolean available = rs.getInt(7) == 1; return new CertificateData( domain, privateKey, chain, DynamicCertificateState.fromStorableFormat(state), pendingOrder, - pendigChallenge, - available + pendigChallenge ); } } @@ -411,15 +409,13 @@ public void saveCertificate(CertificateData cert) { String state = cert.getState().toStorableFormat(); String pendingOrder = cert.getPendingOrderLocation(); String pendigChallenge = cert.getPendingChallengeData(); - int available = cert.isAvailable() ? 1 : 0; psUpdate.setString(1, privateKey); psUpdate.setString(2, chain); psUpdate.setString(3, state); psUpdate.setString(4, pendingOrder); psUpdate.setString(5, pendigChallenge); - psUpdate.setInt(6, available); - psUpdate.setString(7, domain); + psUpdate.setString(6, domain); if (psUpdate.executeUpdate() == 0) { psInsert.setString(1, domain); psInsert.setString(2, privateKey); @@ -427,7 +423,6 @@ public void saveCertificate(CertificateData cert) { psInsert.setString(4, state); psInsert.setString(5, pendingOrder); psInsert.setString(6, pendigChallenge); - psInsert.setInt(7, available); psInsert.executeUpdate(); } diff --git a/carapace-server/src/main/java/org/carapaceproxy/server/RequestsLogger.java b/carapace-server/src/main/java/org/carapaceproxy/server/RequestsLogger.java index ce7e5efcf..4044815e2 100644 --- a/carapace-server/src/main/java/org/carapaceproxy/server/RequestsLogger.java +++ b/carapace-server/src/main/java/org/carapaceproxy/server/RequestsLogger.java @@ -23,19 +23,29 @@ import io.netty.handler.codec.http.HttpHeaderNames; import java.io.BufferedWriter; import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.sql.Timestamp; +import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.Date; import java.util.Locale; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.zip.GZIPOutputStream; import org.carapaceproxy.server.cache.ContentsCache; import org.stringtemplate.v4.NoIndentWriter; import org.stringtemplate.v4.ST; @@ -126,7 +136,65 @@ private void closeAccessLogFile() throws IOException { os = null; } } + + @VisibleForTesting + void rotateAccessLogFile() throws IOException { + String accesslogPath = this.currentConfiguration.getAccessLogPath(); + long maxSize = this.currentConfiguration.getAccessLogMaxSize(); + DateFormat date = new SimpleDateFormat("yyyy-MM-dd-ss"); + String newAccessLogName = accesslogPath + "-" +date.format(new Date()); + + Path currentAccessLogPath = Paths.get(accesslogPath); + Path newAccessLogPath = Paths.get(newAccessLogName); + FileChannel logFileChannel = FileChannel.open(currentAccessLogPath); + + try { + long currentSize = logFileChannel.size(); + if(currentSize >= maxSize && maxSize > 0){ + LOG.log(Level.INFO,"Maximum access log size reached. file: {0} , Size: {1} , maxSize: {2}" , new Object[]{accesslogPath,currentSize,maxSize}); + Files.move(currentAccessLogPath, newAccessLogPath, StandardCopyOption.ATOMIC_MOVE); + closeAccessLogFile(); + // File opening will be retried at next cycle start + //Zip old file + gzipFile(newAccessLogName, newAccessLogName+".gzip", true); + } + } catch (IOException e) { + LOG.log(Level.SEVERE , "Error: Unable to rename file {0} in {1}: " + e , new Object[]{accesslogPath, newAccessLogName}); + } + } + + private void gzipFile(String source_filepath, String destination_zip_filepath, boolean deleteSource) { + byte[] buffer = new byte[1024]; + File source = new File(source_filepath); + File dest = new File(destination_zip_filepath); + + try { + FileOutputStream fileOutputStream = new FileOutputStream(dest); + try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(fileOutputStream)) { + try (FileInputStream fileInput = new FileInputStream(source)) { + int bytes_read; + + while ((bytes_read = fileInput.read(buffer)) > 0) { + gzipOutputStream.write(buffer,0, bytes_read); + } + } + gzipOutputStream.finish(); + gzipOutputStream.close(); + + //delete uncompressed file + if(deleteSource && dest.exists()){ + source.delete(); + } + } + if(verbose){ + LOG.log(Level.INFO, "{0} was compressed successfully", source_filepath); + } + } catch (IOException ex) { + LOG.log(Level.SEVERE, "{0} Compression failed: {1}", new Object[]{source_filepath, ex}); + } + } + public void reloadConfiguration(RuntimeServerConfiguration newConfiguration) { this.newConfiguration = newConfiguration; } @@ -249,6 +317,8 @@ public void run() { if (System.currentTimeMillis() - lastFlush >= currentConfiguration.getAccessLogFlushInterval()) { flushAccessLogFile(); } + //Check if is time to rotate + rotateAccessLogFile(); } catch (InterruptedException ex) { LOG.log(Level.SEVERE, "Interrupt received"); diff --git a/carapace-server/src/main/java/org/carapaceproxy/server/RuntimeServerConfiguration.java b/carapace-server/src/main/java/org/carapaceproxy/server/RuntimeServerConfiguration.java index 9d9e26c2e..675cb850c 100644 --- a/carapace-server/src/main/java/org/carapaceproxy/server/RuntimeServerConfiguration.java +++ b/carapace-server/src/main/java/org/carapaceproxy/server/RuntimeServerConfiguration.java @@ -74,6 +74,7 @@ public class RuntimeServerConfiguration { private int accessLogMaxQueueCapacity = 2000; private int accessLogFlushInterval = 5000; private int accessLogWaitBetweenFailures = 10000; + private long accessLogMaxSize = 524288000; private String userRealmClassname; private int healthProbePeriod = 0; private int dynamicCertificatesManagerPeriod = 0; @@ -130,6 +131,14 @@ public int getAccessLogWaitBetweenFailures() { public void setAccessLogWaitBetweenFailures(int accessLogWaitBetweenFailures) { this.accessLogWaitBetweenFailures = accessLogWaitBetweenFailures; } + + public long getAccessLogMaxSize() { + return accessLogMaxSize; + } + + public void setAccessLogMaxSize(long accessLogMaxSize) { + this.accessLogMaxSize = accessLogMaxSize; + } public String getMapperClassname() { return mapperClassname; @@ -287,6 +296,7 @@ public void configure(ConfigurationStore properties) throws ConfigurationNotVali this.accessLogMaxQueueCapacity = properties.getInt("accesslog.queue.maxcapacity", accessLogMaxQueueCapacity); this.accessLogFlushInterval = properties.getInt("accesslog.flush.interval", accessLogFlushInterval); this.accessLogWaitBetweenFailures = properties.getInt("accesslog.failure.wait", accessLogWaitBetweenFailures); + this.accessLogMaxSize = properties.getLong("accesslog.maxsize", accessLogMaxSize); String tsFormatExample; try { SimpleDateFormat formatter = new SimpleDateFormat(this.accessLogTimestampFormat); @@ -300,6 +310,7 @@ public void configure(ConfigurationStore properties) throws ConfigurationNotVali LOG.info("accesslog.queue.maxcapacity=" + accessLogMaxQueueCapacity); LOG.info("accesslog.flush.interval=" + accessLogFlushInterval); LOG.info("accesslog.failure.wait=" + accessLogWaitBetweenFailures); + LOG.info("accesslog.maxsize=" + accessLogMaxSize); tryConfigureCertificates(properties); tryConfigureListeners(properties); diff --git a/carapace-server/src/main/java/org/carapaceproxy/server/certificates/DynamicCertificatesManager.java b/carapace-server/src/main/java/org/carapaceproxy/server/certificates/DynamicCertificatesManager.java index 023216890..227cd1e8f 100644 --- a/carapace-server/src/main/java/org/carapaceproxy/server/certificates/DynamicCertificatesManager.java +++ b/carapace-server/src/main/java/org/carapaceproxy/server/certificates/DynamicCertificatesManager.java @@ -207,7 +207,7 @@ private CertificateData loadOrCreateDynamicCertificateForDomain(String domain, int daysBeforeRenewal) throws GeneralSecurityException, MalformedURLException { CertificateData cert = store.loadCertificateForDomain(domain); if (cert == null) { - cert = new CertificateData(domain, "", "", WAITING, "", "", false); + cert = new CertificateData(domain, "", "", WAITING, "", ""); } cert.setWildcard(wildcard); cert.setManual(forceManual); @@ -309,7 +309,6 @@ private void certificatesLifecycle() { PrivateKey key = loadOrCreateKeyPairForDomain(domain).getPrivate(); String chain = base64EncodeCertificateChain(certificateChain.toArray(new Certificate[0]), key); cert.setChain(chain); - cert.setAvailable(true); cert.setState(AVAILABLE); notifyCertAvailChanged = true; // all other peers need to know that this cert is available. LOG.log(Level.INFO, "Certificate issuing for domain: {0} SUCCEED. Certificate AVAILABLE.", domain); @@ -325,7 +324,6 @@ private void certificatesLifecycle() { } case AVAILABLE: { // certificate saved/available/not expired if (isCertificateExpired(base64DecodeCertificateChain(cert.getChain()), cert.getDaysBeforeRenewal())) { - cert.setAvailable(false); cert.setState(EXPIRED); notifyCertAvailChanged = true; // all other peers need to know that this cert is expired. } else { @@ -472,13 +470,11 @@ public void setStateOfCertificate(String id, DynamicCertificateState state) { if (certificates.containsKey(id)) { CertificateData cert = store.loadCertificateForDomain(id); if (cert != null) { - boolean prevAvail = cert.isAvailable(); cert.setState(state); - cert.setAvailable(DynamicCertificateState.AVAILABLE.equals(state)); store.saveCertificate(cert); // remember that events are not delivered to the local JVM reloadCertificatesFromDB(); - if (prevAvail != cert.isAvailable() && groupMembershipHandler != null) { + if (groupMembershipHandler != null) { groupMembershipHandler.fireEvent(EVENT_CERT_AVAIL_CHANGED); } } @@ -492,12 +488,8 @@ public void setStateOfCertificate(String id, DynamicCertificateState state) { */ public byte[] getCertificateForDomain(String domain) throws GeneralSecurityException { CertificateData cert = certificates.get(domain); // certs always retrived from cache - if (cert == null) { - LOG.log(Level.SEVERE, "No dynamic certificate for domain {0}", domain); - return null; - } - if (!cert.isAvailable()) { - LOG.log(Level.SEVERE, "Dynamic certificate for domain {0} is not available: {1}", new Object[]{domain, cert}); + if (cert == null || cert.getChain() == null || cert.getChain().isEmpty()) { + LOG.log(Level.SEVERE, "No dynamic certificate available for domain {0}", domain); return null; } return Base64.getDecoder().decode(cert.getChain()); diff --git a/carapace-server/src/test/java/org/carapaceproxy/api/StartAPIServerTest.java b/carapace-server/src/test/java/org/carapaceproxy/api/StartAPIServerTest.java index 15ce8844f..f8e53e94a 100644 --- a/carapace-server/src/test/java/org/carapaceproxy/api/StartAPIServerTest.java +++ b/carapace-server/src/test/java/org/carapaceproxy/api/StartAPIServerTest.java @@ -54,10 +54,10 @@ import static org.carapaceproxy.utils.CertificatesUtils.KEYSTORE_PW; import static org.carapaceproxy.utils.CertificatesUtils.createKeystore; import static org.hamcrest.MatcherAssert.assertThat; +import java.nio.file.Files; import java.security.KeyPair; import java.security.cert.Certificate; import java.security.cert.X509Certificate; -import org.apache.curator.shaded.com.google.common.io.Files; import org.junit.Rule; import org.junit.rules.TemporaryFolder; import org.shredzone.acme4j.util.KeyPairUtils; @@ -290,7 +290,7 @@ public void testCertificates() throws Exception { String expiringDate1 = certificate.getNotAfter().toString(); byte[] keystoreData = createKeystore(originalChain, endUserKeyPair.getPrivate()); File mock1 = tmpFolder.newFile("mock1.p12"); - Files.write(keystoreData, mock1); + 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); @@ -302,7 +302,7 @@ public void testCertificates() throws Exception { String expiringDate2 = certificate.getNotAfter().toString(); keystoreData = createKeystore(originalChain, endUserKeyPair.getPrivate()); File mock2 = tmpFolder.newFile("mock2.p12"); - Files.write(keystoreData, mock2); + 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); @@ -323,7 +323,7 @@ public void testCertificates() throws Exception { 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, "", "", false)); + store.saveCertificate(new CertificateData(dynDomain, "", dynChain, WAITING, "", "")); man.setStateOfCertificate(dynDomain, WAITING); // this reloads certificates from the store // Static certificates diff --git a/carapace-server/src/test/java/org/carapaceproxy/configstore/ConfigurationStoreTest.java b/carapace-server/src/test/java/org/carapaceproxy/configstore/ConfigurationStoreTest.java index 35170c3d6..e404660b4 100644 --- a/carapace-server/src/test/java/org/carapaceproxy/configstore/ConfigurationStoreTest.java +++ b/carapace-server/src/test/java/org/carapaceproxy/configstore/ConfigurationStoreTest.java @@ -30,11 +30,11 @@ import org.carapaceproxy.server.config.ConfigurationNotValidException; import static org.carapaceproxy.utils.TestUtils.assertEqualsKey; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.ArrayMatching.arrayContaining; import org.junit.After; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; import org.carapaceproxy.utils.TestUtils; import org.hamcrest.core.IsNull; import org.junit.Rule; @@ -259,12 +259,12 @@ private void testCertificateOperations() throws Exception { // Certificates saving CertificateData cert1 = new CertificateData( - d1, "encodedPK1", "encodedChain1", DynamicCertificateState.AVAILABLE, order, challenge, true + d1, "encodedPK1", "encodedChain1", DynamicCertificateState.AVAILABLE, order, challenge ); store.saveCertificate(cert1); CertificateData cert2 = new CertificateData( - d2, "encodedPK2", "encodedChain2", DynamicCertificateState.WAITING, null, null, false + d2, "encodedPK2", "encodedChain2", DynamicCertificateState.WAITING, null, null ); store.saveCertificate(cert2); @@ -273,7 +273,6 @@ private void testCertificateOperations() throws Exception { assertEquals(cert2, store.loadCertificateForDomain(d2)); // Cert Updating - cert1.setAvailable(false); cert1.setState(DynamicCertificateState.WAITING); cert1.setPendingOrderLocation(new URL("http://locallhost/updatedorder").toString()); cert1.setPendingChallengeData(JSON.parse("{\"challenge\": \"updateddata\"}").toString()); diff --git a/carapace-server/src/test/java/org/carapaceproxy/server/RequestsLoggerTest.java b/carapace-server/src/test/java/org/carapaceproxy/server/RequestsLoggerTest.java index b8783b52a..f41eabef9 100644 --- a/carapace-server/src/test/java/org/carapaceproxy/server/RequestsLoggerTest.java +++ b/carapace-server/src/test/java/org/carapaceproxy/server/RequestsLoggerTest.java @@ -32,9 +32,14 @@ import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; +import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; +import static junit.framework.Assert.assertEquals; import org.carapaceproxy.EndpointStats; import org.carapaceproxy.MapResult; import org.carapaceproxy.client.ConnectionsManagerStats; @@ -69,7 +74,6 @@ public class RequestsLoggerTest { @Rule public TemporaryFolder tmpDir = new TemporaryFolder(); - @Before public void before() { accessLogFilePath = tmpDir.getRoot().getAbsolutePath() + "/access.log"; @@ -84,12 +88,13 @@ private RuntimeServerConfiguration genConf() { private static List readFile(String path) throws IOException { List content = Files.readLines(new File(path), StandardCharsets.UTF_8); if (DEBUG) { - System.out.println("fileContent=\n"+String.join("\n", content)); + System.out.println("fileContent=\n" + String.join("\n", content)); } return content; } private static final class MockRequestHandler { + HttpMethod reqMethod; String reqHost; String reqUri; @@ -105,7 +110,7 @@ private static final class MockRequestHandler { private static RequestHandler createMockRequestHandler( MockRequestHandler r - ) throws Exception { + ) throws Exception { SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); @@ -138,7 +143,7 @@ private void run(RequestsLogger reqLogger) throws Exception { long startts = System.currentTimeMillis(); reqLogger.run(); if (DEBUG) { - System.out.println("] ------------------------------------ "+(System.currentTimeMillis()-startts)+"ms"); + System.out.println("] ------------------------------------ " + (System.currentTimeMillis() - startts) + "ms"); } } @@ -161,7 +166,7 @@ public void test() throws Exception { { long startts = System.currentTimeMillis(); run(reqLogger); - assertTrue((System.currentTimeMillis()-startts) >= FLUSH_WAIT_TIME); + assertTrue((System.currentTimeMillis() - startts) >= FLUSH_WAIT_TIME); } assertThat((new File(accessLogFilePath)).isFile(), is(true)); @@ -173,7 +178,7 @@ public void test() throws Exception { MockRequestHandler r1 = new MockRequestHandler(); r1.reqMethod = HttpMethod.GET; r1.reqHost = "thehost"; - r1.reqUri = "/index.html"; + r1.reqUri = "/index.html"; r1.remoteIp = "123.123.123.123"; r1.localIp = "234.234.234.234"; r1.startTs = "2018-10-23 10:10:10.000"; @@ -187,26 +192,25 @@ public void test() throws Exception { long startts = System.currentTimeMillis(); run(reqLogger); - assertTrue((System.currentTimeMillis()-startts) < FLUSH_WAIT_TIME); + assertTrue((System.currentTimeMillis() - startts) < FLUSH_WAIT_TIME); reqLogger.flushAccessLogFile(); List rows1 = readFile(accessLogFilePath); assertThat(rows1.size(), is(1)); assertThat(rows1.get(0), is( - "[2018-10-23 10:10:10.000] [GET thehost /index.html] [uid:uid_1, sid:sid_1, ip:123.123.123.123] " - + "server=234.234.234.234, act=CACHE, route=routeid_1, backend=host:1111. time t=1012ms b=542ms")); + "[2018-10-23 10:10:10.000] [GET thehost /index.html] [uid:uid_1, sid:sid_1, ip:123.123.123.123] " + + "server=234.234.234.234, act=CACHE, route=routeid_1, backend=host:1111. time t=1012ms b=542ms")); // Request to log 2. Let's wait 100ms before do the request and check if flush will be done within the // initial FLUSH_WAIT_TIME ms timeframe - System.out.println("Sleeping 100ms"); Thread.sleep(100); MockRequestHandler r2 = new MockRequestHandler(); r2.reqMethod = HttpMethod.POST; r2.reqHost = "thehost2"; - r2.reqUri = "/index2.html"; + r2.reqUri = "/index2.html"; r2.remoteIp = "111.123.123.123"; r2.localIp = "111.234.234.234"; r2.startTs = "2018-10-23 11:10:10.000"; @@ -219,31 +223,28 @@ public void test() throws Exception { reqLogger.logRequest(createMockRequestHandler(r2)); run(reqLogger); - assertTrue((System.currentTimeMillis()-startts) < FLUSH_WAIT_TIME); + assertTrue((System.currentTimeMillis() - startts) < FLUSH_WAIT_TIME); // No flush here. The new line should not have been flushed yet //reqLogger.flushAccessLogFile(); - List rows2 = readFile(accessLogFilePath); assertThat(rows2.size(), is(1)); // This run will wait until flush time is over and than flush long startts2 = System.currentTimeMillis(); run(reqLogger); - assertTrue((System.currentTimeMillis()-startts) >= FLUSH_WAIT_TIME); - assertTrue((System.currentTimeMillis()-startts2) < FLUSH_WAIT_TIME); // should discount the splept 100ms + assertTrue((System.currentTimeMillis() - startts) >= FLUSH_WAIT_TIME); + assertTrue((System.currentTimeMillis() - startts2) < FLUSH_WAIT_TIME); // should discount the splept 100ms //reqLogger.flushAccessLogFile(); - List rows3 = readFile(accessLogFilePath); assertThat(rows3.size(), is(2)); assertThat(rows3.get(1), is( - "[2018-10-23 11:10:10.000] [POST thehost2 /index2.html] [uid:uid_2, sid:sid_2, ip:111.123.123.123] " - + "server=111.234.234.234, act=PROXY, route=routeid_2, backend=host2:2222. time t=912ms b=142ms")); + "[2018-10-23 11:10:10.000] [POST thehost2 /index2.html] [uid:uid_2, sid:sid_2, ip:111.123.123.123] " + + "server=111.234.234.234, act=PROXY, route=routeid_2, backend=host2:2222. time t=912ms b=142ms")); } // Hot configuration reload - RuntimeServerConfiguration c2 = genConf(); c2.setAccessLogFlushInterval(FLUSH_WAIT_TIME); c2.setAccessLogFormat("[] [ ]"); @@ -258,7 +259,7 @@ public void test() throws Exception { MockRequestHandler r1 = new MockRequestHandler(); r1.reqMethod = HttpMethod.GET; r1.reqHost = "thehost"; - r1.reqUri = "/index.html"; + r1.reqUri = "/index.html"; r1.remoteIp = "123.123.123.123"; r1.localIp = "234.234.234.234"; r1.startTs = "2018-10-23 10:10:10.000"; @@ -272,22 +273,21 @@ public void test() throws Exception { long startts = System.currentTimeMillis(); run(reqLogger); - assertTrue((System.currentTimeMillis()-startts) < FLUSH_WAIT_TIME); + assertTrue((System.currentTimeMillis() - startts) < FLUSH_WAIT_TIME); reqLogger.flushAccessLogFile(); List rows1 = readFile(accessLogFilePath); assertThat(rows1.size(), is(3)); assertThat(rows1.get(2), is( - "[2018-10-23 10:10:10.000] [GET thehost /index.html] [uid:uid_1, sid:sid_1, ip:123.123.123.123] " - + "server=234.234.234.234, act=CACHE, route=routeid_1, backend=host:1111. time t=1012ms b=542ms")); + "[2018-10-23 10:10:10.000] [GET thehost /index.html] [uid:uid_1, sid:sid_1, ip:123.123.123.123] " + + "server=234.234.234.234, act=CACHE, route=routeid_1, backend=host:1111. time t=1012ms b=542ms")); // This request will be taken in with the new conf - MockRequestHandler r2 = new MockRequestHandler(); r2.reqMethod = HttpMethod.GET; r2.reqHost = "thehost"; - r2.reqUri = "/index.html"; + r2.reqUri = "/index.html"; r2.remoteIp = "123.123.123.123"; r2.localIp = "234.234.234.234"; r2.startTs = "2018-10-23 10:10:10.000"; @@ -300,18 +300,17 @@ public void test() throws Exception { reqLogger.logRequest(createMockRequestHandler(r2)); run(reqLogger); - assertTrue((System.currentTimeMillis()-startts) < FLUSH_WAIT_TIME); + assertTrue((System.currentTimeMillis() - startts) < FLUSH_WAIT_TIME); reqLogger.flushAccessLogFile(); List rows2 = readFile(accessLogFilePath); assertThat(rows2.size(), is(4)); assertThat(rows2.get(3), is( - "[2018-10-23 10:10] [GET thehost /index.html]")); + "[2018-10-23 10:10] [GET thehost /index.html]")); } // Access log writing issues test - final int WAIT_TIME_BETWEEN_FAILURES = 200; RuntimeServerConfiguration c3 = genConf(); @@ -328,7 +327,7 @@ public void test() throws Exception { MockRequestHandler r1 = new MockRequestHandler(); r1.reqMethod = HttpMethod.GET; r1.reqHost = "thehost"; - r1.reqUri = "/index1.html"; + r1.reqUri = "/index1.html"; r1.remoteIp = "123.123.123.123"; r1.localIp = "234.234.234.234"; r1.startTs = "2018-10-23 11:10:10.000"; @@ -343,10 +342,9 @@ public void test() throws Exception { // This run will try to create the new file but it will fail and wait WAIT_TIME_BETWEEN_FAILURES long startts = System.currentTimeMillis(); run(reqLogger); - assertTrue((System.currentTimeMillis()-startts) >= WAIT_TIME_BETWEEN_FAILURES); + assertTrue((System.currentTimeMillis() - startts) >= WAIT_TIME_BETWEEN_FAILURES); // reqLogger.flushAccessLogFile(); - List rows1 = readFile(accessLogFilePath); assertThat(rows1.size(), is(4)); @@ -354,7 +352,7 @@ public void test() throws Exception { MockRequestHandler r2 = new MockRequestHandler(); r2.reqMethod = HttpMethod.GET; r2.reqHost = "thehost"; - r2.reqUri = "/index2.html"; + r2.reqUri = "/index2.html"; r2.remoteIp = "123.123.123.123"; r2.localIp = "234.234.234.234"; r2.startTs = "2018-10-23 11:10:10.000"; @@ -369,7 +367,7 @@ public void test() throws Exception { MockRequestHandler r3 = new MockRequestHandler(); r3.reqMethod = HttpMethod.GET; r3.reqHost = "thehost"; - r3.reqUri = "/index3.html"; + r3.reqUri = "/index3.html"; r3.remoteIp = "123.123.123.123"; r3.localIp = "234.234.234.234"; r3.startTs = "2018-10-23 11:10:10.000"; @@ -397,27 +395,25 @@ public void test() throws Exception { run(reqLogger); // r1 run(reqLogger); // r2 run(reqLogger); // r3 should be missing, it will wait for flush times - assertTrue((System.currentTimeMillis()-startts2) >= FLUSH_WAIT_TIME - (startts2-startts)); // needs a little more tolerance + assertTrue((System.currentTimeMillis() - startts2) >= FLUSH_WAIT_TIME - (startts2 - startts)); // needs a little more tolerance //reqLogger.flushAccessLogFile(); - List rows2 = readFile(accessLogFilePath); - assertThat(rows2.size(), is(4+2)); + assertThat(rows2.size(), is(4 + 2)); assertThat(rows2.get(4), is( - "[2018-10-23 11:10] [GET thehost /index1.html]")); + "[2018-10-23 11:10] [GET thehost /index1.html]")); assertThat(rows2.get(5), is( - "[2018-10-23 11:10] [GET thehost /index2.html]")); + "[2018-10-23 11:10] [GET thehost /index2.html]")); } // Closing RequestLogger - { // r1 will be taken into before close, so it must be writed on access log MockRequestHandler r1 = new MockRequestHandler(); r1.reqMethod = HttpMethod.GET; r1.reqHost = "thehost"; - r1.reqUri = "/index1.html"; + r1.reqUri = "/index1.html"; r1.remoteIp = "123.123.123.123"; r1.localIp = "234.234.234.234"; r1.startTs = "2018-10-23 10:10:10.000"; @@ -433,11 +429,10 @@ public void test() throws Exception { reqLogger.close(); // r2 will be discarded - MockRequestHandler r2 = new MockRequestHandler(); r2.reqMethod = HttpMethod.GET; r2.reqHost = "thehost"; - r2.reqUri = "/index2.html"; + r2.reqUri = "/index2.html"; r2.remoteIp = "123.123.123.123"; r2.localIp = "234.234.234.234"; r2.startTs = "2018-10-23 10:10:10.000"; @@ -452,18 +447,18 @@ public void test() throws Exception { // First cycle will write r1 long startts = System.currentTimeMillis(); run(reqLogger); - assertTrue((System.currentTimeMillis()-startts) < FLUSH_WAIT_TIME); + assertTrue((System.currentTimeMillis() - startts) < FLUSH_WAIT_TIME); reqLogger.flushAccessLogFile(); List rows1 = readFile(accessLogFilePath); - assertThat(rows1.size(), is(6+1)); + assertThat(rows1.size(), is(6 + 1)); assertThat(rows1.get(6), is( - "[2018-10-23 10:10] [GET thehost /index1.html]")); + "[2018-10-23 10:10] [GET thehost /index1.html]")); // Second cycle should close the file and return immediatly run(reqLogger); - assertTrue((System.currentTimeMillis()-startts) < FLUSH_WAIT_TIME); + assertTrue((System.currentTimeMillis() - startts) < FLUSH_WAIT_TIME); List rows2 = readFile(accessLogFilePath); assertThat(rows2.size(), is(7)); @@ -485,19 +480,19 @@ public void testWithServer() throws Exception { EndpointKey key = new EndpointKey("localhost", wireMockRule.port()); ConnectionsManagerStats stats; - try (HttpProxyServer server = HttpProxyServer.buildForTests("localhost", 0, mapper, tmpDir.newFolder());) { - server.getCurrentConfiguration().setAccessLogPath(tmpDir.getRoot().getAbsolutePath()+"/access.log"); + try ( HttpProxyServer server = HttpProxyServer.buildForTests("localhost", 0, mapper, tmpDir.newFolder());) { + server.getCurrentConfiguration().setAccessLogPath(tmpDir.getRoot().getAbsolutePath() + "/access.log"); server.start(); int port = server.getLocalPort(); - try (RawHttpClient client = new RawHttpClient("localhost", port)) { + try ( RawHttpClient client = new RawHttpClient("localhost", port)) { RawHttpClient.HttpResponse resp = client.executeRequest("GET /index.html HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"); String s = resp.toString(); assertTrue(s.endsWith("it works !!")); assertFalse(resp.getHeaderLines().stream().anyMatch(h -> h.contains("X-Cached"))); } - try (RawHttpClient client = new RawHttpClient("localhost", port)) { + try ( RawHttpClient client = new RawHttpClient("localhost", port)) { { RawHttpClient.HttpResponse resp = client.executeRequest("GET /index.html HTTP/1.1\r\nHost: localhost\r\n\r\n"); String s = resp.toString(); @@ -529,4 +524,59 @@ public void testWithServer() throws Exception { TestUtils.waitForCondition(TestUtils.ALL_CONNECTIONS_CLOSED(stats), 100); } + + @Test + public void testAccessLogRotation() throws Exception { + stubFor(get(urlEqualTo("/index.html")) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", "text/html") + .withHeader("Content-Length", "it works !!".length() + "") + .withBody("it works !!"))); + + TestEndpointMapper mapper = new TestEndpointMapper("localhost", wireMockRule.port(), true); + EndpointKey key = new EndpointKey("localhost", wireMockRule.port()); + + try ( HttpProxyServer server = HttpProxyServer.buildForTests("localhost", 0, mapper, tmpDir.newFolder());) { + server.getCurrentConfiguration().setAccessLogPath(tmpDir.getRoot().getAbsolutePath() + "/access.log"); + server.getCurrentConfiguration().setAccessLogMaxSize(1024); + Path currentAccessLogPath = Paths.get(server.getCurrentConfiguration().getAccessLogPath()); + server.start(); + int port = server.getLocalPort(); + System.out.println("CurrentAccessLogPath " + currentAccessLogPath); + FileChannel logFileChannel = FileChannel.open(currentAccessLogPath); + + while (logFileChannel.size() < 1024) { + try ( RawHttpClient client = new RawHttpClient("localhost", port)) { + RawHttpClient.HttpResponse resp = client.executeRequest("GET /index.html HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"); + String s = resp.toString(); + assertTrue(s.endsWith("it works !!")); + } + + try ( RawHttpClient client = new RawHttpClient("localhost", port)) { + { + RawHttpClient.HttpResponse resp = client.executeRequest("GET /index.html HTTP/1.1\r\nHost: localhost\r\n\r\n"); + String s = resp.toString(); + assertTrue(s.endsWith("it works !!")); + } + + { + RawHttpClient.HttpResponse resp = client.executeRequest("GET /index.html HTTP/1.1\r\nHost: localhost\r\n\r\n"); + String s = resp.toString(); + assertTrue(s.endsWith("it works !!")); + } + } + } + Thread.sleep(3000); + //check if gzip file exist + File[] f = new File(tmpDir.getRoot().getAbsolutePath()).listFiles((dir, name) -> name.startsWith("access") && name.endsWith(".gzip")); + assertTrue(f.length == 1); + try ( RawHttpClient client = new RawHttpClient("localhost", port)) { + RawHttpClient.HttpResponse resp = client.executeRequest("GET /index.html HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"); + String s = resp.toString(); + assertTrue(s.endsWith("it works !!")); + } + assertTrue(logFileChannel.size() > 0); + } + } } diff --git a/carapace-server/src/test/java/org/carapaceproxy/server/certificates/CertificatesTest.java b/carapace-server/src/test/java/org/carapaceproxy/server/certificates/CertificatesTest.java index 77871b760..612d5bbb4 100644 --- a/carapace-server/src/test/java/org/carapaceproxy/server/certificates/CertificatesTest.java +++ b/carapace-server/src/test/java/org/carapaceproxy/server/certificates/CertificatesTest.java @@ -1,21 +1,21 @@ /* - Licensed to Diennea S.r.l. under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. Diennea S.r.l. licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - + * Licensed to Diennea S.r.l. under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Diennea S.r.l. licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * */ package org.carapaceproxy.server.certificates; @@ -199,7 +199,7 @@ public void test() throws Exception { data = dynCertMan.getCertificateDataForDomain("localhost"); assertNotNull(data); assertTrue(data.isManual()); - assertTrue(data.isAvailable()); + assertTrue(data.getState() == DynamicCertificateState.AVAILABLE); } // Request #2: expected uploaded certificate @@ -224,7 +224,7 @@ public void test() throws Exception { data = dynCertMan.getCertificateDataForDomain("localhost"); assertNotNull(data); assertTrue(data.isManual()); - assertTrue(data.isAvailable()); + assertTrue(data.getState() == DynamicCertificateState.AVAILABLE); } // Request #3: expected last uploaded certificate @@ -262,8 +262,7 @@ public void testUploadTypedCertificate(String type) throws Exception { CertificateData data = dynCertsMan.getCertificateDataForDomain("localhost"); assertNotNull(data); assertFalse(data.isManual()); - assertFalse(data.isAvailable()); // no certificate-data uploaded - assertEquals(DynamicCertificateState.WAITING, dynCertsMan.getStateOfCertificate("localhost")); + assertEquals(DynamicCertificateState.WAITING, dynCertsMan.getStateOfCertificate("localhost")); // no certificate-data uploaded } } @@ -277,7 +276,6 @@ public void testUploadTypedCertificate(String type) throws Exception { CertificateData data = dynCertsMan.getCertificateDataForDomain("localhost"); assertNotNull(data); assertEquals(type.equals("manual"), data.isManual()); - assertTrue(data.isAvailable()); assertEquals(DynamicCertificateState.AVAILABLE, dynCertsMan.getStateOfCertificate("localhost")); // check uploaded certificate @@ -307,7 +305,6 @@ public void testUploadTypedCertificate(String type) throws Exception { CertificateData data = dynCertsMan.getCertificateDataForDomain("localhost"); assertNotNull(data); assertEquals(otherType.equals("manual"), data.isManual()); - assertTrue(data.isAvailable()); assertEquals(DynamicCertificateState.AVAILABLE, dynCertsMan.getStateOfCertificate("localhost")); // check uploaded certificate @@ -325,8 +322,7 @@ public void testUploadTypedCertificate(String type) throws Exception { data = dynCertsMan.getCertificateDataForDomain("localhost"); assertNotNull(data); assertFalse(data.isManual()); - assertFalse(data.isAvailable()); // no certificate-data uploaded - assertEquals(DynamicCertificateState.WAITING, dynCertsMan.getStateOfCertificate("localhost")); + assertEquals(DynamicCertificateState.WAITING, dynCertsMan.getStateOfCertificate("localhost")); // no certificate-data uploaded } } } @@ -425,7 +421,7 @@ public void testOCSP() throws Exception { CertificateData data = dynCertMan.getCertificateDataForDomain("localhost"); assertNotNull(data); assertTrue(data.isManual()); - assertTrue(data.isAvailable()); + assertTrue(data.getState() == DynamicCertificateState.AVAILABLE); } // check ocsp response try (RawHttpClient c = new RawHttpClient("localhost", port, true, "localhost")) { @@ -480,7 +476,6 @@ public void testCertificatesRenew() throws Exception { assertTrue(resp.getBodyString().contains("SUCCESS")); CertificateData data = dcMan.getCertificateDataForDomain("localhost"); assertNotNull(data); - assertTrue(data.isAvailable()); assertEquals(DynamicCertificateState.AVAILABLE, data.getState()); assertEquals(45, data.getDaysBeforeRenewal()); assertFalse(data.isManual()); @@ -500,11 +495,11 @@ public void testCertificatesRenew() throws Exception { ConfigurationStore store = dcMan.getConfigurationStore(); store.saveKeyPairForDomain(keyPair, "localhost", false); CertificateData cert = store.loadCertificateForDomain("localhost"); - cert.setAvailable(false); cert.setState(DynamicCertificateState.ORDERING); cert.setPendingOrderLocation("https://localhost/orderlocation"); store.saveCertificate(cert); assertEquals(DynamicCertificateState.ORDERING, dcMan.getStateOfCertificate("localhost")); + assertNotNull(dcMan.getCertificateForDomain("localhost")); // ACME mocking ACMEClient ac = mock(ACMEClient.class); @@ -521,7 +516,6 @@ public void testCertificatesRenew() throws Exception { dcMan.run(); CertificateData updated = dcMan.getCertificateDataForDomain("localhost"); assertNotNull(updated); - assertTrue(updated.isAvailable()); assertEquals(DynamicCertificateState.AVAILABLE, updated.getState()); assertEquals(45, updated.getDaysBeforeRenewal()); assertFalse(updated.isManual()); diff --git a/carapace-server/src/test/java/org/carapaceproxy/server/certificates/DynamicCertificatesManagerTest.java b/carapace-server/src/test/java/org/carapaceproxy/server/certificates/DynamicCertificatesManagerTest.java index e92d01e31..fb2e16280 100644 --- a/carapace-server/src/test/java/org/carapaceproxy/server/certificates/DynamicCertificatesManagerTest.java +++ b/carapace-server/src/test/java/org/carapaceproxy/server/certificates/DynamicCertificatesManagerTest.java @@ -120,17 +120,21 @@ public void testCertificateStateManagement(String runCase) throws Exception { // yet available certificate String d0 = "localhost0"; - CertificateData cd0 = new CertificateData(d0, "", chain, AVAILABLE, "", "", false); + CertificateData cd0 = new CertificateData(d0, "", chain, AVAILABLE, "", ""); when(store.loadCertificateForDomain(eq(d0))).thenReturn(cd0); // certificate to order String d1 = "localhost1"; - CertificateData cd1 = new CertificateData(d1, "", "", WAITING, "", "", false); + CertificateData cd1 = new CertificateData(d1, "", "", WAITING, "", ""); when(store.loadCertificateForDomain(eq(d1))).thenReturn(cd1); man.setConfigurationStore(store); // manual certificate - String d2 = "notacme"; - CertificateData cd2 = new CertificateData(d2, "", "", AVAILABLE, "", "", true); + String d2 = "manual"; + CertificateData cd2 = new CertificateData(d2, "", chain, AVAILABLE, "", ""); when(store.loadCertificateForDomain(eq(d2))).thenReturn(cd2); + // empty manual certificate + String d3 = "emptymanual"; + CertificateData cd3 = new CertificateData(d3, "", "", AVAILABLE, "", ""); + when(store.loadCertificateForDomain(eq(d3))).thenReturn(cd3); man.setConfigurationStore(store); @@ -145,6 +149,9 @@ public void testCertificateStateManagement(String runCase) throws Exception { props.setProperty("certificate.2.hostname", d2); props.setProperty("certificate.2.mode", "manual"); props.setProperty("certificate.2.daysbeforerenewal", "0"); + props.setProperty("certificate.3.hostname", d3); + props.setProperty("certificate.3.mode", "manual"); + props.setProperty("certificate.3.daysbeforerenewal", "0"); ConfigurationStore configStore = new PropertiesConfigurationStore(props); RuntimeServerConfiguration conf = new RuntimeServerConfiguration(); conf.configure(configStore); @@ -152,7 +159,9 @@ public void testCertificateStateManagement(String runCase) throws Exception { assertEquals(AVAILABLE, man.getStateOfCertificate(d0)); assertEquals(AVAILABLE, man.getStateOfCertificate(d2)); + assertEquals(AVAILABLE, man.getStateOfCertificate(d3)); assertNotNull(man.getCertificateForDomain(d2)); + assertNull(man.getCertificateForDomain(d3)); // empty man.setStateOfCertificate(d2, WAITING); // has not to be renewed by the manager (saveCounter = 1) assertEquals(WAITING, man.getStateOfCertificate(d2)); @@ -262,7 +271,7 @@ public void testWidlcardCertificateStateManagement(String runCase) throws Except // certificate to order String domain = "*.localhost"; - CertificateData cd1 = new CertificateData(domain, "", "", WAITING, "", "", false); + CertificateData cd1 = new CertificateData(domain, "", "", WAITING, "", ""); when(store.loadCertificateForDomain(eq(domain))).thenReturn(cd1); man.setConfigurationStore(store);