mirror of https://github.com/grpc/grpc-java.git
s2a: Address minor comments on PR#11113 (#11540)
* Use StandardCharsets in FakeS2AServerTest. * Use add instead of offer in S2AStub. * remove dead code in ProtoUtil.java. * Mark convertTlsProtocolVersion as VisibleForTesting. * S2AStub doesn't return responses at front of queue. * Remove global SHARED_RESOURCE_CHANNELS. * Don't suppress RethrowReflectiveOperationExceptionAsLinkageError. * Update javadoc. * Make clear which certs are used in tests + add how to regenerate.
This commit is contained in:
parent
9faa0f4eb0
commit
fa18fec36e
|
|
@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.Channel;
|
||||
import io.grpc.ChannelCredentials;
|
||||
|
|
@ -30,16 +29,15 @@ import io.grpc.MethodDescriptor;
|
|||
import io.grpc.internal.SharedResourceHolder.Resource;
|
||||
import io.grpc.netty.NettyChannelBuilder;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Provides APIs for managing gRPC channels to S2A servers. Each channel is local and plaintext. If
|
||||
* credentials are provided, they are used to secure the channel.
|
||||
* Provides APIs for managing gRPC channels to an S2A server. Each channel is local and plaintext.
|
||||
* If credentials are provided, they are used to secure the channel.
|
||||
*
|
||||
* <p>This is done as follows: for each S2A server, provides an implementation of gRPC's {@link
|
||||
* <p>This is done as follows: for an S2A server, provides an implementation of gRPC's {@link
|
||||
* SharedResourceHolder.Resource} interface called a {@code Resource<Channel>}. A {@code
|
||||
* Resource<Channel>} is a factory for creating gRPC channels to the S2A server at a given address,
|
||||
* and a channel must be returned to the {@code Resource<Channel>} when it is no longer needed.
|
||||
|
|
@ -56,8 +54,6 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||
*/
|
||||
@ThreadSafe
|
||||
public final class S2AHandshakerServiceChannel {
|
||||
private static final ConcurrentMap<String, Resource<Channel>> SHARED_RESOURCE_CHANNELS =
|
||||
Maps.newConcurrentMap();
|
||||
private static final Duration CHANNEL_SHUTDOWN_TIMEOUT = Duration.ofSeconds(10);
|
||||
|
||||
/**
|
||||
|
|
@ -72,9 +68,7 @@ public final class S2AHandshakerServiceChannel {
|
|||
public static Resource<Channel> getChannelResource(
|
||||
String s2aAddress, ChannelCredentials s2aChannelCredentials) {
|
||||
checkNotNull(s2aAddress);
|
||||
checkNotNull(s2aChannelCredentials);
|
||||
return SHARED_RESOURCE_CHANNELS.computeIfAbsent(
|
||||
s2aAddress, channelResource -> new ChannelResource(s2aAddress, s2aChannelCredentials));
|
||||
return new ChannelResource(s2aAddress, s2aChannelCredentials);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,36 +16,11 @@
|
|||
|
||||
package io.grpc.s2a.handshaker;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/** Converts proto messages to Netty strings. */
|
||||
final class ProtoUtil {
|
||||
/**
|
||||
* Converts {@link Ciphersuite} to its {@link String} representation.
|
||||
*
|
||||
* @param ciphersuite the {@link Ciphersuite} to be converted.
|
||||
* @return a {@link String} representing the ciphersuite.
|
||||
* @throws AssertionError if the {@link Ciphersuite} is not one of the supported ciphersuites.
|
||||
*/
|
||||
static String convertCiphersuite(Ciphersuite ciphersuite) {
|
||||
switch (ciphersuite) {
|
||||
case CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
|
||||
return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
|
||||
case CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
|
||||
return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
|
||||
case CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
|
||||
return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256";
|
||||
case CIPHERSUITE_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
|
||||
return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
|
||||
case CIPHERSUITE_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
|
||||
return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
|
||||
case CIPHERSUITE_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
|
||||
return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
|
||||
default:
|
||||
throw new AssertionError(
|
||||
String.format("Ciphersuite %d is not supported.", ciphersuite.getNumber()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link TLSVersion} object to its {@link String} representation.
|
||||
|
|
@ -54,6 +29,7 @@ final class ProtoUtil {
|
|||
* @return a {@link String} representation of the TLS version.
|
||||
* @throws AssertionError if the {@code tlsVersion} is not one of the supported TLS versions.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static String convertTlsProtocolVersion(TLSVersion tlsVersion) {
|
||||
switch (tlsVersion) {
|
||||
case TLS_VERSION_1_3:
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ class S2AStub implements AutoCloseable {
|
|||
* @throws IOException if an unexpected response is received, or if the {@code reader} or {@code
|
||||
* writer} calls their {@code onError} method.
|
||||
*/
|
||||
@SuppressWarnings("CheckReturnValue")
|
||||
public SessionResp send(SessionReq req) throws IOException, InterruptedException {
|
||||
if (doneWriting && doneReading) {
|
||||
logger.log(Level.INFO, "Stream to the S2A is closed.");
|
||||
|
|
@ -92,9 +93,8 @@ class S2AStub implements AutoCloseable {
|
|||
createWriterIfNull();
|
||||
if (!responses.isEmpty()) {
|
||||
IOException exception = null;
|
||||
SessionResp resp = null;
|
||||
try {
|
||||
resp = responses.take().getResultOrThrow();
|
||||
responses.take().getResultOrThrow();
|
||||
} catch (IOException e) {
|
||||
exception = e;
|
||||
}
|
||||
|
|
@ -104,14 +104,15 @@ class S2AStub implements AutoCloseable {
|
|||
"Received an unexpected response from a host at the S2A's address. The S2A might be"
|
||||
+ " unavailable."
|
||||
+ exception.getMessage());
|
||||
} else {
|
||||
throw new IOException("Received an unexpected response from a host at the S2A's address.");
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
try {
|
||||
writer.onNext(req);
|
||||
} catch (RuntimeException e) {
|
||||
writer.onError(e);
|
||||
responses.offer(Result.createWithThrowable(e));
|
||||
responses.add(Result.createWithThrowable(e));
|
||||
}
|
||||
try {
|
||||
return responses.take().getResultOrThrow();
|
||||
|
|
@ -159,7 +160,7 @@ class S2AStub implements AutoCloseable {
|
|||
@Override
|
||||
public void onNext(SessionResp resp) {
|
||||
verify(!doneReading);
|
||||
responses.offer(Result.createWithResponse(resp));
|
||||
responses.add(Result.createWithResponse(resp));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -169,7 +170,7 @@ class S2AStub implements AutoCloseable {
|
|||
*/
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
responses.offer(Result.createWithThrowable(t));
|
||||
responses.add(Result.createWithThrowable(t));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -180,7 +181,7 @@ class S2AStub implements AutoCloseable {
|
|||
public void onCompleted() {
|
||||
logger.log(Level.INFO, "Reading from the S2A is complete.");
|
||||
doneReading = true;
|
||||
responses.offer(
|
||||
responses.add(
|
||||
Result.createWithThrowable(
|
||||
new ConnectionClosedException("Reading from the S2A is complete.")));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ public final class AccessTokenManager {
|
|||
private final TokenFetcher tokenFetcher;
|
||||
|
||||
/** Creates an {@code AccessTokenManager} based on the environment where the application runs. */
|
||||
@SuppressWarnings("RethrowReflectiveOperationExceptionAsLinkageError")
|
||||
public static Optional<AccessTokenManager> create() {
|
||||
Optional<?> tokenFetcher;
|
||||
try {
|
||||
|
|
@ -38,7 +37,7 @@ public final class AccessTokenManager {
|
|||
} catch (ClassNotFoundException e) {
|
||||
tokenFetcher = Optional.empty();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new AssertionError(e);
|
||||
throw new LinkageError(e.getMessage(), e);
|
||||
}
|
||||
return tokenFetcher.isPresent()
|
||||
? Optional.of(new AccessTokenManager((TokenFetcher) tokenFetcher.get()))
|
||||
|
|
|
|||
|
|
@ -89,10 +89,10 @@ public final class S2AHandshakerServiceChannelTest {
|
|||
|
||||
/**
|
||||
* Creates two {@code Resoure<Channel>}s for the same target address and verifies that they are
|
||||
* equal.
|
||||
* distinct.
|
||||
*/
|
||||
@Test
|
||||
public void getChannelResource_twoEqualChannels() {
|
||||
public void getChannelResource_twoUnEqualChannels() {
|
||||
Resource<Channel> resource =
|
||||
S2AHandshakerServiceChannel.getChannelResource(
|
||||
"localhost:" + plaintextServer.getPort(),
|
||||
|
|
@ -101,19 +101,19 @@ public final class S2AHandshakerServiceChannelTest {
|
|||
S2AHandshakerServiceChannel.getChannelResource(
|
||||
"localhost:" + plaintextServer.getPort(),
|
||||
InsecureChannelCredentials.create());
|
||||
assertThat(resource).isEqualTo(resourceTwo);
|
||||
assertThat(resource).isNotEqualTo(resourceTwo);
|
||||
}
|
||||
|
||||
/** Same as getChannelResource_twoEqualChannels, but use mTLS. */
|
||||
/** Same as getChannelResource_twoUnEqualChannels, but use mTLS. */
|
||||
@Test
|
||||
public void getChannelResource_mtlsTwoEqualChannels() throws Exception {
|
||||
public void getChannelResource_mtlsTwoUnEqualChannels() throws Exception {
|
||||
Resource<Channel> resource =
|
||||
S2AHandshakerServiceChannel.getChannelResource(
|
||||
"localhost:" + mtlsServer.getPort(), getTlsChannelCredentials());
|
||||
Resource<Channel> resourceTwo =
|
||||
S2AHandshakerServiceChannel.getChannelResource(
|
||||
"localhost:" + mtlsServer.getPort(), getTlsChannelCredentials());
|
||||
assertThat(resource).isEqualTo(resourceTwo);
|
||||
assertThat(resource).isNotEqualTo(resourceTwo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package io.grpc.s2a.handshaker;
|
||||
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.logging.Logger;
|
||||
|
|
@ -38,7 +39,11 @@ public final class FakeS2AServer extends S2AServiceGrpc.S2AServiceImplBase {
|
|||
@Override
|
||||
public void onNext(SessionReq req) {
|
||||
logger.info("Received a request from client.");
|
||||
responseObserver.onNext(writer.handleResponse(req));
|
||||
try {
|
||||
responseObserver.onNext(writer.handleResponse(req));
|
||||
} catch (IOException e) {
|
||||
responseObserver.onError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ import io.grpc.ServerBuilder;
|
|||
import io.grpc.benchmarks.Utils;
|
||||
import io.grpc.s2a.handshaker.ValidatePeerCertificateChainReq.VerificationMode;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
|
@ -45,9 +48,7 @@ public final class FakeS2AServerTest {
|
|||
private static final Logger logger = Logger.getLogger(FakeS2AServerTest.class.getName());
|
||||
|
||||
private static final ImmutableList<ByteString> FAKE_CERT_DER_CHAIN =
|
||||
ImmutableList.of(
|
||||
ByteString.copyFrom(
|
||||
new byte[] {'f', 'a', 'k', 'e', '-', 'd', 'e', 'r', '-', 'c', 'h', 'a', 'i', 'n'}));
|
||||
ImmutableList.of(ByteString.copyFrom("fake-der-chain".getBytes(StandardCharsets.US_ASCII)));
|
||||
private int port;
|
||||
private String serverAddress;
|
||||
private SessionResp response = null;
|
||||
|
|
@ -68,7 +69,7 @@ public final class FakeS2AServerTest {
|
|||
|
||||
@Test
|
||||
public void callS2AServerOnce_getTlsConfiguration_returnsValidResult()
|
||||
throws InterruptedException {
|
||||
throws InterruptedException, IOException {
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
logger.info("Client connecting to: " + serverAddress);
|
||||
ManagedChannel channel =
|
||||
|
|
@ -122,9 +123,12 @@ public final class FakeS2AServerTest {
|
|||
GetTlsConfigurationResp.newBuilder()
|
||||
.setClientTlsConfiguration(
|
||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||
.addCertificateChain(FakeWriter.LEAF_CERT)
|
||||
.addCertificateChain(FakeWriter.INTERMEDIATE_CERT_2)
|
||||
.addCertificateChain(FakeWriter.INTERMEDIATE_CERT_1)
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.leafCertFile.toPath()), StandardCharsets.UTF_8))
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.cert1File.toPath()), StandardCharsets.UTF_8))
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.cert2File.toPath()), StandardCharsets.UTF_8))
|
||||
.setMinTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
||||
.setMaxTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
||||
.addCiphersuites(
|
||||
|
|
|
|||
|
|
@ -23,7 +23,10 @@ import com.google.common.collect.ImmutableMap;
|
|||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import com.google.protobuf.ByteString;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
|
|
@ -50,59 +53,18 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
|||
FAILURE
|
||||
}
|
||||
|
||||
public static final String LEAF_CERT =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIICkDCCAjagAwIBAgIUSAtcrPhNNs1zxv51lIfGOVtkw6QwCgYIKoZIzj0EAwIw\n"
|
||||
+ "QTEXMBUGA1UECgwOc2VjdXJpdHktcmVhbG0xEDAOBgNVBAsMB2NvbnRleHQxFDAS\n"
|
||||
+ "BgorBgEEAdZ5AggBDAQyMDIyMCAXDTIzMDcxNDIyMzYwNFoYDzIwNTAxMTI5MjIz\n"
|
||||
+ "NjA0WjARMQ8wDQYDVQQDDAZ1bnVzZWQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC\n"
|
||||
+ "AAQGFlJpLxJMh4HuUm0DKjnUF7larH3tJvroQ12xpk+pPKQepn4ILoq9lZ8Xd3jz\n"
|
||||
+ "U98eDRXG5f4VjnX98DDHE4Ido4IBODCCATQwDgYDVR0PAQH/BAQDAgeAMCAGA1Ud\n"
|
||||
+ "JQEB/wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMIGxBgNV\n"
|
||||
+ "HREBAf8EgaYwgaOGSnNwaWZmZTovL3NpZ25lci1yb2xlLmNvbnRleHQuc2VjdXJp\n"
|
||||
+ "dHktcmVhbG0ucHJvZC5nb29nbGUuY29tL3JvbGUvbGVhZi1yb2xlgjNzaWduZXIt\n"
|
||||
+ "cm9sZS5jb250ZXh0LnNlY3VyaXR5LXJlYWxtLnByb2Quc3BpZmZlLmdvb2eCIGZx\n"
|
||||
+ "ZG4tb2YtdGhlLW5vZGUucHJvZC5nb29nbGUuY29tMB0GA1UdDgQWBBSWSd5Fw6dI\n"
|
||||
+ "TGpt0m1Uxwf0iKqebzAfBgNVHSMEGDAWgBRm5agVVdpWfRZKM7u6OMuzHhqPcDAK\n"
|
||||
+ "BggqhkjOPQQDAgNIADBFAiB0sjRPSYy2eFq8Y0vQ8QN4AZ2NMajskvxnlifu7O4U\n"
|
||||
+ "RwIhANTh5Fkyx2nMYFfyl+W45dY8ODTw3HnlZ4b51hTAdkWl\n"
|
||||
+ "-----END CERTIFICATE-----";
|
||||
public static final String INTERMEDIATE_CERT_2 =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIICQjCCAeigAwIBAgIUKxXRDlnWXefNV5lj5CwhDuXEq7MwCgYIKoZIzj0EAwIw\n"
|
||||
+ "OzEXMBUGA1UECgwOc2VjdXJpdHktcmVhbG0xEDAOBgNVBAsMB2NvbnRleHQxDjAM\n"
|
||||
+ "BgNVBAMMBTEyMzQ1MCAXDTIzMDcxNDIyMzYwNFoYDzIwNTAxMTI5MjIzNjA0WjBB\n"
|
||||
+ "MRcwFQYDVQQKDA5zZWN1cml0eS1yZWFsbTEQMA4GA1UECwwHY29udGV4dDEUMBIG\n"
|
||||
+ "CisGAQQB1nkCCAEMBDIwMjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT/Zu7x\n"
|
||||
+ "UYVyg+T/vg2H+y4I6t36Kc4qxD0eqqZjRLYBVKkUQHxBqc14t0DpoROMYQCNd4DF\n"
|
||||
+ "pcxv/9m6DaJbRk6Ao4HBMIG+MA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\n"
|
||||
+ "AQH/AgEBMFgGA1UdHgEB/wROMEygSjA1gjNzaWduZXItcm9sZS5jb250ZXh0LnNl\n"
|
||||
+ "Y3VyaXR5LXJlYWxtLnByb2Quc3BpZmZlLmdvb2cwEYIPcHJvZC5nb29nbGUuY29t\n"
|
||||
+ "MB0GA1UdDgQWBBRm5agVVdpWfRZKM7u6OMuzHhqPcDAfBgNVHSMEGDAWgBQcjNAh\n"
|
||||
+ "SCHTj+BW8KrzSSLo2ASEgjAKBggqhkjOPQQDAgNIADBFAiEA6KyGd9VxXDZceMZG\n"
|
||||
+ "IsbC40rtunFjLYI0mjZw9RcRWx8CIHCIiIHxafnDaCi+VB99NZfzAdu37g6pJptB\n"
|
||||
+ "gjIY71MO\n"
|
||||
+ "-----END CERTIFICATE-----";
|
||||
public static final String INTERMEDIATE_CERT_1 =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIICODCCAd6gAwIBAgIUXtZECORWRSKnS9rRTJYkiALUXswwCgYIKoZIzj0EAwIw\n"
|
||||
+ "NzEXMBUGA1UECgwOc2VjdXJpdHktcmVhbG0xDTALBgNVBAsMBHJvb3QxDTALBgNV\n"
|
||||
+ "BAMMBDEyMzQwIBcNMjMwNzE0MjIzNjA0WhgPMjA1MDExMjkyMjM2MDRaMDsxFzAV\n"
|
||||
+ "BgNVBAoMDnNlY3VyaXR5LXJlYWxtMRAwDgYDVQQLDAdjb250ZXh0MQ4wDAYDVQQD\n"
|
||||
+ "DAUxMjM0NTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAycVTZrjockbpD59f1a\n"
|
||||
+ "4l1SNL7nSyXz66Guz4eDveQqLmaMBg7vpACfO4CtiAGnolHEffuRtSkdM434m5En\n"
|
||||
+ "bXCjgcEwgb4wDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQIwWAYD\n"
|
||||
+ "VR0eAQH/BE4wTKBKMDWCM3NpZ25lci1yb2xlLmNvbnRleHQuc2VjdXJpdHktcmVh\n"
|
||||
+ "bG0ucHJvZC5zcGlmZmUuZ29vZzARgg9wcm9kLmdvb2dsZS5jb20wHQYDVR0OBBYE\n"
|
||||
+ "FByM0CFIIdOP4FbwqvNJIujYBISCMB8GA1UdIwQYMBaAFMX+vebuj/lYfYEC23IA\n"
|
||||
+ "8HoIW0HsMAoGCCqGSM49BAMCA0gAMEUCIQCfxeXEBd7UPmeImT16SseCRu/6cHxl\n"
|
||||
+ "kTDsq9sKZ+eXBAIgA+oViAVOUhUQO1/6Mjlczg8NmMy2vNtG4V/7g9dMMVU=\n"
|
||||
+ "-----END CERTIFICATE-----";
|
||||
public static final File leafCertFile =
|
||||
new File("src/test/resources/leaf_cert_ec.pem");
|
||||
public static final File cert2File =
|
||||
new File("src/test/resources/int_cert2_ec.pem");
|
||||
public static final File cert1File =
|
||||
new File("src/test/resources/int_cert1_ec.pem");
|
||||
|
||||
// src/test/resources/leaf_key_ec.pem
|
||||
private static final String PRIVATE_KEY =
|
||||
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgqA2U0ld1OOHLMXWf"
|
||||
+ "uyN4GSaqhhudEIaKkll3rdIq0M+hRANCAAQGFlJpLxJMh4HuUm0DKjnUF7larH3t"
|
||||
+ "JvroQ12xpk+pPKQepn4ILoq9lZ8Xd3jzU98eDRXG5f4VjnX98DDHE4Id";
|
||||
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgR2HBqtWTWu4NLiow"
|
||||
+ "ar8vh+9vAmCONE59C+jXNAb9r8ehRANCAATRM8ozcr8PTOVsZNWh+rTmJ6t+rODu"
|
||||
+ "g3LwWpUQq9h7AddjGlLrrTNrceOyO7nh9aEk5plKhs/h7PO8+vkEFsEx";
|
||||
private static final ImmutableMap<SignatureAlgorithm, String>
|
||||
ALGORITHM_TO_SIGNATURE_INSTANCE_IDENTIFIER =
|
||||
ImmutableMap.of(
|
||||
|
|
@ -167,24 +129,32 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
|||
}
|
||||
|
||||
void sendGetTlsConfigResp() {
|
||||
reader.onNext(
|
||||
SessionResp.newBuilder()
|
||||
.setGetTlsConfigurationResp(
|
||||
GetTlsConfigurationResp.newBuilder()
|
||||
.setClientTlsConfiguration(
|
||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||
.addCertificateChain(LEAF_CERT)
|
||||
.addCertificateChain(INTERMEDIATE_CERT_2)
|
||||
.addCertificateChain(INTERMEDIATE_CERT_1)
|
||||
.setMinTlsVersion(TLS_VERSION_1_3)
|
||||
.setMaxTlsVersion(TLS_VERSION_1_3)
|
||||
.addCiphersuites(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
|
||||
.addCiphersuites(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
|
||||
.addCiphersuites(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)))
|
||||
.build());
|
||||
try {
|
||||
reader.onNext(
|
||||
SessionResp.newBuilder()
|
||||
.setGetTlsConfigurationResp(
|
||||
GetTlsConfigurationResp.newBuilder()
|
||||
.setClientTlsConfiguration(
|
||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.leafCertFile.toPath()), StandardCharsets.UTF_8))
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.cert1File.toPath()), StandardCharsets.UTF_8))
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.cert2File.toPath()), StandardCharsets.UTF_8))
|
||||
.setMinTlsVersion(TLS_VERSION_1_3)
|
||||
.setMaxTlsVersion(TLS_VERSION_1_3)
|
||||
.addCiphersuites(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
|
||||
.addCiphersuites(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
|
||||
.addCiphersuites(
|
||||
Ciphersuite
|
||||
.CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)))
|
||||
.build());
|
||||
} catch (IOException e) {
|
||||
reader.onError(e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isFakeWriterClosed() {
|
||||
|
|
@ -195,7 +165,11 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
|||
public void onNext(SessionReq sessionReq) {
|
||||
switch (behavior) {
|
||||
case OK_STATUS:
|
||||
reader.onNext(handleResponse(sessionReq));
|
||||
try {
|
||||
reader.onNext(handleResponse(sessionReq));
|
||||
} catch (IOException e) {
|
||||
reader.onError(e);
|
||||
}
|
||||
break;
|
||||
case EMPTY_RESPONSE:
|
||||
reader.onNext(SessionResp.getDefaultInstance());
|
||||
|
|
@ -216,25 +190,36 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
|||
reader.onCompleted();
|
||||
break;
|
||||
case BAD_TLS_VERSION_RESPONSE:
|
||||
reader.onNext(
|
||||
SessionResp.newBuilder()
|
||||
.setGetTlsConfigurationResp(
|
||||
GetTlsConfigurationResp.newBuilder()
|
||||
.setClientTlsConfiguration(
|
||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||
.addCertificateChain(LEAF_CERT)
|
||||
.addCertificateChain(INTERMEDIATE_CERT_2)
|
||||
.addCertificateChain(INTERMEDIATE_CERT_1)
|
||||
.setMinTlsVersion(TLS_VERSION_1_3)
|
||||
.setMaxTlsVersion(TLS_VERSION_1_2)))
|
||||
.build());
|
||||
try {
|
||||
reader.onNext(
|
||||
SessionResp.newBuilder()
|
||||
.setGetTlsConfigurationResp(
|
||||
GetTlsConfigurationResp.newBuilder()
|
||||
.setClientTlsConfiguration(
|
||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.leafCertFile.toPath()), StandardCharsets.UTF_8))
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.cert1File.toPath()), StandardCharsets.UTF_8))
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.cert2File.toPath()), StandardCharsets.UTF_8))
|
||||
.setMinTlsVersion(TLS_VERSION_1_3)
|
||||
.setMaxTlsVersion(TLS_VERSION_1_2)))
|
||||
.build());
|
||||
} catch (IOException e) {
|
||||
reader.onError(e);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.onNext(handleResponse(sessionReq));
|
||||
try {
|
||||
reader.onNext(handleResponse(sessionReq));
|
||||
} catch (IOException e) {
|
||||
reader.onError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SessionResp handleResponse(SessionReq sessionReq) {
|
||||
SessionResp handleResponse(SessionReq sessionReq) throws IOException {
|
||||
if (sessionReq.hasGetTlsConfigurationReq()) {
|
||||
return handleGetTlsConfigurationReq(sessionReq.getGetTlsConfigurationReq());
|
||||
}
|
||||
|
|
@ -253,7 +238,8 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
|||
.build();
|
||||
}
|
||||
|
||||
private SessionResp handleGetTlsConfigurationReq(GetTlsConfigurationReq req) {
|
||||
private SessionResp handleGetTlsConfigurationReq(GetTlsConfigurationReq req)
|
||||
throws IOException {
|
||||
if (!req.getConnectionSide().equals(ConnectionSide.CONNECTION_SIDE_CLIENT)) {
|
||||
return SessionResp.newBuilder()
|
||||
.setStatus(
|
||||
|
|
@ -267,9 +253,12 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
|||
GetTlsConfigurationResp.newBuilder()
|
||||
.setClientTlsConfiguration(
|
||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||
.addCertificateChain(LEAF_CERT)
|
||||
.addCertificateChain(INTERMEDIATE_CERT_2)
|
||||
.addCertificateChain(INTERMEDIATE_CERT_1)
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.leafCertFile.toPath()), StandardCharsets.UTF_8))
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.cert1File.toPath()), StandardCharsets.UTF_8))
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.cert2File.toPath()), StandardCharsets.UTF_8))
|
||||
.setMinTlsVersion(TLS_VERSION_1_3)
|
||||
.setMaxTlsVersion(TLS_VERSION_1_3)
|
||||
.addCiphersuites(
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package io.grpc.s2a.handshaker;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
import io.grpc.ChannelCredentials;
|
||||
|
|
@ -42,7 +41,6 @@ import io.netty.handler.ssl.OpenSslSessionContext;
|
|||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.ssl.SslProvider;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.logging.Logger;
|
||||
|
|
@ -58,72 +56,12 @@ import org.junit.runners.JUnit4;
|
|||
public final class IntegrationTest {
|
||||
private static final Logger logger = Logger.getLogger(FakeS2AServer.class.getName());
|
||||
|
||||
private static final String CERT_CHAIN =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIICkDCCAjagAwIBAgIUSAtcrPhNNs1zxv51lIfGOVtkw6QwCgYIKoZIzj0EAwIw\n"
|
||||
+ "QTEXMBUGA1UECgwOc2VjdXJpdHktcmVhbG0xEDAOBgNVBAsMB2NvbnRleHQxFDAS\n"
|
||||
+ "BgorBgEEAdZ5AggBDAQyMDIyMCAXDTIzMDcxNDIyMzYwNFoYDzIwNTAxMTI5MjIz\n"
|
||||
+ "NjA0WjARMQ8wDQYDVQQDDAZ1bnVzZWQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC\n"
|
||||
+ "AAQGFlJpLxJMh4HuUm0DKjnUF7larH3tJvroQ12xpk+pPKQepn4ILoq9lZ8Xd3jz\n"
|
||||
+ "U98eDRXG5f4VjnX98DDHE4Ido4IBODCCATQwDgYDVR0PAQH/BAQDAgeAMCAGA1Ud\n"
|
||||
+ "JQEB/wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMIGxBgNV\n"
|
||||
+ "HREBAf8EgaYwgaOGSnNwaWZmZTovL3NpZ25lci1yb2xlLmNvbnRleHQuc2VjdXJp\n"
|
||||
+ "dHktcmVhbG0ucHJvZC5nb29nbGUuY29tL3JvbGUvbGVhZi1yb2xlgjNzaWduZXIt\n"
|
||||
+ "cm9sZS5jb250ZXh0LnNlY3VyaXR5LXJlYWxtLnByb2Quc3BpZmZlLmdvb2eCIGZx\n"
|
||||
+ "ZG4tb2YtdGhlLW5vZGUucHJvZC5nb29nbGUuY29tMB0GA1UdDgQWBBSWSd5Fw6dI\n"
|
||||
+ "TGpt0m1Uxwf0iKqebzAfBgNVHSMEGDAWgBRm5agVVdpWfRZKM7u6OMuzHhqPcDAK\n"
|
||||
+ "BggqhkjOPQQDAgNIADBFAiB0sjRPSYy2eFq8Y0vQ8QN4AZ2NMajskvxnlifu7O4U\n"
|
||||
+ "RwIhANTh5Fkyx2nMYFfyl+W45dY8ODTw3HnlZ4b51hTAdkWl\n"
|
||||
+ "-----END CERTIFICATE-----\n"
|
||||
+ "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIICQjCCAeigAwIBAgIUKxXRDlnWXefNV5lj5CwhDuXEq7MwCgYIKoZIzj0EAwIw\n"
|
||||
+ "OzEXMBUGA1UECgwOc2VjdXJpdHktcmVhbG0xEDAOBgNVBAsMB2NvbnRleHQxDjAM\n"
|
||||
+ "BgNVBAMMBTEyMzQ1MCAXDTIzMDcxNDIyMzYwNFoYDzIwNTAxMTI5MjIzNjA0WjBB\n"
|
||||
+ "MRcwFQYDVQQKDA5zZWN1cml0eS1yZWFsbTEQMA4GA1UECwwHY29udGV4dDEUMBIG\n"
|
||||
+ "CisGAQQB1nkCCAEMBDIwMjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT/Zu7x\n"
|
||||
+ "UYVyg+T/vg2H+y4I6t36Kc4qxD0eqqZjRLYBVKkUQHxBqc14t0DpoROMYQCNd4DF\n"
|
||||
+ "pcxv/9m6DaJbRk6Ao4HBMIG+MA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\n"
|
||||
+ "AQH/AgEBMFgGA1UdHgEB/wROMEygSjA1gjNzaWduZXItcm9sZS5jb250ZXh0LnNl\n"
|
||||
+ "Y3VyaXR5LXJlYWxtLnByb2Quc3BpZmZlLmdvb2cwEYIPcHJvZC5nb29nbGUuY29t\n"
|
||||
+ "MB0GA1UdDgQWBBRm5agVVdpWfRZKM7u6OMuzHhqPcDAfBgNVHSMEGDAWgBQcjNAh\n"
|
||||
+ "SCHTj+BW8KrzSSLo2ASEgjAKBggqhkjOPQQDAgNIADBFAiEA6KyGd9VxXDZceMZG\n"
|
||||
+ "IsbC40rtunFjLYI0mjZw9RcRWx8CIHCIiIHxafnDaCi+VB99NZfzAdu37g6pJptB\n"
|
||||
+ "gjIY71MO\n"
|
||||
+ "-----END CERTIFICATE-----\n"
|
||||
+ "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIICODCCAd6gAwIBAgIUXtZECORWRSKnS9rRTJYkiALUXswwCgYIKoZIzj0EAwIw\n"
|
||||
+ "NzEXMBUGA1UECgwOc2VjdXJpdHktcmVhbG0xDTALBgNVBAsMBHJvb3QxDTALBgNV\n"
|
||||
+ "BAMMBDEyMzQwIBcNMjMwNzE0MjIzNjA0WhgPMjA1MDExMjkyMjM2MDRaMDsxFzAV\n"
|
||||
+ "BgNVBAoMDnNlY3VyaXR5LXJlYWxtMRAwDgYDVQQLDAdjb250ZXh0MQ4wDAYDVQQD\n"
|
||||
+ "DAUxMjM0NTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAycVTZrjockbpD59f1a\n"
|
||||
+ "4l1SNL7nSyXz66Guz4eDveQqLmaMBg7vpACfO4CtiAGnolHEffuRtSkdM434m5En\n"
|
||||
+ "bXCjgcEwgb4wDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQIwWAYD\n"
|
||||
+ "VR0eAQH/BE4wTKBKMDWCM3NpZ25lci1yb2xlLmNvbnRleHQuc2VjdXJpdHktcmVh\n"
|
||||
+ "bG0ucHJvZC5zcGlmZmUuZ29vZzARgg9wcm9kLmdvb2dsZS5jb20wHQYDVR0OBBYE\n"
|
||||
+ "FByM0CFIIdOP4FbwqvNJIujYBISCMB8GA1UdIwQYMBaAFMX+vebuj/lYfYEC23IA\n"
|
||||
+ "8HoIW0HsMAoGCCqGSM49BAMCA0gAMEUCIQCfxeXEBd7UPmeImT16SseCRu/6cHxl\n"
|
||||
+ "kTDsq9sKZ+eXBAIgA+oViAVOUhUQO1/6Mjlczg8NmMy2vNtG4V/7g9dMMVU=\n"
|
||||
+ "-----END CERTIFICATE-----";
|
||||
private static final String ROOT_PEM =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIIBtTCCAVqgAwIBAgIUbAe+8OocndQXRBCElLBxBSdfdV8wCgYIKoZIzj0EAwIw\n"
|
||||
+ "NzEXMBUGA1UECgwOc2VjdXJpdHktcmVhbG0xDTALBgNVBAsMBHJvb3QxDTALBgNV\n"
|
||||
+ "BAMMBDEyMzQwIBcNMjMwNzE0MjIzNjA0WhgPMjA1MDExMjkyMjM2MDRaMDcxFzAV\n"
|
||||
+ "BgNVBAoMDnNlY3VyaXR5LXJlYWxtMQ0wCwYDVQQLDARyb290MQ0wCwYDVQQDDAQx\n"
|
||||
+ "MjM0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaMY2tBW5r1t0+vhayz0ZoGMF\n"
|
||||
+ "boX/ZmmCmIh0iTWg4madvwNOh74CMVVvDUlXZcuVqZ3vVIX/a7PTFVqUwQlKW6NC\n"
|
||||
+ "MEAwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMX+\n"
|
||||
+ "vebuj/lYfYEC23IA8HoIW0HsMAoGCCqGSM49BAMCA0kAMEYCIQDETd27nsUTXKWY\n"
|
||||
+ "CiOno78O09gK95NoTkPU5e2chJYMqAIhALYFAyh7PU5xgFQsN9hiqgsHUc5/pmBG\n"
|
||||
+ "BGjJ1iz8rWGJ\n"
|
||||
+ "-----END CERTIFICATE-----";
|
||||
private static final String PRIVATE_KEY =
|
||||
"-----BEGIN PRIVATE KEY-----\n"
|
||||
+ "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgqA2U0ld1OOHLMXWf\n"
|
||||
+ "uyN4GSaqhhudEIaKkll3rdIq0M+hRANCAAQGFlJpLxJMh4HuUm0DKjnUF7larH3t\n"
|
||||
+ "JvroQ12xpk+pPKQepn4ILoq9lZ8Xd3jzU98eDRXG5f4VjnX98DDHE4Id\n"
|
||||
+ "-----END PRIVATE KEY-----";
|
||||
|
||||
public static final File privateKeyFile =
|
||||
new File("src/test/resources/leaf_key_ec.pem");
|
||||
public static final File rootCertFile =
|
||||
new File("src/test/resources/root_cert_ec.pem");
|
||||
public static final File certChainFile =
|
||||
new File("src/test/resources/cert_chain_ec.pem");
|
||||
private String s2aAddress;
|
||||
private Server s2aServer;
|
||||
private String s2aDelayAddress;
|
||||
|
|
@ -252,13 +190,11 @@ public final class IntegrationTest {
|
|||
|
||||
private static SslContext buildSslContext() throws SSLException {
|
||||
SslContextBuilder sslServerContextBuilder =
|
||||
SslContextBuilder.forServer(
|
||||
new ByteArrayInputStream(CERT_CHAIN.getBytes(UTF_8)),
|
||||
new ByteArrayInputStream(PRIVATE_KEY.getBytes(UTF_8)));
|
||||
SslContextBuilder.forServer(certChainFile, privateKeyFile);
|
||||
SslContext sslServerContext =
|
||||
GrpcSslContexts.configure(sslServerContextBuilder, SslProvider.OPENSSL)
|
||||
.protocols("TLSv1.3", "TLSv1.2")
|
||||
.trustManager(new ByteArrayInputStream(ROOT_PEM.getBytes(UTF_8)))
|
||||
.trustManager(rootCertFile)
|
||||
.clientAuth(ClientAuth.REQUIRE)
|
||||
.build();
|
||||
|
||||
|
|
|
|||
|
|
@ -30,47 +30,6 @@ import org.junit.runners.JUnit4;
|
|||
public final class ProtoUtilTest {
|
||||
@Rule public final Expect expect = Expect.create();
|
||||
|
||||
@Test
|
||||
public void convertCiphersuite_success() {
|
||||
expect
|
||||
.that(
|
||||
ProtoUtil.convertCiphersuite(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256))
|
||||
.isEqualTo("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
|
||||
expect
|
||||
.that(
|
||||
ProtoUtil.convertCiphersuite(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384))
|
||||
.isEqualTo("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
|
||||
expect
|
||||
.that(
|
||||
ProtoUtil.convertCiphersuite(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256))
|
||||
.isEqualTo("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256");
|
||||
expect
|
||||
.that(
|
||||
ProtoUtil.convertCiphersuite(Ciphersuite.CIPHERSUITE_ECDHE_RSA_WITH_AES_128_GCM_SHA256))
|
||||
.isEqualTo("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||
expect
|
||||
.that(
|
||||
ProtoUtil.convertCiphersuite(Ciphersuite.CIPHERSUITE_ECDHE_RSA_WITH_AES_256_GCM_SHA384))
|
||||
.isEqualTo("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384");
|
||||
expect
|
||||
.that(
|
||||
ProtoUtil.convertCiphersuite(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256))
|
||||
.isEqualTo("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertCiphersuite_withUnspecifiedCiphersuite_fails() {
|
||||
AssertionError expected =
|
||||
assertThrows(
|
||||
AssertionError.class,
|
||||
() -> ProtoUtil.convertCiphersuite(Ciphersuite.CIPHERSUITE_UNSPECIFIED));
|
||||
expect.that(expected).hasMessageThat().isEqualTo("Ciphersuite 0 is not supported.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertTlsProtocolVersion_success() {
|
||||
expect
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import io.grpc.s2a.handshaker.S2AIdentity;
|
|||
import io.netty.handler.ssl.OpenSslPrivateKeyMethod;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.cert.CertificateFactory;
|
||||
|
|
@ -61,7 +63,8 @@ public final class S2APrivateKeyMethodTest {
|
|||
private static boolean verifySignature(
|
||||
byte[] dataToSign, byte[] signature, String signatureAlgorithm) throws Exception {
|
||||
Signature sig = Signature.getInstance(signatureAlgorithm);
|
||||
sig.initVerify(extractPublicKeyFromPem(FakeWriter.LEAF_CERT));
|
||||
sig.initVerify(extractPublicKeyFromPem(new String(
|
||||
Files.readAllBytes(FakeWriter.leafCertFile.toPath()), StandardCharsets.UTF_8)));
|
||||
sig.update(dataToSign);
|
||||
return sig.verify(signature);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import io.netty.handler.codec.http2.Http2ConnectionDecoder;
|
|||
import io.netty.handler.codec.http2.Http2ConnectionEncoder;
|
||||
import io.netty.handler.codec.http2.Http2Settings;
|
||||
import io.netty.util.AsciiString;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
|
@ -246,7 +247,11 @@ public class S2AProtocolNegotiatorFactoryTest {
|
|||
return new StreamObserver<SessionReq>() {
|
||||
@Override
|
||||
public void onNext(SessionReq req) {
|
||||
responseObserver.onNext(writer.handleResponse(req));
|
||||
try {
|
||||
responseObserver.onNext(writer.handleResponse(req));
|
||||
} catch (IOException e) {
|
||||
responseObserver.onError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ import io.grpc.s2a.channel.S2AGrpcChannelPool;
|
|||
import io.grpc.s2a.channel.S2AHandshakerServiceChannel;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
|
@ -82,9 +84,12 @@ public class S2AStubTest {
|
|||
GetTlsConfigurationResp.newBuilder()
|
||||
.setClientTlsConfiguration(
|
||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||
.addCertificateChain(FakeWriter.LEAF_CERT)
|
||||
.addCertificateChain(FakeWriter.INTERMEDIATE_CERT_2)
|
||||
.addCertificateChain(FakeWriter.INTERMEDIATE_CERT_1)
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.leafCertFile.toPath()), StandardCharsets.UTF_8))
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.cert1File.toPath()), StandardCharsets.UTF_8))
|
||||
.addCertificateChain(new String(Files.readAllBytes(
|
||||
FakeWriter.cert2File.toPath()), StandardCharsets.UTF_8))
|
||||
.setMinTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
||||
.setMaxTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
||||
.addCiphersuites(
|
||||
|
|
@ -189,26 +194,13 @@ public class S2AStubTest {
|
|||
@Test
|
||||
public void send_receiveDelayedResponse() throws Exception {
|
||||
writer.sendGetTlsConfigResp();
|
||||
SessionResp resp = stub.send(SessionReq.getDefaultInstance());
|
||||
SessionResp expected =
|
||||
SessionResp.newBuilder()
|
||||
.setGetTlsConfigurationResp(
|
||||
GetTlsConfigurationResp.newBuilder()
|
||||
.setClientTlsConfiguration(
|
||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||
.addCertificateChain(FakeWriter.LEAF_CERT)
|
||||
.addCertificateChain(FakeWriter.INTERMEDIATE_CERT_2)
|
||||
.addCertificateChain(FakeWriter.INTERMEDIATE_CERT_1)
|
||||
.setMinTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
||||
.setMaxTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
||||
.addCiphersuites(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
|
||||
.addCiphersuites(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
|
||||
.addCiphersuites(
|
||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)))
|
||||
.build();
|
||||
assertThat(resp).ignoringRepeatedFieldOrder().isEqualTo(expected);
|
||||
IOException expectedException =
|
||||
assertThrows(IOException.class, () -> stub.send(SessionReq.getDefaultInstance()));
|
||||
assertThat(expectedException)
|
||||
.hasMessageThat()
|
||||
.contains("Received an unexpected response from a host at the S2A's address.");
|
||||
|
||||
assertThat(stub.getResponses()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -29,4 +29,41 @@ Sign CSRs for server and client
|
|||
```
|
||||
openssl x509 -req -CA root_cert.pem -CAkey root_key.pem -in server.csr -out server_cert.pem -days 7305 -extfile config.cnf -extensions req_ext
|
||||
openssl x509 -req -CA root_cert.pem -CAkey root_key.pem -in client.csr -out client_cert.pem -days 7305
|
||||
```
|
||||
|
||||
Generate self-signed ECDSA root cert
|
||||
|
||||
```
|
||||
openssl ecparam -name prime256v1 -genkey -noout -out temp.pem
|
||||
openssl pkcs8 -topk8 -in temp.pem -out root_key_ec.pem -nocrypt
|
||||
rm temp.pem
|
||||
openssl req -x509 -days 7305 -new -key root_key_ec.pem -nodes -out root_cert_ec.pem -config root_ec.cnf -extensions 'v3_req'
|
||||
```
|
||||
|
||||
Generate a chain of ECDSA certs
|
||||
|
||||
```
|
||||
openssl ecparam -name prime256v1 -genkey -noout -out temp.pem
|
||||
openssl pkcs8 -topk8 -in temp.pem -out int_key2_ec.pem -nocrypt
|
||||
rm temp.pem
|
||||
openssl req -key int_key2_ec.pem -new -out temp.csr -config int_cert2.cnf
|
||||
openssl x509 -req -days 7305 -in temp.csr -CA root_cert_ec.pem -CAkey root_key_ec.pem -CAcreateserial -out int_cert2_ec.pem -extfile int_cert2.cnf -extensions 'v3_req'
|
||||
|
||||
|
||||
openssl ecparam -name prime256v1 -genkey -noout -out temp.pem
|
||||
openssl pkcs8 -topk8 -in temp.pem -out int_key1_ec.pem -nocrypt
|
||||
rm temp.pem
|
||||
openssl req -key int_key1_ec.pem -new -out temp.csr -config int_cert1.cnf
|
||||
openssl x509 -req -days 7305 -in temp.csr -CA int_cert2_ec.pem -CAkey int_key2_ec.pem -CAcreateserial -out int_cert1_ec.pem -extfile int_cert1.cnf -extensions 'v3_req'
|
||||
|
||||
|
||||
openssl ecparam -name prime256v1 -genkey -noout -out temp.pem
|
||||
openssl pkcs8 -topk8 -in temp.pem -out leaf_key_ec.pem -nocrypt
|
||||
rm temp.pem
|
||||
openssl req -key leaf_key_ec.pem -new -out temp.csr -config leaf.cnf
|
||||
openssl x509 -req -days 7305 -in temp.csr -CA int_cert1_ec.pem -CAkey int_key1_ec.pem -CAcreateserial -out leaf_cert_ec.pem -extfile leaf.cnf -extensions 'v3_req'
|
||||
```
|
||||
|
||||
```
|
||||
cat leaf_cert_ec.pem int_cert1_ec.pem int_cert2_ec.pem > cert_chain_ec.pem
|
||||
```
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIB0jCCAXigAwIBAgIUBV1dftEhhEMTI83L6jpeJn2tuyQwCgYIKoZIzj0EAwIw
|
||||
JjEKMAgGA1UECgwBbzELMAkGA1UECwwCb3UxCzAJBgNVBAMMAmNuMB4XDTI0MDkx
|
||||
OTIzMDQwMFoXDTQ0MDkxOTIzMDQwMFowJjEKMAgGA1UECgwBbzELMAkGA1UECwwC
|
||||
b3UxCzAJBgNVBAMMAmNuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0TPKM3K/
|
||||
D0zlbGTVofq05ierfqzg7oNy8FqVEKvYewHXYxpS660za3Hjsju54fWhJOaZSobP
|
||||
4ezzvPr5BBbBMaOBgzCBgDAOBgNVHQ8BAf8EBAMCB4AwIAYDVR0lAQH/BBYwFAYI
|
||||
KwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFPvP7dnB
|
||||
dg8ZoLB0w62tbvoIRRHPMB8GA1UdIwQYMBaAFHeH+MNh2fgyjNHYP9hLAv9Sl1yD
|
||||
MAoGCCqGSM49BAMCA0gAMEUCIBcsImaxeFjxFXCXYNQJnde+rsEOgbeAHrAC0SZQ
|
||||
NlB2AiEA4epDhw/o+6BfgDbqlZsNEHkScPrwupnBQGLQlmNJe2c=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB1zCCAX6gAwIBAgIUW4GYHncSLeb7Tmw7FMjX/DesReIwCgYIKoZIzj0EAwIw
|
||||
JjEKMAgGA1UECgwBbzELMAkGA1UECwwCb3UxCzAJBgNVBAMMAmNuMB4XDTI0MDkx
|
||||
OTIzMDA0MVoXDTQ0MDkxOTIzMDA0MVowJjEKMAgGA1UECgwBbzELMAkGA1UECwwC
|
||||
b3UxCzAJBgNVBAMMAmNuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAqtg2E+h
|
||||
Wfr5dnewqsCLwM0PohkB83Gh7V3i/TPFkNKF/V6pKdz5a3Z8sicG+g7uJX+eyOoD
|
||||
43Z8woO7MgJl8aOBiTCBhjAOBgNVHQ8BAf8EBAMCAQYwIAYDVR0lAQH/BBYwFAYI
|
||||
KwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE
|
||||
FHeH+MNh2fgyjNHYP9hLAv9Sl1yDMB8GA1UdIwQYMBaAFP+PTOryxis9d7HVfqhP
|
||||
MyMEgMZOMAoGCCqGSM49BAMCA0cAMEQCIHbzJvxHMIDPBRi1e047K0mqKKBSfViS
|
||||
guiDSoQ5g5OuAiBT5ePqDLs4PyrK6XFkiEWoRX8Z5T9y419Go+fpLM+DaA==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB1zCCAX6gAwIBAgIUBBKkTrqFxQUist2pK2uj8/DRnKMwCgYIKoZIzj0EAwIw
|
||||
JjEKMAgGA1UECgwBbzELMAkGA1UECwwCb3UxCzAJBgNVBAMMAmNuMB4XDTI0MDkx
|
||||
OTIyNTYwNloXDTQ0MDkxOTIyNTYwNlowJjEKMAgGA1UECgwBbzELMAkGA1UECwwC
|
||||
b3UxCzAJBgNVBAMMAmNuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFW7/Te2z
|
||||
jS8KlpF8RMMYaZtKf6EZlrZIIo5SO9j6baAKXVna9LmDCrzXnOLIeqOuZq0ODizU
|
||||
i4DFALB2yd5BkaOBiTCBhjAOBgNVHQ8BAf8EBAMCAQYwIAYDVR0lAQH/BBYwFAYI
|
||||
KwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYE
|
||||
FP+PTOryxis9d7HVfqhPMyMEgMZOMB8GA1UdIwQYMBaAFFITbB0BULPtynN9SMki
|
||||
lEarWxcKMAoGCCqGSM49BAMCA0cAMEQCIHK4cTTx4Ti7Te9hA9VVtHoMCt5fL4Cl
|
||||
XnQR6D5xW4pPAiAQ+CilQdZUhVK5bU6wbrwLgcwf+40ETK/KASId5970rQ==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
O = o
|
||||
OU = ou
|
||||
CN = cn
|
||||
|
||||
[v3_req]
|
||||
keyUsage = critical, keyCertSign, cRLSign
|
||||
extendedKeyUsage = critical, clientAuth, serverAuth
|
||||
basicConstraints = critical, CA:true, pathlen: 1
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIB1zCCAX6gAwIBAgIUW4GYHncSLeb7Tmw7FMjX/DesReIwCgYIKoZIzj0EAwIw
|
||||
JjEKMAgGA1UECgwBbzELMAkGA1UECwwCb3UxCzAJBgNVBAMMAmNuMB4XDTI0MDkx
|
||||
OTIzMDA0MVoXDTQ0MDkxOTIzMDA0MVowJjEKMAgGA1UECgwBbzELMAkGA1UECwwC
|
||||
b3UxCzAJBgNVBAMMAmNuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAqtg2E+h
|
||||
Wfr5dnewqsCLwM0PohkB83Gh7V3i/TPFkNKF/V6pKdz5a3Z8sicG+g7uJX+eyOoD
|
||||
43Z8woO7MgJl8aOBiTCBhjAOBgNVHQ8BAf8EBAMCAQYwIAYDVR0lAQH/BBYwFAYI
|
||||
KwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE
|
||||
FHeH+MNh2fgyjNHYP9hLAv9Sl1yDMB8GA1UdIwQYMBaAFP+PTOryxis9d7HVfqhP
|
||||
MyMEgMZOMAoGCCqGSM49BAMCA0cAMEQCIHbzJvxHMIDPBRi1e047K0mqKKBSfViS
|
||||
guiDSoQ5g5OuAiBT5ePqDLs4PyrK6XFkiEWoRX8Z5T9y419Go+fpLM+DaA==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
O = o
|
||||
OU = ou
|
||||
CN = cn
|
||||
|
||||
[v3_req]
|
||||
keyUsage = critical, keyCertSign, cRLSign
|
||||
extendedKeyUsage = critical, clientAuth, serverAuth
|
||||
basicConstraints = critical, CA:true, pathlen: 2
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIB1zCCAX6gAwIBAgIUBBKkTrqFxQUist2pK2uj8/DRnKMwCgYIKoZIzj0EAwIw
|
||||
JjEKMAgGA1UECgwBbzELMAkGA1UECwwCb3UxCzAJBgNVBAMMAmNuMB4XDTI0MDkx
|
||||
OTIyNTYwNloXDTQ0MDkxOTIyNTYwNlowJjEKMAgGA1UECgwBbzELMAkGA1UECwwC
|
||||
b3UxCzAJBgNVBAMMAmNuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFW7/Te2z
|
||||
jS8KlpF8RMMYaZtKf6EZlrZIIo5SO9j6baAKXVna9LmDCrzXnOLIeqOuZq0ODizU
|
||||
i4DFALB2yd5BkaOBiTCBhjAOBgNVHQ8BAf8EBAMCAQYwIAYDVR0lAQH/BBYwFAYI
|
||||
KwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYE
|
||||
FP+PTOryxis9d7HVfqhPMyMEgMZOMB8GA1UdIwQYMBaAFFITbB0BULPtynN9SMki
|
||||
lEarWxcKMAoGCCqGSM49BAMCA0cAMEQCIHK4cTTx4Ti7Te9hA9VVtHoMCt5fL4Cl
|
||||
XnQR6D5xW4pPAiAQ+CilQdZUhVK5bU6wbrwLgcwf+40ETK/KASId5970rQ==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgLIQUM1HkFM/LWND8
|
||||
jCZ4wHXjFZ1ZZmQolahkZB0O1VChRANCAAQCq2DYT6FZ+vl2d7CqwIvAzQ+iGQHz
|
||||
caHtXeL9M8WQ0oX9Xqkp3PlrdnyyJwb6Du4lf57I6gPjdnzCg7syAmXx
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGfm6kyaAMMrmYGhS
|
||||
jxprBwtcZdP6qXlU1cVIO5bOT8qhRANCAAQVbv9N7bONLwqWkXxEwxhpm0p/oRmW
|
||||
tkgijlI72PptoApdWdr0uYMKvNec4sh6o65mrQ4OLNSLgMUAsHbJ3kGR
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
O = o
|
||||
OU = ou
|
||||
CN = cn
|
||||
|
||||
[v3_req]
|
||||
keyUsage = critical, digitalSignature
|
||||
extendedKeyUsage = critical, clientAuth, serverAuth
|
||||
basicConstraints = critical, CA:false
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIB0jCCAXigAwIBAgIUBV1dftEhhEMTI83L6jpeJn2tuyQwCgYIKoZIzj0EAwIw
|
||||
JjEKMAgGA1UECgwBbzELMAkGA1UECwwCb3UxCzAJBgNVBAMMAmNuMB4XDTI0MDkx
|
||||
OTIzMDQwMFoXDTQ0MDkxOTIzMDQwMFowJjEKMAgGA1UECgwBbzELMAkGA1UECwwC
|
||||
b3UxCzAJBgNVBAMMAmNuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0TPKM3K/
|
||||
D0zlbGTVofq05ierfqzg7oNy8FqVEKvYewHXYxpS660za3Hjsju54fWhJOaZSobP
|
||||
4ezzvPr5BBbBMaOBgzCBgDAOBgNVHQ8BAf8EBAMCB4AwIAYDVR0lAQH/BBYwFAYI
|
||||
KwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFPvP7dnB
|
||||
dg8ZoLB0w62tbvoIRRHPMB8GA1UdIwQYMBaAFHeH+MNh2fgyjNHYP9hLAv9Sl1yD
|
||||
MAoGCCqGSM49BAMCA0gAMEUCIBcsImaxeFjxFXCXYNQJnde+rsEOgbeAHrAC0SZQ
|
||||
NlB2AiEA4epDhw/o+6BfgDbqlZsNEHkScPrwupnBQGLQlmNJe2c=
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgR2HBqtWTWu4NLiow
|
||||
ar8vh+9vAmCONE59C+jXNAb9r8ehRANCAATRM8ozcr8PTOVsZNWh+rTmJ6t+rODu
|
||||
g3LwWpUQq9h7AddjGlLrrTNrceOyO7nh9aEk5plKhs/h7PO8+vkEFsEx
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIBrzCCAVWgAwIBAgIUGV+9j5V61CZaa6mbrchDag5miEQwCgYIKoZIzj0EAwIw
|
||||
JjEKMAgGA1UECgwBbzELMAkGA1UECwwCb3UxCzAJBgNVBAMMAmNuMB4XDTI0MDkx
|
||||
OTIyNDMwOFoXDTQ0MDkxOTIyNDMwOFowJjEKMAgGA1UECgwBbzELMAkGA1UECwwC
|
||||
b3UxCzAJBgNVBAMMAmNuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDVPIq1ds
|
||||
/MX52CX9YU1RdEeM89YP4o3BN8OiP2O4qcuc11k4Qu4Mo4RWeN9OJpNElTQJ0K8n
|
||||
/rIvbmw8AIMquaNhMF8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdJQQWMBQGCCsGAQUF
|
||||
BwMBBggrBgEFBQcDAjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRSE2wdAVCz
|
||||
7cpzfUjJIpRGq1sXCjAKBggqhkjOPQQDAgNIADBFAiEA1TEfHWArDnepmtMDQ4wd
|
||||
Q3uqPrV2Ye2KMO67/BHEGIQCIFu3JutXYYVU/CinwH89AJW+FJ7zokaPjCDkbiOH
|
||||
+h+H
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
O = o
|
||||
OU = ou
|
||||
CN = cn
|
||||
|
||||
[v3_req]
|
||||
keyUsage = critical, keyCertSign, cRLSign
|
||||
extendedKeyUsage = serverAuth, clientAuth
|
||||
basicConstraints = critical, CA:true
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgd5oZmQBOtMF0xfc3
|
||||
uRuw5EDhA1thJKKeHfrij9FMkfahRANCAAQNU8irV2z8xfnYJf1hTVF0R4zz1g/i
|
||||
jcE3w6I/Y7ipy5zXWThC7gyjhFZ4304mk0SVNAnQryf+si9ubDwAgyq5
|
||||
-----END PRIVATE KEY-----
|
||||
Loading…
Reference in New Issue