From 80c78ddedeb92b65e9ace803473be3a6e2461ff2 Mon Sep 17 00:00:00 2001 From: sanjaypujare Date: Thu, 14 Nov 2019 10:51:42 -0800 Subject: [PATCH] xds: add inline bytes support to CertificationValidationContext we use in SdsTrustManagerFactory (#6429) --- .../grpc/xds/sds/trust/CertificateUtils.java | 14 ++++++--- .../xds/sds/trust/SdsTrustManagerFactory.java | 29 ++++++++++------- .../sds/trust/SdsTrustManagerFactoryTest.java | 31 +++++++++++++++++++ 3 files changed, 58 insertions(+), 16 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/sds/trust/CertificateUtils.java b/xds/src/main/java/io/grpc/xds/sds/trust/CertificateUtils.java index 805f2039a3..0057ca6e8f 100644 --- a/xds/src/main/java/io/grpc/xds/sds/trust/CertificateUtils.java +++ b/xds/src/main/java/io/grpc/xds/sds/trust/CertificateUtils.java @@ -20,6 +20,7 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; @@ -44,16 +45,19 @@ final class CertificateUtils { * * @param file a {@link File} containing the cert data */ - static synchronized X509Certificate[] toX509Certificates(File file) + static X509Certificate[] toX509Certificates(File file) throws CertificateException, IOException { + FileInputStream fis = new FileInputStream(file); + return toX509Certificates(new BufferedInputStream(fis)); + } + + static synchronized X509Certificate[] toX509Certificates(InputStream inputStream) throws CertificateException, IOException { initInstance(); - FileInputStream fis = new FileInputStream(file); - BufferedInputStream bis = new BufferedInputStream(fis); try { - Collection certs = factory.generateCertificates(bis); + Collection certs = factory.generateCertificates(inputStream); return certs.toArray(new X509Certificate[0]); } finally { - bis.close(); + inputStream.close(); } } diff --git a/xds/src/main/java/io/grpc/xds/sds/trust/SdsTrustManagerFactory.java b/xds/src/main/java/io/grpc/xds/sds/trust/SdsTrustManagerFactory.java index 6db7b7ac03..0ae906a205 100644 --- a/xds/src/main/java/io/grpc/xds/sds/trust/SdsTrustManagerFactory.java +++ b/xds/src/main/java/io/grpc/xds/sds/trust/SdsTrustManagerFactory.java @@ -16,7 +16,6 @@ package io.grpc.xds.sds.trust; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; @@ -54,19 +53,27 @@ public final class SdsTrustManagerFactory extends SimpleTrustManagerFactory { public SdsTrustManagerFactory(CertificateValidationContext certificateValidationContext) throws CertificateException, IOException, CertStoreException { checkNotNull(certificateValidationContext, "certificateValidationContext"); - String certsFile = getTrustedCaFromCertContext(certificateValidationContext); - checkState(!Strings.isNullOrEmpty(certsFile), - "trustedCa.file-name in certificateValidationContext cannot be empty"); createSdsX509TrustManager( - CertificateUtils.toX509Certificates(new File(certsFile)), certificateValidationContext); + getTrustedCaFromCertContext(certificateValidationContext), certificateValidationContext); } - private static String getTrustedCaFromCertContext( - CertificateValidationContext certificateValidationContext) { - checkArgument( - certificateValidationContext.getTrustedCa().getSpecifierCase() == SpecifierCase.FILENAME, - "filename expected"); - return certificateValidationContext.getTrustedCa().getFilename(); + private static X509Certificate[] getTrustedCaFromCertContext( + CertificateValidationContext certificateValidationContext) + throws CertificateException, IOException { + final SpecifierCase specifierCase = + certificateValidationContext.getTrustedCa().getSpecifierCase(); + if (specifierCase == SpecifierCase.FILENAME) { + String certsFile = certificateValidationContext.getTrustedCa().getFilename(); + checkState( + !Strings.isNullOrEmpty(certsFile), + "trustedCa.file-name in certificateValidationContext cannot be empty"); + return CertificateUtils.toX509Certificates(new File(certsFile)); + } else if (specifierCase == SpecifierCase.INLINE_BYTES) { + return CertificateUtils.toX509Certificates( + certificateValidationContext.getTrustedCa().getInlineBytes().newInput()); + } else { + throw new IllegalArgumentException("Not supported: " + specifierCase); + } } private void createSdsX509TrustManager( diff --git a/xds/src/test/java/io/grpc/xds/sds/trust/SdsTrustManagerFactoryTest.java b/xds/src/test/java/io/grpc/xds/sds/trust/SdsTrustManagerFactoryTest.java index 9f1565045b..f03e836081 100644 --- a/xds/src/test/java/io/grpc/xds/sds/trust/SdsTrustManagerFactoryTest.java +++ b/xds/src/test/java/io/grpc/xds/sds/trust/SdsTrustManagerFactoryTest.java @@ -18,6 +18,7 @@ package io.grpc.xds.sds.trust; import static com.google.common.truth.Truth.assertThat; +import com.google.protobuf.ByteString; import io.envoyproxy.envoy.api.v2.auth.CertificateValidationContext; import io.envoyproxy.envoy.api.v2.core.DataSource; import io.grpc.internal.testing.TestUtils; @@ -69,6 +70,26 @@ public class SdsTrustManagerFactoryTest { .isEqualTo(CertificateUtils.toX509Certificates(TestUtils.loadCert(CA_PEM_FILE))[0]); } + @Test + public void constructor_fromInlineBytes() + throws CertificateException, IOException, CertStoreException { + SdsTrustManagerFactory factory = + new SdsTrustManagerFactory(getCertContextFromPathAsInlineBytes(CA_PEM_FILE)); + assertThat(factory).isNotNull(); + TrustManager[] tms = factory.getTrustManagers(); + assertThat(tms).isNotNull(); + assertThat(tms).hasLength(1); + TrustManager myTm = tms[0]; + assertThat(myTm).isInstanceOf(SdsX509TrustManager.class); + SdsX509TrustManager sdsX509TrustManager = (SdsX509TrustManager) myTm; + X509Certificate[] acceptedIssuers = sdsX509TrustManager.getAcceptedIssuers(); + assertThat(acceptedIssuers).isNotNull(); + assertThat(acceptedIssuers).hasLength(1); + X509Certificate caCert = acceptedIssuers[0]; + assertThat(caCert) + .isEqualTo(CertificateUtils.toX509Certificates(TestUtils.loadCert(CA_PEM_FILE))[0]); + } + @Test public void checkServerTrusted_goodCert() throws CertificateException, IOException, CertStoreException { @@ -135,4 +156,14 @@ public class SdsTrustManagerFactoryTest { DataSource.newBuilder().setFilename(TestUtils.loadCert(pemFilePath).getAbsolutePath())) .build(); } + + /** constructs CertificateValidationContext from pemFilePath and sets contents as inline-bytes. */ + private static final CertificateValidationContext getCertContextFromPathAsInlineBytes( + String pemFilePath) throws IOException, CertificateException { + X509Certificate x509Cert = TestUtils.loadX509Cert(pemFilePath); + return CertificateValidationContext.newBuilder() + .setTrustedCa( + DataSource.newBuilder().setInlineBytes(ByteString.copyFrom(x509Cert.getEncoded()))) + .build(); + } }