From ac42ba030f81a787d7bae7c3d0f59070ca7633ba Mon Sep 17 00:00:00 2001 From: Ali Beyad Date: Thu, 20 Jul 2023 15:48:26 -0400 Subject: [PATCH] mobile: Adds the ability to configure the SNI for the xDS connection (#28520) Signed-off-by: Ali Beyad --- mobile/library/cc/engine_builder.cc | 10 ++++++++++ mobile/library/cc/engine_builder.h | 6 ++++++ mobile/library/common/jni/jni_interface.cc | 10 +++++++--- .../engine/EnvoyConfiguration.java | 14 ++++++++----- .../envoymobile/engine/JniLibrary.java | 6 +++--- .../impl/NativeCronvoyEngineBuilderImpl.java | 2 +- .../envoyproxy/envoymobile/EngineBuilder.kt | 16 +++++++++++++++ .../library/objective-c/EnvoyConfiguration.h | 2 ++ .../library/objective-c/EnvoyConfiguration.mm | 5 +++++ mobile/library/swift/EngineBuilder.swift | 20 +++++++++++++++++++ mobile/test/cc/unit/envoy_config_test.cc | 8 ++++++++ .../engine/EnvoyConfigurationTest.kt | 2 ++ .../envoymobile/EngineBuilderTest.kt | 2 ++ mobile/test/swift/EngineBuilderTests.swift | 15 ++++++++++++++ 14 files changed, 106 insertions(+), 12 deletions(-) diff --git a/mobile/library/cc/engine_builder.cc b/mobile/library/cc/engine_builder.cc index 9366d72667af..1b7f90531837 100644 --- a/mobile/library/cc/engine_builder.cc +++ b/mobile/library/cc/engine_builder.cc @@ -58,6 +58,11 @@ XdsBuilder& XdsBuilder::setSslRootCerts(std::string root_certs) { return *this; } +XdsBuilder& XdsBuilder::setSni(std::string sni) { + sni_ = std::move(sni); + return *this; +} + XdsBuilder& XdsBuilder::addRuntimeDiscoveryService(std::string resource_name, const int timeout_in_seconds) { rtds_resource_name_ = std::move(resource_name); @@ -96,6 +101,11 @@ void XdsBuilder::build(envoy::config::bootstrap::v3::Bootstrap* bootstrap) const jwt.set_json_key(jwt_token_); jwt.set_token_lifetime_seconds(jwt_token_lifetime_in_seconds_); } + if (!sni_.empty()) { + auto& channel_args = + *grpc_service.mutable_google_grpc()->mutable_channel_args()->mutable_args(); + channel_args["grpc.default_authority"].set_string_value(sni_); + } if (!rtds_resource_name_.empty()) { auto* layered_runtime = bootstrap->mutable_layered_runtime(); diff --git a/mobile/library/cc/engine_builder.h b/mobile/library/cc/engine_builder.h index 3c6a2640b5c2..23582b770857 100644 --- a/mobile/library/cc/engine_builder.h +++ b/mobile/library/cc/engine_builder.h @@ -62,6 +62,11 @@ class XdsBuilder final { // connection. If no root certs are specified, the operating system defaults are used. XdsBuilder& setSslRootCerts(std::string root_certs); + // Sets the SNI (https://datatracker.ietf.org/doc/html/rfc6066#section-3) on the TLS handshake + // and the authority HTTP header. If not set, the SNI is set by default to the xDS server address + // and the authority HTTP header is not set. + XdsBuilder& setSni(std::string sni); + // Adds Runtime Discovery Service (RTDS) to the Runtime layers of the Bootstrap configuration, // to retrieve dynamic runtime configuration via the xDS management server. // @@ -105,6 +110,7 @@ class XdsBuilder final { std::string jwt_token_; int jwt_token_lifetime_in_seconds_ = DefaultJwtTokenLifetimeSeconds; std::string ssl_root_certs_; + std::string sni_; std::string rtds_resource_name_; int rtds_timeout_in_seconds_ = DefaultXdsTimeout; bool enable_cds_ = false; diff --git a/mobile/library/common/jni/jni_interface.cc b/mobile/library/common/jni/jni_interface.cc index 6371db7e7862..bc5c3316030f 100644 --- a/mobile/library/common/jni/jni_interface.cc +++ b/mobile/library/common/jni/jni_interface.cc @@ -1287,9 +1287,9 @@ extern "C" JNIEXPORT jlong JNICALL Java_io_envoyproxy_envoymobile_engine_JniLibr jboolean trust_chain_verification, jobjectArray filter_chain, jobjectArray stat_sinks, jboolean enable_platform_certificates_validation, jobjectArray runtime_guards, jstring rtds_resource_name, jlong rtds_timeout_seconds, jstring xds_address, jlong xds_port, - jstring xds_jwt_token, jlong xds_jwt_token_lifetime, jstring xds_root_certs, jstring node_id, - jstring node_region, jstring node_zone, jstring node_sub_zone, jstring cds_resources_locator, - jlong cds_timeout_seconds, jboolean enable_cds) { + jstring xds_jwt_token, jlong xds_jwt_token_lifetime, jstring xds_root_certs, jstring xds_sni, + jstring node_id, jstring node_region, jstring node_zone, jstring node_sub_zone, + jstring cds_resources_locator, jlong cds_timeout_seconds, jboolean enable_cds) { Envoy::Platform::EngineBuilder builder; configureBuilder( @@ -1316,6 +1316,10 @@ extern "C" JNIEXPORT jlong JNICALL Java_io_envoyproxy_envoymobile_engine_JniLibr if (!native_root_certs.empty()) { xds_builder.setSslRootCerts(std::move(native_root_certs)); } + std::string native_sni = getCppString(env, xds_sni); + if (!native_sni.empty()) { + xds_builder.setSni(std::move(native_sni)); + } std::string native_rtds_resource_name = getCppString(env, rtds_resource_name); if (!native_rtds_resource_name.empty()) { xds_builder.addRuntimeDiscoveryService(std::move(native_rtds_resource_name), diff --git a/mobile/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java b/mobile/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java index 9832b60d4e25..689238af7ee7 100644 --- a/mobile/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java +++ b/mobile/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java @@ -67,6 +67,7 @@ public enum TrustChainVerification { public final String xdsJwtToken; public final Integer xdsJwtTokenLifetime; public final String xdsRootCerts; + public final String xdsSni; public final String nodeId; public final String nodeRegion; public final String nodeZone; @@ -139,6 +140,8 @@ public enum TrustChainVerification { * @param xdsRootCerts the root certificates to use for the TLS * handshake during connection establishment * with the xDS management server. + * @param xdsSni the SNI (server name identification) to + * use for the TLS handshake. * @param nodeId the node ID in the Node metadata. * @param nodeRegion the node region in the Node metadata. * @param nodeZone the node zone in the Node metadata. @@ -165,9 +168,9 @@ public EnvoyConfiguration( Map keyValueStores, List statSinks, Map runtimeGuards, boolean enablePlatformCertificatesValidation, String rtdsResourceName, Integer rtdsTimeoutSeconds, String xdsAddress, Integer xdsPort, - String xdsJwtToken, Integer xdsJwtTokenLifetime, String xdsRootCerts, String nodeId, - String nodeRegion, String nodeZone, String nodeSubZone, String cdsResourcesLocator, - Integer cdsTimeoutSeconds, boolean enableCds) { + String xdsJwtToken, Integer xdsJwtTokenLifetime, String xdsRootCerts, String xdsSni, + String nodeId, String nodeRegion, String nodeZone, String nodeSubZone, + String cdsResourcesLocator, Integer cdsTimeoutSeconds, boolean enableCds) { JniLibrary.load(); this.grpcStatsDomain = grpcStatsDomain; this.connectTimeoutSeconds = connectTimeoutSeconds; @@ -224,6 +227,7 @@ public EnvoyConfiguration( this.xdsJwtToken = xdsJwtToken; this.xdsJwtTokenLifetime = xdsJwtTokenLifetime; this.xdsRootCerts = xdsRootCerts; + this.xdsSni = xdsSni; this.nodeId = nodeId; this.nodeRegion = nodeRegion; this.nodeZone = nodeZone; @@ -254,8 +258,8 @@ public long createBootstrap() { streamIdleTimeoutSeconds, perTryIdleTimeoutSeconds, appVersion, appId, enforceTrustChainVerification, filter_chain, stats_sinks, enablePlatformCertificatesValidation, runtime_guards, rtdsResourceName, rtdsTimeoutSeconds, - xdsAddress, xdsPort, xdsJwtToken, xdsJwtTokenLifetime, xdsRootCerts, nodeId, nodeRegion, - nodeZone, nodeSubZone, cdsResourcesLocator, cdsTimeoutSeconds, enableCds); + xdsAddress, xdsPort, xdsJwtToken, xdsJwtTokenLifetime, xdsRootCerts, xdsSni, nodeId, + nodeRegion, nodeZone, nodeSubZone, cdsResourcesLocator, cdsTimeoutSeconds, enableCds); } static class ConfigurationException extends RuntimeException { diff --git a/mobile/library/java/io/envoyproxy/envoymobile/engine/JniLibrary.java b/mobile/library/java/io/envoyproxy/envoymobile/engine/JniLibrary.java index 98182676420c..b0eb2cc2c104 100644 --- a/mobile/library/java/io/envoyproxy/envoymobile/engine/JniLibrary.java +++ b/mobile/library/java/io/envoyproxy/envoymobile/engine/JniLibrary.java @@ -311,7 +311,7 @@ public static native long createBootstrap( boolean trustChainVerification, byte[][] filterChain, byte[][] statSinks, boolean enablePlatformCertificatesValidation, byte[][] runtimeGuards, String rtdsResourceName, long rtdsTimeoutSeconds, String xdsAddress, long xdsPort, String xdsJwtToken, - long xdsJwtTokenLifetime, String xdsRootCerts, String nodeId, String nodeRegion, - String nodeZone, String nodeSubZone, String cdsResourcesLocator, long cdsTimeoutSeconds, - boolean enableCds); + long xdsJwtTokenLifetime, String xdsRootCerts, String xdsJni, String nodeId, + String nodeRegion, String nodeZone, String nodeSubZone, String cdsResourcesLocator, + long cdsTimeoutSeconds, boolean enableCds); } diff --git a/mobile/library/java/org/chromium/net/impl/NativeCronvoyEngineBuilderImpl.java b/mobile/library/java/org/chromium/net/impl/NativeCronvoyEngineBuilderImpl.java index ef40522f6a20..2593c0812fb1 100644 --- a/mobile/library/java/org/chromium/net/impl/NativeCronvoyEngineBuilderImpl.java +++ b/mobile/library/java/org/chromium/net/impl/NativeCronvoyEngineBuilderImpl.java @@ -133,7 +133,7 @@ mEnableDrainPostDnsRefresh, quicEnabled(), mEnableGzipDecompression, brotliEnabl keyValueStores, statSinks, runtimeGuards, mEnablePlatformCertificatesValidation, /*rtdsResourceName=*/"", /*rtdsTimeoutSeconds=*/0, /*xdsAddress=*/"", /*xdsPort=*/0, /*xdsJwtToken=*/"", /*xdsJwtTokenLifetime=*/0, /*xdsSslRootCerts=*/"", - mNodeId, mNodeRegion, mNodeZone, mNodeSubZone, /*cdsResourcesLocator=*/"", + /*xdsSni=*/"", mNodeId, mNodeRegion, mNodeZone, mNodeSubZone, /*cdsResourcesLocator=*/"", /*cdsTimeoutSeconds=*/0, /*enableCds=*/false); } } diff --git a/mobile/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt b/mobile/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt index d6ddb8bd6bca..b5ced04a1646 100644 --- a/mobile/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt +++ b/mobile/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt @@ -46,6 +46,7 @@ open class XdsBuilder ( internal var jwtToken: String? = null internal var jwtTokenLifetimeInSeconds: Int = DEFAULT_JWT_TOKEN_LIFETIME_IN_SECONDS internal var sslRootCerts: String? = null + internal var sni: String? = null internal var rtdsResourceName: String? = null internal var rtdsTimeoutInSeconds: Int = DEFAULT_XDS_TIMEOUT_IN_SECONDS internal var enableCds: Boolean = false @@ -86,6 +87,20 @@ open class XdsBuilder ( return this } + /** + * Sets the SNI (https://datatracker.ietf.org/doc/html/rfc6066#section-3) on the TLS handshake + * and the authority HTTP header. If not set, the SNI is set by default to the xDS server address + * and the authority HTTP header is not set. + * + * @param sni The SNI value. + * + * @return this builder. + */ + fun setSni(sni: String): XdsBuilder { + this.sni = sni + return this + } + /** * Adds Runtime Discovery Service (RTDS) to the Runtime layers of the Bootstrap configuration, * to retrieve dynamic runtime configuration via the xDS management server. @@ -719,6 +734,7 @@ open class EngineBuilder( xdsBuilder?.jwtToken, xdsBuilder?.jwtTokenLifetimeInSeconds ?: 0, xdsBuilder?.sslRootCerts, + xdsBuilder?.sni, nodeId, nodeRegion, nodeZone, diff --git a/mobile/library/objective-c/EnvoyConfiguration.h b/mobile/library/objective-c/EnvoyConfiguration.h index a1df1950bbc3..4ecb82f0f76b 100644 --- a/mobile/library/objective-c/EnvoyConfiguration.h +++ b/mobile/library/objective-c/EnvoyConfiguration.h @@ -52,6 +52,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, nullable) NSString *xdsJwtToken; @property (nonatomic, assign) UInt32 xdsJwtTokenLifetimeSeconds; @property (nonatomic, strong, nullable) NSString *xdsSslRootCerts; +@property (nonatomic, strong, nullable) NSString *xdsSni; @property (nonatomic, strong, nullable) NSString *rtdsResourceName; @property (nonatomic, assign) UInt32 rtdsTimeoutSeconds; @property (nonatomic, assign) BOOL enableCds; @@ -111,6 +112,7 @@ NS_ASSUME_NONNULL_BEGIN xdsJwtToken:(nullable NSString *)xdsJwtToken xdsJwtTokenLifetimeSeconds:(UInt32)xdsJwtTokenLifetimeSeconds xdsSslRootCerts:(nullable NSString *)xdsSslRootCerts + xdsSni:(nullable NSString *)xdsSni rtdsResourceName:(nullable NSString *)rtdsResourceName rtdsTimeoutSeconds:(UInt32)rtdsTimeoutSeconds enableCds:(BOOL)enableCds diff --git a/mobile/library/objective-c/EnvoyConfiguration.mm b/mobile/library/objective-c/EnvoyConfiguration.mm index b7f62bbc2c2c..b1a70b867609 100644 --- a/mobile/library/objective-c/EnvoyConfiguration.mm +++ b/mobile/library/objective-c/EnvoyConfiguration.mm @@ -116,6 +116,7 @@ - (instancetype)initWithGrpcStatsDomain:(nullable NSString *)grpcStatsDomain xdsJwtToken:(nullable NSString *)xdsJwtToken xdsJwtTokenLifetimeSeconds:(UInt32)xdsJwtTokenLifetimeSeconds xdsSslRootCerts:(nullable NSString *)xdsSslRootCerts + xdsSni:(nullable NSString *)xdsSni rtdsResourceName:(nullable NSString *)rtdsResourceName rtdsTimeoutSeconds:(UInt32)rtdsTimeoutSeconds enableCds:(BOOL)enableCds @@ -168,6 +169,7 @@ - (instancetype)initWithGrpcStatsDomain:(nullable NSString *)grpcStatsDomain self.xdsJwtToken = xdsJwtToken; self.xdsJwtTokenLifetimeSeconds = xdsJwtTokenLifetimeSeconds; self.xdsSslRootCerts = xdsSslRootCerts; + self.xdsSni = xdsSni; self.rtdsResourceName = rtdsResourceName; self.rtdsTimeoutSeconds = rtdsTimeoutSeconds; self.cdsResourcesLocator = cdsResourcesLocator; @@ -267,6 +269,9 @@ - (instancetype)initWithGrpcStatsDomain:(nullable NSString *)grpcStatsDomain if (self.xdsSslRootCerts != nil) { xdsBuilder.setSslRootCerts([self.xdsSslRootCerts toCXXString]); } + if (self.xdsSni != nil) { + xdsBuilder.setSni([self.xdsSni toCXXString]); + } if (self.rtdsResourceName != nil) { xdsBuilder.addRuntimeDiscoveryService([self.rtdsResourceName toCXXString], self.rtdsTimeoutSeconds); diff --git a/mobile/library/swift/EngineBuilder.swift b/mobile/library/swift/EngineBuilder.swift index 1ebb7a473d76..40331f8752ad 100644 --- a/mobile/library/swift/EngineBuilder.swift +++ b/mobile/library/swift/EngineBuilder.swift @@ -22,6 +22,7 @@ open class XdsBuilder: NSObject { var jwtToken: String? var jwtTokenLifetimeInSeconds: UInt32 = XdsBuilder.defaultJwtTokenLifetimeInSeconds var sslRootCerts: String? + var sni: String? var rtdsResourceName: String? var rtdsTimeoutInSeconds: UInt32 = 0 var enableCds: Bool = false @@ -68,6 +69,19 @@ open class XdsBuilder: NSObject { return self } + /// Sets the SNI (https://datatracker.ietf.org/doc/html/rfc6066#section-3) on the TLS handshake + /// and the authority HTTP header. If not set, the SNI is set by default to the xDS server address + /// and the authority HTTP header is not set. + /// + /// - parameter sni: The SNI (server name identification) value. + /// + /// - returns: This builder. + @discardableResult + public func setSni(sni: String) -> Self { + self.sni = sni + return self + } + /// Adds Runtime Discovery Service (RTDS) to the Runtime layers of the Bootstrap configuration, /// to retrieve dynamic runtime configuration via the xDS management server. /// @@ -743,6 +757,7 @@ open class EngineBuilder: NSObject { var xdsJwtToken: String? var xdsJwtTokenLifetimeSeconds: UInt32 = 0 var xdsSslRootCerts: String? + var xdsSni: String? var rtdsResourceName: String? var rtdsTimeoutSeconds: UInt32 = 0 var enableCds: Bool = false @@ -755,6 +770,7 @@ open class EngineBuilder: NSObject { xdsJwtToken = self.xdsBuilder?.jwtToken xdsJwtTokenLifetimeSeconds = self.xdsBuilder?.jwtTokenLifetimeInSeconds ?? 0 xdsSslRootCerts = self.xdsBuilder?.sslRootCerts + xdsSni = self.xdsBuilder?.sni rtdsResourceName = self.xdsBuilder?.rtdsResourceName rtdsTimeoutSeconds = self.xdsBuilder?.rtdsTimeoutInSeconds ?? 0 enableCds = self.xdsBuilder?.enableCds ?? false @@ -805,6 +821,7 @@ open class EngineBuilder: NSObject { xdsJwtToken: xdsJwtToken, xdsJwtTokenLifetimeSeconds: xdsJwtTokenLifetimeSeconds, xdsSslRootCerts: xdsSslRootCerts, + xdsSni: xdsSni, rtdsResourceName: rtdsResourceName, rtdsTimeoutSeconds: rtdsTimeoutSeconds, enableCds: enableCds, @@ -909,6 +926,9 @@ private extension EngineBuilder { if let xdsSslRootCerts = xdsBuilder.sslRootCerts { cxxXdsBuilder.setSslRootCerts(xdsSslRootCerts.toCXX()) } + if let xdsSni = xdsBuilder.sni { + cxxXdsBuilder.setSni(xdsSni.toCXX()) + } if let rtdsResourceName = xdsBuilder.rtdsResourceName { cxxXdsBuilder.addRuntimeDiscoveryService(rtdsResourceName.toCXX(), Int32(xdsBuilder.rtdsTimeoutInSeconds)) diff --git a/mobile/test/cc/unit/envoy_config_test.cc b/mobile/test/cc/unit/envoy_config_test.cc index d2063656bb85..7b6d21fe4520 100644 --- a/mobile/test/cc/unit/envoy_config_test.cc +++ b/mobile/test/cc/unit/envoy_config_test.cc @@ -287,6 +287,7 @@ TEST(TestConfig, XdsConfig) { xds_builder.setJwtAuthenticationToken(/*token=*/"my_jwt_token", /*token_lifetime_in_seconds=*/500); xds_builder.setSslRootCerts(/*root_certs=*/"my_root_cert"); + xds_builder.setSni(/*sni=*/"fake-td.googleapis.com"); engine_builder.setXds(std::move(xds_builder)); bootstrap = engine_builder.generateBootstrap(); auto& ads_config_with_tokens = bootstrap->dynamic_resources().ads_config(); @@ -313,6 +314,13 @@ TEST(TestConfig, XdsConfig) { .service_account_jwt_access() .token_lifetime_seconds(), 500); + EXPECT_EQ(ads_config_with_tokens.grpc_services(0) + .google_grpc() + .channel_args() + .args() + .at("grpc.default_authority") + .string_value(), + "fake-td.googleapis.com"); } TEST(TestConfig, CopyConstructor) { diff --git a/mobile/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt b/mobile/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt index 25d8dfd670c4..cc6e23031af0 100644 --- a/mobile/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt +++ b/mobile/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt @@ -105,6 +105,7 @@ class EnvoyConfigurationTest { xdsJwtToken: String = "", xdsJwtTokenLifetimeSeconds: Int = 0, xdsSslRootCerts: String = "", + xdsSni: String = "", nodeId: String = "", nodeRegion: String = "", nodeZone: String = "", @@ -154,6 +155,7 @@ class EnvoyConfigurationTest { xdsJwtToken, xdsJwtTokenLifetimeSeconds, xdsSslRootCerts, + xdsSni, nodeId, nodeRegion, nodeZone, diff --git a/mobile/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt b/mobile/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt index f727c23dc2ba..6d9ba62a2655 100644 --- a/mobile/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt +++ b/mobile/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt @@ -209,6 +209,7 @@ class EngineBuilderTest { var xdsBuilder = XdsBuilder("fake_test_address", 0) xdsBuilder.setJwtAuthenticationToken("my_jwt_token") xdsBuilder.setSslRootCerts("my_root_certs") + xdsBuilder.setSni("fake_test_address"); xdsBuilder.addRuntimeDiscoveryService("some_rtds_resource") xdsBuilder.addClusterDiscoveryService("xdstp://fake_test_address/envoy.config.cluster.v3.Cluster/xyz") engineBuilder = EngineBuilder(Standard()) @@ -219,6 +220,7 @@ class EngineBuilderTest { assertThat(engine.envoyConfiguration.xdsAddress).isEqualTo("fake_test_address") assertThat(engine.envoyConfiguration.xdsJwtToken).isEqualTo("my_jwt_token") assertThat(engine.envoyConfiguration.xdsRootCerts).isEqualTo("my_root_certs") + assertThat(engine.envoyConfiguration.xdsSni).isEqualTo("fake_test_address") assertThat(engine.envoyConfiguration.rtdsResourceName).isEqualTo("some_rtds_resource") assertThat(engine.envoyConfiguration.cdsResourcesLocator).isEqualTo("xdstp://fake_test_address/envoy.config.cluster.v3.Cluster/xyz") } diff --git a/mobile/test/swift/EngineBuilderTests.swift b/mobile/test/swift/EngineBuilderTests.swift index 5e0ff03e0d69..c534183ff20d 100644 --- a/mobile/test/swift/EngineBuilderTests.swift +++ b/mobile/test/swift/EngineBuilderTests.swift @@ -391,6 +391,21 @@ final class EngineBuilderTests: XCTestCase { XCTAssertTrue(bootstrapDebugDescription.contains("cds_config {")) XCTAssertTrue(bootstrapDebugDescription.contains("initial_fetch_timeout { seconds: 5 }")) } + + func testAddingXdsSecurityConfigurationWhenRunningEnvoy() { + let xdsBuilder = XdsBuilder(xdsServerAddress: "FAKE_SWIFT_ADDRESS", xdsServerPort: 0) + .setJwtAuthenticationToken(token: "fake_jwt_token", tokenLifetimeInSeconds: 12345) + .setSslRootCerts(rootCerts: "fake_ssl_root_certs") + .setSni(sni: "fake_sni_address") + .addRuntimeDiscoveryService(resourceName: "some_rtds_resource", timeoutInSeconds: 14325) + let bootstrapDebugDescription = EngineBuilder() + .addEngineType(MockEnvoyEngine.self) + .setXds(xdsBuilder) + .bootstrapDebugDescription() + XCTAssertTrue(bootstrapDebugDescription.contains("fake_jwt_token")) + XCTAssertTrue(bootstrapDebugDescription.contains("fake_ssl_root_certs")) + XCTAssertTrue(bootstrapDebugDescription.contains("fake_sni_address")) + } #endif func testXDSDefaultValues() {