Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@

import javax.net.ssl.KeyManagerFactory;

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;

import com.linecorp.armeria.common.AbstractTlsSpec;
import com.linecorp.armeria.common.TlsKeyPair;
import com.linecorp.armeria.common.TlsPeerVerifierFactory;
Expand Down Expand Up @@ -54,14 +58,78 @@ public static ClientTlsSpecBuilder builder() {
return new ClientTlsSpecBuilder();
}

private final Set<String> overrideAlpnProtocols;
private final String endpointIdentificationAlgorithm;

ClientTlsSpec(Set<String> tlsVersions, Set<String> alpnProtocols, Set<String> ciphers,
@Nullable TlsKeyPair tlsKeyPair,
List<X509Certificate> trustedCertificates,
List<TlsPeerVerifierFactory> verifierFactories, TlsEngineType engineType,
Consumer<? super SslContextBuilder> tlsCustomizer,
@Nullable KeyManagerFactory keyManagerFactory) {
super(tlsVersions, alpnProtocols, ciphers, tlsKeyPair, trustedCertificates, verifierFactories,
engineType, tlsCustomizer, keyManagerFactory);
@Nullable KeyManagerFactory keyManagerFactory,
Set<String> overrideAlpnProtocols, String endpointIdentificationAlgorithm) {
super(tlsVersions, alpnProtocols, ciphers, tlsKeyPair,
trustedCertificates, verifierFactories, engineType, tlsCustomizer, keyManagerFactory);
this.overrideAlpnProtocols = ImmutableSet.copyOf(overrideAlpnProtocols);
this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
}

@Override
public Set<String> alpnProtocols() {
if (!overrideAlpnProtocols.isEmpty()) {
return overrideAlpnProtocols;
}
return super.alpnProtocols();
}

Set<String> baseAlpnProtocols() {
return super.alpnProtocols();
}

Set<String> overrideAlpnProtocols() {
return overrideAlpnProtocols;
}

/**
* Returns the endpoint identification algorithm used for JSSE hostname verification.
* An empty string {@code ""} disables JSSE hostname verification.
*/
public String endpointIdentificationAlgorithm() {
return endpointIdentificationAlgorithm;
}

@Override
public boolean equals(@Nullable Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
final ClientTlsSpec that = (ClientTlsSpec) o;
return Objects.equal(overrideAlpnProtocols, that.overrideAlpnProtocols) &&
Objects.equal(endpointIdentificationAlgorithm, that.endpointIdentificationAlgorithm);
}

@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), overrideAlpnProtocols, endpointIdentificationAlgorithm);
}

@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("tlsVersions", tlsVersions())
.add("alpnProtocols", alpnProtocols())
.add("ciphers", ciphers())
.add("tlsKeyPair", tlsKeyPair())
.add("trustedCertificates", trustedCertificates())
.add("verifierFactories", verifierFactories())
.add("engineType", engineType())
.add("tlsCustomizer", tlsCustomizer())
.add("keyManagerFactory", keyManagerFactory())
.add("endpointIdentificationAlgorithm", endpointIdentificationAlgorithm())
.toString();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@

import static java.util.Objects.requireNonNull;

import java.util.Collection;
import java.util.Set;
import java.util.function.Consumer;

import javax.net.ssl.KeyManagerFactory;

import com.google.common.collect.ImmutableSet;

