Skip to content

Commit

Permalink
mobile: Adds authentication token support to the xDS EngineBuilder AP…
Browse files Browse the repository at this point in the history
…Is (envoyproxy#28523)

This change enables passing in an authentication token to the gRPC
headers for authentication with an xDS management server. The invoker
specifies the header key (e.g. `x-goog-api-key`) and value (the
authentication token itself).

This change also updates the GCP Traffic Director integration test to
use API keys (`x-goog-api-key`) for authentication instead of JWT
tokens.

Signed-off-by: Ali Beyad <[email protected]>
  • Loading branch information
abeyad authored Aug 8, 2023
1 parent c29b4ad commit cce97d2
Show file tree
Hide file tree
Showing 15 changed files with 188 additions and 56 deletions.
13 changes: 12 additions & 1 deletion mobile/library/cc/engine_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ namespace Platform {
XdsBuilder::XdsBuilder(std::string xds_server_address, const int xds_server_port)
: xds_server_address_(std::move(xds_server_address)), xds_server_port_(xds_server_port) {}

XdsBuilder& XdsBuilder::setAuthenticationToken(std::string token_header, std::string token) {
authentication_token_header_ = std::move(token_header);
authentication_token_ = std::move(token);
return *this;
}

XdsBuilder& XdsBuilder::setJwtAuthenticationToken(std::string token,
const int token_lifetime_in_seconds) {
jwt_token_ = std::move(token);
Expand Down Expand Up @@ -94,7 +100,12 @@ void XdsBuilder::build(envoy::config::bootstrap::v3::Bootstrap* bootstrap) const
->mutable_root_certs()
->set_inline_string(ssl_root_certs_);
}
if (!jwt_token_.empty()) {

if (!authentication_token_header_.empty() && !authentication_token_.empty()) {
auto* auth_token_metadata = grpc_service.add_initial_metadata();
auth_token_metadata->set_key(authentication_token_header_);
auth_token_metadata->set_value(authentication_token_);
} else if (!jwt_token_.empty()) {
auto& jwt = *grpc_service.mutable_google_grpc()
->add_call_credentials()
->mutable_service_account_jwt_access();
Expand Down
18 changes: 18 additions & 0 deletions mobile/library/cc/engine_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,27 @@ class XdsBuilder final {
// requests.
XdsBuilder(std::string xds_server_address, const int xds_server_port);

// Sets the authentication token in the gRPC headers used to authenticate to the xDS management
// server.
//
// For example, if using API keys to authenticate to Traffic Director on GCP (see
// https://cloud.google.com/docs/authentication/api-keys for details), invoke:
// builder.setAuthenticationToken("x-goog-api-key", api_key_token)
//
// If this method is called, then don't call setJwtAuthenticationToken.
//
// `token_header`: the header name for which the the `token` will be set as a value.
// `token`: the authentication token.
XdsBuilder& setAuthenticationToken(std::string token_header, std::string token);

// Sets JWT as the authentication method to the xDS management server, using the given token.
//
// If setAuthenticationToken is called, then invocations of this method will be ignored.
//
// `token`: the JWT token used to authenticate the client to the xDS management server.
// `token_lifetime_in_seconds`: <optional> the lifetime of the JWT token, in seconds. If none
// (or 0) is specified, then DefaultJwtTokenLifetimeSeconds is used.
// TODO(abeyad): Deprecate and remove this.
XdsBuilder&
setJwtAuthenticationToken(std::string token,
int token_lifetime_in_seconds = DefaultJwtTokenLifetimeSeconds);
Expand Down Expand Up @@ -107,6 +123,8 @@ class XdsBuilder final {

std::string xds_server_address_;
int xds_server_port_;
std::string authentication_token_header_;
std::string authentication_token_;
std::string jwt_token_;
int jwt_token_lifetime_in_seconds_ = DefaultJwtTokenLifetimeSeconds;
std::string ssl_root_certs_;
Expand Down
12 changes: 9 additions & 3 deletions mobile/library/common/jni/jni_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1287,9 +1287,10 @@ 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 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) {
jstring xds_auth_header, jstring xds_auth_token, 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(
Expand All @@ -1308,6 +1309,11 @@ extern "C" JNIEXPORT jlong JNICALL Java_io_envoyproxy_envoymobile_engine_JniLibr
std::string native_xds_address = getCppString(env, xds_address);
if (!native_xds_address.empty()) {
Envoy::Platform::XdsBuilder xds_builder(std::move(native_xds_address), xds_port);
std::string native_xds_auth_header = getCppString(env, xds_auth_header);
if (!native_xds_auth_header.empty()) {
xds_builder.setAuthenticationToken(std::move(native_xds_auth_header),
getCppString(env, xds_auth_token));
}
std::string native_jwt_token = getCppString(env, xds_jwt_token);
if (!native_jwt_token.empty()) {
xds_builder.setJwtAuthenticationToken(std::move(native_jwt_token), xds_jwt_token_lifetime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ public enum TrustChainVerification {
public final Integer rtdsTimeoutSeconds;
public final String xdsAddress;
public final Integer xdsPort;
public final String xdsAuthHeader;
public final String xdsAuthToken;
public final String xdsJwtToken;
public final Integer xdsJwtTokenLifetime;
public final String xdsRootCerts;
Expand Down Expand Up @@ -134,6 +136,11 @@ public enum TrustChainVerification {
* @param rtdsTimeoutSeconds the timeout for RTDS fetches.
* @param xdsAddress the address for the xDS management server.
* @param xdsPort the port for the xDS server.
* @param xdsAuthHeader the HTTP header to use for sending the
* authentication token to the xDS server.
* @param xdsAuthToken the token to send as the authentication
* header value to authenticate with the
* xDS server.
* @param xdsJwtToken the JWT token to use for authenticating
* with the xDS server.
* @param xdsTokenLifetime the lifetime of the JWT token.
Expand Down Expand Up @@ -168,9 +175,10 @@ public EnvoyConfiguration(
Map<String, EnvoyKeyValueStore> keyValueStores, List<String> statSinks,
Map<String, Boolean> runtimeGuards, boolean enablePlatformCertificatesValidation,
String rtdsResourceName, Integer rtdsTimeoutSeconds, String xdsAddress, Integer xdsPort,
String xdsJwtToken, Integer xdsJwtTokenLifetime, String xdsRootCerts, String xdsSni,
String nodeId, String nodeRegion, String nodeZone, String nodeSubZone,
String cdsResourcesLocator, Integer cdsTimeoutSeconds, boolean enableCds) {
String xdsAuthHeader, String xdsAuthToken, 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;
Expand Down Expand Up @@ -224,6 +232,8 @@ public EnvoyConfiguration(
this.rtdsTimeoutSeconds = rtdsTimeoutSeconds;
this.xdsAddress = xdsAddress;
this.xdsPort = xdsPort;
this.xdsAuthHeader = xdsAuthHeader;
this.xdsAuthToken = xdsAuthToken;
this.xdsJwtToken = xdsJwtToken;
this.xdsJwtTokenLifetime = xdsJwtTokenLifetime;
this.xdsRootCerts = xdsRootCerts;
Expand Down Expand Up @@ -258,8 +268,9 @@ public long createBootstrap() {
streamIdleTimeoutSeconds, perTryIdleTimeoutSeconds, appVersion, appId,
enforceTrustChainVerification, filter_chain, stats_sinks,
enablePlatformCertificatesValidation, runtime_guards, rtdsResourceName, rtdsTimeoutSeconds,
xdsAddress, xdsPort, xdsJwtToken, xdsJwtTokenLifetime, xdsRootCerts, xdsSni, nodeId,
nodeRegion, nodeZone, nodeSubZone, cdsResourcesLocator, cdsTimeoutSeconds, enableCds);
xdsAddress, xdsPort, xdsAuthHeader, xdsAuthToken, xdsJwtToken, xdsJwtTokenLifetime,
xdsRootCerts, xdsSni, nodeId, nodeRegion, nodeZone, nodeSubZone, cdsResourcesLocator,
cdsTimeoutSeconds, enableCds);
}

static class ConfigurationException extends RuntimeException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,8 @@ public static native long createBootstrap(
long perTryIdleTimeoutSeconds, String appVersion, String appId,
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 xdsSni, String nodeId,
String nodeRegion, String nodeZone, String nodeSubZone, String cdsResourcesLocator,
long cdsTimeoutSeconds, boolean enableCds);
long rtdsTimeoutSeconds, String xdsAddress, long xdsPort, String xdsAuthenticationHeader,
String xdsAuthenticationToken, String xdsJwtToken, long xdsJwtTokenLifetime,
String xdsRootCerts, String xdsSni, String nodeId, String nodeRegion, String nodeZone,
String nodeSubZone, String cdsResourcesLocator, long cdsTimeoutSeconds, boolean enableCds);
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ mEnableDrainPostDnsRefresh, quicEnabled(), mEnableGzipDecompression, brotliEnabl
mTrustChainVerification, nativeFilterChain, platformFilterChain, stringAccessors,
keyValueStores, statSinks, runtimeGuards, mEnablePlatformCertificatesValidation,
/*rtdsResourceName=*/"", /*rtdsTimeoutSeconds=*/0, /*xdsAddress=*/"",
/*xdsPort=*/0, /*xdsJwtToken=*/"", /*xdsJwtTokenLifetime=*/0, /*xdsSslRootCerts=*/"",
/*xdsPort=*/0, /*xdsAuthenticationHeader=*/"", /*xdsAuthenticationToken=*/"",
/*xdsJwtToken=*/"", /*xdsJwtTokenLifetime=*/0, /*xdsSslRootCerts=*/"",
/*xdsSni=*/"", mNodeId, mNodeRegion, mNodeZone, mNodeSubZone, /*cdsResourcesLocator=*/"",
/*cdsTimeoutSeconds=*/0, /*enableCds=*/false);
}
Expand Down
22 changes: 22 additions & 0 deletions mobile/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ open class XdsBuilder (
private const val DEFAULT_XDS_TIMEOUT_IN_SECONDS: Int = 5
}

internal var authHeader: String? = null
internal var authToken: String? = null
internal var jwtToken: String? = null
internal var jwtTokenLifetimeInSeconds: Int = DEFAULT_JWT_TOKEN_LIFETIME_IN_SECONDS
internal var sslRootCerts: String? = null
Expand All @@ -53,6 +55,24 @@ open class XdsBuilder (
internal var cdsResourcesLocator: String? = null
internal var cdsTimeoutInSeconds: Int = DEFAULT_XDS_TIMEOUT_IN_SECONDS

/**
* Sets the authentication HTTP header and token value for authenticating with the xDS
* management server.
*
* @param header The HTTP authentication header.
* @param token The authentication token to be sent in the header.
*
* @return this builder.
*/
fun setAuthenticationToken(
header: String,
token: String
): XdsBuilder {
this.authHeader = header
this.authToken = token
return this
}

/**
* Sets JWT as the authentication method to the xDS management server, using the given token.
*
Expand Down Expand Up @@ -731,6 +751,8 @@ open class EngineBuilder(
xdsBuilder?.rtdsTimeoutInSeconds ?: 0,
xdsBuilder?.xdsServerAddress,
xdsBuilder?.xdsServerPort ?: 0,
xdsBuilder?.authHeader,
xdsBuilder?.authToken,
xdsBuilder?.jwtToken,
xdsBuilder?.jwtTokenLifetimeInSeconds ?: 0,
xdsBuilder?.sslRootCerts,
Expand Down
4 changes: 4 additions & 0 deletions mobile/library/objective-c/EnvoyConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong, nullable) NSString *nodeSubZone;
@property (nonatomic, strong, nullable) NSString *xdsServerAddress;
@property (nonatomic, assign) UInt32 xdsServerPort;
@property (nonatomic, strong, nullable) NSString *xdsAuthHeader;
@property (nonatomic, strong, nullable) NSString *xdsAuthToken;
@property (nonatomic, strong, nullable) NSString *xdsJwtToken;
@property (nonatomic, assign) UInt32 xdsJwtTokenLifetimeSeconds;
@property (nonatomic, strong, nullable) NSString *xdsSslRootCerts;
Expand Down Expand Up @@ -109,6 +111,8 @@ NS_ASSUME_NONNULL_BEGIN
nodeSubZone:(nullable NSString *)nodeSubZone
xdsServerAddress:(nullable NSString *)xdsServerAddress
xdsServerPort:(UInt32)xdsServerPort
xdsAuthHeader:(nullable NSString *)xdsAuthHeader
xdsAuthToken:(nullable NSString *)xdsAuthToken
xdsJwtToken:(nullable NSString *)xdsJwtToken
xdsJwtTokenLifetimeSeconds:(UInt32)xdsJwtTokenLifetimeSeconds
xdsSslRootCerts:(nullable NSString *)xdsSslRootCerts
Expand Down
8 changes: 8 additions & 0 deletions mobile/library/objective-c/EnvoyConfiguration.mm
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ - (instancetype)initWithGrpcStatsDomain:(nullable NSString *)grpcStatsDomain
nodeSubZone:(nullable NSString *)nodeSubZone
xdsServerAddress:(nullable NSString *)xdsServerAddress
xdsServerPort:(UInt32)xdsServerPort
xdsAuthHeader:(nullable NSString *)xdsAuthHeader
xdsAuthToken:(nullable NSString *)xdsAuthToken
xdsJwtToken:(nullable NSString *)xdsJwtToken
xdsJwtTokenLifetimeSeconds:(UInt32)xdsJwtTokenLifetimeSeconds
xdsSslRootCerts:(nullable NSString *)xdsSslRootCerts
Expand Down Expand Up @@ -166,6 +168,8 @@ - (instancetype)initWithGrpcStatsDomain:(nullable NSString *)grpcStatsDomain
self.nodeSubZone = nodeSubZone;
self.xdsServerAddress = xdsServerAddress;
self.xdsServerPort = xdsServerPort;
self.xdsAuthHeader = xdsAuthHeader;
self.xdsAuthToken = xdsAuthToken;
self.xdsJwtToken = xdsJwtToken;
self.xdsJwtTokenLifetimeSeconds = xdsJwtTokenLifetimeSeconds;
self.xdsSslRootCerts = xdsSslRootCerts;
Expand Down Expand Up @@ -262,6 +266,10 @@ - (instancetype)initWithGrpcStatsDomain:(nullable NSString *)grpcStatsDomain
#ifdef ENVOY_GOOGLE_GRPC
if (self.xdsServerAddress != nil) {
Envoy::Platform::XdsBuilder xdsBuilder([self.xdsServerAddress toCXXString], self.xdsServerPort);
if (self.xdsAuthHeader != nil) {
xdsBuilder.setAuthenticationToken([self.xdsAuthHeader toCXXString],
[self.xdsAuthToken toCXXString]);
}
if (self.xdsJwtToken != nil) {
xdsBuilder.setJwtAuthenticationToken([self.xdsJwtToken toCXXString],
self.xdsJwtTokenLifetimeSeconds);
Expand Down
28 changes: 28 additions & 0 deletions mobile/library/swift/EngineBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ open class XdsBuilder: NSObject {

let xdsServerAddress: String
let xdsServerPort: UInt32
var authHeader: String?
var authToken: String?
var jwtToken: String?
var jwtTokenLifetimeInSeconds: UInt32 = XdsBuilder.defaultJwtTokenLifetimeInSeconds
var sslRootCerts: String?
Expand All @@ -38,6 +40,22 @@ open class XdsBuilder: NSObject {
self.xdsServerPort = xdsServerPort
}

/// Sets the authentication HTTP header and token value for authentication with the xDS
/// management server.
///
/// - parameter header: The HTTP authentication header.
/// - parameter token: The authentication token to be sent in the header.
///
/// - returns: This builder.
@discardableResult
public func setAuthenticationToken(
header: String,
token: String) -> Self {
self.authHeader = header
self.authToken = token
return self
}

/// Sets JWT as the authentication method to the xDS management server, using the given token.
///
/// - parameter token: The JWT token used to authenticate the client to the xDS
Expand Down Expand Up @@ -754,6 +772,8 @@ open class EngineBuilder: NSObject {
func makeConfig() -> EnvoyConfiguration {
var xdsServerAddress: String?
var xdsServerPort: UInt32 = 0
var xdsAuthHeader: String?
var xdsAuthToken: String?
var xdsJwtToken: String?
var xdsJwtTokenLifetimeSeconds: UInt32 = 0
var xdsSslRootCerts: String?
Expand All @@ -767,6 +787,8 @@ open class EngineBuilder: NSObject {
#if ENVOY_GOOGLE_GRPC
xdsServerAddress = self.xdsBuilder?.xdsServerAddress
xdsServerPort = self.xdsBuilder?.xdsServerPort ?? 0
xdsAuthHeader = self.xdsBuilder?.authHeader
xdsAuthToken = self.xdsBuilder?.authToken
xdsJwtToken = self.xdsBuilder?.jwtToken
xdsJwtTokenLifetimeSeconds = self.xdsBuilder?.jwtTokenLifetimeInSeconds ?? 0
xdsSslRootCerts = self.xdsBuilder?.sslRootCerts
Expand Down Expand Up @@ -818,6 +840,8 @@ open class EngineBuilder: NSObject {
nodeSubZone: self.nodeSubZone,
xdsServerAddress: xdsServerAddress,
xdsServerPort: xdsServerPort,
xdsAuthHeader: xdsAuthHeader,
xdsAuthToken: xdsAuthToken,
xdsJwtToken: xdsJwtToken,
xdsJwtTokenLifetimeSeconds: xdsJwtTokenLifetimeSeconds,
xdsSslRootCerts: xdsSslRootCerts,
Expand Down Expand Up @@ -919,6 +943,10 @@ private extension EngineBuilder {
if let xdsBuilder = self.xdsBuilder {
var cxxXdsBuilder = Envoy.Platform.XdsBuilder(xdsBuilder.xdsServerAddress.toCXX(),
Int32(xdsBuilder.xdsServerPort))
if let xdsAuthHeader = xdsBuilder.authHeader {
cxxXdsBuilder.setAuthenticationToken(xdsAuthHeader.toCXX(),
xdsBuilder.authToken?.toCXX() ?? "".toCXX())
}
if let xdsJwtToken = xdsBuilder.jwtToken {
cxxXdsBuilder.setJwtAuthenticationToken(xdsJwtToken.toCXX(),
Int32(xdsBuilder.jwtTokenLifetimeInSeconds))
Expand Down
Loading

0 comments on commit cce97d2

Please sign in to comment.