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 static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import io.grpc.CallOptions;
|
import io.grpc.CallOptions;
|
||||||
import io.grpc.Channel;
|
import io.grpc.Channel;
|
||||||
import io.grpc.ChannelCredentials;
|
import io.grpc.ChannelCredentials;
|
||||||
|
|
@ -30,16 +29,15 @@ import io.grpc.MethodDescriptor;
|
||||||
import io.grpc.internal.SharedResourceHolder.Resource;
|
import io.grpc.internal.SharedResourceHolder.Resource;
|
||||||
import io.grpc.netty.NettyChannelBuilder;
|
import io.grpc.netty.NettyChannelBuilder;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides APIs for managing gRPC channels to S2A servers. Each channel is local and plaintext. If
|
* Provides APIs for managing gRPC channels to an S2A server. Each channel is local and plaintext.
|
||||||
* credentials are provided, they are used to secure the channel.
|
* 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
|
* 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,
|
* 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.
|
* 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
|
@ThreadSafe
|
||||||
public final class S2AHandshakerServiceChannel {
|
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);
|
private static final Duration CHANNEL_SHUTDOWN_TIMEOUT = Duration.ofSeconds(10);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -72,9 +68,7 @@ public final class S2AHandshakerServiceChannel {
|
||||||
public static Resource<Channel> getChannelResource(
|
public static Resource<Channel> getChannelResource(
|
||||||
String s2aAddress, ChannelCredentials s2aChannelCredentials) {
|
String s2aAddress, ChannelCredentials s2aChannelCredentials) {
|
||||||
checkNotNull(s2aAddress);
|
checkNotNull(s2aAddress);
|
||||||
checkNotNull(s2aChannelCredentials);
|
return new ChannelResource(s2aAddress, s2aChannelCredentials);
|
||||||
return SHARED_RESOURCE_CHANNELS.computeIfAbsent(
|
|
||||||
s2aAddress, channelResource -> new ChannelResource(s2aAddress, s2aChannelCredentials));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -16,36 +16,11 @@
|
||||||
|
|
||||||
package io.grpc.s2a.handshaker;
|
package io.grpc.s2a.handshaker;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/** Converts proto messages to Netty strings. */
|
/** Converts proto messages to Netty strings. */
|
||||||
final class ProtoUtil {
|
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.
|
* 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.
|
* @return a {@link String} representation of the TLS version.
|
||||||
* @throws AssertionError if the {@code tlsVersion} is not one of the supported TLS versions.
|
* @throws AssertionError if the {@code tlsVersion} is not one of the supported TLS versions.
|
||||||
*/
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
static String convertTlsProtocolVersion(TLSVersion tlsVersion) {
|
static String convertTlsProtocolVersion(TLSVersion tlsVersion) {
|
||||||
switch (tlsVersion) {
|
switch (tlsVersion) {
|
||||||
case TLS_VERSION_1_3:
|
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
|
* @throws IOException if an unexpected response is received, or if the {@code reader} or {@code
|
||||||
* writer} calls their {@code onError} method.
|
* writer} calls their {@code onError} method.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("CheckReturnValue")
|
||||||
public SessionResp send(SessionReq req) throws IOException, InterruptedException {
|
public SessionResp send(SessionReq req) throws IOException, InterruptedException {
|
||||||
if (doneWriting && doneReading) {
|
if (doneWriting && doneReading) {
|
||||||
logger.log(Level.INFO, "Stream to the S2A is closed.");
|
logger.log(Level.INFO, "Stream to the S2A is closed.");
|
||||||
|
|
@ -92,9 +93,8 @@ class S2AStub implements AutoCloseable {
|
||||||
createWriterIfNull();
|
createWriterIfNull();
|
||||||
if (!responses.isEmpty()) {
|
if (!responses.isEmpty()) {
|
||||||
IOException exception = null;
|
IOException exception = null;
|
||||||
SessionResp resp = null;
|
|
||||||
try {
|
try {
|
||||||
resp = responses.take().getResultOrThrow();
|
responses.take().getResultOrThrow();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
exception = 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"
|
"Received an unexpected response from a host at the S2A's address. The S2A might be"
|
||||||
+ " unavailable."
|
+ " unavailable."
|
||||||
+ exception.getMessage());
|
+ exception.getMessage());
|
||||||
|
} else {
|
||||||
|
throw new IOException("Received an unexpected response from a host at the S2A's address.");
|
||||||
}
|
}
|
||||||
return resp;
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
writer.onNext(req);
|
writer.onNext(req);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
writer.onError(e);
|
writer.onError(e);
|
||||||
responses.offer(Result.createWithThrowable(e));
|
responses.add(Result.createWithThrowable(e));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return responses.take().getResultOrThrow();
|
return responses.take().getResultOrThrow();
|
||||||
|
|
@ -159,7 +160,7 @@ class S2AStub implements AutoCloseable {
|
||||||
@Override
|
@Override
|
||||||
public void onNext(SessionResp resp) {
|
public void onNext(SessionResp resp) {
|
||||||
verify(!doneReading);
|
verify(!doneReading);
|
||||||
responses.offer(Result.createWithResponse(resp));
|
responses.add(Result.createWithResponse(resp));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -169,7 +170,7 @@ class S2AStub implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable t) {
|
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() {
|
public void onCompleted() {
|
||||||
logger.log(Level.INFO, "Reading from the S2A is complete.");
|
logger.log(Level.INFO, "Reading from the S2A is complete.");
|
||||||
doneReading = true;
|
doneReading = true;
|
||||||
responses.offer(
|
responses.add(
|
||||||
Result.createWithThrowable(
|
Result.createWithThrowable(
|
||||||
new ConnectionClosedException("Reading from the S2A is complete.")));
|
new ConnectionClosedException("Reading from the S2A is complete.")));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ public final class AccessTokenManager {
|
||||||
private final TokenFetcher tokenFetcher;
|
private final TokenFetcher tokenFetcher;
|
||||||
|
|
||||||
/** Creates an {@code AccessTokenManager} based on the environment where the application runs. */
|
/** Creates an {@code AccessTokenManager} based on the environment where the application runs. */
|
||||||
@SuppressWarnings("RethrowReflectiveOperationExceptionAsLinkageError")
|
|
||||||
public static Optional<AccessTokenManager> create() {
|
public static Optional<AccessTokenManager> create() {
|
||||||
Optional<?> tokenFetcher;
|
Optional<?> tokenFetcher;
|
||||||
try {
|
try {
|
||||||
|
|
@ -38,7 +37,7 @@ public final class AccessTokenManager {
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
tokenFetcher = Optional.empty();
|
tokenFetcher = Optional.empty();
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
throw new AssertionError(e);
|
throw new LinkageError(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
return tokenFetcher.isPresent()
|
return tokenFetcher.isPresent()
|
||||||
? Optional.of(new AccessTokenManager((TokenFetcher) tokenFetcher.get()))
|
? 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
|
* Creates two {@code Resoure<Channel>}s for the same target address and verifies that they are
|
||||||
* equal.
|
* distinct.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void getChannelResource_twoEqualChannels() {
|
public void getChannelResource_twoUnEqualChannels() {
|
||||||
Resource<Channel> resource =
|
Resource<Channel> resource =
|
||||||
S2AHandshakerServiceChannel.getChannelResource(
|
S2AHandshakerServiceChannel.getChannelResource(
|
||||||
"localhost:" + plaintextServer.getPort(),
|
"localhost:" + plaintextServer.getPort(),
|
||||||
|
|
@ -101,19 +101,19 @@ public final class S2AHandshakerServiceChannelTest {
|
||||||
S2AHandshakerServiceChannel.getChannelResource(
|
S2AHandshakerServiceChannel.getChannelResource(
|
||||||
"localhost:" + plaintextServer.getPort(),
|
"localhost:" + plaintextServer.getPort(),
|
||||||
InsecureChannelCredentials.create());
|
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
|
@Test
|
||||||
public void getChannelResource_mtlsTwoEqualChannels() throws Exception {
|
public void getChannelResource_mtlsTwoUnEqualChannels() throws Exception {
|
||||||
Resource<Channel> resource =
|
Resource<Channel> resource =
|
||||||
S2AHandshakerServiceChannel.getChannelResource(
|
S2AHandshakerServiceChannel.getChannelResource(
|
||||||
"localhost:" + mtlsServer.getPort(), getTlsChannelCredentials());
|
"localhost:" + mtlsServer.getPort(), getTlsChannelCredentials());
|
||||||
Resource<Channel> resourceTwo =
|
Resource<Channel> resourceTwo =
|
||||||
S2AHandshakerServiceChannel.getChannelResource(
|
S2AHandshakerServiceChannel.getChannelResource(
|
||||||
"localhost:" + mtlsServer.getPort(), getTlsChannelCredentials());
|
"localhost:" + mtlsServer.getPort(), getTlsChannelCredentials());
|
||||||
assertThat(resource).isEqualTo(resourceTwo);
|
assertThat(resource).isNotEqualTo(resourceTwo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package io.grpc.s2a.handshaker;
|
package io.grpc.s2a.handshaker;
|
||||||
|
|
||||||
import io.grpc.stub.StreamObserver;
|
import io.grpc.stub.StreamObserver;
|
||||||
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
@ -38,7 +39,11 @@ public final class FakeS2AServer extends S2AServiceGrpc.S2AServiceImplBase {
|
||||||
@Override
|
@Override
|
||||||
public void onNext(SessionReq req) {
|
public void onNext(SessionReq req) {
|
||||||
logger.info("Received a request from client.");
|
logger.info("Received a request from client.");
|
||||||
|
try {
|
||||||
responseObserver.onNext(writer.handleResponse(req));
|
responseObserver.onNext(writer.handleResponse(req));
|
||||||
|
} catch (IOException e) {
|
||||||
|
responseObserver.onError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@ import io.grpc.ServerBuilder;
|
||||||
import io.grpc.benchmarks.Utils;
|
import io.grpc.benchmarks.Utils;
|
||||||
import io.grpc.s2a.handshaker.ValidatePeerCertificateChainReq.VerificationMode;
|
import io.grpc.s2a.handshaker.ValidatePeerCertificateChainReq.VerificationMode;
|
||||||
import io.grpc.stub.StreamObserver;
|
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.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
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 Logger logger = Logger.getLogger(FakeS2AServerTest.class.getName());
|
||||||
|
|
||||||
private static final ImmutableList<ByteString> FAKE_CERT_DER_CHAIN =
|
private static final ImmutableList<ByteString> FAKE_CERT_DER_CHAIN =
|
||||||
ImmutableList.of(
|
ImmutableList.of(ByteString.copyFrom("fake-der-chain".getBytes(StandardCharsets.US_ASCII)));
|
||||||
ByteString.copyFrom(
|
|
||||||
new byte[] {'f', 'a', 'k', 'e', '-', 'd', 'e', 'r', '-', 'c', 'h', 'a', 'i', 'n'}));
|
|
||||||
private int port;
|
private int port;
|
||||||
private String serverAddress;
|
private String serverAddress;
|
||||||
private SessionResp response = null;
|
private SessionResp response = null;
|
||||||
|
|
@ -68,7 +69,7 @@ public final class FakeS2AServerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void callS2AServerOnce_getTlsConfiguration_returnsValidResult()
|
public void callS2AServerOnce_getTlsConfiguration_returnsValidResult()
|
||||||
throws InterruptedException {
|
throws InterruptedException, IOException {
|
||||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
logger.info("Client connecting to: " + serverAddress);
|
logger.info("Client connecting to: " + serverAddress);
|
||||||
ManagedChannel channel =
|
ManagedChannel channel =
|
||||||
|
|
@ -122,9 +123,12 @@ public final class FakeS2AServerTest {
|
||||||
GetTlsConfigurationResp.newBuilder()
|
GetTlsConfigurationResp.newBuilder()
|
||||||
.setClientTlsConfiguration(
|
.setClientTlsConfiguration(
|
||||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||||
.addCertificateChain(FakeWriter.LEAF_CERT)
|
.addCertificateChain(new String(Files.readAllBytes(
|
||||||
.addCertificateChain(FakeWriter.INTERMEDIATE_CERT_2)
|
FakeWriter.leafCertFile.toPath()), StandardCharsets.UTF_8))
|
||||||
.addCertificateChain(FakeWriter.INTERMEDIATE_CERT_1)
|
.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)
|
.setMinTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
||||||
.setMaxTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
.setMaxTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
||||||
.addCiphersuites(
|
.addCiphersuites(
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,10 @@ import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import io.grpc.stub.StreamObserver;
|
import io.grpc.stub.StreamObserver;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
|
|
@ -50,59 +53,18 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
||||||
FAILURE
|
FAILURE
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String LEAF_CERT =
|
public static final File leafCertFile =
|
||||||
"-----BEGIN CERTIFICATE-----\n"
|
new File("src/test/resources/leaf_cert_ec.pem");
|
||||||
+ "MIICkDCCAjagAwIBAgIUSAtcrPhNNs1zxv51lIfGOVtkw6QwCgYIKoZIzj0EAwIw\n"
|
public static final File cert2File =
|
||||||
+ "QTEXMBUGA1UECgwOc2VjdXJpdHktcmVhbG0xEDAOBgNVBAsMB2NvbnRleHQxFDAS\n"
|
new File("src/test/resources/int_cert2_ec.pem");
|
||||||
+ "BgorBgEEAdZ5AggBDAQyMDIyMCAXDTIzMDcxNDIyMzYwNFoYDzIwNTAxMTI5MjIz\n"
|
public static final File cert1File =
|
||||||
+ "NjA0WjARMQ8wDQYDVQQDDAZ1bnVzZWQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC\n"
|
new File("src/test/resources/int_cert1_ec.pem");
|
||||||
+ "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-----";
|
|
||||||
|
|
||||||
|
// src/test/resources/leaf_key_ec.pem
|
||||||
private static final String PRIVATE_KEY =
|
private static final String PRIVATE_KEY =
|
||||||
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgqA2U0ld1OOHLMXWf"
|
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgR2HBqtWTWu4NLiow"
|
||||||
+ "uyN4GSaqhhudEIaKkll3rdIq0M+hRANCAAQGFlJpLxJMh4HuUm0DKjnUF7larH3t"
|
+ "ar8vh+9vAmCONE59C+jXNAb9r8ehRANCAATRM8ozcr8PTOVsZNWh+rTmJ6t+rODu"
|
||||||
+ "JvroQ12xpk+pPKQepn4ILoq9lZ8Xd3jzU98eDRXG5f4VjnX98DDHE4Id";
|
+ "g3LwWpUQq9h7AddjGlLrrTNrceOyO7nh9aEk5plKhs/h7PO8+vkEFsEx";
|
||||||
private static final ImmutableMap<SignatureAlgorithm, String>
|
private static final ImmutableMap<SignatureAlgorithm, String>
|
||||||
ALGORITHM_TO_SIGNATURE_INSTANCE_IDENTIFIER =
|
ALGORITHM_TO_SIGNATURE_INSTANCE_IDENTIFIER =
|
||||||
ImmutableMap.of(
|
ImmutableMap.of(
|
||||||
|
|
@ -167,15 +129,19 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendGetTlsConfigResp() {
|
void sendGetTlsConfigResp() {
|
||||||
|
try {
|
||||||
reader.onNext(
|
reader.onNext(
|
||||||
SessionResp.newBuilder()
|
SessionResp.newBuilder()
|
||||||
.setGetTlsConfigurationResp(
|
.setGetTlsConfigurationResp(
|
||||||
GetTlsConfigurationResp.newBuilder()
|
GetTlsConfigurationResp.newBuilder()
|
||||||
.setClientTlsConfiguration(
|
.setClientTlsConfiguration(
|
||||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||||
.addCertificateChain(LEAF_CERT)
|
.addCertificateChain(new String(Files.readAllBytes(
|
||||||
.addCertificateChain(INTERMEDIATE_CERT_2)
|
FakeWriter.leafCertFile.toPath()), StandardCharsets.UTF_8))
|
||||||
.addCertificateChain(INTERMEDIATE_CERT_1)
|
.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)
|
.setMinTlsVersion(TLS_VERSION_1_3)
|
||||||
.setMaxTlsVersion(TLS_VERSION_1_3)
|
.setMaxTlsVersion(TLS_VERSION_1_3)
|
||||||
.addCiphersuites(
|
.addCiphersuites(
|
||||||
|
|
@ -183,8 +149,12 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
||||||
.addCiphersuites(
|
.addCiphersuites(
|
||||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
|
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
|
||||||
.addCiphersuites(
|
.addCiphersuites(
|
||||||
Ciphersuite.CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)))
|
Ciphersuite
|
||||||
|
.CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)))
|
||||||
.build());
|
.build());
|
||||||
|
} catch (IOException e) {
|
||||||
|
reader.onError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isFakeWriterClosed() {
|
boolean isFakeWriterClosed() {
|
||||||
|
|
@ -195,7 +165,11 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
||||||
public void onNext(SessionReq sessionReq) {
|
public void onNext(SessionReq sessionReq) {
|
||||||
switch (behavior) {
|
switch (behavior) {
|
||||||
case OK_STATUS:
|
case OK_STATUS:
|
||||||
|
try {
|
||||||
reader.onNext(handleResponse(sessionReq));
|
reader.onNext(handleResponse(sessionReq));
|
||||||
|
} catch (IOException e) {
|
||||||
|
reader.onError(e);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EMPTY_RESPONSE:
|
case EMPTY_RESPONSE:
|
||||||
reader.onNext(SessionResp.getDefaultInstance());
|
reader.onNext(SessionResp.getDefaultInstance());
|
||||||
|
|
@ -216,25 +190,36 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
||||||
reader.onCompleted();
|
reader.onCompleted();
|
||||||
break;
|
break;
|
||||||
case BAD_TLS_VERSION_RESPONSE:
|
case BAD_TLS_VERSION_RESPONSE:
|
||||||
|
try {
|
||||||
reader.onNext(
|
reader.onNext(
|
||||||
SessionResp.newBuilder()
|
SessionResp.newBuilder()
|
||||||
.setGetTlsConfigurationResp(
|
.setGetTlsConfigurationResp(
|
||||||
GetTlsConfigurationResp.newBuilder()
|
GetTlsConfigurationResp.newBuilder()
|
||||||
.setClientTlsConfiguration(
|
.setClientTlsConfiguration(
|
||||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||||
.addCertificateChain(LEAF_CERT)
|
.addCertificateChain(new String(Files.readAllBytes(
|
||||||
.addCertificateChain(INTERMEDIATE_CERT_2)
|
FakeWriter.leafCertFile.toPath()), StandardCharsets.UTF_8))
|
||||||
.addCertificateChain(INTERMEDIATE_CERT_1)
|
.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)
|
.setMinTlsVersion(TLS_VERSION_1_3)
|
||||||
.setMaxTlsVersion(TLS_VERSION_1_2)))
|
.setMaxTlsVersion(TLS_VERSION_1_2)))
|
||||||
.build());
|
.build());
|
||||||
|
} catch (IOException e) {
|
||||||
|
reader.onError(e);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
try {
|
||||||
reader.onNext(handleResponse(sessionReq));
|
reader.onNext(handleResponse(sessionReq));
|
||||||
|
} catch (IOException e) {
|
||||||
|
reader.onError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionResp handleResponse(SessionReq sessionReq) {
|
SessionResp handleResponse(SessionReq sessionReq) throws IOException {
|
||||||
if (sessionReq.hasGetTlsConfigurationReq()) {
|
if (sessionReq.hasGetTlsConfigurationReq()) {
|
||||||
return handleGetTlsConfigurationReq(sessionReq.getGetTlsConfigurationReq());
|
return handleGetTlsConfigurationReq(sessionReq.getGetTlsConfigurationReq());
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +238,8 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SessionResp handleGetTlsConfigurationReq(GetTlsConfigurationReq req) {
|
private SessionResp handleGetTlsConfigurationReq(GetTlsConfigurationReq req)
|
||||||
|
throws IOException {
|
||||||
if (!req.getConnectionSide().equals(ConnectionSide.CONNECTION_SIDE_CLIENT)) {
|
if (!req.getConnectionSide().equals(ConnectionSide.CONNECTION_SIDE_CLIENT)) {
|
||||||
return SessionResp.newBuilder()
|
return SessionResp.newBuilder()
|
||||||
.setStatus(
|
.setStatus(
|
||||||
|
|
@ -267,9 +253,12 @@ final class FakeWriter implements StreamObserver<SessionReq> {
|
||||||
GetTlsConfigurationResp.newBuilder()
|
GetTlsConfigurationResp.newBuilder()
|
||||||
.setClientTlsConfiguration(
|
.setClientTlsConfiguration(
|
||||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||||
.addCertificateChain(LEAF_CERT)
|
.addCertificateChain(new String(Files.readAllBytes(
|
||||||
.addCertificateChain(INTERMEDIATE_CERT_2)
|
FakeWriter.leafCertFile.toPath()), StandardCharsets.UTF_8))
|
||||||
.addCertificateChain(INTERMEDIATE_CERT_1)
|
.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)
|
.setMinTlsVersion(TLS_VERSION_1_3)
|
||||||
.setMaxTlsVersion(TLS_VERSION_1_3)
|
.setMaxTlsVersion(TLS_VERSION_1_3)
|
||||||
.addCiphersuites(
|
.addCiphersuites(
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package io.grpc.s2a.handshaker;
|
package io.grpc.s2a.handshaker;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
|
||||||
import io.grpc.ChannelCredentials;
|
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.SslContext;
|
||||||
import io.netty.handler.ssl.SslContextBuilder;
|
import io.netty.handler.ssl.SslContextBuilder;
|
||||||
import io.netty.handler.ssl.SslProvider;
|
import io.netty.handler.ssl.SslProvider;
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.concurrent.FutureTask;
|
import java.util.concurrent.FutureTask;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
@ -58,72 +56,12 @@ import org.junit.runners.JUnit4;
|
||||||
public final class IntegrationTest {
|
public final class IntegrationTest {
|
||||||
private static final Logger logger = Logger.getLogger(FakeS2AServer.class.getName());
|
private static final Logger logger = Logger.getLogger(FakeS2AServer.class.getName());
|
||||||
|
|
||||||
private static final String CERT_CHAIN =
|
public static final File privateKeyFile =
|
||||||
"-----BEGIN CERTIFICATE-----\n"
|
new File("src/test/resources/leaf_key_ec.pem");
|
||||||
+ "MIICkDCCAjagAwIBAgIUSAtcrPhNNs1zxv51lIfGOVtkw6QwCgYIKoZIzj0EAwIw\n"
|
public static final File rootCertFile =
|
||||||
+ "QTEXMBUGA1UECgwOc2VjdXJpdHktcmVhbG0xEDAOBgNVBAsMB2NvbnRleHQxFDAS\n"
|
new File("src/test/resources/root_cert_ec.pem");
|
||||||
+ "BgorBgEEAdZ5AggBDAQyMDIyMCAXDTIzMDcxNDIyMzYwNFoYDzIwNTAxMTI5MjIz\n"
|
public static final File certChainFile =
|
||||||
+ "NjA0WjARMQ8wDQYDVQQDDAZ1bnVzZWQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC\n"
|
new File("src/test/resources/cert_chain_ec.pem");
|
||||||
+ "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-----";
|
|
||||||
|
|
||||||
private String s2aAddress;
|
private String s2aAddress;
|
||||||
private Server s2aServer;
|
private Server s2aServer;
|
||||||
private String s2aDelayAddress;
|
private String s2aDelayAddress;
|
||||||
|
|
@ -252,13 +190,11 @@ public final class IntegrationTest {
|
||||||
|
|
||||||
private static SslContext buildSslContext() throws SSLException {
|
private static SslContext buildSslContext() throws SSLException {
|
||||||
SslContextBuilder sslServerContextBuilder =
|
SslContextBuilder sslServerContextBuilder =
|
||||||
SslContextBuilder.forServer(
|
SslContextBuilder.forServer(certChainFile, privateKeyFile);
|
||||||
new ByteArrayInputStream(CERT_CHAIN.getBytes(UTF_8)),
|
|
||||||
new ByteArrayInputStream(PRIVATE_KEY.getBytes(UTF_8)));
|
|
||||||
SslContext sslServerContext =
|
SslContext sslServerContext =
|
||||||
GrpcSslContexts.configure(sslServerContextBuilder, SslProvider.OPENSSL)
|
GrpcSslContexts.configure(sslServerContextBuilder, SslProvider.OPENSSL)
|
||||||
.protocols("TLSv1.3", "TLSv1.2")
|
.protocols("TLSv1.3", "TLSv1.2")
|
||||||
.trustManager(new ByteArrayInputStream(ROOT_PEM.getBytes(UTF_8)))
|
.trustManager(rootCertFile)
|
||||||
.clientAuth(ClientAuth.REQUIRE)
|
.clientAuth(ClientAuth.REQUIRE)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,47 +30,6 @@ import org.junit.runners.JUnit4;
|
||||||
public final class ProtoUtilTest {
|
public final class ProtoUtilTest {
|
||||||
@Rule public final Expect expect = Expect.create();
|
@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
|
@Test
|
||||||
public void convertTlsProtocolVersion_success() {
|
public void convertTlsProtocolVersion_success() {
|
||||||
expect
|
expect
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ import io.grpc.s2a.handshaker.S2AIdentity;
|
||||||
import io.netty.handler.ssl.OpenSslPrivateKeyMethod;
|
import io.netty.handler.ssl.OpenSslPrivateKeyMethod;
|
||||||
import io.netty.handler.ssl.SslContextBuilder;
|
import io.netty.handler.ssl.SslContextBuilder;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
|
|
@ -61,7 +63,8 @@ public final class S2APrivateKeyMethodTest {
|
||||||
private static boolean verifySignature(
|
private static boolean verifySignature(
|
||||||
byte[] dataToSign, byte[] signature, String signatureAlgorithm) throws Exception {
|
byte[] dataToSign, byte[] signature, String signatureAlgorithm) throws Exception {
|
||||||
Signature sig = Signature.getInstance(signatureAlgorithm);
|
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);
|
sig.update(dataToSign);
|
||||||
return sig.verify(signature);
|
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.Http2ConnectionEncoder;
|
||||||
import io.netty.handler.codec.http2.Http2Settings;
|
import io.netty.handler.codec.http2.Http2Settings;
|
||||||
import io.netty.util.AsciiString;
|
import io.netty.util.AsciiString;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
@ -246,7 +247,11 @@ public class S2AProtocolNegotiatorFactoryTest {
|
||||||
return new StreamObserver<SessionReq>() {
|
return new StreamObserver<SessionReq>() {
|
||||||
@Override
|
@Override
|
||||||
public void onNext(SessionReq req) {
|
public void onNext(SessionReq req) {
|
||||||
|
try {
|
||||||
responseObserver.onNext(writer.handleResponse(req));
|
responseObserver.onNext(writer.handleResponse(req));
|
||||||
|
} catch (IOException e) {
|
||||||
|
responseObserver.onError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ import io.grpc.s2a.channel.S2AGrpcChannelPool;
|
||||||
import io.grpc.s2a.channel.S2AHandshakerServiceChannel;
|
import io.grpc.s2a.channel.S2AHandshakerServiceChannel;
|
||||||
import io.grpc.stub.StreamObserver;
|
import io.grpc.stub.StreamObserver;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -82,9 +84,12 @@ public class S2AStubTest {
|
||||||
GetTlsConfigurationResp.newBuilder()
|
GetTlsConfigurationResp.newBuilder()
|
||||||
.setClientTlsConfiguration(
|
.setClientTlsConfiguration(
|
||||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
||||||
.addCertificateChain(FakeWriter.LEAF_CERT)
|
.addCertificateChain(new String(Files.readAllBytes(
|
||||||
.addCertificateChain(FakeWriter.INTERMEDIATE_CERT_2)
|
FakeWriter.leafCertFile.toPath()), StandardCharsets.UTF_8))
|
||||||
.addCertificateChain(FakeWriter.INTERMEDIATE_CERT_1)
|
.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)
|
.setMinTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
||||||
.setMaxTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
.setMaxTlsVersion(TLSVersion.TLS_VERSION_1_3)
|
||||||
.addCiphersuites(
|
.addCiphersuites(
|
||||||
|
|
@ -189,26 +194,13 @@ public class S2AStubTest {
|
||||||
@Test
|
@Test
|
||||||
public void send_receiveDelayedResponse() throws Exception {
|
public void send_receiveDelayedResponse() throws Exception {
|
||||||
writer.sendGetTlsConfigResp();
|
writer.sendGetTlsConfigResp();
|
||||||
SessionResp resp = stub.send(SessionReq.getDefaultInstance());
|
IOException expectedException =
|
||||||
SessionResp expected =
|
assertThrows(IOException.class, () -> stub.send(SessionReq.getDefaultInstance()));
|
||||||
SessionResp.newBuilder()
|
assertThat(expectedException)
|
||||||
.setGetTlsConfigurationResp(
|
.hasMessageThat()
|
||||||
GetTlsConfigurationResp.newBuilder()
|
.contains("Received an unexpected response from a host at the S2A's address.");
|
||||||
.setClientTlsConfiguration(
|
|
||||||
GetTlsConfigurationResp.ClientTlsConfiguration.newBuilder()
|
assertThat(stub.getResponses()).isEmpty();
|
||||||
.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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -30,3 +30,40 @@ 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 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
|
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