This is an automated email from the ASF dual-hosted git repository. sewen pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/flink.git
commit 69a727d1f9b6ef39ffb707f6d4ef46c534944ab5 Author: Stephan Ewen <se...@apache.org> AuthorDate: Fri Jan 10 17:21:11 2020 +0100 [FLINK-15174][security] (follow-up) Add a test for exceptions on invalid / malformed fingerprint and refine docs. --- docs/ops/security-ssl.md | 30 ++++++++++++++-------- .../org/apache/flink/runtime/net/SSLUtilsTest.java | 17 ++++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/docs/ops/security-ssl.md b/docs/ops/security-ssl.md index 4bb4e93..fd26599 100644 --- a/docs/ops/security-ssl.md +++ b/docs/ops/security-ssl.md @@ -51,15 +51,24 @@ Internal connectivity includes: All internal connections are SSL authenticated and encrypted. The connections use **mutual authentication**, meaning both server and client side of each connection need to present the certificate to each other. The certificate acts effectively as a shared secret when a dedicated CA is used to exclusively sign an internal cert. +The certificate for internal communication is not needed by any other party to interact with Flink, and can be simply +added to the container images, or attached to the YARN deployment. -It is highly recommended to generate a dedicated certificate (self-signed) for a Flink deployment. The certificate for internal communication -is not needed by any other party to interact with Flink, and can be simply added to the container images, or attached to the YARN deployment. + - The easiest way to realize this setup is by generating a dedicated public/private key pair and self-signed certificate + for the Flink deployment. The key- and truststore are identical and contains only that key pair / certificate. + An example is [shown below](#example-ssl-setup-standalone-and-kubernetes). -An environment where operators are constrained to use firm wide Internal CA and can not generate self-signed certificate, specify the SHA1 certificate fingerprint to protect the cluster allowing only specific certificate to trusted by the cluster. + - In an environment where operators are constrained to use firm-wide Internal CA (cannot generate self-signed certificates), + the recommendation is to still have a dedicated key pair / certificate for the Flink deployment, signed by that CA. + However, the TrustStore must then also contain the CA's public certificate tho accept the deployment's certificate + during the SSL handshake (requirement in JDK TrustStore implementation). + + **NOTE:** Because of that, it is critical that you specify the fingerprint of the deployment certificate + (`security.ssl.internal.cert.fingerprint`), when it is not self-signed, to pin that certificate as the only trusted + certificate and prevent the TrustStore from trusting all certificates signed by that CA. -*Note: Because internal connections are mutually authenticated with shared certificates, Flink can skip hostname verification. This makes container-based setups easier.* - -*IMPORTANT: Do not use certificate issued by public CA without pinning the fingerprint of the certificate.* +*Note: Because internal connections are mutually authenticated with shared certificates, Flink can skip hostname verification. +This makes container-based setups easier.* ### External / REST Connectivity @@ -107,9 +116,9 @@ need to be set up such that the truststore trusts the keystore's certificate. #### Internal Connectivity -Because internal communication is mutually authenticated, keystore and truststore typically contain the same dedicated certificate. -The certificate can use wild card hostnames or addresses, because the certificate is expected to be a shared secret and host -names are not verified. It is even possible to use the same file (the keystore) also as the truststore. +Because internal communication is mutually authenticated between server and client side, keystore and truststore typically refer to a dedicated +certificate that acts as a shared secret. In such a setup, the certificate can use wild card hostnames or addresses. +WHen using self-signed certificates, it is even possible to use the same file as keystore and truststore. {% highlight yaml %} security.ssl.internal.keystore: /path/to/file.keystore @@ -119,7 +128,8 @@ security.ssl.internal.truststore: /path/to/file.truststore security.ssl.internal.truststore-password: truststore_password {% endhighlight %} -When using certificate from public CA, Use certificate pinning to allow only specific internal certificate to establish the connectivity. +When using a certificate that is not self-signed, but signed by a CA, you need to use certificate pinning to allow only a +a specific certificate to be trusted when establishing the connectivity. {% highlight yaml %} security.ssl.internal.cert.fingerprint: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/net/SSLUtilsTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/net/SSLUtilsTest.java index 2c3bb05..863cf71 100644 --- a/flink-runtime/src/test/java/org/apache/flink/runtime/net/SSLUtilsTest.java +++ b/flink-runtime/src/test/java/org/apache/flink/runtime/net/SSLUtilsTest.java @@ -49,6 +49,7 @@ import java.util.List; import java.util.Locale; import static org.hamcrest.Matchers.arrayContainingInAnyOrder; +import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -455,6 +456,22 @@ public class SSLUtilsTest extends TestLogger { arrayContainingInAnyOrder(sslAlgorithms)); } + @Test + public void testInvalidFingerprintParsing() throws Exception { + final Configuration config = createInternalSslConfigWithKeyAndTrustStores(); + final String fingerprint = getCertificateFingerprint(config, "flink.test"); + + config.setString(SecurityOptions.SSL_INTERNAL_CERT_FINGERPRINT, fingerprint.substring(0, fingerprint.length() - 3)); + + try { + SSLUtils.createInternalServerSSLEngineFactory(config); + fail("expected exception"); + } + catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("malformed fingerprint")); + } + } + // ------------------------------- utils ---------------------------------- private Configuration createRestSslConfigWithKeyStore() {