xds: add inline bytes support to CertificationValidationContext we use in SdsTrustManagerFactory (#6429)

This commit is contained in:
sanjaypujare 2019-11-14 10:51:42 -08:00 committed by GitHub
parent 48929c4d50
commit 80c78ddede
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 16 deletions

View File

@ -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<? extends Certificate> certs = factory.generateCertificates(bis);
Collection<? extends Certificate> certs = factory.generateCertificates(inputStream);
return certs.toArray(new X509Certificate[0]);
} finally {
bis.close();
inputStream.close();
}
}

View File

@ -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(

View File

@ -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();
}
}