diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d2c4c988..fa8e83c807 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Added +- Traffic Router: TR now generates a self-signed certificate at startup and uses it as the default TLS cert. + The default certificate is used whenever a client attempts an SSL handshake for an SNI host which does not match + any of the other certificates. - Traffic Ops Golang Endpoints - /api/1.4/users `(GET,POST,PUT)` - /api/1.1/deliveryservices/xmlId/:xmlid/sslkeys `GET` diff --git a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java index 85f8c0731a..6fe6399a13 100644 --- a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java +++ b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java @@ -19,103 +19,105 @@ import com.comcast.cdn.traffic_control.traffic_router.secure.HandshakeData; import com.comcast.cdn.traffic_control.traffic_router.secure.KeyManager; import org.apache.log4j.Logger; -import org.apache.tomcat.util.modeler.Registry; +import org.apache.tomcat.jni.SSL; +import org.apache.tomcat.util.net.NioChannel; import org.apache.tomcat.util.net.NioEndpoint; import org.apache.tomcat.util.net.SSLHostConfig; import org.apache.tomcat.util.net.SSLHostConfigCertificate; +import org.apache.tomcat.util.net.SocketEvent; +import org.apache.tomcat.util.net.SocketProcessorBase; +import org.apache.tomcat.util.net.SocketWrapperBase; + import java.util.Map; import java.util.Set; public class RouterNioEndpoint extends NioEndpoint { - private static final Logger LOGGER = Logger.getLogger(RouterNioEndpoint.class); - // Grabs the aliases from our custom certificate registry, creates a sslHostConfig for them - // and adds the newly created config to the list of sslHostConfigs. We also remove the default config - // since it won't be found in our registry. This allows OpenSSL to start successfully and serve our - // certificates. When we are done we call the parent classes initialiseSsl. - @SuppressWarnings({"PMD.SignatureDeclareThrowsException"}) - @Override - protected void initialiseSsl() throws Exception { - if (isSSLEnabled()) { - destroySsl(); - sslHostConfigs.clear(); - final KeyManager keyManager = new KeyManager(); - final CertificateRegistry certificateRegistry = keyManager.getCertificateRegistry(); - replaceSSLHosts(certificateRegistry.getHandshakeData()); - - //Now let initialiseSsl do it's thing. - super.initialiseSsl(); - certificateRegistry.setEndPoint(this); - } - } - - synchronized private void replaceSSLHosts(final Map sslHostsData) { - final Set aliases = sslHostsData.keySet(); - boolean firstAlias = true; - String lastHostName = ""; - - for (final String alias : aliases) { - final SSLHostConfig sslHostConfig = new SSLHostConfig(); - final SSLHostConfigCertificate cert = new SSLHostConfigCertificate(sslHostConfig, SSLHostConfigCertificate.Type.RSA); - cert.setCertificateKeyAlias(alias); - sslHostConfig.addCertificate(cert); - sslHostConfig.setCertificateKeyAlias(alias); - sslHostConfig.setHostName(sslHostsData.get(alias).getHostname()); - sslHostConfig.setProtocols("all"); - sslHostConfig.setConfigType(getSslConfigType()); - sslHostConfig.setCertificateVerification("none"); - LOGGER.info("sslHostConfig: "+sslHostConfig.getHostName()+" "+sslHostConfig.getTruststoreAlgorithm()); - - if (!sslHostConfig.getHostName().equals(lastHostName)) { - addSslHostConfig(sslHostConfig, true); - lastHostName = sslHostConfig.getHostName(); - } - - if (firstAlias && ! "".equals(alias)) { - // One of the configs must be set as the default - setDefaultSSLHostConfigName(sslHostConfig.getHostName()); - firstAlias = false; - } - } - - } - - synchronized public void reloadSSLHosts(final Map cr) { - replaceSSLHosts(cr); - - for (final HandshakeData data : cr.values()) { - final SSLHostConfig sslHostConfig = sslHostConfigs.get(data.getHostname()); - sslHostConfig.setConfigType(getSslConfigType()); - createSSLContext(sslHostConfig); - } - } - - @Override - protected SSLHostConfig getSSLHostConfig(final String sniHostName) { - return super.getSSLHostConfig(sniHostName.toLowerCase()); - } - - private void unregisterJmx(final SSLHostConfig sslHostConfig) { - final Registry registry = Registry.getRegistry(null, null); - registry.unregisterComponent(sslHostConfig.getObjectName()); - for (final SSLHostConfigCertificate sslHostConfigCert : sslHostConfig.getCertificates()) { - registry.unregisterComponent(sslHostConfigCert.getObjectName()); - } - } - - @Override - public void addSslHostConfig(final SSLHostConfig sslHostConfig, final boolean replace) throws IllegalArgumentException { - final String key = sslHostConfig.getHostName(); - if (key == null || key.length() == 0) { - throw new IllegalArgumentException(sm.getString("endpoint.noSslHostName")); - } - - SSLHostConfig previous = null; - if (replace) { - previous = sslHostConfigs.get(key); - } - super.addSslHostConfig(sslHostConfig, replace); - if (previous != null) { - unregisterJmx(previous); - } - } + private static final Logger LOGGER = Logger.getLogger(RouterNioEndpoint.class); + + // Grabs the aliases from our custom certificate registry, creates a sslHostConfig for them + // and adds the newly created config to the list of sslHostConfigs. We also remove the default config + // since it won't be found in our registry. This allows OpenSSL to start successfully and serve our + // certificates. When we are done we call the parent classes initialiseSsl. + @SuppressWarnings({"PMD.SignatureDeclareThrowsException"}) + @Override + protected void initialiseSsl() throws Exception{ + if (isSSLEnabled()){ + destroySsl(); + sslHostConfigs.clear(); + final KeyManager keyManager = new KeyManager(); + final CertificateRegistry certificateRegistry = keyManager.getCertificateRegistry(); + replaceSSLHosts(certificateRegistry.getHandshakeData()); + + //Now let initialiseSsl do it's thing. + super.initialiseSsl(); + certificateRegistry.setEndPoint(this); + } + } + + synchronized public void replaceSSLHosts(final Map sslHostsData){ + final Set aliases = sslHostsData.keySet(); + String lastHostName = ""; + + for (final String alias : aliases){ + final SSLHostConfig sslHostConfig = new SSLHostConfig(); + final SSLHostConfigCertificate cert = new SSLHostConfigCertificate(sslHostConfig, SSLHostConfigCertificate.Type.RSA); + cert.setCertificateKeyAlias(alias); + sslHostConfig.addCertificate(cert); + sslHostConfig.setCertificateKeyAlias(alias); + sslHostConfig.setHostName(sslHostsData.get(alias).getHostname()); + sslHostConfig.setProtocols("all"); + sslHostConfig.setCertificateVerification("none"); + LOGGER.info("sslHostConfig: " + sslHostConfig.getHostName() + " " + sslHostConfig.getTruststoreAlgorithm()); + + if (!sslHostConfig.getHostName().equals(lastHostName)){ + addSslHostConfig(sslHostConfig, true); + lastHostName = sslHostConfig.getHostName(); + } + + if (CertificateRegistry.DEFAULT_SSL_KEY.equals(alias)){ + // One of the configs must be set as the default + setDefaultSSLHostConfigName(sslHostConfig.getHostName()); + } + } + } + + @Override + protected SSLHostConfig getSSLHostConfig(final String sniHostName){ + return super.getSSLHostConfig(sniHostName.toLowerCase()); + } + + @Override + protected SocketProcessorBase createSocketProcessor( + final SocketWrapperBase socketWrapper, final SocketEvent event){ + return new RouterSocketProcessor(socketWrapper, event); + } + + /** + * This class is the equivalent of the Worker, but will simply use in an + * external Executor thread pool. + */ + protected class RouterSocketProcessor extends SocketProcessor { + + public RouterSocketProcessor(final SocketWrapperBase socketWrapper, final SocketEvent event){ + super(socketWrapper, event); + } + + /* This override has been added as a temporary hack to resolve an issue in Tomcat. + Once the issue has been corrected in Tomcat then this can be removed. The + 'SSL.getLastErrorNumber()' removes an unwanted error condition from the error stack + in those cases where some error condition has caused the socket to get closed and + then the processor was put back on the processor stack for reuse in a future connection. + */ + @Override + protected void doRun(){ + final SocketWrapperBase localWrapper = socketWrapper; + final NioChannel socket = localWrapper.getSocket(); + super.doRun(); + if (!socket.isOpen()){ + SSL.getLastErrorNumber(); + } + } + } + } + diff --git a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateDataConverter.java b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateDataConverter.java index b3990fbe54..cd1e48b8ac 100644 --- a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateDataConverter.java +++ b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateDataConverter.java @@ -64,18 +64,20 @@ else if (!hostMatch) { log.warn("Service name doesn't match the subject of the certificate = "+certificateData.getHostname()); } else if (!modMatch) { - log.error("Modulus of the private key does not match the public key modulus for certificate host: "+certificateData.getHostname()); + log.warn("Modulus of the private key does not match the public key modulus for certificate host: "+certificateData.getHostname()); } } catch (CertificateNotYetValidException er) { - log.error("Failed to convert certificate data for delivery service = " + certificateData.getHostname() - + ", because the certificate is not valid yet. "); + log.warn("Failed to convert certificate data for delivery service = " + certificateData.getHostname() + + ", because the certificate is not valid yet. This certificate will not be used by " + + "Traffic Router."); } catch (CertificateExpiredException ex ) { - log.error("Failed to convert certificate data for delivery service = " + certificateData.getHostname() - + ", because the certificate has expired. "); + log.warn("Failed to convert certificate data for delivery service = " + certificateData.getHostname() + + ", because the certificate has expired. This certificate will not be used by Traffic Router."); } catch (Exception e) { - log.error("Failed to convert certificate data (delivery service = " + certificateData.getDeliveryservice() - + ", hostname = " + certificateData.getHostname() + ") from traffic ops to handshake data! " + log.warn("Failed to convert certificate data (delivery service = " + certificateData.getDeliveryservice() + + ", hostname = " + certificateData.getHostname() + ") from traffic ops to handshake data! This " + + "certificate will not be used by Traffic Router. " + e.getClass().getSimpleName() + ": " + e.getMessage(), e); } return null; diff --git a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateRegistry.java b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateRegistry.java index 848c8b09ed..e0984181db 100644 --- a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateRegistry.java +++ b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateRegistry.java @@ -18,13 +18,26 @@ import com.comcast.cdn.traffic_control.traffic_router.protocol.RouterNioEndpoint; import com.comcast.cdn.traffic_control.traffic_router.shared.CertificateData; import org.apache.log4j.Logger; - +import sun.security.tools.keytool.CertAndKeyGen; +import sun.security.util.ObjectIdentifier; +import sun.security.x509.BasicConstraintsExtension; +import sun.security.x509.CertificateExtensions; +import sun.security.x509.ExtendedKeyUsageExtension; +import sun.security.x509.KeyUsageExtension; + +import java.security.PrivateKey; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; +import java.util.HashMap; import java.util.Map; +import java.util.Vector; + +import sun.security.x509.X500Name; +import java.security.cert.X509Certificate; +import java.util.Date; public class CertificateRegistry { + public static final String DEFAULT_SSL_KEY = "default.invalid"; private static final Logger log = Logger.getLogger(CertificateRegistry.class); private CertificateDataConverter certificateDataConverter = new CertificateDataConverter(); volatile private Map handshakeDataMap = new HashMap<>(); @@ -40,6 +53,41 @@ public static CertificateRegistry getInstance() { return CertificateRegistryHolder.DELIVERY_SERVICE_CERTIFICATES; } + @SuppressWarnings("PMD.UseArrayListInsteadOfVector") + private static HandshakeData createDefaultSsl() { + try { + final CertificateExtensions extensions = new CertificateExtensions(); + final KeyUsageExtension keyUsageExtension = new KeyUsageExtension(); + keyUsageExtension.set(KeyUsageExtension.DIGITAL_SIGNATURE, true); + keyUsageExtension.set(KeyUsageExtension.KEY_ENCIPHERMENT, true); + keyUsageExtension.set(KeyUsageExtension.KEY_CERTSIGN, true); + extensions.set(keyUsageExtension.getExtensionId().toString(), keyUsageExtension); + final Vector objectIdentifiers = new Vector<>(); + objectIdentifiers.add(new ObjectIdentifier("1.3.6.1.5.5.7.3.1")); + objectIdentifiers.add(new ObjectIdentifier("1.3.6.1.5.5.7.3.2")); + final ExtendedKeyUsageExtension extendedKeyUsageExtension = new ExtendedKeyUsageExtension( true, + objectIdentifiers); + extensions.set(extendedKeyUsageExtension.getExtensionId().toString(), extendedKeyUsageExtension); + extensions.set(BasicConstraintsExtension.NAME, new BasicConstraintsExtension(true, + new BasicConstraintsExtension(true,-1).getExtensionValue())); + final CertAndKeyGen certGen = new CertAndKeyGen("RSA", "SHA1WithRSA", null); + certGen.generate(2048); + + //Generate self signed certificate + final X509Certificate[] chain = new X509Certificate[1]; + chain[0] = certGen.getSelfCertificate(new X500Name("C=US; ST=CO; L=Denver; " + + "O=Apache Traffic Control; OU=Apache Foundation; OU=Hosted by Traffic Control; " + + "OU=CDNDefault; CN="+DEFAULT_SSL_KEY), new Date(System.currentTimeMillis() - 1000L * 60 ), + (long) 3 * 365 * 24 * 3600, extensions); + final PrivateKey serverPrivateKey = certGen.getPrivateKey(); + return new HandshakeData(DEFAULT_SSL_KEY, DEFAULT_SSL_KEY, chain, serverPrivateKey); + } + catch (Exception e) { + log.error("Could not generate the default certificate: "+e.getMessage(),e); + return null; + } + } + public List getAliases() { return new ArrayList<>(handshakeDataMap.keySet()); } @@ -70,7 +118,6 @@ synchronized public void importCertificateDataList(final List c for (final CertificateData certificateData : certificateDataList) { try { final String alias = certificateData.alias(); - if (!master.containsKey(alias)) { final HandshakeData handshakeData = certificateDataConverter.toHandshakeData(certificateData); if (handshakeData != null) { @@ -89,7 +136,6 @@ synchronized public void importCertificateDataList(final List c log.error("Failed to import certificate data for delivery service: '" + certificateData.getDeliveryservice() + "', hostname: '" + certificateData.getHostname() + "'"); } } - // find CertificateData which has been removed for (final String alias : previousData.keySet()) { @@ -110,12 +156,27 @@ synchronized public void importCertificateDataList(final List c } } + // Check to see if a Default cert has been provided by Traffic Ops + if (!master.containsKey(DEFAULT_SSL_KEY)){ + // Check to see if a Default cert has been provided/created previously + if (handshakeDataMap.containsKey(DEFAULT_SSL_KEY)) { + master.put(DEFAULT_SSL_KEY, handshakeDataMap.get(DEFAULT_SSL_KEY)); + }else{ + // create a new default certificate + final HandshakeData defaultHd = createDefaultSsl(); + if (defaultHd == null){ + log.error("Failed to initialize the CertificateRegistry because of a problem with the 'default' " + + "certificate. Returning the Certificate Registry without a default."); + return; + } + master.put(DEFAULT_SSL_KEY, defaultHd); + } + } handshakeDataMap = master; if (sslEndpoint != null) { - sslEndpoint.reloadSSLHosts(changes); + sslEndpoint.replaceSSLHosts(changes); } - } public CertificateDataConverter getCertificateDataConverter() { diff --git a/traffic_router/connector/src/test/java/secure/CertificateRegistryTest.java b/traffic_router/connector/src/test/java/secure/CertificateRegistryTest.java index d01da22e93..01119bb6fd 100644 --- a/traffic_router/connector/src/test/java/secure/CertificateRegistryTest.java +++ b/traffic_router/connector/src/test/java/secure/CertificateRegistryTest.java @@ -87,6 +87,7 @@ public void itImportsCertificateData() throws Exception { verify(certificateDataConverter).toHandshakeData(certificateData3); assertThat(certificateRegistry.getAliases(), - containsInAnyOrder("ds-1.some-cdn.example.com", "ds-2.some-cdn.example.com", "ds-3.some-cdn.example.com")); + containsInAnyOrder(CertificateRegistry.DEFAULT_SSL_KEY, "ds-1.some-cdn.example.com", + "ds-2.some-cdn.example.com", "ds-3.some-cdn.example.com")); } } diff --git a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/external/RouterTest.java b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/external/RouterTest.java index 452e4fa994..2c6efab6a4 100644 --- a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/external/RouterTest.java +++ b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/external/RouterTest.java @@ -27,6 +27,7 @@ import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.ssl.SSLContextBuilder; @@ -217,8 +218,6 @@ public void before() throws Exception { InputStream keystoreStream = getClass().getClassLoader().getResourceAsStream("keystore.jks"); trustStore.load(keystoreStream, "changeit".toCharArray()); TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).init(trustStore); - - httpClient = HttpClientBuilder.create() .setSSLSocketFactory(new ClientSslSocketFactory("tr.https-only-test.thecdn.example.com")) .setSSLHostnameVerifier(new TestHostnameVerifier()) @@ -438,9 +437,12 @@ public void itRejectsCrConfigWithMissingCert() throws Exception { try (CloseableHttpResponse response = httpClient.execute(httpGet)){ int code = response.getStatusLine().getStatusCode(); - assertThat("Expected to get an ssl handshake error! But got: "+code, + assertThat("Expected a server error code (503) But got: "+code, code, greaterThan(500)); } + catch (SSLHandshakeException she) { + // Expected result of getting the self-signed _default_ certificate + } // Pretend someone did a cr-config snapshot that would have updated the location to be different HttpPost httpPost = new HttpPost("http://localhost:" + testHttpPort + "/crconfig-2"); @@ -494,9 +496,12 @@ public void itRejectsCrConfigWithMissingCert() throws Exception { try (CloseableHttpResponse response = httpClient.execute(httpGet)){ int code = response.getStatusLine().getStatusCode(); - assertThat("Expected to get an ssl handshake error! But got: "+code, + assertThat("Expected an server error code! But got: "+code, code, greaterThan(500)); } + catch (SSLHandshakeException she) { + // expected result of getting the self-signed _default_ certificate + } // Go back to the cr-config that makes the delivery service https again // Pretend someone did a cr-config snapshot that would have updated the location to be different @@ -511,6 +516,11 @@ public void itRejectsCrConfigWithMissingCert() throws Exception { httpPost = new HttpPost("http://localhost:"+ testHttpPort + "/certificates"); httpClient.execute(httpPost).close(); + httpClient = HttpClientBuilder.create() + .setSSLSocketFactory(new ClientSslSocketFactory("https-additional")) + .setSSLHostnameVerifier(new TestHostnameVerifier()) + .disableRedirectHandling() + .build(); // Our initial test cr config data sets cert poller to 10 seconds Thread.sleep(25000L); @@ -518,10 +528,13 @@ public void itRejectsCrConfigWithMissingCert() throws Exception { httpGet.addHeader("Host", "tr." + "https-additional" + ".bar"); try (CloseableHttpResponse response = httpClient.execute(httpGet)) { - assertThat(response.getStatusLine().getStatusCode(), equalTo(302)); - } catch (SSLHandshakeException e) { - // Expected, this means we're doing the right thing - } + int code = response.getStatusLine().getStatusCode(); + assertThat("Expected an server error code! But got: "+code, + code, equalTo(302)); + } catch (SSLHandshakeException e) { + + fail(e.getMessage()); + } httpGet = new HttpGet("https://localhost:" + routerSecurePort + "/stuff?fakeClientIpAddress=12.34.56.78"); httpGet.addHeader("Host", "tr." + httpsNoCertsId + ".bar"); @@ -598,7 +611,7 @@ class ClientSslSocketFactory extends SSLConnectionSocketFactory { private final String host; public ClientSslSocketFactory(String host) throws Exception { - super(SSLContextBuilder.create().loadTrustMaterial(trustStore, null).build(), + super(SSLContextBuilder.create().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build(), new TestHostnameVerifier()); this.host = host; } @@ -607,7 +620,6 @@ protected void prepareSocket(final SSLSocket sslSocket) throws IOException { SNIHostName serverName = new SNIHostName(host); List serverNames = new ArrayList<>(1); serverNames.add(serverName); - SSLParameters params = sslSocket.getSSLParameters(); params.setServerNames(serverNames); sslSocket.setSSLParameters(params); diff --git a/traffic_router/core/src/test/resources/api/1.3/cdns/name/thecdn/sslkeys.json b/traffic_router/core/src/test/resources/api/1.3/cdns/name/thecdn/sslkeys.json index c5a9b3d173..f987f6e630 100644 --- a/traffic_router/core/src/test/resources/api/1.3/cdns/name/thecdn/sslkeys.json +++ b/traffic_router/core/src/test/resources/api/1.3/cdns/name/thecdn/sslkeys.json @@ -4,8 +4,8 @@ "deliveryservice": "https-nocert", "certificate": { "comment" : "The following is just a self signed certificate and key to use for testing this is NOT private data from a CA", - "key": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBMTNESjAybUhY\nUHUyOEh0aEg0UzhVNlpIUjNLRmNmc25hSDZzTllEeWxEVkdTZFFoClhyejJYS3dzWVFzeC9lVTFu\nKzRKZTNHazhNZmJ1cnMzYjVyNWdwNTBvQloxMzNEczM2U0RBTyt6ejdMMHY1TEYKUGJPeHpSaHZq\nRlZJZFZramdzazRUUjFUYVlQNzBMT2p3b1ZkRExNb0RmNXRmZEMvYzFIdzVkd09ibFBHWkMrWApF\nTzREUG12azR3TmwweGFXVDdJbXN5ckJJU01ueUhBUElYQkwyREFHc0pYVXBvQjVhckNnbVNDNU41\nOTQ3Y0VpCjJRY2tIaDBWdWJlOUM5VytNbVUvT1VQTWc3TnVTTk55anlsZldzV2poSUZtUXBZUmo5\nWnppTGYxSzlsaDl6MUYKUlR2ckxpMUcwY1h4ODYxZ05qVHNhNjFrLzlBRUl6R2crVzBLRVFJREFR\nQUJBb0lCQUdLcGYzUTNKc3VaWnYwWQpzN0RZZTlxZkVwT1F5YllhTzhEcUNmbHl0U1RVaFB6NGpk\nT3lHK3p5MkZ3VTRXOFIwZzRNMkFEVldhRC9GZ3lkCkFsVTFGc0VQeWY4cWFnN0t5MS9jR2phS2o4\nRTFoa3BaYjhUREQxRUt1TUwrcDNFK1FqbjU1clBDRTFvR0hJTkcKVVYrYTdiTU1OUEs3cXU3c2Mx\nRGZuTC9YbURCRGpEczBzN3BkL1NXanhBeWwzR3I3Z1dFRVdTRzNlVnBXeSt3Sgo1Qlh5ZlU2NnM0\nMHczd1lzV0pCSVpjL0lBRC9xOWFNMWFJYmhnZUtud1IwRFZWaTI5MU5udFR6eGM2TWNqM2YrClFO\nZGRjQ0VOOWFQVmFjUi9SVkhrRjhDeEtTUWZlNnFsamIvaTc4eXFwVHpQV3k2dkZld2d3Sjh5dzhR\nbDZVRlYKUHFGUEdKVUNnWUVBN3piMWMwT1l6dEVVSERzMW81ZlAyak1UdXNXVThrN0VUYUdiWFly\ncWJqZU9kemdsdktNTQpRYldLUEdkeDY1alhkbHhrRlJIajBjTmVQWHY4cG1lWHNUOG8yVHN3VDZa\nclBaSkVvS1pyWnE4b1FpQmFjWVlOCmtWVDBqbzBnRnJualhOQjVUM3lzUVFuVDF2WitITWhVQ0cz\ndzNOMTJNKy95VFNRQ2FYclpKMzhDZ1lFQTVvN0YKeWFKN2V6NUxUcjhTeDZ5L0tXT1lwVkNlSFh2\nUnF0a0VQS0dIbnVQZXdoaERPZUF5cE4xVEs5SDIvMjhiZkI5TAoxK0JyWmkwTCtMMjBwMjZIVWQv\nK0p2UHlFRTJKOHVjVHE2UFIra2xydTJYUW83U215RjBnR0hwZzVaY3dBOUhYCnI0NGdtQ2dIeG1j\nay8ycVJnV0VuWXVISklsQ2laWE9PL09RZ0ZtOENnWUFjQ2pNbk9hczF3dWc2anU0d3FPRGkKVU01\nbFBEZkRWMXhIUlVReTZNK2w3N2t4WEZHQUZSU2d0eWptLzdFb3pwZWk5aDE5SXNXemx0VDdIQWQz\nY2ZragorNlZNSVZYK1lDRjk3Q0ZETzM2bllLeTFZNWwyYVNJNkFOMVJ3RlVjbE5tRHphUUtuekNK\neHg4ZnVYRDY2cmgrCjdIUXBUNFJGZmtER3JndmlWVllTL1FLQmdRRGtEWXMweEVSeUJvOUZDQmtT\nYXh2M1c2MnNyODZHaVdnK0gwVmkKbDhCbmVTeHBQc2lZWWR5V1dOb2crU0hoVGN5WS9QZnZRK3ZY\nK0d6a0VQbTF0ODJnUGZqT0hQUnVEZFNLOE9qegpHU3JrOEdUZ3kzZ1J4ZXBIUEY0MytDMEtUSDdR\nK0dycEdxUEEvYStiSDRGb0o4aGZlbk1VQ3hRQm5sTFVHUGJ4CnpOQzBmd0tCZ0NhWlpMSWFaZVFF\nSmt2aTBpbWcxdS9OT0tSVHFOZjZXSVlkQVh2WEsxR0E1TElOU2pvM0NNNXAKL1RodEN6bVBiaVF3\nZysrdlpkdlVmVEJ1MzNsTFhaRTk0bzRKQ3M0VU50a1Jodmk3ZGJPU083Y3phaUFVckthdgp0a0p4\nbFl0R3ZGTkdRN1JKYUttekt3MXFxKzVyM1B4RktTVG4vc1ltb3hUMysvbUE5YkRnCi0tLS0tRU5E\nIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==", - "crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZsekNDQTMrZ0F3SUJBZ0lDRUFNd0RRWUpL\nb1pJaHZjTkFRRUxCUUF3WkRFTE1Ba0dBMVVFQmhNQ1ZWTXgKRVRBUEJnTlZCQWdNQ0VOdmJHOXlZ\nV1J2TVJBd0RnWURWUVFLREFkRGIyMWpZWE4wTVE0d0RBWURWUVFMREFWSgpVRU5FVGpFZ01CNEdB\nMVVFQXd3WFZHVnpkR2x1WnlCSmJuUmxjbTFsWkdsaGRHVWdRMEV3SGhjTk1UWXdPVEl6Ck1qSTFN\nVE0wV2hjTk16VXhNVEl6TWpJMU1UTTBXakIvTVFzd0NRWURWUVFHRXdKVlV6RVJNQThHQTFVRUNC\nTUkKUTI5c2IzSmhaRzh4RHpBTkJnTlZCQWNUQmtSbGJuWmxjakVRTUE0R0ExVUVDaE1IUTI5dFky\nRnpkREVPTUF3RwpBMVVFQ3hNRlNWQkRSRTR4S2pBb0JnTlZCQU1VSVNvdWFIUjBjSE10Ym05alpY\nSjBMblJvWldOa2JpNWxlR0Z0CmNHeGxMbU52YlRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdn\nRVBBRENDQVFvQ2dnRUJBTmR3eWROcGgxejcKdHZCN1lSK0V2Rk9tUjBkeWhYSDdKMmgrckRXQThw\nUTFSa25VSVY2ODlseXNMR0VMTWYzbE5aL3VDWHR4cFBESAoyN3E3TjIrYStZS2VkS0FXZGQ5dzdO\nK2tnd0R2czgreTlMK1N4VDJ6c2MwWWI0eFZTSFZaSTRMSk9FMGRVMm1ECis5Q3pvOEtGWFF5ektB\nMytiWDNRdjNOUjhPWGNEbTVUeG1Rdmx4RHVBejVyNU9NRFpkTVdsayt5SnJNcXdTRWoKSjhod0R5\nRndTOWd3QnJDVjFLYUFlV3F3b0prZ3VUZWZlTzNCSXRrSEpCNGRGYm0zdlF2VnZqSmxQemxEeklP\negpia2pUY284cFgxckZvNFNCWmtLV0VZL1djNGkzOVN2WllmYzlSVVU3Nnk0dFJ0SEY4Zk90WURZ\nMDdHdXRaUC9RCkJDTXhvUGx0Q2hFQ0F3RUFBYU9DQVRZd2dnRXlNQWtHQTFVZEV3UUNNQUF3RVFZ\nSllJWklBWWI0UWdFQkJBUUQKQWdaQU1ETUdDV0NHU0FHRytFSUJEUVFtRmlSUGNHVnVVMU5NSUVk\nbGJtVnlZWFJsWkNCVFpYSjJaWElnUTJWeQpkR2xtYVdOaGRHVXdIUVlEVlIwT0JCWUVGRE5EbHR2\neVVRdGthNk1tYW43alUxbTJlanlmTUlHWUJnTlZIU01FCmdaQXdnWTJBRktOeFFYNHlRZ3FBbmZK\nOW9NZkFzcytUTjhLNW9YR2tiekJ0TVFzd0NRWURWUVFHRXdKVlV6RVIKTUE4R0ExVUVDQXdJUTI5\nc2IzSmhaRzh4RHpBTkJnTlZCQWNNQmtSbGJuWmxjakVRTUE0R0ExVUVDZ3dIUTI5dApZMkZ6ZERF\nT01Bd0dBMVVFQ3d3RlNWQkRSRTR4R0RBV0JnTlZCQU1NRDFSbGMzUnBibWNnVW05dmRDQkRRWUlD\nCkVBQXdEZ1lEVlIwUEFRSC9CQVFEQWdXZ01CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUJNQTBH\nQ1NxR1NJYjMKRFFFQkN3VUFBNElDQVFDdG90ODFqbmdodkZpMXQwTiswNTB5alhSSDNhWUxzNmFS\nWDdZQ3hOMGVRblpydmNlNQp2c3B4cWdqNDFJQ0psV2d6RXNSUlhHMVVad3M5SmhPeEVISmdhM0hY\nQmNmMklFd2YwQXZkNjhHWTdPSk51enNXCk40U1dYZTBJaThEVysvMHAyK3BZbWQvSTNRM0VWQ05O\nZ2NUWjlhOFRIckxaRWNPcDhFNXQyZmpFTFVkUi9EQjIKU1ZDa1YvcFAwTU95WUV1YmM5VFNiVXRS\nOFlsUjNzM0l4K1lNOW1Pd1VRSHRFNWo2OXliL2pQOE83b3RpS0tHdAplWVFOVklnS3JTSEUzOHd0\nVlplSXhwcExYSW44UHZBc0xBOFc4SVFwVUFyNlUzMVB2Z09UWjg5UVVYREFHNFFUCjJGd2tWcnEr\nU1NoVlhGWHRDd0dpZTR1Tm5xYnZzcEhNMWI3YnEyQWF1dmppWTNMLzQ1ZVlOWXNiNVozNVhvb1IK\nNnZ4VTlublBNS3ZOQjRJUEJvak9Nc2FiSVY2bjlaRWdkV3lHZEFlRFpSUldNWnhzTHJJalBZcXNw\nNWNJSy9JVwpUaVltQmZ3M3N2UC9WVWV6aW1NNUhWM3UvZ08yKzdjZFhnSFduWVFUSlcrcUlaVnM3\nWjUzcUtFR1pzZGxHTmxSCjhjaXA2dENwWTVTbm1JS0tTS3pQRnFONEdRRGlpeWNWMGFrdmR3b0Rk\nTWJxd1pDQ1grWnBncjVaeThnQ3hQcEsKNkRwSzNBT3pSZ0RGMkpNc1BvMUkzTlN6WXRkS2ZyZS9X\nSnhQWmdWZTdUMzdhNmtPTEk3anFHbEsvbVFjYW1xUgp6MUJFK2w5Y0drazRwK002b2UvaXd1QVlI\nTExtYkNCRmxHczNJcXNuY0U4bVhyNERGdEpOSHNsRTdBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUt\nLS0tLQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJRnN6Q0NBNXVnQXdJQkFnSUNFQUF3\nRFFZSktvWklodmNOQVFFTEJRQXdiVEVMTUFrR0ExVUVCaE1DVlZNeApFVEFQQmdOVkJBZ01DRU52\nYkc5eVlXUnZNUTh3RFFZRFZRUUhEQVpFWlc1MlpYSXhFREFPQmdOVkJBb01CME52CmJXTmhjM1F4\nRGpBTUJnTlZCQXNNQlVsUVEwUk9NUmd3RmdZRFZRUUREQTlVWlhOMGFXNW5JRkp2YjNRZ1EwRXcK\nSGhjTk1UWXdPVEl6TWpFeE56SXdXaGNOTXpnd09ERTVNakV4TnpJd1dqQmtNUXN3Q1FZRFZRUUdF\nd0pWVXpFUgpNQThHQTFVRUNBd0lRMjlzYjNKaFpHOHhFREFPQmdOVkJBb01CME52YldOaGMzUXhE\nakFNQmdOVkJBc01CVWxRClEwUk9NU0F3SGdZRFZRUUREQmRVWlhOMGFXNW5JRWx1ZEdWeWJXVmth\nV0YwWlNCRFFUQ0NBaUl3RFFZSktvWkkKaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFPQ2lC\nV09BOE15andReTFzRVc4SDNVME1CaWlyU2xyUjk0aApDOU9mQjc5TnVWQVQ3U29qNkVYK0RkeDQx\neGhyY1lUSDArRk5BVW15RFJuUkticlFRTlJ1alpPZytud0VTcXNxCmUxRmJ2cXJKZUZSdStGQmxX\nSTBCTlNnSEVWdFo4cjZtY0ZuV3V2cXBrOHF2Q1BSemJGUjhKSU1kRisxbzkzZzYKaDdxanlOdk5z\nNjZ0UkRieFRHbnpDaEMrNXVVRElubTU5ekdiMnVFdXFlbldkNFZMaXRQVGRyQjRmTkFXODhiaApC\nWDhpSWVCV0xDUGRWT1NLUW9VeEFkaEplM1R4RXlnd1ZYV3dsUHpONjhmL2NyY0FZTmNrVFo1Yzdm\nTzdNV0JCCkR6T0kzcUxRc2R2L1lzR1dSM2g4Z2ZwaDcwMlBndW50Q25PbWhzdjVkZCtwcTAxR20z\nMzJzT0V4dHdONEF3bkoKeFk4REdmbDZYNmVNS2ZoQmt4VmVrbytLaTJEdW1vcWxrN2xIOGcvTXg3\nVCtvTDNDbkR2SHJUZy9Oa0YrV1hzcQphMUFuTGZyRGtyQjRnRVJLSHMrVzhjMVhyNXZNM1hMR2lZ\nTEtkVGw5aFp6ejFaRU1OaUozYXE2aW5TOGlVNkxiCmIxeHhDZldjdGV0Q0VabklxbGlSMkszODlG\nVHI3SDdQdldOTVhGb3M3ek5Ldm81WS81RjIwYjlkRXZJWnFjUnMKYVJhTXFYYmxqbnZUOHpiWFpn\nVTI4YzJpMnZmU2YxSEIrSkFaSTYzVG5oZlVybExDTDRGc3YrRnJNKzduSjdaOQoyY2lYR3ZaUG9T\nL0FWRzdvUW91cEx1UGk0VW1rYUM1RzVsSVpaNXhNbzBIV2oraXN0bVZVOGtkZmltalNVZy9ZCjI5\nazl1RzBSQWdNQkFBR2paakJrTUIwR0ExVWREZ1FXQkJTamNVRitNa0lLZ0ozeWZhREh3TExQa3pm\nQ3VUQWYKQmdOVkhTTUVHREFXZ0JTbXB2bEJPZXJ6NEJ6c2hYUVlKR3VqeVNEVmJUQVNCZ05WSFJN\nQkFmOEVDREFHQVFILwpBZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJoakFOQmdrcWhraUc5dzBCQVFz\nRkFBT0NBZ0VBb1o2V0w2YjlPWjdpCm0xTTdLQ0Q5ZHhPbFBUWEp0bGpJMTlIWWNvdW9panRIckRo\nMjRnVHdsTzlkOWxRSWVIa1ovVzhNVjYwRHZOQ2QKUEtrajMzYXNBdG1NaEtHeTI0alRGcGF3WXRa\naytON3p3MnlHY2gwR0J0UWk3dkZpSmIvaWpGRHI5bzM3cDJWZQp0QU5KUm5WNFEwVWhYTUJId0VO\ndFZZemVjUVhVbWV3c1ErTGkvZnAwb3hUaVppekhXMUlkalM5c2hQcmFJUE9BCmNVL0F4enc5ZFph\nOXkxc1RudnI4RmRkTUZLV01oOFlubHIyajRjQTM5R0kzVmt3c0RaN2EyUnhLTGpEY2FWNTkKUXpG\nOEFFUnMvNFJ4bXVaWTVCVW5oWTNDQ2EwdzZiWGV5d1cxS0hlN0tlUkI1bDVaNkRHWU0yUVlJRy9r\nZUhKcgowb0VXUzE3ZjNtSlZzampQMVlMenV1cnJVQ3Mxc2xjbTZYM3Y2M2FjTm5ubitncGhzM2Y4\nMmdzS0xhOUJWcW05CnJHM1BNTUg0VzlvazFlUUl0bEswMzNEclBrN1RqNnpLVGRHWjJMbDY5U0VZ\nMzZCQ0RSaEd5R0tUZ1RnNU5LZHAKT2g0QWJPNzgreHBCTUV2NW4xZCsvSFg2Zi9CL2l3dFdCbVA5\nTmduZTU1RW5LRHR3V1k3T201My9KM21iMXNrNwpJb2FuYzdMaHN2clozRWgwV3dUMi9XK3lEVkFZ\nbVVLTHd6bVQ5aUtPbm1FUWdMWE1GbmRjMERrQTIwRjVCZWhVCmNwUnI1WmFhaUZqWDZiRU1adHFU\nRVo4dUZFSmorcElCUlExYUlybHZiMlo2bjZsV3NrekcwRlp1cFRUeUluZVYKT1pOUEhMRDhZY2Fv\nc1J3czBrTG03VGcyMXYyNnRvMD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=" + "key": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzI0b0NxaW1QUy8yZ0gKUUlVRHd5ODRleUNrTXlTeSt6YWhTNEpSOHJaeE9MbEpkZVBHVFZBU0dsandYb2NTV2tvTkFvWGtvN05GVmdEUApjVC9uR1ZZVVQzSEE0N25zcUFBUGlCMEtWUlh0dmtiRk9XL1hzV1d3ZE1mc2psbStsWEl3c1NLTnB4b3NWb28vCkFsbHBEbUU1QmJsQlR0aER0M1libTZGYW9Ud0NSemRGVndqM3Nud0pzRDhHdUMxa0VqMGViY0p3RTY2d0xhRjkKWU14RmZrQk9Ib3NCa2xic0tQWlhJM3J3eVpPYXBlZXhKUlphSC9ZeVJVRnlSdXMvUTRWUlJ4VGVteEh5cG4yKwo0N1NQd1E2ZVlBR3FWVXR5YWtYVEtmc1FndURpMmNXcWdYYytMeXhnK3EzMVQ3UTM3SE5GUkkxWWxrTTVWOTNYCkQ3S1NYZU8zQWdNQkFBRUNnZ0VCQUpYczdZbmhWYUI5M094RkNrWmhWbTY1RWJOS2NnV0FSL0xHa2hsWUhoU0gKYWU0OUJQTm1JZ1FWTVdBc1BoTGZqZUZJZGpkUHRBRmRWZUM1ZUtlZGI2SEsxdmhJTi8wNFpJUlhFMmVMQlNVWApYYkVGT3hqWnh3RjNXd1lrVkpJV3Rid1JHc0NCZ3NWaVZJYi9DQWxGenBJT2pTWnEyb1A0L0l2NWM3ZDJnbGxpCllWU2lSR3N5UzdZdzA1RjVKMkl1TFBBcjJPYVZscTRxMlpQa3pML3hlSDlKeDk3M2tEL3p4bktkakZTWmpZRFAKcVpnYm05bDcwcWxIK1hVL2JUZ1drT2wvNnVYbHR1UDZvOHZ1cUdMSVg0NnkreTl1azlOWUhjNHBTc05XajNsVQo4UVdtQ1lQNDBCaS9wdE5lM3JnbTVFdERVeFhKVXMxb0NONFFBaFFOL0VFQ2dZRUE0dUp2Qkg0KzBBdk9GQmNvClpldGlIOUZseWVLaCtkcWFtanIzbWh5WlduaGhyRTZERnVYR2dlanc3UExVMUpSQTJMYlluRDZFS25kWGhjUUoKRzVlMFhzb1VoMHd5bG1iVG9kV1FIYlJ1dnFmUG8yVEFOYTVEWGxFSHBNb2pEaGQ2Wi9yRE40K3BEcDhUbUs4Kwo2bzJVRFd1WUp1MXZGR0ttTUpHU2RhdU9QMUVDZ1lFQXpscVpKTDY0aDdXV2Fvdkg0d1FONjd3TXpDUTBMMjFnCm1RRlVja2hRSGFxbTdUMEpCWFQxaThIMGloelh3WVVpMHY5L0RWSE9hdWxNUEt1eFdVSVdKVGpqQ0w3MUN6K0EKWHExWDg5S3NvbkJTOTlMMzJLUm9pbFZ6K1ljTUNJRk4vY3RpV05TM3lSRmZpR0UxUDV5QUUvV3NoYldSMGF2bQpyalIwaVZjU2dJY0NnWUJpaHNxSFBQdXlCUzVjOHlHTUFRZi9vVU4reEhocXRFL25JaXhjTkljMERvcjc5S3hnCnlTL0hRbzA5bU1acittV2V0dWlpRVZQN3pRK28rMVNwTXR3VlBkUmtYT2FyQWNSdHh2eHFxZXhkeHlvWVhxeEoKbzMrRitkSkQ4YlAvYnBxdGhPdzV1SjFGeURjT1d5d0xWNmd2bThYYlFjaTNKWS9lRDVsMm1DV1J3UUtCZ0JqRwozZzZBYSsyM2l2aitFYUViY29SMGp1RFFGQWdCelJCeURXNnZhaGMxejFjNjllTlcyTWpRSUFtWlR2cW9mcmJ4CkFKTmIyRG9VQ3hoWjBUQ1RjODlDVmxoTmZXUzlXaStFQnNSNjdrbU96UmQrbUUzRjU5dDhTVEdUMm9rRzVaTnMKb1VGalFUSCtTUWM2RE1lM2hkVmZzVGhZeGNwMEpuMlNSTS9jeVpidkFvR0FWd3I1ZFp3K1NzK3MvMmRDRDdRdgplV0ZvRkxwdkV0eG8zMHNSKy95WVZGWCtpWXk2WmxCaEpDU0c3aU00RUVnUGYzSFBYVWR5b1MwVzB0NUkvL1d3Cm9ZQ2wwNlBiWVk2QkpiRk9MYnRrMjlVV3R0ckF6Yjd1K0tsMytEb2N2TnJnRisvbmJIN3JTY1VKNys5aTZXOXYKSTdvS09jZDV0SjlGMnRETmVkcUlGcms9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K", + "crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURZakNDQWtvQ0NRRG4va0YwcGszc2F6QU5CZ2txaGtpRzl3MEJBUXNGQURCeU1Rc3dDUVlEVlFRR0V3SlYKVXpFTE1Ba0dBMVVFQ0F3Q1EwOHhEREFLQmdOVkJBY01BMFJGVGpFUE1BMEdBMVVFQ2d3R1FYQmhZMmhsTVFzdwpDUVlEVlFRTERBSlVRekVxTUNnR0ExVUVBd3doS2k1b2RIUndjeTF1YjJObGNuUXVkR2hsWTJSdUxtVjRZVzF3CmJHVXVZMjl0TUNBWERURTVNRE13TnpBd05URXlOVm9ZRHpJeE1Ua3dNakV4TURBMU1USTFXakJ5TVFzd0NRWUQKVlFRR0V3SlZVekVMTUFrR0ExVUVDQXdDUTA4eEREQUtCZ05WQkFjTUEwUkZUakVQTUEwR0ExVUVDZ3dHUVhCaApZMmhsTVFzd0NRWURWUVFMREFKVVF6RXFNQ2dHQTFVRUF3d2hLaTVvZEhSd2N5MXViMk5sY25RdWRHaGxZMlJ1CkxtVjRZVzF3YkdVdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXR1S0EKcW9wajB2OW9CMENGQThNdk9Ic2dwRE1rc3ZzMm9VdUNVZksyY1RpNVNYWGp4azFRRWhwWThGNkhFbHBLRFFLRgo1S096UlZZQXozRS81eGxXRkU5eHdPTzU3S2dBRDRnZENsVVY3YjVHeFRsdjE3RmxzSFRIN0k1WnZwVnlNTEVpCmphY2FMRmFLUHdKWmFRNWhPUVc1UVU3WVE3ZDJHNXVoV3FFOEFrYzNSVmNJOTdKOENiQS9Ccmd0WkJJOUhtM0MKY0JPdXNDMmhmV0RNUlg1QVRoNkxBWkpXN0NqMlZ5TjY4TW1UbXFYbnNTVVdXaC8yTWtWQmNrYnJQME9GVVVjVQozcHNSOHFaOXZ1TzBqOEVPbm1BQnFsVkxjbXBGMHluN0VJTGc0dG5GcW9GM1BpOHNZUHF0OVUrME4reHpSVVNOCldKWkRPVmZkMXcreWtsM2p0d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQmpyL2lBT2lWZGt1aFYKTmxqcTIwMXowZDRIYnFsTFMvL20wSENZMW9MVmdJVjZiRXpBbG9BMFh0WVh2SForajcxYXBLVk8vSjdacXVnRQpQOW5sY29BeFN5a2NmT3lkcDg1Z3hOYWptUXVSeVFJZFU3cHh2UHdPdDhVVktJK1lLaXJHczBZWExQRlRGdVJyClNKd1BRYlhRMThhdlZJYUFGYTNvVDdOK2pEVTNXN0QzenAvUU1rREJoRDhiSTJzcU1mVVpLSVE4blo1c1o2NFQKYkYwQTZZem9vcGppQ0Z2Yyt1WHdJenY0ZHU1bE1XczIzcmgxU2EySjhBWXBqUkZXLzhYS2kvTVNmTE9EYXdkcApXWldXYzM4YXlOT0d0anJIMTg0azZDWk14cFNhcExnZUF2RTFtcFdubURYVHFBTjB1RkM4MWt5YVhFeFZDOWwyCkh0RXQ4Q25aCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" }, "hostname": "*.https-nocert.thecdn.example.com" }, @@ -40,8 +40,8 @@ "deliveryservice": "https-additional", "certificate": { "comment" : "The following is just a self signed certificate and key to use for testing this is NOT private data from a CA", - "key": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBc2Y0NnV5OGJ2\nQk5rMGhCaEVsbHdGT0dqREh6M1hJY1hteDRVNThNZG9Fa1JId0VTCjVONnd3NFV6bDAvRDcyMlJV\nODlMeHB4bldvclJmdVZNQldnOGVFcXBUb2NUS2NOZHhtZmdEUWZTcTZ1ODNTWkUKTmFCZFArK2g5\nYTJJRFZXWGFldVRhcVA3Q3lVVG52Sld5Mm1JalJWZkRGQWRWWHNhU1M4RGRYUWdibEJTelJ6NwpL\nMXFHVWt1RlZQc0R0ODZBYVF3TnN5R2ZDN3ltcUkzNU1FQ3hTdzNPd2lXSlAyZTg3U2E5UG9Pdjcr\nZUs2NVJnCmM3dzNkSXQxZUlyS3B6OWpQV1RPTkJOK0JhWFdvcHNXZ3UvdVd4Q1pnUk9qaXBWVUFK\nNHhrNFRGMjd0S28zRDUKSHd4RVZOeStlck9FTGI3VWxuaHMxaG1LdVI2RTZwREpHSyt1UFFJREFR\nQUJBb0lCQURkb1RYNFJkdysvOWNXUwpoYlZCbEN0YjVmYXdQQXhZblZlVE1Lekl4ME1yRzZKTUlr\nYU9yL1hkVkNjSkZKUkd4bE9SbHlRWGNmRDBmNnlCCjBuMW9hbEtENDFwbm4rYURRNERNdXlrelF6\naGZlS1piRUNhbGFnSEtKZCtsaWxHa1VFTVBxMDhxQnE3OGRyUW0KK2kvT0JVenQxeTJ0RHNTYVVw\nOXZmQ01tNkNXT1pKOHN6eWZrSk1ZZVVLdXptOWwzMGNNeW84anF0bi9LQjZWWApEVkZmNGpqU1FM\nTzBYbUo1M012TW1xUzlGaVRUdklpQm9iNnkxMEtWZjZpWk5MZnVnVExoWFhQaDFDNTJTUTVvCjZj\nVWdqanh5NFhmYUdub0Y1NlF4M0FIZWRpd0Z6eEFpWGlKOCswUFB3bWI2Q1FGOU1jSzV0QjQzcVZx\nNWNKNFcKTVF1SWpsMENnWUVBMkM3SFh6OHppODQ0anJHa1VvUmF3NE9QcitBdnFIVGY1NEJ2Ujhz\nTzc2NkljRzEvUytmdQoxbXQ2RnBRQVZGeHJvWmxEWHkrWGtTQ0toaEM3cmh6cHQzaVJuRkhkWFpT\nM25MM2ZjWnIzUCtFSXNyb3hLeVFRCmg3dy8xYnEzd3JwUnNOWjZpdDNVSHJvVlRLU2tZQzZvOUor\nYzRPYjVQRzVGcFRvZk81dmRWWHNDZ1lFQTBzYkYKd3pjYzEvcTdEVXpkTkVTaWtNMFdMMkFZanBH\nOFpEYTY0eUcrZ1JkWjhjWmpJUzlkVFpWWVpUODNFSnp2T2dyWgo1NmFYTVN2QVc2ak1oY1VDR05K\nN3JaaGl1Uk9HNVdWM3FzMnFkbmtkQlgrdGhrUE9HT3lNYnhsN1ltUlZXTG11CjBFV3NMQ3VHVFov\neDV5NG02WmNGQldRZUkreVMxanZTTXVkelVhY0NnWUJvVG1ISjlnK2o1Qk5yM2hCZjlCWnIKQVY1\naHlMU1YvaFpPZDZ5NW9pTUp5RmR5ajVKOUNHSTN1TkhHZFJDWG82UVc2NEVUT3o1Uk9yYzdxblV6\ndENXYwpiYU1zSGwvRm1Fempac1daNWVCb1JPYlNmWDNkeDkvbDdoR0t5VFdDMGkwNk9ySVRzS1o1\nVU9XWC9sU0ZSOTRqCmNhUGE2L2JUam8weUJKSXZTNndHWXdLQmdDN045dkpmbGFjY1JWY3h2MWt3\nK0l5QkRqRWMvTGNFQTdxWk1LenAKUEYxOEt2djJXdUx1bXFCMHpubEZMVndpRFRsdFdYQUlYVUNN\nLzUwYkFiZWV4TlZ3UUFpUGN6UzM4bGVVVFp0LwpLaUEreXNRQzB5eWlkK3l1OG94bE16SHBKODZa\nQlFtNHZ2L2I5bW5jWDZJL2JHS29wM1BJQksxamhrUE9hdUhrCjVZVzNBb0dBVEtVZlhkWTNad0hM\nWlUxSm1lRldKb29kOW10SHNrM1QyT2hCdDBwNUpSU3hVYWxOY0tkZEcvMVgKMFFCN1E1NWxMZEIz\nT1k2b1NDaEtuK1dUMWNwQ1N3d09PQlJNTmZPOVR1c252NkU2ZlNRWWVwdGNmV2lOb3VBWQpYaDVn\nQTRORzJHeUM5TW9tZUxQbUY0NmJsdU5UYzFxREMzeVZVcVQzdDkxY1RwNytWems9Ci0tLS0tRU5E\nIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==", - "crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZuakNDQTRhZ0F3SUJBZ0lDRUFFd0RRWUpL\nb1pJaHZjTkFRRUxCUUF3WkRFTE1Ba0dBMVVFQmhNQ1ZWTXgKRVRBUEJnTlZCQWdNQ0VOdmJHOXlZ\nV1J2TVJBd0RnWURWUVFLREFkRGIyMWpZWE4wTVE0d0RBWURWUVFMREFWSgpVRU5FVGpFZ01CNEdB\nMVVFQXd3WFZHVnpkR2x1WnlCSmJuUmxjbTFsWkdsaGRHVWdRMEV3SGhjTk1UWXdPVEl6Ck1qSXpO\nREl4V2hjTk16VXhNVEl6TWpJek5ESXhXakNCaFRFTE1Ba0dBMVVFQmhNQ1ZWTXhFVEFQQmdOVkJB\nZ1QKQ0VOdmJHOXlZV1J2TVE4d0RRWURWUVFIRXdaRVpXNTJaWEl4RURBT0JnTlZCQW9UQjBOdmJX\nTmhjM1F4RGpBTQpCZ05WQkFzVEJVbFFRMFJPTVRBd0xnWURWUVFERkNjcUxtaDBkSEF0ZEc4dGFI\nUjBjSE10ZEdWemRDNTBhR1ZqClpHNHVaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RR\nRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQ3gKL2pxN0x4dThFMlRTRUdFU1dYQVU0YU1NZlBkY2h4\nZWJIaFRud3gyZ1NSRWZBUkxrM3JERGhUT1hUOFB2YlpGVAp6MHZHbkdkYWl0Ris1VXdGYUR4NFNx\nbE9oeE1wdzEzR1orQU5COUtycTd6ZEprUTFvRjAvNzZIMXJZZ05WWmRwCjY1TnFvL3NMSlJPZThs\nYkxhWWlORlY4TVVCMVZleHBKTHdOMWRDQnVVRkxOSFBzcldvWlNTNFZVK3dPM3pvQnAKREEyekla\nOEx2S2FvamZrd1FMRkxEYzdDSllrL1o3enRKcjArZzYvdjU0cnJsR0J6dkRkMGkzVjRpc3FuUDJN\nOQpaTTQwRTM0RnBkYWlteGFDNys1YkVKbUJFNk9LbFZRQW5qR1RoTVhidTBxamNQa2ZERVJVM0w1\nNnM0UXR2dFNXCmVHeldHWXE1SG9UcWtNa1lyNjQ5QWdNQkFBR2pnZ0UyTUlJQk1qQUpCZ05WSFJN\nRUFqQUFNQkVHQ1dDR1NBR0cKK0VJQkFRUUVBd0lHUURBekJnbGdoa2dCaHZoQ0FRMEVKaFlrVDNC\nbGJsTlRUQ0JIWlc1bGNtRjBaV1FnVTJWeQpkbVZ5SUVObGNuUnBabWxqWVhSbE1CMEdBMVVkRGdR\nV0JCVHlRTUw1UzdMbW5PeTlpRUQxdkUwL1ZzN1FTRENCCm1BWURWUjBqQklHUU1JR05nQlNqY1VG\nK01rSUtnSjN5ZmFESHdMTFBremZDdWFGeHBHOHdiVEVMTUFrR0ExVUUKQmhNQ1ZWTXhFVEFQQmdO\nVkJBZ01DRU52Ykc5eVlXUnZNUTh3RFFZRFZRUUhEQVpFWlc1MlpYSXhFREFPQmdOVgpCQW9NQjBO\ndmJXTmhjM1F4RGpBTUJnTlZCQXNNQlVsUVEwUk9NUmd3RmdZRFZRUUREQTlVWlhOMGFXNW5JRkp2\nCmIzUWdRMEdDQWhBQU1BNEdBMVVkRHdFQi93UUVBd0lGb0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VG\nQlFjREFUQU4KQmdrcWhraUc5dzBCQVFzRkFBT0NBZ0VBQWJpN09yQUNDbldKd3dDM2dmWUVBMmpI\nZ0FNMDRoK1FGQ1hRUnhCZApkd0ZLNDNTaVIwME1CTUdObVl1YUd0RWNTMGZacTVORFp1eFVOZHVM\nMmZselQzbkJ3Sm5DbEZ3aXd0YWwrcTE2CkV2QWtBbUQvU2pxNm5CYm5qNUlqNkRlRE5kOHRJd0ps\ncDMrdCs0RE9rNWt2a2FxS2ptd29EM3RlNG1QdnNIeXQKNElpRG1wRnpqeG83b2o5VkY0RTVtMjZV\nM240aENUYnJ2Ui9RNWlCdDhpT3M1YU8rVlpuTWNyQ3htbmhSYU1sVQpOaXkwTGxCZVVJQ213TE95\nNERQeDc1WVdDMzZEUVhMS2dMcnZ4RktIRmI2SlJoMmNLYzNpcVc3allhNjJwbmhHCllXb1pDdkJO\neXZqbkpIbGZYVDBUNitDN3Btb0ZLNTV5dGNhdFByQk82VEI3TFhUcjlJN2JIN0R2aU9SS1MwMFoK\nOHlPMktva1M1WVZ0T2c4NnNHT2lFOFQxMDFzc0xSNUhWZmVDTVJqc0J4eXdUdUxNRyt1cE9lWDhk\nMGhlUjZNbgp3RlFxUDR0V1A0WEZkSGd0cHlaZHBVYTBXVkZTVXJueDAvV1pDbXZLNFNQcmhzUG5s\nWUptaGtTRldkWHczcnJRCjZaL2tZZFM5VDM2SG9EMW1rcmdiMWRPTnNNd0Zpb1BqZ2RmRU1Xb001\nVWJ6L1p4RHp2V2ZDQWovVnloOVc0VFoKcEljUG8xZmhNQVJQcVVDY2N1ZVc3ckpOSDhwSm5yY0VU\nZ2xLdDY3SnZ2S1dKdzhLcEo1ajNzSERkUG56N1Z3NgpsNnRwVWJYU2U2SzY1Zy9Fc25EYkFDS21v\neldQNFVnSGY5akJ0c2FLK0hnUHVKRlYvMlBzMG96bW1XWGxQU0JJCitxQT0KLS0tLS1FTkQgQ0VS\nVElGSUNBVEUtLS0tLQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJRnN6Q0NBNXVnQXdJ\nQkFnSUNFQUF3RFFZSktvWklodmNOQVFFTEJRQXdiVEVMTUFrR0ExVUVCaE1DVlZNeApFVEFQQmdO\nVkJBZ01DRU52Ykc5eVlXUnZNUTh3RFFZRFZRUUhEQVpFWlc1MlpYSXhFREFPQmdOVkJBb01CME52\nCmJXTmhjM1F4RGpBTUJnTlZCQXNNQlVsUVEwUk9NUmd3RmdZRFZRUUREQTlVWlhOMGFXNW5JRkp2\nYjNRZ1EwRXcKSGhjTk1UWXdPVEl6TWpFeE56SXdXaGNOTXpnd09ERTVNakV4TnpJd1dqQmtNUXN3\nQ1FZRFZRUUdFd0pWVXpFUgpNQThHQTFVRUNBd0lRMjlzYjNKaFpHOHhFREFPQmdOVkJBb01CME52\nYldOaGMzUXhEakFNQmdOVkJBc01CVWxRClEwUk9NU0F3SGdZRFZRUUREQmRVWlhOMGFXNW5JRWx1\nZEdWeWJXVmthV0YwWlNCRFFUQ0NBaUl3RFFZSktvWkkKaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29D\nZ2dJQkFPQ2lCV09BOE15andReTFzRVc4SDNVME1CaWlyU2xyUjk0aApDOU9mQjc5TnVWQVQ3U29q\nNkVYK0RkeDQxeGhyY1lUSDArRk5BVW15RFJuUkticlFRTlJ1alpPZytud0VTcXNxCmUxRmJ2cXJK\nZUZSdStGQmxXSTBCTlNnSEVWdFo4cjZtY0ZuV3V2cXBrOHF2Q1BSemJGUjhKSU1kRisxbzkzZzYK\naDdxanlOdk5zNjZ0UkRieFRHbnpDaEMrNXVVRElubTU5ekdiMnVFdXFlbldkNFZMaXRQVGRyQjRm\nTkFXODhiaApCWDhpSWVCV0xDUGRWT1NLUW9VeEFkaEplM1R4RXlnd1ZYV3dsUHpONjhmL2NyY0FZ\nTmNrVFo1YzdmTzdNV0JCCkR6T0kzcUxRc2R2L1lzR1dSM2g4Z2ZwaDcwMlBndW50Q25PbWhzdjVk\nZCtwcTAxR20zMzJzT0V4dHdONEF3bkoKeFk4REdmbDZYNmVNS2ZoQmt4VmVrbytLaTJEdW1vcWxr\nN2xIOGcvTXg3VCtvTDNDbkR2SHJUZy9Oa0YrV1hzcQphMUFuTGZyRGtyQjRnRVJLSHMrVzhjMVhy\nNXZNM1hMR2lZTEtkVGw5aFp6ejFaRU1OaUozYXE2aW5TOGlVNkxiCmIxeHhDZldjdGV0Q0Vabklx\nbGlSMkszODlGVHI3SDdQdldOTVhGb3M3ek5Ldm81WS81RjIwYjlkRXZJWnFjUnMKYVJhTXFYYmxq\nbnZUOHpiWFpnVTI4YzJpMnZmU2YxSEIrSkFaSTYzVG5oZlVybExDTDRGc3YrRnJNKzduSjdaOQoy\nY2lYR3ZaUG9TL0FWRzdvUW91cEx1UGk0VW1rYUM1RzVsSVpaNXhNbzBIV2oraXN0bVZVOGtkZmlt\nalNVZy9ZCjI5azl1RzBSQWdNQkFBR2paakJrTUIwR0ExVWREZ1FXQkJTamNVRitNa0lLZ0ozeWZh\nREh3TExQa3pmQ3VUQWYKQmdOVkhTTUVHREFXZ0JTbXB2bEJPZXJ6NEJ6c2hYUVlKR3VqeVNEVmJU\nQVNCZ05WSFJNQkFmOEVDREFHQVFILwpBZ0VBTUE0R0ExVWREd0VCL3dRRUF3SUJoakFOQmdrcWhr\naUc5dzBCQVFzRkFBT0NBZ0VBb1o2V0w2YjlPWjdpCm0xTTdLQ0Q5ZHhPbFBUWEp0bGpJMTlIWWNv\ndW9panRIckRoMjRnVHdsTzlkOWxRSWVIa1ovVzhNVjYwRHZOQ2QKUEtrajMzYXNBdG1NaEtHeTI0\nalRGcGF3WXRaaytON3p3MnlHY2gwR0J0UWk3dkZpSmIvaWpGRHI5bzM3cDJWZQp0QU5KUm5WNFEw\nVWhYTUJId0VOdFZZemVjUVhVbWV3c1ErTGkvZnAwb3hUaVppekhXMUlkalM5c2hQcmFJUE9BCmNV\nL0F4enc5ZFphOXkxc1RudnI4RmRkTUZLV01oOFlubHIyajRjQTM5R0kzVmt3c0RaN2EyUnhLTGpE\nY2FWNTkKUXpGOEFFUnMvNFJ4bXVaWTVCVW5oWTNDQ2EwdzZiWGV5d1cxS0hlN0tlUkI1bDVaNkRH\nWU0yUVlJRy9rZUhKcgowb0VXUzE3ZjNtSlZzampQMVlMenV1cnJVQ3Mxc2xjbTZYM3Y2M2FjTm5u\nbitncGhzM2Y4MmdzS0xhOUJWcW05CnJHM1BNTUg0VzlvazFlUUl0bEswMzNEclBrN1RqNnpLVGRH\nWjJMbDY5U0VZMzZCQ0RSaEd5R0tUZ1RnNU5LZHAKT2g0QWJPNzgreHBCTUV2NW4xZCsvSFg2Zi9C\nL2l3dFdCbVA5TmduZTU1RW5LRHR3V1k3T201My9KM21iMXNrNwpJb2FuYzdMaHN2clozRWgwV3dU\nMi9XK3lEVkFZbVVLTHd6bVQ5aUtPbm1FUWdMWE1GbmRjMERrQTIwRjVCZWhVCmNwUnI1WmFhaUZq\nWDZiRU1adHFURVo4dUZFSmorcElCUlExYUlybHZiMlo2bjZsV3NrekcwRlp1cFRUeUluZVYKT1pO\nUEhMRDhZY2Fvc1J3czBrTG03VGcyMXYyNnRvMD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=" + "key": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRREJnK2VuSnRsTkUxMTgKR0tFWGFpM1A0UW5uNnZGMG1vZ3pHOWNrZWEyQTBTYlVmeDBKMFF3TWptaGE0Z3pmNkp3bnkyRDBBSDBVUjgrYwozS0g0ZGJmVnJKL0Uzcjk5ZjZuQmlZaHlxN3hGSzlQQ1BnK05LTEdZZHBzMGhLd0FOelhGOW16dGl3NmZ2d3RBCi9IMy9vV2tlMktTQkdQL2R0NmlSQk92WmQrR0cwMVRDWDZRTmM1OTVVMEc0SEE2R1l1K09lbDVvR3NVOFYxTTIKV2tVcWlTVnRuQjJWM1NJdDRyNERSVXBMYmZqeEFON2hMTGZYQUxraTN5WDZmUXJDUG9iaXJmSFAzU2cvaklweApQMVZMK281Q250b2ZCYmNnOGVlVWsxOTdpQlVzMUxOUEc4dXU2d3B6R254UzJ6eC9lWGtFY21TR256cFlPQTRDCnlOOEV2Sm1aQWdNQkFBRUNnZ0VBT3JOd2lkdlcvdkpvNFVQM1djcnpxcU54QmREVy9iQUNzTDQ1UE85TUdrOVgKb0E0UEdQTTQzSFkyWVp0QW5JdExFeWMyZWMzTUkyTEZMNmdkMmVpYm8wMkNDWTRvT0VHSmxSUExPRDJ3RnF0OAp5T2RhZ0U5ZjBBZnFmTHZpRVE2dVdTYXZWRDlpYUVMamZ3c1lqWHJCRUlKWEpISVk2NERTdVdyc3dFTUZQb2hGCm0vb1F1cmF5dzlqSkl2NzA2MUFQdFhJWHorNHB6OHY5VzNDdjVnK0ZoOVFIR3RwRnJEZG96dzdxV01QelNzdjgKMENibTIwUDhodndUYnhSc1NpT3RDYWlGN0xJdGZVS0k2UEVSVTdpWHF1RHFLQlZtbnBZbUhXYm5Ccnl1VjNDNQp2L1VvUm1EeVJjQ254dzdYZWhVMk90UEI0K014dVdWOWZOaVdnN3pRQVFLQmdRRGdVL3FtcFIrUmFyWm5jSVErCnN5NDBSeEYwbEhmTmZacjFvUmszZjdoSTJwc0h3bWRNTmZtZnNDN3p3bm1iQmlWU2F2VjllUVJ0MEtIdy81TUMKMXBWRHRDV3NnUW00TDYvS3dZa29LZWg3YXl1aEFXSDVxclNSZlVpeG1tcHo4VVJYUlNTSjNPbXFkYUpVdlhIOQpsNjFCanBSYS9qZW9ONlo1QUFBT1k4V3F3UUtCZ1FEYzFqMnQ2MFdQMDc1ZlZKSjB1bENCN2hIbC9TM1FVTDJqCmI4ZmNjTkw2ajVXbXJ4UEJmTDBRcEpRQWhOc1RQdE9mRGdRL0xsckR0ZzVOZFRMU1JFSFh4S2s5N1NuWGY5ZTUKZGVTYnRuNjJ6VDVwdWp1YkFLSndoVnA4cXNjSGVnRkFoamhDTDliUjhlVEVlK0ZpT3BCYjdhYmNueHNwZ1RXMApURjA0aExIYzJRS0JnQzRPTDhTczIvbFA3bGo0U2I1UnJTZkFlMzN5eVZIZitzTjVLcU14VHBWdWhDdW9wdXFICm5sTkJxYklUK0VGeWxwRUFNcHhyRHhTNG83YkYwZG5nVWs3UEduajdHUksrZjVuaCtCWE4zTlFSNGFneGozcmgKcUNiQ2tQMGRsY051QWpqa2tpYlh1d1ZyRjBQTWpTMmlTVWpQUy9nT2YwRERCQ09OYzNXQTJHRkJBb0dCQUprTAoxU1V5Tnp4TlI5TXpmbWh0TXh4SXpKaXlsTXlaR0VRclZMeWVhR2tEbDNnMFA2SEpmQklMclJLTEFIVGZCclJsCmQyWCtEeU14aWNuK25pRUE4d3pCRzNWeVpwd1Yyb0NLaHN1dmR6UGpIQTBUNXZrdVFHVncxZHd1VXM4SXE5TjIKOFloVk5UQzh6b21wUFBMaG1XaE1WR2J6MFZRN1d1ZkFRSjdKdjZaSkFvR0FQQVRKNHFjdnRiRzc5TkNFa0xRYgo0eUY5MGI4eW45YTZhbEpUVFkxVzU2TDY4SDl1U3lReTBVanpCaFl3by84ZU11WDI2anJ4MHIrOUQ1d0NIT0RiCi9MNnlkOFRPcmdmZU1wMGh4cGZET1JsRnFOdTFtUzIyZmxZVzZtRVJNRkhwYUd5WGErRDMzaTBQelV2WitkeUkKNnlZWlBCWCt5dTdVTzhiYzVPZGRESDQ9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K", + "crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURwakNDQW80Q0NRRElERFk4N1lDM2JEQU5CZ2txaGtpRzl3MEJBUXNGQURDQmt6RUxNQWtHQTFVRUJoTUMKVlZNeEN6QUpCZ05WQkFnTUFrTlBNUXd3Q2dZRFZRUUhEQU5FUlU0eER6QU5CZ05WQkFvTUJrRndZV05vWlRFTApNQWtHQTFVRUN3d0NWRU14TFRBckJnTlZCQU1NSkNvdWFIUjBjQzFoWkdScGRHbHZibUZzTG5Sb1pXTmtiaTVsCmVHRnRjR3hsTG1OdmJURWNNQm9HQ1NxR1NJYjNEUUVKQVJZTmRHTkFZWEJoWTJobExtOXlaekFnRncweE9UQXoKTVRneU1UQXpORFphR0E4eU1URTVNREl5TWpJeE1ETTBObG93Z1pNeEN6QUpCZ05WQkFZVEFsVlRNUXN3Q1FZRApWUVFJREFKRFR6RU1NQW9HQTFVRUJ3d0RSRVZPTVE4d0RRWURWUVFLREFaQmNHRmphR1V4Q3pBSkJnTlZCQXNNCkFsUkRNUzB3S3dZRFZRUUREQ1FxTG1oMGRIQXRZV1JrYVhScGIyNWhiQzUwYUdWalpHNHVaWGhoYlhCc1pTNWoKYjIweEhEQWFCZ2txaGtpRzl3MEJDUUVXRFhSalFHRndZV05vWlM1dmNtY3dnZ0VpTUEwR0NTcUdTSWIzRFFFQgpBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRREJnK2VuSnRsTkUxMThHS0VYYWkzUDRRbm42dkYwbW9nekc5Y2tlYTJBCjBTYlVmeDBKMFF3TWptaGE0Z3pmNkp3bnkyRDBBSDBVUjgrYzNLSDRkYmZWckovRTNyOTlmNm5CaVloeXE3eEYKSzlQQ1BnK05LTEdZZHBzMGhLd0FOelhGOW16dGl3NmZ2d3RBL0gzL29Xa2UyS1NCR1AvZHQ2aVJCT3ZaZCtHRwowMVRDWDZRTmM1OTVVMEc0SEE2R1l1K09lbDVvR3NVOFYxTTJXa1VxaVNWdG5CMlYzU0l0NHI0RFJVcExiZmp4CkFON2hMTGZYQUxraTN5WDZmUXJDUG9iaXJmSFAzU2cvaklweFAxVkwrbzVDbnRvZkJiY2c4ZWVVazE5N2lCVXMKMUxOUEc4dXU2d3B6R254UzJ6eC9lWGtFY21TR256cFlPQTRDeU44RXZKbVpBZ01CQUFFd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBTGFSZlc3WmVlMmlmT1RzdTFmYi8rSUcrYXh5emVwTm1QUkx5NDNHNkhwazdhN3Y2Y2pBCitXOW9Bc3psYURIam1UUEZ3OE10RVo2bFBGb1NzVFB5Y0dLMjR4d0tiRFA5NDZGcEV4eDRsaFBabFVOdUNrajYKS1pNS05GdjZFRkx6U0xBUUlZUGIzN1h2Qmw3M2FOM3ZMZEFESUZ4eGgvNVpUTUhBYzRoRlBIa1hWYWVNRjNpZAptT3p0bDZhMGtqaloyVEcrMkZNS3RCOFlEZFdidnRGVUFkL08rRVN3MVY2MTNOV3N3RUUvQS9lbHNNdnJaN1lZCnVhNlE5STJUa3RzQU1relQzSmY5KzNsdFc0RXZ0OS95VHYwZmFmL2RzN3NVR3ZXcnd1QU5ucEl1T2tKOW9JUDAKOFhURUwxTkE3NktlUFdTcDROWk9Yc3lnR05qbWtJNXNRZzQ9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" }, "hostname": "*.http-additional.thecdn.example.com" }