From d61972eb358c072b33c90ee878936e38fec25819 Mon Sep 17 00:00:00 2001 From: Paris Larkins Date: Thu, 19 Sep 2024 16:17:48 +1000 Subject: [PATCH 1/6] Add new settings plugins.security.ssl.http.enforce_cert_reload_dn_verification and plugins.security.ssl.transport.enforce_cert_reload_dn_verification, to control whether DN validation should be performed when hot reloading certificates Signed-off-by: Paris Larkins --- .../security/ssl/DefaultSecurityKeyStore.java | 28 +++- .../ssl/OpenSearchSecuritySSLPlugin.java | 17 +++ .../security/ssl/util/SSLConfigConstants.java | 5 +- .../SecuritySSLReloadCertsActionTests.java | 139 ++++++++++++++++-- src/test/resources/ssl/reload/README.txt | 29 ++++ .../resources/ssl/reload/node-new-ca.crt.pem | 82 +++++++++++ .../resources/ssl/reload/node-new-ca.key.pem | 28 ++++ .../ssl/reload/secondary-root-ca.pem | 29 ++++ .../ssl/reload/secondary-signing-ca.pem | 29 ++++ src/test/resources/ssl/reload/truststore.jks | Bin 1398 -> 4230 bytes 10 files changed, 366 insertions(+), 20 deletions(-) create mode 100644 src/test/resources/ssl/reload/README.txt create mode 100644 src/test/resources/ssl/reload/node-new-ca.crt.pem create mode 100644 src/test/resources/ssl/reload/node-new-ca.key.pem create mode 100644 src/test/resources/ssl/reload/secondary-root-ca.pem create mode 100644 src/test/resources/ssl/reload/secondary-signing-ca.pem diff --git a/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java b/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java index 9be2582b7f..ec1ce63f64 100644 --- a/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java +++ b/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java @@ -132,7 +132,9 @@ private void printJCEWarnings() { public final SslProvider sslTransportServerProvider; public final SslProvider sslTransportClientProvider; private final boolean httpSSLEnabled; + private final boolean httpSSLEnforceCertReloadDnVerification; private final boolean transportSSLEnabled; + private final boolean transportSSLEnforceCertReloadDnVerification; private ArrayList enabledHttpCiphersJDKProvider; private ArrayList enabledHttpCiphersOpenSSLProvider; @@ -165,10 +167,18 @@ public DefaultSecurityKeyStore(final Settings settings, final Path configPath) { SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_DEFAULT ); + httpSSLEnforceCertReloadDnVerification = settings.getAsBoolean( + SSLConfigConstants.SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION, + SSLConfigConstants.SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT + ); transportSSLEnabled = settings.getAsBoolean( SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_DEFAULT ); + transportSSLEnforceCertReloadDnVerification = settings.getAsBoolean( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION, + SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT + ); final boolean useOpenSSLForHttpIfAvailable = OpenSearchSecuritySSLPlugin.OPENSSL_SUPPORTED && settings.getAsBoolean(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, true); final boolean useOpenSSLForTransportIfAvailable = OpenSearchSecuritySSLPlugin.OPENSSL_SUPPORTED @@ -421,7 +431,7 @@ public void initTransportSSLConfig() { certFromTruststore = new CertFromTruststore(truststoreProps, truststoreAlias); } - validateNewCerts(transportCerts, certFromKeystore.getCerts()); + validateNewCerts(transportCerts, certFromKeystore.getCerts(), transportSSLEnforceCertReloadDnVerification); transportServerSslContext = buildSSLServerContext( certFromKeystore.getServerKey(), certFromKeystore.getServerCert(), @@ -472,7 +482,7 @@ public void initTransportSSLConfig() { certFromFile = new CertFromFile(certProps); } - validateNewCerts(transportCerts, certFromFile.getCerts()); + validateNewCerts(transportCerts, certFromFile.getCerts(), transportSSLEnforceCertReloadDnVerification); transportServerSslContext = buildSSLServerContext( certFromFile.getServerPemKey(), certFromFile.getServerPemCert(), @@ -570,7 +580,7 @@ public void initHttpSSLConfig() { certFromTruststore = new CertFromTruststore(truststoreProps, truststoreAlias); } - validateNewCerts(httpCerts, certFromKeystore.getCerts()); + validateNewCerts(httpCerts, certFromKeystore.getCerts(), httpSSLEnforceCertReloadDnVerification); httpSslContext = buildSSLServerContext( certFromKeystore.getServerKey(), certFromKeystore.getServerCert(), @@ -601,7 +611,7 @@ public void initHttpSSLConfig() { ); CertFromFile certFromFile = new CertFromFile(certFileProps); - validateNewCerts(httpCerts, certFromFile.getCerts()); + validateNewCerts(httpCerts, certFromFile.getCerts(), httpSSLEnforceCertReloadDnVerification); httpSslContext = buildSSLServerContext( certFromFile.getServerPemKey(), certFromFile.getServerPemCert(), @@ -632,11 +642,13 @@ public void initHttpSSLConfig() { * If the current and new certificates are same, skip remaining checks. * For new X509 cert to be valid Issuer, Subject DN must be the same and * new certificates should expire after current ones. - * @param currentX509Certs Array of current x509 certificates - * @param newX509Certs Array of x509 certificates which will replace our current cert + * + * @param currentX509Certs Array of current x509 certificates + * @param newX509Certs Array of x509 certificates which will replace our current cert + * @param verifyValidDNs Whether to verify that new certs have valid IssuerDN, SubjectDN and SAN * @throws Exception if certificate is invalid */ - private void validateNewCerts(final X509Certificate[] currentX509Certs, final X509Certificate[] newX509Certs) throws Exception { + private void validateNewCerts(final X509Certificate[] currentX509Certs, final X509Certificate[] newX509Certs, final boolean verifyValidDNs) throws Exception { // First time we init certs ignore validity check if (currentX509Certs == null) { @@ -653,7 +665,7 @@ private void validateNewCerts(final X509Certificate[] currentX509Certs, final X5 } // Check if new X509 certs have valid IssuerDN, SubjectDN or SAN - if (!hasValidDNs(currentX509Certs, newX509Certs)) { + if (verifyValidDNs && !hasValidDNs(currentX509Certs, newX509Certs)) { throw new Exception("New Certs do not have valid Issuer DN, Subject DN or SAN."); } } diff --git a/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java b/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java index e6a1b47888..86de1c7493 100644 --- a/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java +++ b/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java @@ -638,6 +638,23 @@ public List> getSettings() { Setting.longSetting(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_VALIDATION_DATE, -1, -1, Property.NodeScope, Property.Filtered) ); + settings.add( + Setting.boolSetting( + SSLConfigConstants.SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION, + SSLConfigConstants.SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT, + Property.NodeScope, + Property.Filtered + ) + ); + settings.add( + Setting.boolSetting( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION, + SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT, + Property.NodeScope, + Property.Filtered + ) + ); + return settings; } diff --git a/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java b/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java index a3b9348496..64b5d7a392 100644 --- a/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java +++ b/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java @@ -38,6 +38,8 @@ public final class SSLConfigConstants { public static final String SECURITY_SSL_HTTP_TRUSTSTORE_ALIAS = "plugins.security.ssl.http.truststore_alias"; public static final String SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH = "plugins.security.ssl.http.truststore_filepath"; public static final String SECURITY_SSL_HTTP_TRUSTSTORE_TYPE = "plugins.security.ssl.http.truststore_type"; + public static final String SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION = "plugins.security.ssl.http.enforce_cert_reload_dn_verification"; + public static final Boolean SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT = true; public static final String SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE = "plugins.security.ssl.transport.enable_openssl_if_available"; public static final String SECURITY_SSL_TRANSPORT_ENABLED = "plugins.security.ssl.transport.enabled"; @@ -46,7 +48,8 @@ public final class SSLConfigConstants { "plugins.security.ssl.transport.enforce_hostname_verification"; public static final String SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME = "plugins.security.ssl.transport.resolve_hostname"; - + public static final String SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION = "plugins.security.ssl.transport.enforce_cert_reload_dn_verification"; + public static final Boolean SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT = true; public static final String SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS = "plugins.security.ssl.transport.keystore_alias"; public static final String SECURITY_SSL_TRANSPORT_SERVER_KEYSTORE_ALIAS = "plugins.security.ssl.transport.server.keystore_alias"; public static final String SECURITY_SSL_TRANSPORT_CLIENT_KEYSTORE_ALIAS = "plugins.security.ssl.transport.client.keystore_alias"; diff --git a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java index 244967cf76..ef6f4dd294 100644 --- a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java +++ b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java @@ -77,6 +77,21 @@ public class SecuritySSLReloadCertsActionTests extends SingleClusterTest { ) ); + private final List> NEW_CA_NODE_CERT_DETAILS = List.of( + Map.of( + "issuer_dn", + "CN=Example Com Inc. Secondary Signing CA,OU=Example Com Inc. Secondary Signing CA,O=Example Com Inc.,DC=example,DC=com", + "subject_dn", + "CN=node-1.example.com,OU=SSL,O=Test,L=Test,C=DE", + "san", + "[[2, localhost], [2, node-1.example.com], [7, 127.0.0.1], [8, 1.2.3.4.5.5]]", + "not_before", + "2024-09-17T00:15:48Z", + "not_after", + "2034-09-15T00:15:48Z" + ) + ); + private String pemCertFilePath; private String pemKeyFilePath; private final String defaultCertFilePath = "ssl/reload/node.crt.pem"; @@ -186,6 +201,93 @@ public void testReloadHttpSSLSameCertsPass() throws Exception { assertReloadCertificateSuccess(rh, "http", getInitCertDetailsExpectedResponse()); } + + @Test + public void testReloadHttpCertDifferentTrustChain_skipDnValidationPass() throws Exception { + updateFiles(defaultCertFilePath, pemCertFilePath); + updateFiles(defaultKeyFilePath, pemKeyFilePath); + initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true, false, true); + + RestHelper rh = getRestHelperAdminUser(); + // Change http certs to one signed by a different CA than the previous one + updateFiles("ssl/reload/node-new-ca.crt.pem", pemCertFilePath); + updateFiles("ssl/reload/node-new-ca.key.pem", pemKeyFilePath); + + RestHelper.HttpResponse reloadCertsResponse = rh.executePutRequest(RELOAD_HTTP_CERTS_ENDPOINT, null); + + assertThat(reloadCertsResponse.getStatusCode(), is(200)); + final var expectedJsonResponse = DefaultObjectMapper.objectMapper.createObjectNode(); + expectedJsonResponse.put("message", "updated http certs"); + assertThat(reloadCertsResponse.getBody(), is(expectedJsonResponse.toString())); + + String certDetailsResponse = rh.executeSimpleRequest(GET_CERT_DETAILS_ENDPOINT); + assertThat(DefaultObjectMapper.readTree(certDetailsResponse), is(getNewCertAuthorityUpdatedCertDetailsExpectedResponse("http"))); + } + + @Test + public void testReloadHttpCertDifferentTrustChain_noSkipDnValidationFail() throws Exception { + updateFiles(defaultCertFilePath, pemCertFilePath); + updateFiles(defaultKeyFilePath, pemKeyFilePath); + initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true, true, true); + + RestHelper rh = getRestHelperAdminUser(); + // Change http certs to one signed by a different CA than the previous one + updateFiles("ssl/reload/node-new-ca.crt.pem", pemCertFilePath); + updateFiles("ssl/reload/node-new-ca.key.pem", pemKeyFilePath); + + RestHelper.HttpResponse reloadCertsResponse = rh.executePutRequest(RELOAD_HTTP_CERTS_ENDPOINT, null); + + assertThat(reloadCertsResponse.getStatusCode(), is(500)); + assertThat( + DefaultObjectMapper.readTree(reloadCertsResponse.getBody()).get("error").get("root_cause").get(0).get("reason").asText(), + is("OpenSearchSecurityException[Error while initializing http SSL layer from PEM: java.lang.Exception: " + + "New Certs do not have valid Issuer DN, Subject DN or SAN.]; nested: Exception[New Certs do not have valid Issuer DN, Subject DN or SAN.];") + ); + } + + @Test + public void testReloadTransportCertDifferentTrustChain_skipDnValidationPass() throws Exception { + updateFiles(defaultCertFilePath, pemCertFilePath); + updateFiles(defaultKeyFilePath, pemKeyFilePath); + initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true, true, false); + + RestHelper rh = getRestHelperAdminUser(); + // Change transport certs to one signed by a different CA than the previous one + updateFiles("ssl/reload/node-new-ca.crt.pem", pemCertFilePath); + updateFiles("ssl/reload/node-new-ca.key.pem", pemKeyFilePath); + + RestHelper.HttpResponse reloadCertsResponse = rh.executePutRequest(RELOAD_TRANSPORT_CERTS_ENDPOINT, null); + + assertThat(reloadCertsResponse.getStatusCode(), is(200)); + final var expectedJsonResponse = DefaultObjectMapper.objectMapper.createObjectNode(); + expectedJsonResponse.put("message", "updated transport certs"); + assertThat(reloadCertsResponse.getBody(), is(expectedJsonResponse.toString())); + + String certDetailsResponse = rh.executeSimpleRequest(GET_CERT_DETAILS_ENDPOINT); + assertThat(DefaultObjectMapper.readTree(certDetailsResponse), is(getNewCertAuthorityUpdatedCertDetailsExpectedResponse("transport"))); + } + + @Test + public void testReloadTransportCertDifferentTrustChain_noSkipDnValidationFail() throws Exception { + updateFiles(defaultCertFilePath, pemCertFilePath); + updateFiles(defaultKeyFilePath, pemKeyFilePath); + initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true, true, true); + + RestHelper rh = getRestHelperAdminUser(); + // Change transport certs to one signed by a different CA than the previous one + updateFiles("ssl/reload/node-new-ca.crt.pem", pemCertFilePath); + updateFiles("ssl/reload/node-new-ca.key.pem", pemKeyFilePath); + + RestHelper.HttpResponse reloadCertsResponse = rh.executePutRequest(RELOAD_TRANSPORT_CERTS_ENDPOINT, null); + + assertThat(reloadCertsResponse.getStatusCode(), is(500)); + assertThat( + DefaultObjectMapper.readTree(reloadCertsResponse.getBody()).get("error").get("root_cause").get(0).get("reason").asText(), + is("OpenSearchSecurityException[Error while initializing transport SSL layer from PEM: java.lang.Exception: " + + "New Certs do not have valid Issuer DN, Subject DN or SAN.]; nested: Exception[New Certs do not have valid Issuer DN, Subject DN or SAN.];") + ); + } + /** * * @param rh RestHelper to perform rest actions on the cluster @@ -211,6 +313,15 @@ private void updateFiles(String srcFile, String dstFile) { FileHelper.copyFileContents(FileHelper.getAbsoluteFilePathFromClassPath(srcFile).toString(), dstFile); } + private JsonNode getNewCertAuthorityUpdatedCertDetailsExpectedResponse(String updateChannel) { + String updateKey = (Objects.equals(updateChannel, "http")) ? HTTP_CERTIFICATES_LIST_KEY : TRANSPORT_CERTIFICATES_LIST_KEY; + String oldKey = (Objects.equals(updateChannel, "http")) ? TRANSPORT_CERTIFICATES_LIST_KEY : HTTP_CERTIFICATES_LIST_KEY; + final var updatedCertDetailsResponse = DefaultObjectMapper.objectMapper.createObjectNode(); + updatedCertDetailsResponse.set(updateKey, buildCertsInfoNode(NEW_CA_NODE_CERT_DETAILS)); + updatedCertDetailsResponse.set(oldKey, buildCertsInfoNode(NODE_CERT_DETAILS)); + return updatedCertDetailsResponse; + } + private JsonNode getUpdatedCertDetailsExpectedResponse(String updateChannel) { String updateKey = (Objects.equals(updateChannel, "http")) ? HTTP_CERTIFICATES_LIST_KEY : TRANSPORT_CERTIFICATES_LIST_KEY; String oldKey = (Objects.equals(updateChannel, "http")) ? TRANSPORT_CERTIFICATES_LIST_KEY : HTTP_CERTIFICATES_LIST_KEY; @@ -270,31 +381,37 @@ private RestHelper getRestHelperNonAdminUser() { private void initClusterWithTestCerts() throws Exception { updateFiles(defaultCertFilePath, pemCertFilePath); updateFiles(defaultKeyFilePath, pemKeyFilePath); - initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true); + initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true, true, true); } /** * Helper method to initialize test cluster for SSL Certificate Reload Tests - * @param transportPemCertFilePath Absolute Path to transport pem cert file - * @param transportPemKeyFilePath Absolute Path to transport pem key file - * @param httpPemCertFilePath Absolute Path to transport pem cert file - * @param httpPemKeyFilePath Absolute Path to transport pem key file - * @param sslCertReload Sets the ssl cert reload flag + * + * @param transportPemCertFilePath Absolute Path to transport pem cert file + * @param transportPemKeyFilePath Absolute Path to transport pem key file + * @param httpPemCertFilePath Absolute Path to transport pem cert file + * @param httpPemKeyFilePath Absolute Path to transport pem key file + * @param sslCertReload Sets the ssl cert reload flag + * @param httpEnforceReloadDnVerification */ private void initTestCluster( - final String transportPemCertFilePath, - final String transportPemKeyFilePath, - final String httpPemCertFilePath, - final String httpPemKeyFilePath, - final boolean sslCertReload + final String transportPemCertFilePath, + final String transportPemKeyFilePath, + final String httpPemCertFilePath, + final String httpPemKeyFilePath, + final boolean sslCertReload, + final boolean httpEnforceReloadDnVerification, + final boolean transportEnforceReloadDnVerification ) throws Exception { final Settings settings = Settings.builder() .putList(ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, "CN=kirk,OU=client,O=client,L=Test,C=DE") .putList(ConfigConstants.SECURITY_NODES_DN, "CN=node-1.example.com,OU=SSL,O=Test,L=Test,C=DE") .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION, httpEnforceReloadDnVerification) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION, transportEnforceReloadDnVerification) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, transportPemCertFilePath) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, transportPemKeyFilePath) .put( diff --git a/src/test/resources/ssl/reload/README.txt b/src/test/resources/ssl/reload/README.txt new file mode 100644 index 0000000000..a149c42284 --- /dev/null +++ b/src/test/resources/ssl/reload/README.txt @@ -0,0 +1,29 @@ +Commands to generate node-new-ca.crt.pem, node-new-ca.key.pem, secondary-root-ca.pem, secondary-signing-ca.pem: + +# generate new secondary root CA +openssl genrsa -out secondary-root-ca-key.pem 2048 +openssl req -new -x509 -sha256 -days 3650 -key secondary-root-ca-key.pem -subj "/DC=com/DC=example/O=Example Com Inc./OU=Example Com Inc. Secondary Root CA/CN=Example Com Inc. Secondary Root CA" -addext "basicConstraints = critical,CA:TRUE" -addext "keyUsage = critical, digitalSignature, keyCertSign, cRLSign" -addext "subjectKeyIdentifier = hash" -addext "authorityKeyIdentifier = keyid:always,issuer:always" -out secondary-root-ca.pem + +# generate new secondary signing CA, signed by the new secondary root CA + +openssl genrsa -out secondary-signing-ca-key-temp.pem 2048 +openssl pkcs8 -inform PEM -outform PEM -in secondary-signing-ca-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out secondary-signing-ca-key.pem +openssl req -new -key secondary-signing-ca-key.pem -subj "/DC=com/DC=example/O=Example Com Inc./OU=Example Com Inc. Secondary Signing CA/CN=Example Com Inc. Secondary Signing CA" -out secondary-signing-ca-key.csr +printf "basicConstraints = critical,CA:TRUE" > secondary-signing-ca_ext.conf +printf "basicConstraints = critical,CA:TRUE\nkeyUsage = critical, digitalSignature, keyCertSign, cRLSign\nsubjectKeyIdentifier = hash\nauthorityKeyIdentifier = keyid:always,issuer:always" > secondary-signing-ca_ext.conf +openssl x509 -req -in secondary-signing-ca-key.csr -out secondary-signing-ca.pem -CA secondary-root-ca.pem -CAkey secondary-root-ca-key.pem -CAcreateserial -days 3650 -extfile secondary-signing-ca_ext.conf + +# generate a new node cert, signed by the new secondary signing key CA +openssl genrsa -out node-new-ca-key-temp.pem 2048 +openssl pkcs8 -inform PEM -outform PEM -in node-new-ca-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out node-new-ca.key.pem +openssl req -new -key node-new-ca.key.pem -subj "/C=DE/L=Test/O=Test/OU=SSL/CN=node-1.example.com" -out node-new-ca.csr +printf "subjectAltName = RID:1.2.3.4.5.5, DNS:node-1.example.com, DNS:localhost, IP:127.0.0.1" > node-new-ca_ext.conf +openssl x509 -req -in node-new-ca.csr -out node-new-ca.pem -CA secondary-signing-ca.pem -CAkey secondary-signing-ca-key.pem -CAcreateserial -days 3650 -extfile node-new-ca_ext.conf + +cat node-new-ca.pem > node-new-ca.crt.pem +cat secondary-signing-ca.pem >> node-new-ca.crt.pem +cat secondary-root-ca.pem >> node-new-ca.crt.pem + +# for tests to pass, the new secondary-signing-ca.pem and secondary-root-ca.pem keys should also be added to the truststore.jks file, e.g.: +keytool -import -alias secondary-root-ca -file secondary-root-ca.pem -storetype JKS -keystore truststore.jks +keytool -import -alias secondary-signing-ca -file secondary-signing-ca.pem -storetype JKS -keystore truststore.jks diff --git a/src/test/resources/ssl/reload/node-new-ca.crt.pem b/src/test/resources/ssl/reload/node-new-ca.crt.pem new file mode 100644 index 0000000000..2bf9284f09 --- /dev/null +++ b/src/test/resources/ssl/reload/node-new-ca.crt.pem @@ -0,0 +1,82 @@ +-----BEGIN CERTIFICATE----- +MIIEBzCCAu+gAwIBAgIUUN4lYU0yobNFo1xcluReeadmlaUwDQYJKoZIhvcNAQEL +BQAwgakxEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMS4wLAYDVQQLDCVFeGFtcGxl +IENvbSBJbmMuIFNlY29uZGFyeSBTaWduaW5nIENBMS4wLAYDVQQDDCVFeGFtcGxl +IENvbSBJbmMuIFNlY29uZGFyeSBTaWduaW5nIENBMB4XDTI0MDkxNzAwMTU0OFoX +DTM0MDkxNTAwMTU0OFowVjELMAkGA1UEBhMCREUxDTALBgNVBAcMBFRlc3QxDTAL +BgNVBAoMBFRlc3QxDDAKBgNVBAsMA1NTTDEbMBkGA1UEAwwSbm9kZS0xLmV4YW1w +bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtJG372aVfTYZ +tQ6udEQzC9RNy8+SqBZEproPBdYupOZ2l0tKgGykoAI0iX/p3gzQlYBSmSVduKLZ +n5E/nQCb+Rqbi1uoZrojEQxq538RXWmI9X72MyKFnqcgjZW9qCBn0ok5J0fSp7kS +55I6IzJhrJFqJKdn/i1dTReyg0tjSa/dR2yHbFj97gdXAnnte7xa87ounKZoFtme +rhhfVfbnkxQfSFecg0AltBiuhB9TxovRTo1TOVPpAUhBFBaj4ILSyGJdG9qQ11OM +L+QUd6TjQB0qFSVaf/BGu/0Umz1lp1OrrQkouaTQfuQ+3tOY3hwCM4PdL03YbBYX +r/H7EmhJ2QIDAQABo3kwdzA1BgNVHREELjAsiAUqAwQFBYISbm9kZS0xLmV4YW1w +bGUuY29tgglsb2NhbGhvc3SHBH8AAAEwHQYDVR0OBBYEFCBH9UyAoNd2nq/4PHuP +6XqCvcMnMB8GA1UdIwQYMBaAFFLGvw6mimoIfjgzjHjhUfVNAeAIMA0GCSqGSIb3 +DQEBCwUAA4IBAQAOhTfnE+uTD0PQy+/HT2uQKRMsn+f6CeiHTgTWkA7+XXECXyBI +B8cGnXEqNRg7gInrnYpsNv19Q5v4fghMG+5mTO0iDhSCL3ttXVy3J7yvb9IWgc12 +34YC7BeTe8DB+vATTnxEibOqXX8YhB/n9pB/xoqs7XUTVTP56QYcMZZvjzdIJhp9 +kpydel7TIDqJmG7HPkjVn0caxdsGFaBF5XmI4o73xlJVEZrN5OMy9yao6kXrNiqD +GPRg6y3KTtrGXNImTs9+iJhLfBtT3i8/UU7T8vC9yfU6JDC6CWDRIwHNtIBY2Yp+ +cLMxoh/SZHFqLPguzH2RWmwa7mgEOet1RYVe +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFCDCCA/CgAwIBAgIUfUpmQ/BPCGTsPLW7rrPbkEU1RcwwDQYJKoZIhvcNAQEL +BQAwgaMxEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSswKQYDVQQLDCJFeGFtcGxl +IENvbSBJbmMuIFNlY29uZGFyeSBSb290IENBMSswKQYDVQQDDCJFeGFtcGxlIENv +bSBJbmMuIFNlY29uZGFyeSBSb290IENBMB4XDTI0MDkxNzAwMTU0OFoXDTM0MDkx +NTAwMTU0OFowgakxEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZ +FgdleGFtcGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMS4wLAYDVQQLDCVF +eGFtcGxlIENvbSBJbmMuIFNlY29uZGFyeSBTaWduaW5nIENBMS4wLAYDVQQDDCVF +eGFtcGxlIENvbSBJbmMuIFNlY29uZGFyeSBTaWduaW5nIENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjUd34V1uf+OwGXIBce+4O/UX35yCxY0LHt48 +wNIGkEs3StbTG5/qjkeAIFr2EUpRX5c0n5sIWdJX1cV/drWrhUzy6Ya1jvQiTA+i +k4YVVkFsz9QajgP+UPS06ZLkFldBofd/Su4GW5YEBlOBfxbsr8+E+73M/8sU1/wD +QLwPZGrkN7Cc37qi0Sf3blCNsjwfZPrGm+J/4hxdlJKuimo3Ctfwtlv/cIJZv7aG +RPksgsiirrk//nrW24wCQjqernuRayT0+2KL7OIn7UH2XL4nUUKU4cHYJOeiTNz+ +ds/uP1FG5WAvQ7CEyh6z2aXxGhZ89ZquATFy2paLpqfWgARiiwIDAQABo4IBKjCC +ASYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFFLG +vw6mimoIfjgzjHjhUfVNAeAIMIHjBgNVHSMEgdswgdiAFLmdh4hHmYd6TqjvfdgK +1x/HzhmeoYGppIGmMIGjMRMwEQYKCZImiZPyLGQBGRYDY29tMRcwFQYKCZImiZPy +LGQBGRYHZXhhbXBsZTEZMBcGA1UECgwQRXhhbXBsZSBDb20gSW5jLjErMCkGA1UE +CwwiRXhhbXBsZSBDb20gSW5jLiBTZWNvbmRhcnkgUm9vdCBDQTErMCkGA1UEAwwi +RXhhbXBsZSBDb20gSW5jLiBTZWNvbmRhcnkgUm9vdCBDQYIULRaaYWRGTgsg6K21 +3Aw9UyZJF+8wDQYJKoZIhvcNAQELBQADggEBAJo5QHvLgfH3VVJlNwFrGdNH1dCh +/mqPpqhjHCG8OUl2H8+dFsu/WfY7k/tcrMHCJHSVMbBiPxKM1MlR2aSIrGW7SNVZ +mrk0QfBHvhKdXOnUcPjp6CL7BAwgrKT9h0/v5ky/GutAL0L7N1Enntw+WWdI0SAn +JIaCzEN4s3VniDSyULZ7J3E4z7wmeLhzHf1ugyEoPOehP1RZzVJDLExZ30dXDUlG +qUQaUkBAjclD4i5vybF+CGGhCzIi0UTb+VmHNfi3yqYwltYGJzELvYw3ce/cVkSm +B4Qqx0niiFQfguX6MduWB067IXDLKu51ovnA+h72FKd7iZSrKg+qCEy0eYA= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFAjCCA+qgAwIBAgIULRaaYWRGTgsg6K213Aw9UyZJF+8wDQYJKoZIhvcNAQEL +BQAwgaMxEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSswKQYDVQQLDCJFeGFtcGxl +IENvbSBJbmMuIFNlY29uZGFyeSBSb290IENBMSswKQYDVQQDDCJFeGFtcGxlIENv +bSBJbmMuIFNlY29uZGFyeSBSb290IENBMB4XDTI0MDkxNzAwMTU0OFoXDTM0MDkx +NTAwMTU0OFowgaMxEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZ +FgdleGFtcGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSswKQYDVQQLDCJF +eGFtcGxlIENvbSBJbmMuIFNlY29uZGFyeSBSb290IENBMSswKQYDVQQDDCJFeGFt +cGxlIENvbSBJbmMuIFNlY29uZGFyeSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAqRYm2F+Ejfg3Vqmld+dXzIThERJuzyqpq7FUNegfAebM +e7aelHiAMSecYroxj990HdCp1yDhryRxzdGHkPK7VHzH695th8N1su7wO37cspjX +ZxMexiZuwV1t/N8khi20MItqa6sYY4gkBLoGiT5DdJNTJHv3Ammx+PmYHIRF0S1P +P1j2nd+Kxaj1Il4sInUo7BqbmO794QdICgJQ5XFeXmEV+4uhoPSHEoOfAlWUTKA9 +a9rugrY0k3JlUTF0tIPLEWOcMxEcQj6uYFehxakwiOnZwgkJMCSbhsoEBzq+i7Eb +2Wob7d2Gn0De3Z+ZruVIJzY0MpHWrDUyny/Qi17nDwIDAQABo4IBKjCCASYwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFLmdh4hHmYd6 +TqjvfdgK1x/HzhmeMIHjBgNVHSMEgdswgdiAFLmdh4hHmYd6TqjvfdgK1x/Hzhme +oYGppIGmMIGjMRMwEQYKCZImiZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYH +ZXhhbXBsZTEZMBcGA1UECgwQRXhhbXBsZSBDb20gSW5jLjErMCkGA1UECwwiRXhh +bXBsZSBDb20gSW5jLiBTZWNvbmRhcnkgUm9vdCBDQTErMCkGA1UEAwwiRXhhbXBs +ZSBDb20gSW5jLiBTZWNvbmRhcnkgUm9vdCBDQYIULRaaYWRGTgsg6K213Aw9UyZJ +F+8wDQYJKoZIhvcNAQELBQADggEBAI6PJGGXH2fIlrZQFZXkuLqjMrR8K+/60cq0 +4qqjTg8p+vQyB66BJSh4BiUM2sh7SwGKpehNB8QQXEZoyzpWY+Cdcm4ty4F430xS +uz/uW0NObhnJnyURlHf1szHTr91/1yX7eCtpUA1X9cjtXYS/uR911BCotdgmp3N9 +lHp+DjMx3j/xsGAuC1B2vmuLaMXA8SeYziDx+9KUHidMM7v/JsDZwc8XKCK+i12s +yIAv7Tuk5drq3x7ZCA3k9Xja/YqpaPNSP6iVsdM57NLPfZA9ilNuSMD49No6q9wW +dJ7sJEGDdICEBTuL9bCnwv/PZQ8ohJMJ+7Ike8f6tz8TsH3C+fg= +-----END CERTIFICATE----- diff --git a/src/test/resources/ssl/reload/node-new-ca.key.pem b/src/test/resources/ssl/reload/node-new-ca.key.pem new file mode 100644 index 0000000000..1fa12aa5e5 --- /dev/null +++ b/src/test/resources/ssl/reload/node-new-ca.key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC0kbfvZpV9Nhm1 +Dq50RDML1E3Lz5KoFkSmug8F1i6k5naXS0qAbKSgAjSJf+neDNCVgFKZJV24otmf +kT+dAJv5GpuLW6hmuiMRDGrnfxFdaYj1fvYzIoWepyCNlb2oIGfSiTknR9KnuRLn +kjojMmGskWokp2f+LV1NF7KDS2NJr91HbIdsWP3uB1cCee17vFrzui6cpmgW2Z6u +GF9V9ueTFB9IV5yDQCW0GK6EH1PGi9FOjVM5U+kBSEEUFqPggtLIYl0b2pDXU4wv +5BR3pONAHSoVJVp/8Ea7/RSbPWWnU6utCSi5pNB+5D7e05jeHAIzg90vTdhsFhev +8fsSaEnZAgMBAAECggEABVlpxwxVcmOnaE86iNQ6ZOfRtC9+iz85omzRpB0fvZ/c +NIg0+U/+ooTeNJKXBY6AoWUvTT0npSAh7VG6vjZ16G/K2tqIxx5NiqRBCIGhrJBD +T+6GcaZcqgIOe1NLzo7DNJ//EvRUP8bCUhzpXwCPlzKpn9Nbx9JlOLLyhWQ22Uhx +NQVIOd3qvhAvU/LF03fMPAqxeHXD0KOQNNxNPqwTWW1rRi6bzvMud0icQhDjTVBf +gUhowZFdDnt3NIiMmh997Fnjbx2J5BTJ/tWnyG4pVO8d4JX5RDcZOx+MFBO9ypQ/ +FqhGu+J3xjMzSP+Y7kKHI60KBMCRnz2hEUP2IN+xxwKBgQDkiBtpJkRshaP27Bbw +xpuSvsKRAYdMDSlfReKQHEs3hJ0w3wFT0ofgMS49PyzHu0TyQ39jNAJ3YkdpRpIC +nI9fcDV4xS6G5kz72U4yamm1RF7TdMoU1WWMqmtm7i9Cdjrd7z/WGnBUH2pmenJ7 +IDoeALme+GxNwyakaSKaemOlGwKBgQDKRc/uln6AIxtlWBqgo8XGLyzReK0EYdnN +jwp7CcOuza//q9/P1fh/NA4rj0uiPD0SYX92DmaGRuuF/FwQ7OnAw9x81JlQeBbW +iSH3IzFSXP6kuY+SpUkRuWLXuNByIbsICOWN761PyIDV7TJAG/e6G/SLHUoOA6+G +aOQopG+gGwKBgDdmIzbvNuET2HaQLtN5YddF9QaP10uBWUkmOND0eutfc3eYZ8r5 +G0Umxu3D9cgJRqJv6F6VChAEvAjyOYz2hO7+1YeMTUYYaAsZV5JzJ2Lwywf5pM8+ +F9rsqRKPpNc4r/aC+/eb+yT5ZKKpBj2Ax3XkeRrnX+HN7/0lG2VVS/iHAoGAFAvN +KqkRimNwUJ/lq6vvas+8ElpyUy/bZQrbEAyMryNFYQJIoRFkmj6vdNOzvDVaHBs7 +hZixwnb+2n2DJk5EcE046cosE5SDNunKSvLa7X234t1dBDyLPE1yJUz0o4sCPS6c +iW+KbpDBa/Ig+8eJypEAsFTLxQ3KdHiqu/hn86cCgYBygyypD9R11k8X46ayXFcV +C+bpC4GsRliRvA0smFIAC75urzngLYyyP2ueonusE0cNYARlcbV3FcLDLuvEGoJL +enlYi4k9F+nCZaQ2ylWl2H6ud0/kCnIfjv+4Knf15Wz58VkH09AvbmqJNyd6kB0e +19JMEgOOugnWgfUNsBipfQ== +-----END PRIVATE KEY----- diff --git a/src/test/resources/ssl/reload/secondary-root-ca.pem b/src/test/resources/ssl/reload/secondary-root-ca.pem new file mode 100644 index 0000000000..81d8309898 --- /dev/null +++ b/src/test/resources/ssl/reload/secondary-root-ca.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFAjCCA+qgAwIBAgIULRaaYWRGTgsg6K213Aw9UyZJF+8wDQYJKoZIhvcNAQEL +BQAwgaMxEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSswKQYDVQQLDCJFeGFtcGxl +IENvbSBJbmMuIFNlY29uZGFyeSBSb290IENBMSswKQYDVQQDDCJFeGFtcGxlIENv +bSBJbmMuIFNlY29uZGFyeSBSb290IENBMB4XDTI0MDkxNzAwMTU0OFoXDTM0MDkx +NTAwMTU0OFowgaMxEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZ +FgdleGFtcGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSswKQYDVQQLDCJF +eGFtcGxlIENvbSBJbmMuIFNlY29uZGFyeSBSb290IENBMSswKQYDVQQDDCJFeGFt +cGxlIENvbSBJbmMuIFNlY29uZGFyeSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAqRYm2F+Ejfg3Vqmld+dXzIThERJuzyqpq7FUNegfAebM +e7aelHiAMSecYroxj990HdCp1yDhryRxzdGHkPK7VHzH695th8N1su7wO37cspjX +ZxMexiZuwV1t/N8khi20MItqa6sYY4gkBLoGiT5DdJNTJHv3Ammx+PmYHIRF0S1P +P1j2nd+Kxaj1Il4sInUo7BqbmO794QdICgJQ5XFeXmEV+4uhoPSHEoOfAlWUTKA9 +a9rugrY0k3JlUTF0tIPLEWOcMxEcQj6uYFehxakwiOnZwgkJMCSbhsoEBzq+i7Eb +2Wob7d2Gn0De3Z+ZruVIJzY0MpHWrDUyny/Qi17nDwIDAQABo4IBKjCCASYwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFLmdh4hHmYd6 +TqjvfdgK1x/HzhmeMIHjBgNVHSMEgdswgdiAFLmdh4hHmYd6TqjvfdgK1x/Hzhme +oYGppIGmMIGjMRMwEQYKCZImiZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYH +ZXhhbXBsZTEZMBcGA1UECgwQRXhhbXBsZSBDb20gSW5jLjErMCkGA1UECwwiRXhh +bXBsZSBDb20gSW5jLiBTZWNvbmRhcnkgUm9vdCBDQTErMCkGA1UEAwwiRXhhbXBs +ZSBDb20gSW5jLiBTZWNvbmRhcnkgUm9vdCBDQYIULRaaYWRGTgsg6K213Aw9UyZJ +F+8wDQYJKoZIhvcNAQELBQADggEBAI6PJGGXH2fIlrZQFZXkuLqjMrR8K+/60cq0 +4qqjTg8p+vQyB66BJSh4BiUM2sh7SwGKpehNB8QQXEZoyzpWY+Cdcm4ty4F430xS +uz/uW0NObhnJnyURlHf1szHTr91/1yX7eCtpUA1X9cjtXYS/uR911BCotdgmp3N9 +lHp+DjMx3j/xsGAuC1B2vmuLaMXA8SeYziDx+9KUHidMM7v/JsDZwc8XKCK+i12s +yIAv7Tuk5drq3x7ZCA3k9Xja/YqpaPNSP6iVsdM57NLPfZA9ilNuSMD49No6q9wW +dJ7sJEGDdICEBTuL9bCnwv/PZQ8ohJMJ+7Ike8f6tz8TsH3C+fg= +-----END CERTIFICATE----- diff --git a/src/test/resources/ssl/reload/secondary-signing-ca.pem b/src/test/resources/ssl/reload/secondary-signing-ca.pem new file mode 100644 index 0000000000..53f989d0b3 --- /dev/null +++ b/src/test/resources/ssl/reload/secondary-signing-ca.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFCDCCA/CgAwIBAgIUfUpmQ/BPCGTsPLW7rrPbkEU1RcwwDQYJKoZIhvcNAQEL +BQAwgaMxEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSswKQYDVQQLDCJFeGFtcGxl +IENvbSBJbmMuIFNlY29uZGFyeSBSb290IENBMSswKQYDVQQDDCJFeGFtcGxlIENv +bSBJbmMuIFNlY29uZGFyeSBSb290IENBMB4XDTI0MDkxNzAwMTU0OFoXDTM0MDkx +NTAwMTU0OFowgakxEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZ +FgdleGFtcGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMS4wLAYDVQQLDCVF +eGFtcGxlIENvbSBJbmMuIFNlY29uZGFyeSBTaWduaW5nIENBMS4wLAYDVQQDDCVF +eGFtcGxlIENvbSBJbmMuIFNlY29uZGFyeSBTaWduaW5nIENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjUd34V1uf+OwGXIBce+4O/UX35yCxY0LHt48 +wNIGkEs3StbTG5/qjkeAIFr2EUpRX5c0n5sIWdJX1cV/drWrhUzy6Ya1jvQiTA+i +k4YVVkFsz9QajgP+UPS06ZLkFldBofd/Su4GW5YEBlOBfxbsr8+E+73M/8sU1/wD +QLwPZGrkN7Cc37qi0Sf3blCNsjwfZPrGm+J/4hxdlJKuimo3Ctfwtlv/cIJZv7aG +RPksgsiirrk//nrW24wCQjqernuRayT0+2KL7OIn7UH2XL4nUUKU4cHYJOeiTNz+ +ds/uP1FG5WAvQ7CEyh6z2aXxGhZ89ZquATFy2paLpqfWgARiiwIDAQABo4IBKjCC +ASYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFFLG +vw6mimoIfjgzjHjhUfVNAeAIMIHjBgNVHSMEgdswgdiAFLmdh4hHmYd6TqjvfdgK +1x/HzhmeoYGppIGmMIGjMRMwEQYKCZImiZPyLGQBGRYDY29tMRcwFQYKCZImiZPy +LGQBGRYHZXhhbXBsZTEZMBcGA1UECgwQRXhhbXBsZSBDb20gSW5jLjErMCkGA1UE +CwwiRXhhbXBsZSBDb20gSW5jLiBTZWNvbmRhcnkgUm9vdCBDQTErMCkGA1UEAwwi +RXhhbXBsZSBDb20gSW5jLiBTZWNvbmRhcnkgUm9vdCBDQYIULRaaYWRGTgsg6K21 +3Aw9UyZJF+8wDQYJKoZIhvcNAQELBQADggEBAJo5QHvLgfH3VVJlNwFrGdNH1dCh +/mqPpqhjHCG8OUl2H8+dFsu/WfY7k/tcrMHCJHSVMbBiPxKM1MlR2aSIrGW7SNVZ +mrk0QfBHvhKdXOnUcPjp6CL7BAwgrKT9h0/v5ky/GutAL0L7N1Enntw+WWdI0SAn +JIaCzEN4s3VniDSyULZ7J3E4z7wmeLhzHf1ugyEoPOehP1RZzVJDLExZ30dXDUlG +qUQaUkBAjclD4i5vybF+CGGhCzIi0UTb+VmHNfi3yqYwltYGJzELvYw3ce/cVkSm +B4Qqx0niiFQfguX6MduWB067IXDLKu51ovnA+h72FKd7iZSrKg+qCEy0eYA= +-----END CERTIFICATE----- diff --git a/src/test/resources/ssl/reload/truststore.jks b/src/test/resources/ssl/reload/truststore.jks index c750f9807aa22339c19d05e510990a57ceef4758..217c4d09b4f5b162bf6ede35fb2fd19594d7643b 100644 GIT binary patch delta 4196 zcmV-q5S#Dz3Wgy-FoF<*0s#Xsf)FeQ2`Yw2hW8Bt2LYgh5FG@95E(Fn5EU?j5D^9m zDuzgg_YDCD2B3lv0x*IP{sI92FoF;Fkw7aH3y2teV%KE-MHD{guQeLr8q(9yk$)tA zFM<4bb*1t?DM&>|2%CerL^6{oqhGZlovK>+EUsZblPP^hD~L%q zxW~7Pddh0Quz8MtIjhRlcHKX!)?~_n9VJ04tbRUiid|(je>zqAnluKlCsI%Q{d3+9Z|8OGY3x7y zE<%>#Q(8y4VXvO3xvRq5;)Gs5s5vxA$NYR{X7piJUYrJl>2Cc8_;Y`3exC-y%I1fu z|NEzt!9|78QrN}*5I9V@zo`9xF>?D|Jw)0&wUcAKd~)7nqACu2VfqH|Qlk?ksH9rv*UjIeMYJ!$5891rewLTb^}}Hu$h0 zPAh=ST!yzDAX#n?{32YgS;v4MGNIIf>Vj^#dL!B6y+^!%2J#D}cC_B(eRMjy?I&d6 zQ#XARl>73#`fz&sK||&YdDz9(H!CH=%_W2#z!a7c=F56HHo{>$QC~GGj$iaMdHlsW zq`O;q4zH)#*rSu-oRiL$Wy#A4oFd%mrPW1m?d-Wym>G{@7;_kdcGorAAkif=MGJBGbYSSH$%cSDZ7oW200}*ovw67d9V`cS($YR2iLE%&gL>%oKJg#!cNpcVYle zlLvfIG|VSIadx&k+Kq?z67}{awDo+EaOsa?eBNKg6T-viRPWK>|4Hi+a;Yg?m+}J$=Fb^DN=&hCpJAnnCB?TEGC%gWEy-nOm-EO%uAZe$+^1?b zE`fp{%v5&q$%gyd2_457A=xVl@+ylDQb`!N3RjjT{S6}iVxQc-oNY)em5Pp0nlc?`;`TZyx&?>rr%QZw_H4}BJkMLEwq{J@o=7vTZb3ho!V&I}9gOG){N##Qc+ z%25D(;BXxH<9YB`$+5V&SMVskNkbp5f?NG zqh9mr7%6)TSL!WR-t#m>3=BwjgEby$Ig0iu7{qR$xJyM60oGycF#dSI9qVSj27@udR)=?(~`0@$pGegMv2Ow?3NU) zJ$aSmId9+@mCM0n7 zctJ!HpH6eG0>f;6ENJ@TF`9)h%uOQ>E&9vHVKamsG942JJ%T`$grWT~KJlB_4;8~Hen_?Bp*W(Eo`+JqajMOOrZ$4FO}459xo zIQny(s>$7dorWQ=|0GyXEx3+@tN$FI!=9rC@>H%mwt7Kg!S+Hy9T$r@K;c51wS&z} zibe4eBh&$i{Dl%E3CywYySs&vNSY5{A-Ar|t(+Slb(GM{CHtbuS;u*ShlO{)+z3T) z@aR7ZjG@leT+)MEy}dhWTy=n~xAls{>kaaW(X4HMhUWSh!PK3D__)v3DPR^PLZ_$m zCn9yZnEpoS4(xcBL;Sdt7%5Gxmwx2H2vU!|9(OD`;Bg8aqk$=2h2AV9@=2qirW`=o zS!qSbf_NcqscGAXzCLi~g8oZlXkyszsc7Hoz*)X&(oa!9EJxH`Em+EGfgSLqB6$63 zHwZg_uGcd}(^GsPeLrYC^SL-@gD(%g6*1p>UWfm~(rQfn3LYr>UI4%SSXXv~d0kpZ z&_Kk&Aj<(j#grr>%fm~cblR(U9wZax)d{<^;K-t)!!2f3h0Ff<;GiK+0W%G&+nz!C zWsk0i`jMm87>Q%b#5P^Cn@{KIiGytCug1=Q$+@X;sai!*QJO`Wbs}E}y}yvUhkpK; zAN%~N)SIFSg;tGHUB%I+(PIS)f$fPcNSQvT84MFe3~a_XT7^i48zg5$P)*vc%+&R= zf}6Ppzz6fRY`+pOjSBLSASTqG!b5)9{F=T}mv!~#v5_9?q6P+^Ph7m}RSKUyxhc$l z?}K!eD1B}9MkH>@jmYHp6Ucvoe^>64>kXNL=Ab~*zmSciqDuk45NwHOqpBT3P+WW+ z?+?pvP`gx-YXI|D*F23>;IEX8*ajn0|-pbN)#y9=d!=lE=2v`(1Zh9{;$(Qz`! zV1T;jS(7#KQRfG?<2{!`j4ZW{;F~&TB{RSr@}JtnV(Fhz*ujaIzDsP) z5JRm7`XP)5R@G^*t0Kr0omt;i5M0Gf{}oIn?=)H_YkS!2bH98s9EP#L3G+ch#guG4 z#CdcX(R31XC`=5qgf#z>ZT>5wAE@Pw^(g;|m z-88M6cJ5U)Bi~+>tGsIlg?xn6IU`U;ng0!KzNtfl_QDN`|6$*dLIsuAv{Nyw01(>n ziIV8_7bv{6)EkUku<>N$DlI;9z4y%-_&_3%2FBZh)UOvllP;gBjdA1Tm1q90w)k5e;_LW delta 1341 zcmV-D1;YAM1qCpI1px*L zDuzgg_YDCD2B3lj@-Tt~?g9Y-FoFcRae3egG^!`N|uiWS)NYr0K$2~!PvU^FxeAQr*)jTJ(#*e8yQ zdcgN_Ejb(F3;ReP4(W)YJ0@Andbbu39;Wvl3&}V3y>Ru8O*2*B5t|npn$-pwtvDDK z#nee&HaB;>dd6al&|l+*{rU^+1qrf22Pw@lw;tB<97!(Q)l*A`9evzu*HbU_zspJ|K6Grpsj3}c=pbJ8GXhugda6pwmX+^%yH(H;PEx#ae_nT6iteH|! zqP(-g3b;0PIVidgGdFRJ=MnhC&SmBa;DqpVHP4x}30bDu%Urtl`R2~uH7fCmKWmSh zH@qcMNG~GFvdzjgelvsYh)kJ((#z;r&_jR&+UL66E!L5NSR-J`JdK9Q|2dl>4AEWf z+69VFS)i4{?eB-Fy@-b6qf5$;5&iS88Rx=Mw6ac*hgaUJmLj&&G?Pb(s)6lrQ&wCX zb8o$m@gEHpW5-dC&DUAs3N#^}=^UZ^;6U&Ozi4`FAd|0qw$$vXIx*9K;C1)4sDW@4 zy^U)cDCczg=MYcVJ}nbB;+}UHnd^(>&HqByd8Cf@*+$)94c3cjRox1s{dILT==n1O z0yl?hu<8FDpV|`{T1;72`>#<8;BtCgncM>(J9mfRTwCl|pgx~{b&<=pRWbqcfibzk~3_+%DH#Ji1rLu6+N8Vk)0mm(;fbkb+V!5m`MJmV2d zu}&Ja%Dm^rgxZmXPj4qm_p=fC}7s;{??PX(k%9YpYSGAYgyel5=)xnW(zZa#~j zxFIn7)h150{p+gR<4fM1ta?K42VI3$_)lkIH1>Vitduu=o;V71SM^bK557wGkDZ6B zX@bUa_C2rs2FiSYio$o`Iw16uS;MC!Bfu-FGSSaJ1>2EmegJ#9T~L>tX&$Sa-6jM* zenjwtLnq|l7Xhg4J}X5p#*xWy9t~14JkZE)L5mKL4iJt#U;iVJMR9}D!D%(KO(s6P z-JNYM?L;b;*8{l%3cRo4y+}GFzyCj*-R}$LC9Q#PlS~tTX-j~+08esmOkFCVjf4j= z$;XoCTg!V`wl>gsIZXR&{m@;8n7JN3#=M=OsZP4%+grOum!AXs%2`Q)O-1klK+-XH zJ!T}tXb|IW_)Op)cW5GX@0W7C?UCy7+=C7GFKI~B%I!;A#jrdQb>PoIz1nyy_AQ1^ z?N{(iLBLF0rv!Yw^DQ?TKziP&yD&{KF)$4V31Egu0c8UO0s#d81R!5j#|R$F6Yf5- zUZVTP!BjaL^Nd Date: Tue, 24 Sep 2024 13:48:29 +1000 Subject: [PATCH 2/6] Revert some unintended whitespace changes, add some missing javadoc for new initTestCluster params Signed-off-by: Paris Larkins --- .../security/ssl/DefaultSecurityKeyStore.java | 1 - .../security/ssl/util/SSLConfigConstants.java | 1 + .../SecuritySSLReloadCertsActionTests.java | 28 +++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java b/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java index ec1ce63f64..6e8ba2a4bd 100644 --- a/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java +++ b/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java @@ -642,7 +642,6 @@ public void initHttpSSLConfig() { * If the current and new certificates are same, skip remaining checks. * For new X509 cert to be valid Issuer, Subject DN must be the same and * new certificates should expire after current ones. - * * @param currentX509Certs Array of current x509 certificates * @param newX509Certs Array of x509 certificates which will replace our current cert * @param verifyValidDNs Whether to verify that new certs have valid IssuerDN, SubjectDN and SAN diff --git a/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java b/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java index 64b5d7a392..ada61cbb30 100644 --- a/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java +++ b/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java @@ -48,6 +48,7 @@ public final class SSLConfigConstants { "plugins.security.ssl.transport.enforce_hostname_verification"; public static final String SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME = "plugins.security.ssl.transport.resolve_hostname"; + public static final String SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION = "plugins.security.ssl.transport.enforce_cert_reload_dn_verification"; public static final Boolean SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT = true; public static final String SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS = "plugins.security.ssl.transport.keystore_alias"; diff --git a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java index ef6f4dd294..13c70b8985 100644 --- a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java +++ b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java @@ -386,22 +386,22 @@ private void initClusterWithTestCerts() throws Exception { /** * Helper method to initialize test cluster for SSL Certificate Reload Tests - * - * @param transportPemCertFilePath Absolute Path to transport pem cert file - * @param transportPemKeyFilePath Absolute Path to transport pem key file - * @param httpPemCertFilePath Absolute Path to transport pem cert file - * @param httpPemKeyFilePath Absolute Path to transport pem key file - * @param sslCertReload Sets the ssl cert reload flag - * @param httpEnforceReloadDnVerification + * @param transportPemCertFilePath Absolute Path to transport pem cert file + * @param transportPemKeyFilePath Absolute Path to transport pem key file + * @param httpPemCertFilePath Absolute Path to transport pem cert file + * @param httpPemKeyFilePath Absolute Path to transport pem key file + * @param sslCertReload Sets the ssl cert reload flag + * @param httpEnforceReloadDnVerification Sets the http enforce reload dn verification flag + * @param transportEnforceReloadDnVerification Sets the transport enforce reload dn verification flag */ private void initTestCluster( - final String transportPemCertFilePath, - final String transportPemKeyFilePath, - final String httpPemCertFilePath, - final String httpPemKeyFilePath, - final boolean sslCertReload, - final boolean httpEnforceReloadDnVerification, - final boolean transportEnforceReloadDnVerification + final String transportPemCertFilePath, + final String transportPemKeyFilePath, + final String httpPemCertFilePath, + final String httpPemKeyFilePath, + final boolean sslCertReload, + final boolean httpEnforceReloadDnVerification, + final boolean transportEnforceReloadDnVerification ) throws Exception { final Settings settings = Settings.builder() .putList(ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, "CN=kirk,OU=client,O=client,L=Test,C=DE") From 18ded5c2bb7f8e6549b03302510d9fac268551a1 Mon Sep 17 00:00:00 2001 From: Paris Larkins Date: Thu, 26 Sep 2024 09:38:14 +1000 Subject: [PATCH 3/6] Apply Spotless formatting Signed-off-by: Paris Larkins --- .../security/ssl/DefaultSecurityKeyStore.java | 6 ++++- .../security/ssl/util/SSLConfigConstants.java | 6 +++-- .../SecuritySSLReloadCertsActionTests.java | 22 ++++++++++++------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java b/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java index 6e8ba2a4bd..95eb3a97db 100644 --- a/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java +++ b/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java @@ -647,7 +647,11 @@ public void initHttpSSLConfig() { * @param verifyValidDNs Whether to verify that new certs have valid IssuerDN, SubjectDN and SAN * @throws Exception if certificate is invalid */ - private void validateNewCerts(final X509Certificate[] currentX509Certs, final X509Certificate[] newX509Certs, final boolean verifyValidDNs) throws Exception { + private void validateNewCerts( + final X509Certificate[] currentX509Certs, + final X509Certificate[] newX509Certs, + final boolean verifyValidDNs + ) throws Exception { // First time we init certs ignore validity check if (currentX509Certs == null) { diff --git a/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java b/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java index ada61cbb30..0c09368c21 100644 --- a/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java +++ b/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java @@ -38,7 +38,8 @@ public final class SSLConfigConstants { public static final String SECURITY_SSL_HTTP_TRUSTSTORE_ALIAS = "plugins.security.ssl.http.truststore_alias"; public static final String SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH = "plugins.security.ssl.http.truststore_filepath"; public static final String SECURITY_SSL_HTTP_TRUSTSTORE_TYPE = "plugins.security.ssl.http.truststore_type"; - public static final String SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION = "plugins.security.ssl.http.enforce_cert_reload_dn_verification"; + public static final String SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION = + "plugins.security.ssl.http.enforce_cert_reload_dn_verification"; public static final Boolean SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT = true; public static final String SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE = "plugins.security.ssl.transport.enable_openssl_if_available"; @@ -49,7 +50,8 @@ public final class SSLConfigConstants { public static final String SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME = "plugins.security.ssl.transport.resolve_hostname"; - public static final String SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION = "plugins.security.ssl.transport.enforce_cert_reload_dn_verification"; + public static final String SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION = + "plugins.security.ssl.transport.enforce_cert_reload_dn_verification"; public static final Boolean SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT = true; public static final String SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS = "plugins.security.ssl.transport.keystore_alias"; public static final String SECURITY_SSL_TRANSPORT_SERVER_KEYSTORE_ALIAS = "plugins.security.ssl.transport.server.keystore_alias"; diff --git a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java index 13c70b8985..5f88d8ce16 100644 --- a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java +++ b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java @@ -201,7 +201,6 @@ public void testReloadHttpSSLSameCertsPass() throws Exception { assertReloadCertificateSuccess(rh, "http", getInitCertDetailsExpectedResponse()); } - @Test public void testReloadHttpCertDifferentTrustChain_skipDnValidationPass() throws Exception { updateFiles(defaultCertFilePath, pemCertFilePath); @@ -239,9 +238,11 @@ public void testReloadHttpCertDifferentTrustChain_noSkipDnValidationFail() throw assertThat(reloadCertsResponse.getStatusCode(), is(500)); assertThat( - DefaultObjectMapper.readTree(reloadCertsResponse.getBody()).get("error").get("root_cause").get(0).get("reason").asText(), - is("OpenSearchSecurityException[Error while initializing http SSL layer from PEM: java.lang.Exception: " - + "New Certs do not have valid Issuer DN, Subject DN or SAN.]; nested: Exception[New Certs do not have valid Issuer DN, Subject DN or SAN.];") + DefaultObjectMapper.readTree(reloadCertsResponse.getBody()).get("error").get("root_cause").get(0).get("reason").asText(), + is( + "OpenSearchSecurityException[Error while initializing http SSL layer from PEM: java.lang.Exception: " + + "New Certs do not have valid Issuer DN, Subject DN or SAN.]; nested: Exception[New Certs do not have valid Issuer DN, Subject DN or SAN.];" + ) ); } @@ -264,7 +265,10 @@ public void testReloadTransportCertDifferentTrustChain_skipDnValidationPass() th assertThat(reloadCertsResponse.getBody(), is(expectedJsonResponse.toString())); String certDetailsResponse = rh.executeSimpleRequest(GET_CERT_DETAILS_ENDPOINT); - assertThat(DefaultObjectMapper.readTree(certDetailsResponse), is(getNewCertAuthorityUpdatedCertDetailsExpectedResponse("transport"))); + assertThat( + DefaultObjectMapper.readTree(certDetailsResponse), + is(getNewCertAuthorityUpdatedCertDetailsExpectedResponse("transport")) + ); } @Test @@ -282,9 +286,11 @@ public void testReloadTransportCertDifferentTrustChain_noSkipDnValidationFail() assertThat(reloadCertsResponse.getStatusCode(), is(500)); assertThat( - DefaultObjectMapper.readTree(reloadCertsResponse.getBody()).get("error").get("root_cause").get(0).get("reason").asText(), - is("OpenSearchSecurityException[Error while initializing transport SSL layer from PEM: java.lang.Exception: " - + "New Certs do not have valid Issuer DN, Subject DN or SAN.]; nested: Exception[New Certs do not have valid Issuer DN, Subject DN or SAN.];") + DefaultObjectMapper.readTree(reloadCertsResponse.getBody()).get("error").get("root_cause").get(0).get("reason").asText(), + is( + "OpenSearchSecurityException[Error while initializing transport SSL layer from PEM: java.lang.Exception: " + + "New Certs do not have valid Issuer DN, Subject DN or SAN.]; nested: Exception[New Certs do not have valid Issuer DN, Subject DN or SAN.];" + ) ); } From 1841a593cdaa26b18b3854a1d85077212fef6839 Mon Sep 17 00:00:00 2001 From: Paris Larkins Date: Mon, 30 Sep 2024 09:38:25 +1000 Subject: [PATCH 4/6] Add tests to cover default behaviour of the new settings Signed-off-by: Paris Larkins --- .../SecuritySSLReloadCertsActionTests.java | 73 ++++++++++++++++--- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java index 5f88d8ce16..0f3773c15c 100644 --- a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java +++ b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java @@ -246,6 +246,29 @@ public void testReloadHttpCertDifferentTrustChain_noSkipDnValidationFail() throw ); } + @Test + public void testReloadHttpCertDifferentTrustChain_defaultSettingValidationFail() throws Exception { + updateFiles(defaultCertFilePath, pemCertFilePath); + updateFiles(defaultKeyFilePath, pemKeyFilePath); + initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true, null, true); + + RestHelper rh = getRestHelperAdminUser(); + // Change http certs to one signed by a different CA than the previous one + updateFiles("ssl/reload/node-new-ca.crt.pem", pemCertFilePath); + updateFiles("ssl/reload/node-new-ca.key.pem", pemKeyFilePath); + + RestHelper.HttpResponse reloadCertsResponse = rh.executePutRequest(RELOAD_HTTP_CERTS_ENDPOINT, null); + + assertThat(reloadCertsResponse.getStatusCode(), is(500)); + assertThat( + DefaultObjectMapper.readTree(reloadCertsResponse.getBody()).get("error").get("root_cause").get(0).get("reason").asText(), + is( + "OpenSearchSecurityException[Error while initializing http SSL layer from PEM: java.lang.Exception: " + + "New Certs do not have valid Issuer DN, Subject DN or SAN.]; nested: Exception[New Certs do not have valid Issuer DN, Subject DN or SAN.];" + ) + ); + } + @Test public void testReloadTransportCertDifferentTrustChain_skipDnValidationPass() throws Exception { updateFiles(defaultCertFilePath, pemCertFilePath); @@ -294,6 +317,29 @@ public void testReloadTransportCertDifferentTrustChain_noSkipDnValidationFail() ); } + @Test + public void testReloadTransportCertDifferentTrustChain_defaultSettingValidationFail() throws Exception { + updateFiles(defaultCertFilePath, pemCertFilePath); + updateFiles(defaultKeyFilePath, pemKeyFilePath); + initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true, true, null); + + RestHelper rh = getRestHelperAdminUser(); + // Change transport certs to one signed by a different CA than the previous one + updateFiles("ssl/reload/node-new-ca.crt.pem", pemCertFilePath); + updateFiles("ssl/reload/node-new-ca.key.pem", pemKeyFilePath); + + RestHelper.HttpResponse reloadCertsResponse = rh.executePutRequest(RELOAD_TRANSPORT_CERTS_ENDPOINT, null); + + assertThat(reloadCertsResponse.getStatusCode(), is(500)); + assertThat( + DefaultObjectMapper.readTree(reloadCertsResponse.getBody()).get("error").get("root_cause").get(0).get("reason").asText(), + is( + "OpenSearchSecurityException[Error while initializing transport SSL layer from PEM: java.lang.Exception: " + + "New Certs do not have valid Issuer DN, Subject DN or SAN.]; nested: Exception[New Certs do not have valid Issuer DN, Subject DN or SAN.];" + ) + ); + } + /** * * @param rh RestHelper to perform rest actions on the cluster @@ -397,8 +443,8 @@ private void initClusterWithTestCerts() throws Exception { * @param httpPemCertFilePath Absolute Path to transport pem cert file * @param httpPemKeyFilePath Absolute Path to transport pem key file * @param sslCertReload Sets the ssl cert reload flag - * @param httpEnforceReloadDnVerification Sets the http enforce reload dn verification flag - * @param transportEnforceReloadDnVerification Sets the transport enforce reload dn verification flag + * @param httpEnforceReloadDnVerification Sets the http enforce reload dn verification flag if non-null + * @param transportEnforceReloadDnVerification Sets the transport enforce reload dn verification flag if non-null */ private void initTestCluster( final String transportPemCertFilePath, @@ -406,18 +452,16 @@ private void initTestCluster( final String httpPemCertFilePath, final String httpPemKeyFilePath, final boolean sslCertReload, - final boolean httpEnforceReloadDnVerification, - final boolean transportEnforceReloadDnVerification + final Boolean httpEnforceReloadDnVerification, + final Boolean transportEnforceReloadDnVerification ) throws Exception { - final Settings settings = Settings.builder() + final Settings.Builder settingsBuilder = Settings.builder() .putList(ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, "CN=kirk,OU=client,O=client,L=Test,C=DE") .putList(ConfigConstants.SECURITY_NODES_DN, "CN=node-1.example.com,OU=SSL,O=Test,L=Test,C=DE") .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION, httpEnforceReloadDnVerification) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION, transportEnforceReloadDnVerification) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, transportPemCertFilePath) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, transportPemKeyFilePath) .put( @@ -430,8 +474,17 @@ private void initTestCluster( SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/reload/root-ca.pem") ) - .put(ConfigConstants.SECURITY_SSL_CERT_RELOAD_ENABLED, sslCertReload) - .build(); + .put(ConfigConstants.SECURITY_SSL_CERT_RELOAD_ENABLED, sslCertReload); + + if (httpEnforceReloadDnVerification != null) settingsBuilder.put( + SSLConfigConstants.SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION, + httpEnforceReloadDnVerification + ); + + if (transportEnforceReloadDnVerification != null) settingsBuilder.put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION, + transportEnforceReloadDnVerification + ); final Settings initTransportClientSettings = Settings.builder() .put( @@ -445,7 +498,7 @@ private void initTestCluster( ) .build(); - setup(initTransportClientSettings, new DynamicSecurityConfig(), settings, true, clusterConfiguration); + setup(initTransportClientSettings, new DynamicSecurityConfig(), settingsBuilder.build(), true, clusterConfiguration); } } From e2ceeeb8571d7ae7deb8378242bab1ce0d8925b7 Mon Sep 17 00:00:00 2001 From: Paris Larkins Date: Thu, 3 Oct 2024 09:38:05 +1000 Subject: [PATCH 5/6] Replace default value constants with in-line values. Improve default behaviour test cases Signed-off-by: Paris Larkins --- .../org/opensearch/security/ssl/DefaultSecurityKeyStore.java | 4 ++-- .../opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java | 4 ++-- .../org/opensearch/security/ssl/util/SSLConfigConstants.java | 2 -- .../security/ssl/SecuritySSLReloadCertsActionTests.java | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java b/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java index 95eb3a97db..8b31d58d6b 100644 --- a/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java +++ b/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java @@ -169,7 +169,7 @@ public DefaultSecurityKeyStore(final Settings settings, final Path configPath) { ); httpSSLEnforceCertReloadDnVerification = settings.getAsBoolean( SSLConfigConstants.SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION, - SSLConfigConstants.SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT + true ); transportSSLEnabled = settings.getAsBoolean( SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, @@ -177,7 +177,7 @@ public DefaultSecurityKeyStore(final Settings settings, final Path configPath) { ); transportSSLEnforceCertReloadDnVerification = settings.getAsBoolean( SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION, - SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT + true ); final boolean useOpenSSLForHttpIfAvailable = OpenSearchSecuritySSLPlugin.OPENSSL_SUPPORTED && settings.getAsBoolean(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, true); diff --git a/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java b/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java index 86de1c7493..57d40745cd 100644 --- a/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java +++ b/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java @@ -641,7 +641,7 @@ public List> getSettings() { settings.add( Setting.boolSetting( SSLConfigConstants.SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION, - SSLConfigConstants.SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT, + true, Property.NodeScope, Property.Filtered ) @@ -649,7 +649,7 @@ public List> getSettings() { settings.add( Setting.boolSetting( SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION, - SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT, + true, Property.NodeScope, Property.Filtered ) diff --git a/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java b/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java index 0c09368c21..9d715269a4 100644 --- a/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java +++ b/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java @@ -40,7 +40,6 @@ public final class SSLConfigConstants { public static final String SECURITY_SSL_HTTP_TRUSTSTORE_TYPE = "plugins.security.ssl.http.truststore_type"; public static final String SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION = "plugins.security.ssl.http.enforce_cert_reload_dn_verification"; - public static final Boolean SECURITY_SSL_HTTP_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT = true; public static final String SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE = "plugins.security.ssl.transport.enable_openssl_if_available"; public static final String SECURITY_SSL_TRANSPORT_ENABLED = "plugins.security.ssl.transport.enabled"; @@ -52,7 +51,6 @@ public final class SSLConfigConstants { public static final String SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION = "plugins.security.ssl.transport.enforce_cert_reload_dn_verification"; - public static final Boolean SECURITY_SSL_TRANSPORT_ENFORCE_CERT_RELOAD_DN_VERIFICATION_DEFAULT = true; public static final String SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS = "plugins.security.ssl.transport.keystore_alias"; public static final String SECURITY_SSL_TRANSPORT_SERVER_KEYSTORE_ALIAS = "plugins.security.ssl.transport.server.keystore_alias"; public static final String SECURITY_SSL_TRANSPORT_CLIENT_KEYSTORE_ALIAS = "plugins.security.ssl.transport.client.keystore_alias"; diff --git a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java index 0f3773c15c..362261ec01 100644 --- a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java +++ b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java @@ -250,7 +250,7 @@ public void testReloadHttpCertDifferentTrustChain_noSkipDnValidationFail() throw public void testReloadHttpCertDifferentTrustChain_defaultSettingValidationFail() throws Exception { updateFiles(defaultCertFilePath, pemCertFilePath); updateFiles(defaultKeyFilePath, pemKeyFilePath); - initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true, null, true); + initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true, null, null); RestHelper rh = getRestHelperAdminUser(); // Change http certs to one signed by a different CA than the previous one @@ -321,7 +321,7 @@ public void testReloadTransportCertDifferentTrustChain_noSkipDnValidationFail() public void testReloadTransportCertDifferentTrustChain_defaultSettingValidationFail() throws Exception { updateFiles(defaultCertFilePath, pemCertFilePath); updateFiles(defaultKeyFilePath, pemKeyFilePath); - initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true, true, null); + initTestCluster(pemCertFilePath, pemKeyFilePath, pemCertFilePath, pemKeyFilePath, true, null, null); RestHelper rh = getRestHelperAdminUser(); // Change transport certs to one signed by a different CA than the previous one From d74905f1afc7c8a8b8765125ef65cb0b4afde189 Mon Sep 17 00:00:00 2001 From: Paris Larkins Date: Wed, 16 Oct 2024 09:37:51 +1100 Subject: [PATCH 6/6] Refactor getNewCertAuthorityUpdatedCertDetailsExpectedResponse and getUpdatedCertDetailsExpectedResponse helpers into simplified getCertDetailsExpectedResponse Signed-off-by: Paris Larkins --- .../SecuritySSLReloadCertsActionTests.java | 41 +++++++------------ 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java index 362261ec01..b738d72627 100644 --- a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java +++ b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java @@ -14,7 +14,6 @@ import java.io.IOException; import java.util.List; import java.util.Map; -import java.util.Objects; import com.fasterxml.jackson.databind.JsonNode; import org.junit.After; @@ -44,10 +43,8 @@ public class SecuritySSLReloadCertsActionTests extends SingleClusterTest { private final String RELOAD_HTTP_CERTS_ENDPOINT = "_opendistro/_security/api/ssl/http/reloadcerts"; @Rule public TemporaryFolder testFolder = new TemporaryFolder(); - private final String HTTP_CERTIFICATES_LIST_KEY = "http_certificates_list"; - private final String TRANSPORT_CERTIFICATES_LIST_KEY = "transport_certificates_list"; - private final List> NODE_CERT_DETAILS = List.of( + private final List> INITIAL_NODE_CERT_DETAILS = List.of( Map.of( "issuer_dn", "CN=Example Com Inc. Signing CA,OU=Example Com Inc. Signing CA,O=Example Com Inc.,DC=example,DC=com", @@ -131,7 +128,7 @@ public void testReloadTransportSSLCertsPass() throws Exception { updateFiles(newCertFilePath, pemCertFilePath); updateFiles(newKeyFilePath, pemKeyFilePath); - assertReloadCertificateSuccess(rh, "transport", getUpdatedCertDetailsExpectedResponse("transport")); + assertReloadCertificateSuccess(rh, "transport", getCertDetailsExpectedResponse(INITIAL_NODE_CERT_DETAILS, NEW_NODE_CERT_DETAILS)); } @Test @@ -148,7 +145,7 @@ public void testReloadHttpSSLCertsPass() throws Exception { updateFiles(newCertFilePath, pemCertFilePath); updateFiles(newKeyFilePath, pemKeyFilePath); - assertReloadCertificateSuccess(rh, "http", getUpdatedCertDetailsExpectedResponse("http")); + assertReloadCertificateSuccess(rh, "http", getCertDetailsExpectedResponse(NEW_NODE_CERT_DETAILS, INITIAL_NODE_CERT_DETAILS)); } @Test @@ -220,7 +217,10 @@ public void testReloadHttpCertDifferentTrustChain_skipDnValidationPass() throws assertThat(reloadCertsResponse.getBody(), is(expectedJsonResponse.toString())); String certDetailsResponse = rh.executeSimpleRequest(GET_CERT_DETAILS_ENDPOINT); - assertThat(DefaultObjectMapper.readTree(certDetailsResponse), is(getNewCertAuthorityUpdatedCertDetailsExpectedResponse("http"))); + assertThat( + DefaultObjectMapper.readTree(certDetailsResponse), + is(getCertDetailsExpectedResponse(NEW_CA_NODE_CERT_DETAILS, INITIAL_NODE_CERT_DETAILS)) + ); } @Test @@ -290,7 +290,7 @@ public void testReloadTransportCertDifferentTrustChain_skipDnValidationPass() th String certDetailsResponse = rh.executeSimpleRequest(GET_CERT_DETAILS_ENDPOINT); assertThat( DefaultObjectMapper.readTree(certDetailsResponse), - is(getNewCertAuthorityUpdatedCertDetailsExpectedResponse("transport")) + is(getCertDetailsExpectedResponse(INITIAL_NODE_CERT_DETAILS, NEW_CA_NODE_CERT_DETAILS)) ); } @@ -365,29 +365,18 @@ private void updateFiles(String srcFile, String dstFile) { FileHelper.copyFileContents(FileHelper.getAbsoluteFilePathFromClassPath(srcFile).toString(), dstFile); } - private JsonNode getNewCertAuthorityUpdatedCertDetailsExpectedResponse(String updateChannel) { - String updateKey = (Objects.equals(updateChannel, "http")) ? HTTP_CERTIFICATES_LIST_KEY : TRANSPORT_CERTIFICATES_LIST_KEY; - String oldKey = (Objects.equals(updateChannel, "http")) ? TRANSPORT_CERTIFICATES_LIST_KEY : HTTP_CERTIFICATES_LIST_KEY; - final var updatedCertDetailsResponse = DefaultObjectMapper.objectMapper.createObjectNode(); - updatedCertDetailsResponse.set(updateKey, buildCertsInfoNode(NEW_CA_NODE_CERT_DETAILS)); - updatedCertDetailsResponse.set(oldKey, buildCertsInfoNode(NODE_CERT_DETAILS)); - return updatedCertDetailsResponse; - } - - private JsonNode getUpdatedCertDetailsExpectedResponse(String updateChannel) { - String updateKey = (Objects.equals(updateChannel, "http")) ? HTTP_CERTIFICATES_LIST_KEY : TRANSPORT_CERTIFICATES_LIST_KEY; - String oldKey = (Objects.equals(updateChannel, "http")) ? TRANSPORT_CERTIFICATES_LIST_KEY : HTTP_CERTIFICATES_LIST_KEY; + private JsonNode getCertDetailsExpectedResponse( + List> httpCertDetails, + List> transportCertDetails + ) { final var updatedCertDetailsResponse = DefaultObjectMapper.objectMapper.createObjectNode(); - updatedCertDetailsResponse.set(updateKey, buildCertsInfoNode(NEW_NODE_CERT_DETAILS)); - updatedCertDetailsResponse.set(oldKey, buildCertsInfoNode(NODE_CERT_DETAILS)); + updatedCertDetailsResponse.set("http_certificates_list", buildCertsInfoNode(httpCertDetails)); + updatedCertDetailsResponse.set("transport_certificates_list", buildCertsInfoNode(transportCertDetails)); return updatedCertDetailsResponse; } private JsonNode getInitCertDetailsExpectedResponse() { - final var initCertDetailsResponse = DefaultObjectMapper.objectMapper.createObjectNode(); - initCertDetailsResponse.set(HTTP_CERTIFICATES_LIST_KEY, buildCertsInfoNode(NODE_CERT_DETAILS)); - initCertDetailsResponse.set(TRANSPORT_CERTIFICATES_LIST_KEY, buildCertsInfoNode(NODE_CERT_DETAILS)); - return initCertDetailsResponse; + return getCertDetailsExpectedResponse(INITIAL_NODE_CERT_DETAILS, INITIAL_NODE_CERT_DETAILS); } private JsonNode buildCertsInfoNode(final List> certsInfo) {