diff --git a/cloudplatform/cloudplatform-connectivity/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/KeyStoreReader.java b/cloudplatform/cloudplatform-connectivity/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/KeyStoreReader.java index 618f9ab282..55965736f4 100644 --- a/cloudplatform/cloudplatform-connectivity/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/KeyStoreReader.java +++ b/cloudplatform/cloudplatform-connectivity/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/KeyStoreReader.java @@ -53,7 +53,7 @@ static KeyStore createKeyStore( Try.of(() -> loadCertificates(certReader)).getOrElseThrow(e -> new DestinationAccessException(MSG_CERT, e)); final PrivateKey privateKey = Try.of(() -> loadKey(keyReader, password)).getOrElseThrow(e -> new DestinationAccessException(MSG_KEY, e)); - final KeyStore keyStore = KeyStore.getInstance("JKS"); + final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); keyStore.setKeyEntry(alias, privateKey, password, clientCertificates); return keyStore; @@ -65,7 +65,7 @@ static Certificate[] loadCertificates( @Nonnull final Reader certReader ) IOException { final List certs = new ArrayList<>(); - final CertificateFactory factory = CertificateFactory.getInstance("X509"); + final CertificateFactory factory = CertificateFactory.getInstance("X.509"); try( PEMParser pemParser = new PEMParser(certReader) ) { PemObject object; diff --git a/cloudplatform/connectivity-apache-httpclient4/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/KeyStoreReaderTest.java b/cloudplatform/connectivity-apache-httpclient4/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/KeyStoreReaderTest.java index 20629e6869..9059e31e28 100644 --- a/cloudplatform/connectivity-apache-httpclient4/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/KeyStoreReaderTest.java +++ b/cloudplatform/connectivity-apache-httpclient4/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/KeyStoreReaderTest.java @@ -31,7 +31,7 @@ void testPem() final FileReader certs = new FileReader(CRT_PATH), key = new FileReader(KEY_PATH); final KeyStore createdKeystore = createKeyStore(ALIAS, PASS, certs, key); - assertThat(createdKeystore.getType()).isEqualTo("JKS"); + assertThat(createdKeystore.getType()).isEqualTo(KeyStore.getDefaultType()); assertThat(createdKeystore.getProvider()).isNotNull(); assertThat(createdKeystore.getCertificateChain(ALIAS)).hasSize(1); diff --git a/cloudplatform/connectivity-fips-sample/pom.xml b/cloudplatform/connectivity-fips-sample/pom.xml new file mode 100644 index 0000000000..b6feb5a2e7 --- /dev/null +++ b/cloudplatform/connectivity-fips-sample/pom.xml @@ -0,0 +1,143 @@ + + + 4.0.0 + + com.sap.cloud.sdk.cloudplatform + cloudplatform-parent + 5.31.0-SNAPSHOT + + connectivity-fips-sample + Connectivity - FIPS Sample + Non-released sample module that runs connectivity tests under the FIPS-approved Bouncy Castle provider. + https://sap.github.io/cloud-sdk/docs/java/getting-started + + SAP SE + https://www.sap.com + + + + The Apache Software License, Version 2.0 + https://www.apache.org/licenses/LICENSE-2.0.txt + + + + + SAP + cloudsdk@sap.com + SAP SE + https://www.sap.com + + + + 2.1.2 + 2.1.9 + + + + com.sap.cloud.sdk.cloudplatform + cloudplatform-connectivity + + + org.bouncycastle + bcprov-jdk18on + + + org.bouncycastle + bcpkix-jdk18on + + + test + + + org.bouncycastle + bc-fips + ${bc-fips.version} + test + + + org.bouncycastle + bcpkix-fips + ${bcpkix-fips.version} + test + + + org.projectlombok + lombok + provided + + + org.junit.jupiter + junit-jupiter-api + test + + + org.assertj + assertj-core + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + ${argLine} -Dorg.bouncycastle.fips.approved_only=true + + + + org.apache.maven.plugins + maven-dependency-plugin + + + org.bouncycastle:bc-fips + org.bouncycastle:bcpkix-fips + com.sap.cloud.sdk.cloudplatform:cloudplatform-connectivity + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + true + + + org.apache.maven.plugins + maven-pmd-plugin + true + + + org.apache.maven.plugins + maven-javadoc-plugin + true + + + org.jacoco + jacoco-maven-plugin + true + + + + + + release + + release + + + + + org.sonatype.central + central-publishing-maven-plugin + + + injected-central-publishing + + + + + + + + + diff --git a/cloudplatform/connectivity-fips-sample/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/FipsProviderTest.java b/cloudplatform/connectivity-fips-sample/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/FipsProviderTest.java new file mode 100644 index 0000000000..b61c5cd68b --- /dev/null +++ b/cloudplatform/connectivity-fips-sample/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/FipsProviderTest.java @@ -0,0 +1,71 @@ +package com.sap.cloud.sdk.cloudplatform.connectivity; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.FileReader; +import java.security.KeyStore; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Security; + +import org.bouncycastle.crypto.CryptoServicesRegistrar; +import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import lombok.SneakyThrows; + +/** + * Regression guard for the P1 fix: asserts that {@code KeyStoreReader.createKeyStore()} produces a PKCS12 keystore. Run + * with {@code mvn test -P fips-approved}. + */ +@Tag( "fips-approved" ) +class FipsProviderTest +{ + private static final String RES = "src/test/resources/certificates"; + private static final String CRT_PATH = RES + "/client-cert.crt"; + private static final String KEY_PATH = RES + "/client-cert.key"; + private static final String ALIAS = "client-cert"; + private static final char[] EMPTY_PASSWORD = new char[0]; + + @AfterAll + static void removeBouncyCastleFips() + { + Security.removeProvider("BCFIPS"); + } + + @BeforeAll + static void registerBouncyCastleFips() + { + Security.insertProviderAt(new BouncyCastleFipsProvider(), 1); + + assertThat(Security.getProvider("BCFIPS")) + .describedAs("BC FIPS provider must be registered as a JCA provider") + .isNotNull(); + + assertThat(CryptoServicesRegistrar.isInApprovedOnlyMode()) + .describedAs("BC FIPS must be in approved-only mode. ") + .isTrue(); + } + + @Test + @SneakyThrows + void keystoreTypeIsP12() + { + final KeyStore keyStore = + KeyStoreReader.createKeyStore(ALIAS, EMPTY_PASSWORD, new FileReader(CRT_PATH), new FileReader(KEY_PATH)); + + assertThat(keyStore.getType()).isEqualTo("pkcs12"); + } + + @Test + void md5IsRejectedInApprovedOnlyMode() + { + assertThatThrownBy(() -> MessageDigest.getInstance("MD5", "BCFIPS")) + .isInstanceOf(NoSuchAlgorithmException.class); + + } +} diff --git a/cloudplatform/connectivity-fips-sample/src/test/resources/certificates/client-cert.crt b/cloudplatform/connectivity-fips-sample/src/test/resources/certificates/client-cert.crt new file mode 100644 index 0000000000..8b313ee502 --- /dev/null +++ b/cloudplatform/connectivity-fips-sample/src/test/resources/certificates/client-cert.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIUDfIuo9MZ6BTCuQAndYmYHMsnKrYwDQYJKoZIhvcNAQEL +BQAwajELMAkGA1UEBhMCREUxFDASBgNVBAgMC0JyYW5kZW5idXJnMRAwDgYDVQQK +DAdQb3RzZGFtMR8wHQYJKoZIhvcNAQkBFhBjbG91ZHNka0BzYXAuY29tMRIwEAYD +VQQDDAlsb2NhbGhvc3QwHhcNMjQwMTEyMTAyOTMwWhcNMzQwMTA5MTAyOTMwWjBq +MQswCQYDVQQGEwJERTEUMBIGA1UECAwLQnJhbmRlbmJ1cmcxEDAOBgNVBAoMB1Bv +dHNkYW0xHzAdBgkqhkiG9w0BCQEWEGNsb3Vkc2RrQHNhcC5jb20xEjAQBgNVBAMM +CWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALSd6Fz/ +ZfDA52fZBuB+kP0JT5b8HqcKMX/Smt7S5bi5DwFi/RhHoaD1o5td8HPIP+N6sm8s +l/HiZhZmIleGabyOUiO1JnglHijElrJZrny6ZYJcrzMkOWGtM/8mUZRXzm6Ae8bP +pib6Kza3qsIq5Br0yBo/XOClbE+BFilvoUGiBb78eIHH14OQGYMkXzbUWJOVTQ6q +5tlfQP1yHm9txVvlMwD+qqS1LjNdj3L72vFrkZil2AHXA0pdWLWn13K8r0U6+RNT +99mYEw/5BoaOZA0NRX3kFeCGJKDz92SEdzbPU2F4+dt8/Is3Xj397zku/OITWRtW +oQTOgp4l01ev2TcCAwEAAaNVMFMwCQYDVR0TBAIwADALBgNVHQ8EBAMCBaAwGgYD +VR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMB0GA1UdDgQWBBQChuZYKEuGYQLWgSPS +njRacT/rJjANBgkqhkiG9w0BAQsFAAOCAQEAXqiPPxWiNXw9stwC3PIwMbgHjmJG +0gSy/OLOWihP8Fet4m2mhYiZ6E1vx1THjgl7+s1BYc4HE7GgXrvoSEKJsTUUVjCf +u4xbN4YxBjxBSs0If0hOPrtOEln5ij6rKuTFh9+cskt4MYgy+XuP0iT7MOrk7jqp +Jx6QdPbQEPTdmZ0XWlJz+qP+BQIl/lTcD7GoBS/tCYoyaljmfMMGaJ83HVlKfMpH +ELWFT2Y4mSNFo1jOFt7lR+cWy9YJ9gerxEskHKYqIX0e4ELhSyovix4c7dUstszy +RjVcfhNI8gsxAbkT+mYuIMl4zkTA1yUcmqEgBhxA9vIVD7kfL8S0bELBHA== +-----END CERTIFICATE----- diff --git a/cloudplatform/connectivity-fips-sample/src/test/resources/certificates/client-cert.key b/cloudplatform/connectivity-fips-sample/src/test/resources/certificates/client-cert.key new file mode 100644 index 0000000000..250483648d --- /dev/null +++ b/cloudplatform/connectivity-fips-sample/src/test/resources/certificates/client-cert.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC0nehc/2XwwOdn +2QbgfpD9CU+W/B6nCjF/0pre0uW4uQ8BYv0YR6Gg9aObXfBzyD/jerJvLJfx4mYW +ZiJXhmm8jlIjtSZ4JR4oxJayWa58umWCXK8zJDlhrTP/JlGUV85ugHvGz6Ym+is2 +t6rCKuQa9MgaP1zgpWxPgRYpb6FBogW+/HiBx9eDkBmDJF821FiTlU0OqubZX0D9 +ch5vbcVb5TMA/qqktS4zXY9y+9rxa5GYpdgB1wNKXVi1p9dyvK9FOvkTU/fZmBMP ++QaGjmQNDUV95BXghiSg8/dkhHc2z1NhePnbfPyLN149/e85LvziE1kbVqEEzoKe +JdNXr9k3AgMBAAECggEADh8af8roKX6rmQ763qqGo4IK2v8zVlQRsrDAsxNCKsMt +TSp0J2XSWUdbV1Zs6mCJvjtloBOYfaz51l596OH1emyWN3x+WX5tcTqNnbwtTEs2 +jI66lAENC3oDSruwPSzwUutwwgaSMxH0Nv79NtkrpH/m9UZm+Jl2cnDhTrQPo5Xp +siezDaO1vhX1WyHXKvSZy04+k1idy38XcZTMQ3xquapc4QhkYB3hj8qbF63gZUiw +Q7XhvETavKYCoVL5yC1RkNVZT5cCGzyQJePWvApQLB+ynr/aNjstjQhCcv74x0b3 +9Zs56UD5sTw3JwSlQmDGX72689qx/VO3OOEXJYzcoQKBgQDlzvpcifmzGLodGZcG +RPSauvRoAb7osSSAOU3ANNaP10jOJG/qiG4d99c1wC0wGSRFeILAAUIU5xuq5k2X +Sl5LfSSmwK8z1d2LfAXoEx91PlF9/MH5UncQIclHn+hsevu5eFwDkx1oKE5l9whB +hlgzTGKCO1lbUPL499poDFa2hQKBgQDJM6+Da5OebqXZ/BPtY5jCcoGgBl4L8NQW +EN668TbGGdcFXcsIbbN+qaFik8h37TU76xI8EQoW4YVDIGivHQXFmPpvpylglHto +4RcPRNE+0rykNasoCrEqEcL+WAX4b3+0dgszNgsZLA64kLZQa5fMjn2+nVvn+YSU +AwGs6TlziwKBgCx3bThEtl0yNqj0z6U16IKcFDifxdnulNp+vA2p665vgLXqlQEz +nuMLlsfexJ+e7cbHd71BQREcWt0prO/OQwqmT1Y4yG3mPvUDbX0nXhnokgonwzzD ++SfU8cZ7KZT8AwMzR9KlP7Zsvia6sw1CuoRKjnEWnMavliQYiVlCsfClAoGAQDXJ +doR3aOFg9o83ANR/JNcMPTiq/N6PoLcjjb97Pn9ympjTOc5gsTSLd304ReWizot3 +l0nM0X6JW+HU5sW5WNU4XzeWwebA97iV9l589LKmVzV1eOLopUdj1m3bAez7cWkW +q/I8Wn0v+YDdXg7oM/TpdlKbyQ1dXSsUds07c38CgYBfi2Zo2R2Sgfq6bQyCmzze +740nqiBTPf7NuA9n2yESOFUkskaLcWb5o83iT71I2eUxZJCSelgXxVHtGK5y3PLu +QWVWgN/qn6D3skuQNXEY5iAQ/C47Rq15ZUcWF2utzkAxrmgcSUjrj7xjsk5MG3RX +mK1AS3XT0sLIpGuhSUNrOw== +-----END PRIVATE KEY----- diff --git a/cloudplatform/connectivity-ztis/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/ZeroTrustIdentityService.java b/cloudplatform/connectivity-ztis/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/ZeroTrustIdentityService.java index b9433549d1..842b49cba2 100644 --- a/cloudplatform/connectivity-ztis/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/ZeroTrustIdentityService.java +++ b/cloudplatform/connectivity-ztis/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/ZeroTrustIdentityService.java @@ -209,7 +209,7 @@ KeyStore loadKeyStore( @Nonnull final X509Svid svid ) final KeyStore.Entry privateKeyEntry = new PrivateKeyEntry(svid.getPrivateKey(), svid.getChainArray()); final KeyStore keyStore; try { - keyStore = KeyStore.getInstance("JKS"); + keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); keyStore.setEntry("spiffe", privateKeyEntry, new KeyStore.PasswordProtection(new char[0])); } diff --git a/cloudplatform/pom.xml b/cloudplatform/pom.xml index 93565fd994..b0f1bd2ff0 100644 --- a/cloudplatform/pom.xml +++ b/cloudplatform/pom.xml @@ -42,6 +42,7 @@ connectivity-oauth connectivity-apache-httpclient4 connectivity-apache-httpclient5 + connectivity-fips-sample resilience resilience-api resilience4j @@ -59,6 +60,17 @@ ${project.basedir}/../../ + + non-release + + + !release + + + + connectivity-fips-sample + + release diff --git a/module-inventory.json b/module-inventory.json index 71f993b182..348da66b0a 100644 --- a/module-inventory.json +++ b/module-inventory.json @@ -120,6 +120,17 @@ "parentArtifactId": "cloudplatform-parent", "excludeFromBlackDuckScan": false }, + { + "groupId": "com.sap.cloud.sdk.cloudplatform", + "artifactId": "connectivity-fips-sample", + "packaging": "jar", + "releaseAudience": "None", + "releaseMaturity": "Stable", + "pomFile": "cloudplatform/connectivity-fips-sample/pom.xml", + "parentGroupId": "com.sap.cloud.sdk.cloudplatform", + "parentArtifactId": "cloudplatform-parent", + "excludeFromBlackDuckScan": true + }, { "groupId": "com.sap.cloud.sdk.cloudplatform", "artifactId": "connectivity-oauth", diff --git a/pom.xml b/pom.xml index a2172a42bb..cf80eb76e9 100644 --- a/pom.xml +++ b/pom.xml @@ -705,6 +705,7 @@ com.sap.cloud.sdk.datamodel:odata-v4-api-sample com.sap.cloud.sdk.datamodel:openapi-api-sample com.sap.cloud.sdk.datamodel:openapi-api-apache-sample + com.sap.cloud.sdk.cloudplatform:connectivity-fips-sample