import com.linecorp.armeria.common.AbstractTlsSpecBuilder;
import com.linecorp.armeria.common.SessionProtocol;
import com.linecorp.armeria.common.annotation.Nullable;
Expand All @@ -37,30 +40,45 @@
@UnstableApi
public final class ClientTlsSpecBuilder extends AbstractTlsSpecBuilder<ClientTlsSpecBuilder, ClientTlsSpec> {

private Set<String> alpnProtocols = SslContextUtil.DEFAULT_ALPN_PROTOCOLS;
private Set<String> baseAlpnProtocols = SslContextUtil.DEFAULT_ALPN_PROTOCOLS;
private Set<String> overrideAlpnProtocols = ImmutableSet.of();
private Consumer<? super SslContextBuilder> tlsCustomizer = SslContextUtil.DEFAULT_NOOP_CUSTOMIZER;
@Nullable
private KeyManagerFactory keyManagerFactory;
private String endpointIdentificationAlgorithm = "HTTPS";

ClientTlsSpecBuilder() {}

ClientTlsSpecBuilder(ClientTlsSpec clientTlsSpec) {
super(clientTlsSpec.ciphers(), clientTlsSpec.tlsKeyPair(), clientTlsSpec.trustedCertificates(),
clientTlsSpec.verifierFactories(), clientTlsSpec.engineType());
alpnProtocols = clientTlsSpec.alpnProtocols();
baseAlpnProtocols = clientTlsSpec.baseAlpnProtocols();
overrideAlpnProtocols = clientTlsSpec.overrideAlpnProtocols();
keyManagerFactory = clientTlsSpec.keyManagerFactory();
tlsCustomizer = clientTlsSpec.tlsCustomizer();
endpointIdentificationAlgorithm = clientTlsSpec.endpointIdentificationAlgorithm();
}

ClientTlsSpecBuilder alpnProtocols(SessionProtocol sessionProtocol) {
if (sessionProtocol.isExplicitHttp1()) {
alpnProtocols = SslContextUtil.DEFAULT_HTTP1_ALPN_PROTOCOLS;
baseAlpnProtocols = SslContextUtil.DEFAULT_HTTP1_ALPN_PROTOCOLS;
} else {
alpnProtocols = SslContextUtil.DEFAULT_ALPN_PROTOCOLS;
baseAlpnProtocols = SslContextUtil.DEFAULT_ALPN_PROTOCOLS;
}
return this;
}

/**
* Sets the ALPN protocol names that take precedence over the protocols
* derived from the {@link SessionProtocol}. If not empty, these are returned
* by {@link ClientTlsSpec#alpnProtocols()} instead of the default.
*/
public ClientTlsSpecBuilder alpnProtocols(Collection<String> alpnProtocols) {
requireNonNull(alpnProtocols, "alpnProtocols");
overrideAlpnProtocols = ImmutableSet.copyOf(alpnProtocols);
return this;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

ClientTlsSpecBuilder tlsCustomizer(Consumer<? super SslContextBuilder> tlsCustomizer) {
this.tlsCustomizer = requireNonNull(tlsCustomizer, "tlsCustomizer");
return this;
Expand All @@ -71,13 +89,27 @@ ClientTlsSpecBuilder keyManagerFactory(KeyManagerFactory keyManagerFactory) {
return this;
}

/**
* Sets the endpoint identification algorithm for JSSE hostname verification.
* Use {@code "HTTPS"} (the default) for standard hostname verification, or {@code ""}
* to disable JSSE hostname verification (e.g. when peer identity is verified by a
* custom {@link com.linecorp.armeria.common.TlsPeerVerifierFactory}).
*/
public ClientTlsSpecBuilder endpointIdentificationAlgorithm(String algorithm) {
requireNonNull(algorithm, "algorithm");
endpointIdentificationAlgorithm = algorithm;
return this;
}

/**
* Returns a newly created {@link ClientTlsSpec} with the properties set so far.
*/
@Override
public ClientTlsSpec build() {
return new ClientTlsSpec(SslContextUtil.supportedTlsVersions(engineType().sslProvider()),
alpnProtocols, ciphers(), tlsKeyPair(), trustedCertificates(),
verifierFactories(), engineType(), tlsCustomizer, keyManagerFactory);
baseAlpnProtocols, ciphers(), tlsKeyPair(),
trustedCertificates(), verifierFactories(), engineType(), tlsCustomizer,
keyManagerFactory, overrideAlpnProtocols,
endpointIdentificationAlgorithm);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public final Set<String> tlsVersions() {
/**
* Returns the supported ALPN protocols.
*/
public final Set<String> alpnProtocols() {
public Set<String> alpnProtocols() {
return alpnProtocols;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,6 @@ public final class SslContextUtil {
ImmutableSet.of(ApplicationProtocolNames.HTTP_1_1);
public static final Consumer<? super SslContextBuilder> DEFAULT_NOOP_CUSTOMIZER = ignored -> {};

private static final ApplicationProtocolConfig ALPN_CONFIG = new ApplicationProtocolConfig(
Protocol.ALPN,
// NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers.
SelectorFailureBehavior.NO_ADVERTISE,
// ACCEPT is currently the only mode supported by both OpenSsl and JDK providers.
SelectedListenerFailureBehavior.ACCEPT,
ApplicationProtocolNames.HTTP_2,
ApplicationProtocolNames.HTTP_1_1);

// OpenSSL's default enabled TLSv1.3 ciphers as documented at https://wiki.openssl.org/index.php/TLS1.3
private static final List<String> TLS_V13_CIPHERS = ImmutableList.of("TLS_AES_256_GCM_SHA384",
"TLS_CHACHA20_POLY1305_SHA256",
Expand Down Expand Up @@ -139,7 +130,7 @@ private static SslContext toSslContext0(ClientTlsSpec clientTlsSpec) throws Exce
if (keyPair != null) {
builder.keyManager(keyPair.privateKey(), keyPair.certificateChain());
}
builder.endpointIdentificationAlgorithm("HTTPS");
builder.endpointIdentificationAlgorithm(clientTlsSpec.endpointIdentificationAlgorithm());

applyCommonConfigs(clientTlsSpec, builder);

Expand Down
5 changes: 5 additions & 0 deletions dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ hibernate-validator8 = "8.0.3.Final"
# used by :it:xds-istio
istio = "1.29.1"
j2objc = "3.1"
json-path = "3.0.0"
jackson = "2.21.2"
jakarta-inject = "2.0.1"
jakarta-validation = "3.1.1"
Expand Down Expand Up @@ -591,6 +592,10 @@ version.ref = "hibernate-validator8"
module = "com.google.j2objc:j2objc-annotations"
version.ref = "j2objc"

[libraries.json-path]
module = "com.jayway.jsonpath:json-path"
version.ref = "json-path"

[libraries.jakarta-inject]
module = "jakarta.inject:jakarta.inject-api"
version.ref = "jakarta-inject"
Expand Down
1 change: 0 additions & 1 deletion it/xds-client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ dependencies {
api libs.protobuf.java.util
api libs.controlplane.server
api libs.controlplane.cache
api libs.protoc.pgv.java.stub
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.google.common.escape.Escaper;
import com.google.common.escape.Escapers;
import com.google.protobuf.GeneratedMessage;
import com.google.protobuf.Message;
import com.google.protobuf.util.JsonFormat;
import com.google.protobuf.util.JsonFormat.Parser;
import com.google.protobuf.util.JsonFormat.TypeRegistry;
Expand Down Expand Up @@ -54,10 +54,10 @@ public static Bootstrap fromYaml(String yaml) {
}

@SuppressWarnings("unchecked")
public static <T extends GeneratedMessage> T fromYaml(String yaml, Class<T> clazz) {
final GeneratedMessage.Builder<?> builder;
public static <T extends Message> T fromYaml(String yaml, Class<T> clazz) {
final Message.Builder builder;
try {
builder = (GeneratedMessage.Builder<?>) clazz.getMethod("newBuilder").invoke(null);
builder = (Message.Builder) clazz.getMethod("newBuilder").invoke(null);
final JsonNode jsonNode = mapper.reader().readTree(yaml);
parser.merge(jsonNode.toString(), builder);
} catch (Exception e) {
Expand All @@ -67,10 +67,10 @@ public static <T extends GeneratedMessage> T fromYaml(String yaml, Class<T> claz
}

@SuppressWarnings("unchecked")
public static <T extends GeneratedMessage> T fromJson(String json, Class<T> clazz) {
final GeneratedMessage.Builder<?> builder;
public static <T extends Message> T fromJson(String json, Class<T> clazz) {
final Message.Builder builder;
try {
builder = (GeneratedMessage.Builder<?>) clazz.getMethod("newBuilder").invoke(null);
builder = (Message.Builder) clazz.getMethod("newBuilder").invoke(null);
final JsonNode jsonNode = jsonMapper.reader().readTree(json);
parser.merge(jsonNode.toString(), builder);
} catch (Exception e) {
Expand Down
Loading
Loading