Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: multi universe support, adding universe_domain field #1282

Merged
merged 36 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4ddad12
feat: first draft of tpc support, adding universe_domain field
TimurSadykov Sep 12, 2023
c41f542
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Sep 12, 2023
3957bd0
Update oauth2_http/java/com/google/auth/oauth2/GoogleCredentials.java
TimurSadykov Sep 13, 2023
41de188
fix: adding tests
TimurSadykov Sep 13, 2023
efe23b1
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Sep 13, 2023
090674f
fix: move universe_domain to very base Credential, tests cleanup
TimurSadykov Nov 2, 2023
3eb4047
fix: resolve a conflict in tests
TimurSadykov Nov 2, 2023
da7e1b7
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Nov 2, 2023
72e4dd0
Merge branch 'main' into tpc-stage1
TimurSadykov Nov 2, 2023
c192155
Merge branch 'main' into tpc-stage1
TimurSadykov Nov 14, 2023
35f79d0
feat: updates for ToString, hashCode and equals
TimurSadykov Nov 14, 2023
0749124
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Nov 14, 2023
763f6b0
feat: refactor ExternalAccount to use base class universe domain, upd…
TimurSadykov Nov 14, 2023
309312d
fix: test fixes
TimurSadykov Nov 20, 2023
c63ed36
fix: javadoc updates and other nits
TimurSadykov Nov 20, 2023
3b46e38
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Nov 20, 2023
bc2360f
Merge remote-tracking branch 'origin/main' into tpc-stage1
TimurSadykov Nov 24, 2023
482603f
fix: universe comparison fix, restoring the original univerDeomain fi…
TimurSadykov Nov 25, 2023
0c21a72
fix: deprecating a duplicate universeDomain field
TimurSadykov Nov 29, 2023
4b21ca2
fix: restore the original behavior of equals and hashcode for UserCre…
TimurSadykov Nov 29, 2023
bab1ccc
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Nov 29, 2023
a009715
Merge branch 'main' into tpc-stage1
lsirac Dec 7, 2023
de8c400
fix: comments addressed
TimurSadykov Dec 7, 2023
9659e40
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Dec 7, 2023
1bc4d3f
fix: docs update for Credentials.java
TimurSadykov Dec 8, 2023
c671f0d
Update docs GoogleCredentials.java constructor
TimurSadykov Dec 8, 2023
64b9d0a
fix: javadoc fixes
TimurSadykov Dec 8, 2023
bc51410
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Dec 8, 2023
a4c4a09
getUniverseDomain throws IOExcpetion, more tests
TimurSadykov Dec 12, 2023
439b486
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Dec 12, 2023
69c966e
fix: universeDomain from deprecated constructors
TimurSadykov Dec 12, 2023
18e1429
fix: revert common json parsing, other comments addressed
TimurSadykov Dec 14, 2023
8c21b7e
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Dec 14, 2023
eceba5a
fix: few nits addressed
TimurSadykov Dec 19, 2023
bfbd4fc
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Dec 19, 2023
6a3b81c
Merge branch 'main' into tpc-stage1
lsirac Dec 19, 2023
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
16 changes: 16 additions & 0 deletions credentials/java/com/google/auth/Credentials.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public abstract class Credentials implements Serializable {

private static final long serialVersionUID = 808575179767517313L;

public static final String GOOGLE_DEFAULT_UNIVERSE = "googleapis.com";
TimurSadykov marked this conversation as resolved.
Show resolved Hide resolved

/**
* A constant string name describing the authentication technology.
*
Expand All @@ -54,6 +56,20 @@ public abstract class Credentials implements Serializable {
*/
public abstract String getAuthenticationType();

/**
* Gets the universe domain for the credential in a blocking manner, refreshing tokens if
* required.
*
* @return a universe domain value in the format some-domain.xyz. By default, returns the Google
* universe domain googleapis.com.
* @throws IOException extending classes might have to do remote calls to determine the universe
* domain. The exception must implement {@link Retryable} and {@code isRetryable()} will
* return true if the operation may be retried.
*/
public String getUniverseDomain() throws IOException {
return GOOGLE_DEFAULT_UNIVERSE;
}

/**
* Get the current request metadata, refreshing tokens if required.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ public static Builder newBuilder() {
public int hashCode() {
return Objects.hash(
super.hashCode(),
getAccessToken(),
aeitzman marked this conversation as resolved.
Show resolved Hide resolved
clientId,
clientSecret,
refreshToken,
Expand Down Expand Up @@ -281,6 +282,7 @@ public boolean equals(Object obj) {
ExternalAccountAuthorizedUserCredentials credentials =
(ExternalAccountAuthorizedUserCredentials) obj;
return super.equals(credentials)
&& Objects.equals(this.getAccessToken(), credentials.getAccessToken())
&& Objects.equals(this.clientId, credentials.clientId)
&& Objects.equals(this.clientSecret, credentials.clientSecret)
&& Objects.equals(this.refreshToken, credentials.refreshToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ abstract static class CredentialSource implements java.io.Serializable {
@Nullable private final String serviceAccountImpersonationUrl;
@Nullable private final String clientId;
@Nullable private final String clientSecret;
@Nullable private final String universeDomain;

// This is used for Workforce Pools. It is passed to the Security Token Service during token
// exchange in the `options` param and will be embedded in the token by the Security Token
Expand Down Expand Up @@ -215,7 +214,6 @@ protected ExternalAccountCredentials(
this.environmentProvider =
environmentProvider == null ? SystemEnvironmentProvider.getInstance() : environmentProvider;
this.workforcePoolUserProject = null;
this.universeDomain = null;
this.serviceAccountImpersonationOptions =
new ServiceAccountImpersonationOptions(new HashMap<String, Object>());

Expand Down Expand Up @@ -269,8 +267,6 @@ protected ExternalAccountCredentials(ExternalAccountCredentials.Builder builder)
"The workforce_pool_user_project parameter should only be provided for a Workforce Pool configuration.");
}

this.universeDomain = builder.universeDomain;

validateTokenUrl(tokenUrl);
if (serviceAccountImpersonationUrl != null) {
validateServiceAccountImpersonationInfoUrl(serviceAccountImpersonationUrl);
Expand Down Expand Up @@ -593,11 +589,6 @@ public String getWorkforcePoolUserProject() {
return workforcePoolUserProject;
}

@Nullable
String getUniverseDomain() {
return universeDomain;
}

@Nullable
public ServiceAccountImpersonationOptions getServiceAccountImpersonationOptions() {
return serviceAccountImpersonationOptions;
Expand Down Expand Up @@ -734,7 +725,12 @@ public abstract static class Builder extends GoogleCredentials.Builder {
@Nullable protected Collection<String> scopes;
@Nullable protected String workforcePoolUserProject;
@Nullable protected ServiceAccountImpersonationOptions serviceAccountImpersonationOptions;
@Nullable protected String universeDomain;

/* The field is not being used and value not set. Superseded by the same field in the
{@link GoogleCredential.Builder}.
*/
@Nullable @Deprecated protected String universeDomain;
lsirac marked this conversation as resolved.
Show resolved Hide resolved

@Nullable protected ExternalAccountMetricsHandler metricsHandler;

protected Builder() {}
Expand All @@ -754,7 +750,6 @@ protected Builder(ExternalAccountCredentials credentials) {
this.environmentProvider = credentials.environmentProvider;
this.workforcePoolUserProject = credentials.workforcePoolUserProject;
this.serviceAccountImpersonationOptions = credentials.serviceAccountImpersonationOptions;
this.universeDomain = credentials.universeDomain;
this.metricsHandler = credentials.metricsHandler;
}

Expand Down Expand Up @@ -928,8 +923,9 @@ public Builder setServiceAccountImpersonationOptions(Map<String, Object> options
* @return this {@code Builder} object
*/
@CanIgnoreReturnValue
@Override
public Builder setUniverseDomain(String universeDomain) {
this.universeDomain = universeDomain;
super.setUniverseDomain(universeDomain);
TimurSadykov marked this conversation as resolved.
Show resolved Hide resolved
return this;
}

Expand Down
130 changes: 124 additions & 6 deletions oauth2_http/java/com/google/auth/oauth2/GoogleCredentials.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.JsonObjectParser;
import com.google.api.client.util.Preconditions;
import com.google.auth.Credentials;
import com.google.auth.http.HttpTransportFactory;
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.IOException;
Expand All @@ -47,6 +50,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nullable;

/** Base type for credentials for authorizing calls to Google APIs using OAuth2. */
Expand All @@ -59,6 +63,8 @@ public class GoogleCredentials extends OAuth2Credentials implements QuotaProject
static final String SERVICE_ACCOUNT_FILE_TYPE = "service_account";
static final String GDCH_SERVICE_ACCOUNT_FILE_TYPE = "gdch_service_account";

private final String universeDomain;

protected final String quotaProjectId;

private static final DefaultCredentialsProvider defaultCredentialsProvider =
Expand All @@ -71,7 +77,10 @@ public class GoogleCredentials extends OAuth2Credentials implements QuotaProject
* @return the credentials instance
*/
public static GoogleCredentials create(AccessToken accessToken) {
return GoogleCredentials.newBuilder().setAccessToken(accessToken).build();
return GoogleCredentials.newBuilder()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deprecate this constructor in favor of the builder?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you forgot to deprecate it?

.setAccessToken(accessToken)
.setUniverseDomain(Credentials.GOOGLE_DEFAULT_UNIVERSE)
.build();
}

/**
Expand Down Expand Up @@ -170,6 +179,7 @@ public static GoogleCredentials fromStream(
if (fileType == null) {
throw new IOException("Error reading credentials from stream, 'type' field not specified.");
}

if (USER_FILE_TYPE.equals(fileType)) {
return UserCredentials.fromJson(fileContents, transportFactory);
}
Expand All @@ -186,14 +196,20 @@ public static GoogleCredentials fromStream(
fileType)) {
return ExternalAccountAuthorizedUserCredentials.fromJson(fileContents, transportFactory);
}
if ("impersonated_service_account".equals(fileType)) {
if (ImpersonatedCredentials.IMPERSONATED_CREDENTIALS_FILE_TYPE.equals(fileType)) {
return ImpersonatedCredentials.fromJson(fileContents, transportFactory);
}
throw new IOException(
String.format(
"Error reading credentials from stream, 'type' value '%s' not recognized."
+ " Expecting '%s' or '%s'.",
fileType, USER_FILE_TYPE, SERVICE_ACCOUNT_FILE_TYPE));
+ " Valid values are '%s', '%s', '%s', '%s', '%s', '%s'.",
fileType,
USER_FILE_TYPE,
SERVICE_ACCOUNT_FILE_TYPE,
GDCH_SERVICE_ACCOUNT_FILE_TYPE,
ExternalAccountCredentials.EXTERNAL_ACCOUNT_FILE_TYPE,
ExternalAccountAuthorizedUserCredentials.EXTERNAL_ACCOUNT_AUTHORIZED_USER_FILE_TYPE,
ImpersonatedCredentials.IMPERSONATED_CREDENTIALS_FILE_TYPE));
}

/**
Expand All @@ -206,6 +222,27 @@ public GoogleCredentials createWithQuotaProject(String quotaProject) {
return this.toBuilder().setQuotaProjectId(quotaProject).build();
}

/**
* Gets the universe domain for the credential.
*
* @return An explicit universe domain if it was explicitly provided, invokes the super
* implementation otherwise
*/
@Override
public String getUniverseDomain() throws IOException {
return this.universeDomain;
TimurSadykov marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Checks if universe domain equals to {@link Credentials#GOOGLE_DEFAULT_UNIVERSE}.
*
* @return true if universeDomain equals to {@link Credentials#GOOGLE_DEFAULT_UNIVERSE}, false
* otherwise
*/
boolean isDefaultUniverseDomain() {
return this.universeDomain.equals(Credentials.GOOGLE_DEFAULT_UNIVERSE);
}

/**
* Adds quota project ID to requestMetadata if present.
*
Expand Down Expand Up @@ -237,33 +274,97 @@ protected GoogleCredentials() {
this(new Builder());
}

/**
* Constructor with an explicit access token and quotaProjectId.
*
* <p>Deprecated, please use the {@link GoogleCredentials#GoogleCredentials(Builder)} constructor
* whenever possible.
*
* @param accessToken initial or temporary access token
* @param quotaProjectId a quotaProjectId, a project id to be used for billing purposes
*/
@Deprecated
protected GoogleCredentials(AccessToken accessToken, String quotaProjectId) {
super(accessToken);
this.quotaProjectId = quotaProjectId;
this.universeDomain = Credentials.GOOGLE_DEFAULT_UNIVERSE;
}

/**
* Constructor with explicit access token.
*
* @param accessToken initial or temporary access token
*/
@Deprecated
TimurSadykov marked this conversation as resolved.
Show resolved Hide resolved
public GoogleCredentials(AccessToken accessToken) {
this(accessToken, null);
}

/**
* Constructor that relies on a {@link GoogleCredential.Builder} to provide all the necessary
* field values for initialization.
*
* @param builder an instance of a builder
*/
protected GoogleCredentials(Builder builder) {
this(builder.getAccessToken(), builder.getQuotaProjectId());
super(builder.getAccessToken());
this.quotaProjectId = builder.getQuotaProjectId();
TimurSadykov marked this conversation as resolved.
Show resolved Hide resolved

if (builder.universeDomain == null || builder.universeDomain.trim().isEmpty()) {
TimurSadykov marked this conversation as resolved.
Show resolved Hide resolved
this.universeDomain = Credentials.GOOGLE_DEFAULT_UNIVERSE;
} else {
this.universeDomain = builder.getUniverseDomain();
}
}

/**
* Constructor with explicit access token and refresh times
* Constructor with explicit access token and refresh margins.
*
* <p>Deprecated, please use the {@link GoogleCredentials#GoogleCredentials(Builder)} constructor
* whenever possible.
*
* @param accessToken initial or temporary access token
*/
@Deprecated
protected GoogleCredentials(
AccessToken accessToken, Duration refreshMargin, Duration expirationMargin) {
super(accessToken, refreshMargin, expirationMargin);
this.quotaProjectId = null;
this.universeDomain = Credentials.GOOGLE_DEFAULT_UNIVERSE;
}

/**
* A helper for overriding the toString() method. This allows inheritance of super class fields.
* Extending classes can override this implementation and call super implementation and add more
* fields. Same cannot be done with overriding the toString() directly.
*
* @return an instance of the ToStringHelper that has public fields added
*/
protected ToStringHelper toStringHelper() {
return MoreObjects.toStringHelper(this)
.omitNullValues()
.add("quotaProjectId", this.quotaProjectId)
.add("universeDomain", this.universeDomain);
}

@Override
public String toString() {
return toStringHelper().toString();
}

@Override
public boolean equals(Object obj) {
aeitzman marked this conversation as resolved.
Show resolved Hide resolved
if (!(obj instanceof GoogleCredentials)) {
return false;
}
GoogleCredentials other = (GoogleCredentials) obj;
return Objects.equals(this.quotaProjectId, other.quotaProjectId)
&& Objects.equals(this.universeDomain, other.universeDomain);
}

@Override
public int hashCode() {
return Objects.hash(this.quotaProjectId, this.universeDomain);
}

public static Builder newBuilder() {
Expand Down Expand Up @@ -348,12 +449,20 @@ public GoogleCredentials createDelegated(String user) {

public static class Builder extends OAuth2Credentials.Builder {
@Nullable protected String quotaProjectId;
@Nullable protected String universeDomain;

protected Builder() {}

protected Builder(GoogleCredentials credentials) {
setAccessToken(credentials.getAccessToken());
this.quotaProjectId = credentials.quotaProjectId;
this.universeDomain = credentials.universeDomain;
}

protected Builder(GoogleCredentials.Builder builder) {
setAccessToken(builder.getAccessToken());
this.quotaProjectId = builder.quotaProjectId;
this.universeDomain = builder.universeDomain;
}

public GoogleCredentials build() {
Expand All @@ -366,10 +475,19 @@ public Builder setQuotaProjectId(String quotaProjectId) {
return this;
}

public Builder setUniverseDomain(String universeDomain) {
this.universeDomain = universeDomain;
return this;
}

public String getQuotaProjectId() {
return this.quotaProjectId;
}

public String getUniverseDomain() {
return this.universeDomain;
}

@Override
@CanIgnoreReturnValue
public Builder setAccessToken(AccessToken token) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@
public class ImpersonatedCredentials extends GoogleCredentials
implements ServiceAccountSigner, IdTokenProvider {

static final String IMPERSONATED_CREDENTIALS_FILE_TYPE = "impersonated_service_account";

private static final long serialVersionUID = -2133257318957488431L;
private static final String RFC3339 = "yyyy-MM-dd'T'HH:mm:ssX";
private static final int TWELVE_HOURS_IN_SECONDS = 43200;
Expand Down
Loading