Skip to content

Commit 26da0d3

Browse files
feat: support GDC-H Credentials (#1642)
* chore: initial additions to handle GDC-H API audience * chore: add unit tests for GDC-H * chore: cleanup of logic * chore: decompose tests into separate methods * chore: fix clirr diff check * chore: fmt:format * chore: add support in `ClientSettings` * chore: add showcase IT for GDCH credentials * chore: comments * chore: improve tests * chore: add partial IT for testing context credential * chore: recreate GdchCredentials with audience using convenience method * chore: more readable api audience logic * chore: no wildcard imports * chore: javadoc for public methods * chore: gdch test to use default null initialization * chore: tear down for gdch IT * chore: `assertThrows` for gdch ITs * chore: mvn fmt:format * test: remove context test * docs: explain that audience will be overriden if set through client/stub settings * test: test audience setting should modify initial credentials * chore: clirr check * chore: ignore gdch changes * chore: format * chore: default to endpoint if audience not provided * test: refresh gdch creds to confirm audience works * chore: fmt * chore: fmt * chore: better test names in ClientContextTest * chore: better test names for showcase tests * chore: simplify refresh verification logic * chore: include outcome in gdch it test names * chore: expand comments in GDCH ITs * test: intercept mock transport to verify audience * chore: fmt * chore: move auth test-jar to shared dependencies * chore: cleanup * chore: use inferred version for auth library * deps: update google-auth-java-library to 1.19.0 * choreL fmt ITGdch.java * chore: import auth test-jar using common version variable * chore: remove auth test-jar import from first-party-dependencies * chore: add license headers to new files * chore: revert google-auth-version to be obtained from main branch * chore: correct showcase parent pom indentation * chore: remove resource declaration for native test build
1 parent 41007a9 commit 26da0d3

12 files changed

Lines changed: 602 additions & 1 deletion

File tree

gax-java/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ target
1515

1616
# IntelliJ
1717
.idea
18+
.ijwb
1819
*.iml
1920
out
2021

gax-java/gax/clirr-ignored-differences.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
<className>com/google/api/gax/paging/Page</className>
88
<method>* stream*(*)</method>
99
</difference>
10+
<difference>
11+
<!-- add gdchApiAudience to ClientContext -->
12+
<differenceType>7013</differenceType>
13+
<className>com/google/api/gax/rpc/*</className>
14+
<method>* *Gdch*(*)</method>
15+
</difference>
1016
<difference>
1117
<differenceType>7006</differenceType>
1218
<className>com/google/api/gax/rpc/ServerStreamingCallSettings$Builder</className>

gax-java/gax/src/main/java/com/google/api/gax/rpc/ClientContext.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
*/
3030
package com.google.api.gax.rpc;
3131

32+
import com.google.api.client.util.Strings;
3233
import com.google.api.core.ApiClock;
3334
import com.google.api.core.BetaApi;
3435
import com.google.api.core.NanoClock;
@@ -40,11 +41,13 @@
4041
import com.google.api.gax.tracing.ApiTracerFactory;
4142
import com.google.api.gax.tracing.BaseApiTracerFactory;
4243
import com.google.auth.Credentials;
44+
import com.google.auth.oauth2.GdchCredentials;
4345
import com.google.auto.value.AutoValue;
4446
import com.google.common.collect.ImmutableList;
4547
import com.google.common.collect.ImmutableMap;
4648
import com.google.common.collect.Sets;
4749
import java.io.IOException;
50+
import java.net.URI;
4851
import java.util.Collections;
4952
import java.util.HashMap;
5053
import java.util.List;
@@ -109,6 +112,13 @@ public abstract class ClientContext {
109112
@Nonnull
110113
public abstract ApiTracerFactory getTracerFactory();
111114

115+
/**
116+
* Gets the API audience used when creating a Client that uses {@link
117+
* com.google.auth.oauth2.GdchCredentials}
118+
*/
119+
@Nullable
120+
public abstract String getGdchApiAudience();
121+
112122
public static Builder newBuilder() {
113123
return new AutoValue_ClientContext.Builder()
114124
.setBackgroundResources(Collections.<BackgroundResource>emptyList())
@@ -119,7 +129,8 @@ public static Builder newBuilder() {
119129
.setStreamWatchdog(null)
120130
.setStreamWatchdogCheckInterval(Duration.ZERO)
121131
.setTracerFactory(BaseApiTracerFactory.getInstance())
122-
.setQuotaProjectId(null);
132+
.setQuotaProjectId(null)
133+
.setGdchApiAudience(null);
123134
}
124135

125136
public abstract Builder toBuilder();
@@ -167,6 +178,30 @@ public static ClientContext create(StubSettings settings) throws IOException {
167178

168179
Credentials credentials = settings.getCredentialsProvider().getCredentials();
169180

181+
String settingsGdchApiAudience = settings.getGdchApiAudience();
182+
if (credentials instanceof GdchCredentials) {
183+
// We recompute the GdchCredentials with the audience
184+
String audienceString;
185+
if (!Strings.isNullOrEmpty(settingsGdchApiAudience)) {
186+
audienceString = settingsGdchApiAudience;
187+
} else if (!Strings.isNullOrEmpty(settings.getEndpoint())) {
188+
audienceString = settings.getEndpoint();
189+
} else {
190+
throw new IllegalArgumentException("Could not infer GDCH api audience from settings");
191+
}
192+
193+
URI gdchAudienceUri;
194+
try {
195+
gdchAudienceUri = URI.create(audienceString);
196+
} catch (IllegalArgumentException ex) { // thrown when passing a malformed uri string
197+
throw new IllegalArgumentException("The GDC-H API audience string is not a valid URI", ex);
198+
}
199+
credentials = ((GdchCredentials) credentials).createWithGdchAudience(gdchAudienceUri);
200+
} else if (!Strings.isNullOrEmpty(settingsGdchApiAudience)) {
201+
throw new IllegalArgumentException(
202+
"GDC-H API audience can only be set when using GdchCredentials");
203+
}
204+
170205
if (settings.getQuotaProjectId() != null && credentials != null) {
171206
// If the quotaProjectId is set, wrap original credentials with correct quotaProjectId as
172207
// QuotaProjectIdHidingCredentials.
@@ -325,6 +360,17 @@ public abstract static class Builder {
325360
@BetaApi("The surface for tracing is not stable yet and may change in the future.")
326361
public abstract Builder setTracerFactory(ApiTracerFactory tracerFactory);
327362

363+
/**
364+
* Sets the API audience used by {@link com.google.auth.oauth2.GdchCredentials} It cannot be
365+
* used if other type of {@link com.google.auth.Credentials} is used
366+
*
367+
* <p>If the provided credentials already contain an api audience, it will be overriden by this
368+
* one
369+
*
370+
* @param gdchApiAudience the audience to be used - must be a valid URI string
371+
*/
372+
public abstract Builder setGdchApiAudience(String gdchApiAudience);
373+
328374
public abstract ClientContext build();
329375
}
330376
}

gax-java/gax/src/main/java/com/google/api/gax/rpc/ClientSettings.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ public final Duration getWatchdogCheckInterval() {
111111
return stubSettings.getStreamWatchdogCheckInterval();
112112
}
113113

114+
/** Gets the GDCH API audience that was previously set in this Builder */
115+
public final String getGdchApiAudience() {
116+
return stubSettings.getGdchApiAudience();
117+
}
118+
114119
public String toString() {
115120
return MoreObjects.toStringHelper(this)
116121
.add("executorProvider", getExecutorProvider())
@@ -124,6 +129,7 @@ public String toString() {
124129
.add("quotaProjectId", getQuotaProjectId())
125130
.add("watchdogProvider", getWatchdogProvider())
126131
.add("watchdogCheckInterval", getWatchdogCheckInterval())
132+
.add("gdchApiAudience", getGdchApiAudience())
127133
.toString();
128134
}
129135

@@ -255,6 +261,18 @@ public B setWatchdogCheckInterval(@Nullable Duration checkInterval) {
255261
return self();
256262
}
257263

264+
/**
265+
* Sets the GDC-H api audience. This is intended only to be used with {@link
266+
* com.google.auth.oauth2.GdchCredentials} If this field is set and other type of {@link
267+
* com.google.auth.Credentials} is used then an {@link IllegalArgumentException} will be thrown.
268+
* If the provided credentials already have an api audience, then it will be overriden by this
269+
* audience
270+
*/
271+
public B setGdchApiAudience(@Nullable String gdchApiAudience) {
272+
stubSettings.setGdchApiAudience(gdchApiAudience);
273+
return self();
274+
}
275+
258276
/**
259277
* Gets the ExecutorProvider that was previously set on this Builder. This ExecutorProvider is
260278
* to use for running asynchronous API call logic (such as retries and long-running operations),
@@ -322,6 +340,12 @@ public Duration getWatchdogCheckInterval() {
322340
return stubSettings.getStreamWatchdogCheckInterval();
323341
}
324342

343+
/** Gets the GDCH API audience that was previously set in this Builder */
344+
@Nullable
345+
public String getGdchApiAudience() {
346+
return stubSettings.getGdchApiAudience();
347+
}
348+
325349
/** Applies the given settings updater function to the given method settings builders. */
326350
protected static void applyToAllUnaryMethods(
327351
Iterable<UnaryCallSettings.Builder<?, ?>> methodSettingsBuilders,
@@ -344,6 +368,7 @@ public String toString() {
344368
.add("quotaProjectId", getQuotaProjectId())
345369
.add("watchdogProvider", getWatchdogProvider())
346370
.add("watchdogCheckInterval", getWatchdogCheckInterval())
371+
.add("gdchApiAudience", getGdchApiAudience())
347372
.toString();
348373
}
349374
}

gax-java/gax/src/main/java/com/google/api/gax/rpc/StubSettings.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public abstract class StubSettings<SettingsT extends StubSettings<SettingsT>> {
7373
private final String endpoint;
7474
private final String mtlsEndpoint;
7575
private final String quotaProjectId;
76+
@Nullable private final String gdchApiAudience;
7677
@Nullable private final WatchdogProvider streamWatchdogProvider;
7778
@Nonnull private final Duration streamWatchdogCheckInterval;
7879
@Nonnull private final ApiTracerFactory tracerFactory;
@@ -103,6 +104,7 @@ protected StubSettings(Builder builder) {
103104
this.streamWatchdogCheckInterval = builder.streamWatchdogCheckInterval;
104105
this.tracerFactory = builder.tracerFactory;
105106
this.deprecatedExecutorProviderSet = builder.deprecatedExecutorProviderSet;
107+
this.gdchApiAudience = builder.gdchApiAudience;
106108
}
107109

108110
/** @deprecated Please use {@link #getBackgroundExecutorProvider()}. */
@@ -172,6 +174,12 @@ public ApiTracerFactory getTracerFactory() {
172174
return tracerFactory;
173175
}
174176

177+
/** Gets the GDCH API audience to be used with {@link com.google.auth.oauth2.GdchCredentials} */
178+
@Nullable
179+
public final String getGdchApiAudience() {
180+
return gdchApiAudience;
181+
}
182+
175183
@Override
176184
public String toString() {
177185
return MoreObjects.toStringHelper(this)
@@ -188,6 +196,7 @@ public String toString() {
188196
.add("streamWatchdogProvider", streamWatchdogProvider)
189197
.add("streamWatchdogCheckInterval", streamWatchdogCheckInterval)
190198
.add("tracerFactory", tracerFactory)
199+
.add("gdchApiAudience", gdchApiAudience)
191200
.toString();
192201
}
193202

@@ -205,6 +214,7 @@ public abstract static class Builder<
205214
private String endpoint;
206215
private String mtlsEndpoint;
207216
private String quotaProjectId;
217+
@Nullable private String gdchApiAudience;
208218
@Nullable private WatchdogProvider streamWatchdogProvider;
209219
@Nonnull private Duration streamWatchdogCheckInterval;
210220
@Nonnull private ApiTracerFactory tracerFactory;
@@ -234,6 +244,7 @@ protected Builder(StubSettings settings) {
234244
this.streamWatchdogCheckInterval = settings.streamWatchdogCheckInterval;
235245
this.tracerFactory = settings.tracerFactory;
236246
this.deprecatedExecutorProviderSet = settings.deprecatedExecutorProviderSet;
247+
this.gdchApiAudience = settings.gdchApiAudience;
237248
}
238249

239250
/** Get Quota Project ID from Client Context * */
@@ -268,6 +279,7 @@ protected Builder(ClientContext clientContext) {
268279
this.streamWatchdogCheckInterval = Duration.ofSeconds(10);
269280
this.tracerFactory = BaseApiTracerFactory.getInstance();
270281
this.deprecatedExecutorProviderSet = false;
282+
this.gdchApiAudience = null;
271283
} else {
272284
ExecutorProvider fixedExecutorProvider =
273285
FixedExecutorProvider.create(clientContext.getExecutor());
@@ -289,6 +301,7 @@ protected Builder(ClientContext clientContext) {
289301
this.streamWatchdogCheckInterval = clientContext.getStreamWatchdogCheckInterval();
290302
this.tracerFactory = clientContext.getTracerFactory();
291303
this.quotaProjectId = getQuotaProjectIdFromClientContext(clientContext);
304+
this.gdchApiAudience = clientContext.getGdchApiAudience();
292305
}
293306
}
294307

@@ -435,6 +448,18 @@ public B setStreamWatchdogCheckInterval(@Nonnull Duration checkInterval) {
435448
return self();
436449
}
437450

451+
/**
452+
* Sets the API audience used by {@link com.google.auth.oauth2.GdchCredentials} It cannot be
453+
* used if other type of {@link com.google.auth.Credentials} is used. If the provided
454+
* credentials already have an api audience set, then it will be overriden by this audience
455+
*
456+
* @param gdchApiAudience the audience to be used - must be a valid URI string
457+
*/
458+
public B setGdchApiAudience(String gdchApiAudience) {
459+
this.gdchApiAudience = gdchApiAudience;
460+
return self();
461+
}
462+
438463
/**
439464
* Configures the {@link ApiTracerFactory} that will be used to generate traces.
440465
*
@@ -513,6 +538,11 @@ public ApiTracerFactory getTracerFactory() {
513538
return tracerFactory;
514539
}
515540

541+
/** Gets the GDCH API audience that was previously set in this Builder */
542+
public String getGdchApiAudience() {
543+
return gdchApiAudience;
544+
}
545+
516546
/** Applies the given settings updater function to the given method settings builders. */
517547
protected static void applyToAllUnaryMethods(
518548
Iterable<UnaryCallSettings.Builder<?, ?>> methodSettingsBuilders,
@@ -540,6 +570,7 @@ public String toString() {
540570
.add("streamWatchdogProvider", streamWatchdogProvider)
541571
.add("streamWatchdogCheckInterval", streamWatchdogCheckInterval)
542572
.add("tracerFactory", tracerFactory)
573+
.add("gdchApiAudience", gdchApiAudience)
543574
.toString();
544575
}
545576
}

0 commit comments

Comments
 (0)