Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 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
7 changes: 7 additions & 0 deletions google-cloud-bigtable/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@
<!-- Use client defined default endpoints -->
<!-- Can be overriden on the commandline via `-Dbigtable.cfe-data-endpoint=bigtableadmin.googleapis.com:443` -->
<bigtable.cfe-data-endpoint/>
<bigtable.cfe-jwt-audience/>
<bigtable.cfe-admin-endpoint/>
<bigtable.directpath-data-endpoint/>
<bigtable.directpath-jwt-audience/>
<bigtable.directpath-admin-endpoint/>

<!-- This is used by bigtable-prod-batch-it profile to ensure that tests work on the batch endpoint.
Expand Down Expand Up @@ -425,6 +427,7 @@
<bigtable.env>cloud</bigtable.env>
<bigtable.data-endpoint>${bigtable.cfe-data-endpoint}</bigtable.data-endpoint>
<bigtable.admin-endpoint>${bigtable.cfe-admin-endpoint}</bigtable.admin-endpoint>
<bigtable.data-jwt-audience>${bigtable.cfe-jwt-audience}</bigtable.data-jwt-audience>
<bigtable.enable-grpc-logs>${bigtable.enable-grpc-logs}</bigtable.enable-grpc-logs>
<bigtable.grpc-log-dir>${project.build.directory}/test-grpc-logs/prod-it</bigtable.grpc-log-dir>
</systemPropertyVariables>
Expand Down Expand Up @@ -475,6 +478,7 @@
<bigtable.env>cloud</bigtable.env>
<bigtable.data-endpoint>${bigtable.cfe-data-batch-endpoint}</bigtable.data-endpoint>
<bigtable.admin-endpoint>${bigtable.cfe-admin-endpoint}</bigtable.admin-endpoint>
<bigtable.data-jwt-audience>${bigtable.cfe-jwt-audience}</bigtable.data-jwt-audience>
<bigtable.enable-grpc-logs>${bigtable.enable-grpc-logs}</bigtable.enable-grpc-logs>
<bigtable.grpc-log-dir>${project.build.directory}/test-grpc-logs/prod-batch-it</bigtable.grpc-log-dir>
</systemPropertyVariables>
Expand Down Expand Up @@ -510,6 +514,7 @@
<bigtable.env>cloud</bigtable.env>
<bigtable.data-endpoint>${bigtable.directpath-data-endpoint}</bigtable.data-endpoint>
<bigtable.admin-endpoint>${bigtable.directpath-admin-endpoint}</bigtable.admin-endpoint>
<bigtable.data-jwt-audience>${bigtable.directpath-jwt-audience}</bigtable.data-jwt-audience>
<bigtable.enable-grpc-logs>${bigtable.enable-grpc-logs}</bigtable.enable-grpc-logs>
<bigtable.grpc-log-dir>${project.build.directory}/test-grpc-logs/directpath-it</bigtable.grpc-log-dir>
<bigtable.connection-mode>REQUIRE_DIRECT_PATH</bigtable.connection-mode>
Expand Down Expand Up @@ -551,6 +556,7 @@
<bigtable.env>cloud</bigtable.env>
<bigtable.data-endpoint>${bigtable.cfe-data-endpoint}</bigtable.data-endpoint>
<bigtable.admin-endpoint>${bigtable.cfe-admin-endpoint}</bigtable.admin-endpoint>
<bigtable.data-jwt-audience>${bigtable.cfe-jwt-audience}</bigtable.data-jwt-audience>
<bigtable.enable-grpc-logs>${bigtable.enable-grpc-logs}</bigtable.enable-grpc-logs>
<bigtable.grpc-log-dir>${project.build.directory}/test-grpc-logs/cfe-it</bigtable.grpc-log-dir>
<bigtable.connection-mode>REQUIRE_CFE</bigtable.connection-mode>
Expand Down Expand Up @@ -589,6 +595,7 @@
<bigtable.env>cloud</bigtable.env>
<bigtable.data-endpoint>${bigtable.directpath-data-endpoint}</bigtable.data-endpoint>
<bigtable.admin-endpoint>${bigtable.directpath-admin-endpoint}</bigtable.admin-endpoint>
<bigtable.data-jwt-audience>${bigtable.directpath-jwt-audience}</bigtable.data-jwt-audience>
<bigtable.enable-grpc-logs>${bigtable.enable-grpc-logs}</bigtable.enable-grpc-logs>
<bigtable.grpc-log-dir>${project.build.directory}/test-grpc-logs/directpath-ipv4only-it</bigtable.grpc-log-dir>
<bigtable.connection-mode>REQUIRE_DIRECT_PATH_IPV4</bigtable.connection-mode>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public class BigtableClientContext {

private static final Logger logger = Logger.getLogger(BigtableClientContext.class.getName());

private static final String DEFAULT_DATA_JWT_AUDIENCE = "https://bigtable.googleapis.com/";

@Nullable private final OpenTelemetry openTelemetry;
@Nullable private final OpenTelemetrySdk internalOpenTelemetry;
private final MetricsProvider metricsProvider;
Expand Down Expand Up @@ -228,13 +230,13 @@ private static OpenTelemetry getOpenTelemetryFromMetricsProvider(

private static void patchCredentials(EnhancedBigtableStubSettings.Builder settings)
throws IOException {
int i = settings.getEndpoint().lastIndexOf(":");
String host = settings.getEndpoint().substring(0, i);
String audience = settings.getJwtAudienceMapping().get(host);

if (audience == null) {
return;
// Default jwt audience is always the service name unless it's override to
// test / staging for testing
String audience = DEFAULT_DATA_JWT_AUDIENCE;
if (settings.getJwtAudienceOverride() != null) {
audience = settings.getJwtAudienceOverride();
}
Comment thread
mutianf marked this conversation as resolved.
Outdated

URI audienceUri = null;
try {
audienceUri = new URI(audience);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,19 +249,11 @@ public class EnhancedBigtableStubSettings extends StubSettings<EnhancedBigtableS
.add("https://www.googleapis.com/auth/cloud-platform")
.build();

/**
* In most cases, jwt audience == service name. However in some cases, this is not the case. The
* following mapping is used to patch the audience in a JWT token.
*/
private static final Map<String, String> DEFAULT_JWT_AUDIENCE_MAPPING =
ImmutableMap.of("batch-bigtable.googleapis.com", "https://bigtable.googleapis.com/");

private final String projectId;
private final String instanceId;
private final String appProfileId;
private final boolean isRefreshingChannel;
private ImmutableList<String> primedTableIds;
private final Map<String, String> jwtAudienceMapping;
private final boolean enableRoutingCookie;
private final boolean enableRetryInfo;
private final boolean enableSkipTrailers;
Expand All @@ -287,6 +279,7 @@ public class EnhancedBigtableStubSettings extends StubSettings<EnhancedBigtableS
private final MetricsProvider metricsProvider;
@Nullable private final String metricsEndpoint;
@Nonnull private final InternalMetricsProvider internalMetricsProvider;
private final String jwtAudienceOverride;

private EnhancedBigtableStubSettings(Builder builder) {
super(builder);
Expand All @@ -311,13 +304,13 @@ private EnhancedBigtableStubSettings(Builder builder) {
appProfileId = builder.appProfileId;
isRefreshingChannel = builder.isRefreshingChannel;
primedTableIds = builder.primedTableIds;
jwtAudienceMapping = builder.jwtAudienceMapping;
enableRoutingCookie = builder.enableRoutingCookie;
enableRetryInfo = builder.enableRetryInfo;
enableSkipTrailers = builder.enableSkipTrailers;
metricsProvider = builder.metricsProvider;
metricsEndpoint = builder.metricsEndpoint;
internalMetricsProvider = builder.internalMetricsProvider;
jwtAudienceOverride = builder.jwtAudienceOverride;
Comment thread
mutianf marked this conversation as resolved.
Outdated

// Per method settings.
readRowsSettings = builder.readRowsSettings.build();
Expand Down Expand Up @@ -376,9 +369,14 @@ public List<String> getPrimedTableIds() {
return primedTableIds;
}

/**
* @deprecated This is a no op and will always return an empty map. Audience is always set to
* bigtable service name.
*/
@InternalApi("Used for internal testing")
@Deprecated
Comment thread
mutianf marked this conversation as resolved.
public Map<String, String> getJwtAudienceMapping() {
return jwtAudienceMapping;
return ImmutableMap.of();
}

public MetricsProvider getMetricsProvider() {
Expand Down Expand Up @@ -748,7 +746,7 @@ public static class Builder extends StubSettings.Builder<EnhancedBigtableStubSet
private String appProfileId;
private boolean isRefreshingChannel;
private ImmutableList<String> primedTableIds;
private Map<String, String> jwtAudienceMapping;
private String jwtAudienceOverride;
private boolean enableRoutingCookie;
private boolean enableRetryInfo;
private boolean enableSkipTrailers;
Expand Down Expand Up @@ -789,7 +787,6 @@ private Builder() {
this.appProfileId = SERVER_DEFAULT_APP_PROFILE_ID;
this.isRefreshingChannel = true;
primedTableIds = ImmutableList.of();
jwtAudienceMapping = DEFAULT_JWT_AUDIENCE_MAPPING;
setCredentialsProvider(defaultCredentialsProviderBuilder().build());
this.enableRoutingCookie = true;
this.enableRetryInfo = true;
Expand Down Expand Up @@ -928,12 +925,12 @@ private Builder(EnhancedBigtableStubSettings settings) {
appProfileId = settings.appProfileId;
isRefreshingChannel = settings.isRefreshingChannel;
primedTableIds = settings.primedTableIds;
jwtAudienceMapping = settings.jwtAudienceMapping;
enableRoutingCookie = settings.enableRoutingCookie;
enableRetryInfo = settings.enableRetryInfo;
metricsProvider = settings.metricsProvider;
metricsEndpoint = settings.getMetricsEndpoint();
internalMetricsProvider = settings.internalMetricsProvider;
jwtAudienceOverride = settings.jwtAudienceOverride;

// Per method settings.
readRowsSettings = settings.readRowsSettings.toBuilder();
Expand Down Expand Up @@ -1075,9 +1072,20 @@ public List<String> getPrimedTableIds() {
return primedTableIds;
}

/**
* @deprecated This is a no op. Audience is always set to bigtable service name. Set the
* audience with {@link #setJwtAudienceOverride(String)} instead.
*/
@InternalApi("Used for internal testing")
Comment thread
mutianf marked this conversation as resolved.
@Deprecated
public Builder setJwtAudienceMapping(Map<String, String> jwtAudienceMapping) {
this.jwtAudienceMapping = Preconditions.checkNotNull(jwtAudienceMapping);
return this;
}

/** Set the jwt audience override. */
@InternalApi("Used for internal testing")
public Builder setJwtAudienceOverride(String audienceOverride) {
Comment thread
mutianf marked this conversation as resolved.
Outdated
this.jwtAudienceOverride = audienceOverride;
return this;
}

Expand Down Expand Up @@ -1140,9 +1148,19 @@ public boolean areInternalMetricsEnabled() {
return internalMetricsProvider == DISABLED_INTERNAL_OTEL_PROVIDER;
}

/**
* @deprecated This is a no op and will always return an empty map. Audience is always set to
* bigtable service name.
*/
@InternalApi("Used for internal testing")
@Deprecated
public Map<String, String> getJwtAudienceMapping() {
Comment thread
mutianf marked this conversation as resolved.
return jwtAudienceMapping;
return ImmutableMap.of();
}

/** Return the jwt audience override. */
String getJwtAudienceOverride() {
return this.jwtAudienceOverride;
}

/**
Expand Down Expand Up @@ -1318,7 +1336,6 @@ public String toString() {
.add("appProfileId", appProfileId)
.add("isRefreshingChannel", isRefreshingChannel)
.add("primedTableIds", primedTableIds)
.add("jwtAudienceMapping", jwtAudienceMapping)
.add("enableRoutingCookie", enableRoutingCookie)
.add("enableRetryInfo", enableRetryInfo)
.add("enableSkipTrailers", enableSkipTrailers)
Expand All @@ -1340,6 +1357,7 @@ public String toString() {
.add("metricsProvider", metricsProvider)
.add("metricsEndpoint", metricsEndpoint)
.add("areInternalMetricsEnabled", internalMetricsProvider == DEFAULT_INTERNAL_OTEL_PROVIDER)
.add("jwtAudienceOverride", jwtAudienceOverride)
Comment thread
mutianf marked this conversation as resolved.
Outdated
.add("parent", super.toString())
.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ public void testNewClientsShareTransportChannel() throws Exception {

// Make sure that only 1 instance is created by each provider
Mockito.verify(transportChannelProvider, Mockito.times(1)).getTransportChannel();
Mockito.verify(credentialsProvider, Mockito.times(1)).getCredentials();
// getCredentials was called twice, in patchCredentials and when creating the fixed
// credentials in BigtableClientContext
Mockito.verify(credentialsProvider, Mockito.times(2)).getCredentials();
Mockito.verify(executorProvider, Mockito.times(1)).getExecutor();
Mockito.verify(watchdogProvider, Mockito.times(1)).getWatchdog();
}
Expand Down Expand Up @@ -270,7 +272,9 @@ public void testCreateWithRefreshingChannel() throws Exception {
factory.createForInstance("other-project", "other-instance");

// Make sure that only 1 instance is created by each provider
Mockito.verify(credentialsProvider, Mockito.times(1)).getCredentials();
// getCredentials was called twice, in patchCredentials and when creating the fixed credentials
// in BigtableClientContext
Mockito.verify(credentialsProvider, Mockito.times(2)).getCredentials();
Mockito.verify(executorProvider, Mockito.times(1)).getExecutor();
Mockito.verify(watchdogProvider, Mockito.times(1)).getWatchdog();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,6 @@ public void enableRetryInfoFalseValueTest() throws IOException {
"appProfileId",
"isRefreshingChannel",
"primedTableIds",
"jwtAudienceMapping",
"enableRoutingCookie",
"enableRetryInfo",
"enableSkipTrailers",
Expand All @@ -1013,6 +1012,7 @@ public void enableRetryInfoFalseValueTest() throws IOException {
"metricsProvider",
"metricsEndpoint",
"areInternalMetricsEnabled",
"jwtAudienceOverride",
Comment thread
mutianf marked this conversation as resolved.
Outdated
};

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@
import com.google.cloud.bigtable.data.v2.stub.sql.SqlProtoFactory;
import com.google.cloud.bigtable.data.v2.stub.sql.SqlServerStream;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Queues;
import com.google.common.io.BaseEncoding;
import com.google.protobuf.ByteString;
Expand Down Expand Up @@ -224,8 +223,8 @@ public void testJwtAudience()
String expectedAudience = "http://localaudience";
EnhancedBigtableStubSettings settings =
defaultSettings.toBuilder()
.setJwtAudienceMapping(ImmutableMap.of("localhost", expectedAudience))
.setCredentialsProvider(FixedCredentialsProvider.create(jwtCreds))
.setJwtAudienceOverride(expectedAudience)
.build();
try (EnhancedBigtableStub stub = EnhancedBigtableStub.create(settings)) {
stub.readRowCallable().futureCall(Query.create("fake-table")).get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public boolean apply(InetSocketAddress input) {

private static final String DATA_ENDPOINT_PROPERTY_NAME = "bigtable.data-endpoint";
private static final String ADMIN_ENDPOINT_PROPERTY_NAME = "bigtable.admin-endpoint";
private static final String DATA_JWT_OVERRIDE_PROPERTY_NAME = "bigtable.data-jwt-audience";

private static final String PROJECT_PROPERTY_NAME = "bigtable.project";
private static final String INSTANCE_PROPERTY_NAME = "bigtable.instance";
Expand Down Expand Up @@ -106,6 +107,7 @@ static CloudEnv fromSystemProperties() {
return new CloudEnv(
getOptionalProperty(DATA_ENDPOINT_PROPERTY_NAME, ""),
getOptionalProperty(ADMIN_ENDPOINT_PROPERTY_NAME, ""),
getOptionalProperty(DATA_JWT_OVERRIDE_PROPERTY_NAME, ""),
getOptionalProperty(CMEK_KMS_KEY_PROPERTY_NAME, ""),
getRequiredProperty(PROJECT_PROPERTY_NAME),
getRequiredProperty(INSTANCE_PROPERTY_NAME),
Expand All @@ -117,6 +119,7 @@ static CloudEnv fromSystemProperties() {
private CloudEnv(
@Nullable String dataEndpoint,
@Nullable String adminEndpoint,
@Nullable String jwtAudienceOverride,
@Nullable String kmsKeyName,
String projectId,
String instanceId,
Expand All @@ -137,6 +140,9 @@ private CloudEnv(
if (!Strings.isNullOrEmpty(appProfileId)) {
dataSettings.setAppProfileId(appProfileId);
}
if (!Strings.isNullOrEmpty(jwtAudienceOverride)) {
dataSettings.stubSettings().setJwtAudienceOverride(jwtAudienceOverride);
}

configureConnection(dataSettings.stubSettings());
configureUserAgent(dataSettings.stubSettings());
Expand Down
Loading