Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "1.41.0-rc1"
".": "1.41.0"
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand Down Expand Up @@ -632,6 +631,12 @@ public static String getServiceAccountsUrl() {
+ "/computeMetadata/v1/instance/service-accounts/?recursive=true";
}

/** Url to retrieve the default service account entry from the Metadata Server. */
static String getDefaultServiceAccountUrl() {
return getMetadataServerUrl(DefaultCredentialsProvider.DEFAULT)
+ "/computeMetadata/v1/instance/service-accounts/default/email";
}

public static String getIdentityDocumentUrl() {
return getMetadataServerUrl(DefaultCredentialsProvider.DEFAULT)
+ "/computeMetadata/v1/instance/service-accounts/default/identity";
Expand Down Expand Up @@ -733,7 +738,7 @@ public byte[] sign(byte[] toSign) {

private String getDefaultServiceAccount() throws IOException {
HttpResponse response =
getMetadataResponse(getServiceAccountsUrl(), RequestType.UNTRACKED, false);
getMetadataResponse(getDefaultServiceAccountUrl(), RequestType.UNTRACKED, false);
int statusCode = response.getStatusCode();
if (statusCode == HttpStatusCodes.STATUS_CODE_NOT_FOUND) {
throw new IOException(
Expand All @@ -756,12 +761,7 @@ private String getDefaultServiceAccount() throws IOException {
// Mock transports will have success code with empty content by default.
throw new IOException(METADATA_RESPONSE_EMPTY_CONTENT_ERROR_MESSAGE);
}
GenericData responseData = response.parseAs(GenericData.class);
LoggingUtils.logResponsePayload(
responseData, LOGGER_PROVIDER, "Received default service account payload");
Map<String, Object> defaultAccount =
OAuth2Utils.validateMap(responseData, "default", PARSE_ERROR_ACCOUNT);
return OAuth2Utils.validateString(defaultAccount, "email", PARSE_ERROR_ACCOUNT);
return response.parseAsString();
}

public static class Builder extends GoogleCredentials.Builder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.json.GenericJson;
import com.google.api.client.util.Data;
import com.google.api.core.InternalApi;
import com.google.auth.RequestMetadataCallback;
import com.google.auth.http.HttpTransportFactory;
import com.google.common.base.MoreObjects;
Expand Down Expand Up @@ -97,6 +98,9 @@ public abstract class ExternalAccountCredentials extends GoogleCredentials {

private EnvironmentProvider environmentProvider;

private int connectTimeout;
private int readTimeout;

/**
* Constructor with minimum identifying information and custom HTTP transport. Does not support
* workforce credentials.
Expand Down Expand Up @@ -271,6 +275,8 @@ protected ExternalAccountCredentials(ExternalAccountCredentials.Builder builder)
: builder.metricsHandler;

this.name = GoogleCredentialsInfo.EXTERNAL_ACCOUNT_CREDENTIALS.getCredentialName();
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
}

ImpersonatedCredentials buildImpersonatedCredentials() {
Expand Down Expand Up @@ -305,6 +311,8 @@ ImpersonatedCredentials buildImpersonatedCredentials() {
.setScopes(new ArrayList<>(scopes))
.setLifetime(this.serviceAccountImpersonationOptions.lifetime)
.setIamEndpointOverride(serviceAccountImpersonationUrl)
.setConnectTimeout(connectTimeout)
.setReadTimeout(readTimeout)
.build();
}

Expand Down Expand Up @@ -533,7 +541,9 @@ protected AccessToken exchangeExternalCredentialForAccessToken(

StsRequestHandler.Builder requestHandler =
StsRequestHandler.newBuilder(
tokenUrl, stsTokenExchangeRequest, transportFactory.create().createRequestFactory());
tokenUrl, stsTokenExchangeRequest, transportFactory.create().createRequestFactory())
.setConnectTimeout(connectTimeout)
.setReadTimeout(readTimeout);

// If this credential was initialized with a Workforce configuration then the
// workforcePoolUserProject must be passed to the Security Token Service via the internal
Expand Down Expand Up @@ -771,6 +781,9 @@ public abstract static class Builder extends GoogleCredentials.Builder {
@Nullable protected String workforcePoolUserProject;
@Nullable protected ServiceAccountImpersonationOptions serviceAccountImpersonationOptions;

protected int connectTimeout = 20000; // Default to 20000ms = 20s
protected int readTimeout = 20000; // Default to 20000ms = 20s

/* The field is not being used and value not set. Superseded by the same field in the
{@link GoogleCredentials.Builder}.
*/
Expand All @@ -796,6 +809,8 @@ protected Builder(ExternalAccountCredentials credentials) {
this.workforcePoolUserProject = credentials.workforcePoolUserProject;
this.serviceAccountImpersonationOptions = credentials.serviceAccountImpersonationOptions;
this.metricsHandler = credentials.metricsHandler;
this.connectTimeout = credentials.connectTimeout;
this.readTimeout = credentials.readTimeout;
}

/**
Expand Down Expand Up @@ -988,6 +1003,20 @@ public Builder setUniverseDomain(String universeDomain) {
return this;
}

/** Warning: Not for public use and can be removed at any time. */
@InternalApi
public Builder setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
return this;
}

/** Warning: Not for public use and can be removed at any time. */
@InternalApi
public Builder setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
return this;
}

/**
* Sets the optional Environment Provider.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonObjectParser;
import com.google.api.client.util.GenericData;
import com.google.api.core.InternalApi;
import com.google.auth.CredentialTypeForMetrics;
import com.google.auth.ServiceAccountSigner;
import com.google.auth.http.HttpCredentialsAdapter;
Expand Down Expand Up @@ -117,6 +118,9 @@ public class ImpersonatedCredentials extends GoogleCredentials

private transient Calendar calendar;

private int connectTimeout;
private int readTimeout;

/**
* @param sourceCredentials the source credential used to acquire the impersonated credentials. It
* should be either a user account credential or a service account credential.
Expand Down Expand Up @@ -559,6 +563,8 @@ private ImpersonatedCredentials(Builder builder) throws IOException {
+ "does not match %s universe domain set for impersonated credentials.",
this.sourceCredentials.getUniverseDomain(), builder.getUniverseDomain()));
}
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
}

/**
Expand Down Expand Up @@ -587,6 +593,12 @@ public AccessToken refreshAccessToken() throws IOException {
|| (isDefaultUniverseDomain()
&& ((ServiceAccountCredentials) this.sourceCredentials)
.shouldUseAssertionFlowForGdu())) {
if (this.sourceCredentials instanceof IdentityPoolCredentials) {
this.sourceCredentials =
((IdentityPoolCredentials) this.sourceCredentials)
.toBuilder().setConnectTimeout(connectTimeout).setReadTimeout(readTimeout).build();
}

try {
this.sourceCredentials.refreshIfExpired();
} catch (IOException e) {
Expand Down Expand Up @@ -616,6 +628,8 @@ public AccessToken refreshAccessToken() throws IOException {

HttpContent requestContent = new JsonHttpContent(parser.getJsonFactory(), body);
HttpRequest request = requestFactory.buildPostRequest(url, requestContent);
request.setConnectTimeout(connectTimeout);
request.setReadTimeout(readTimeout);
adapter.initialize(request);
request.setParser(parser);
MetricsUtils.setMetricsHeader(
Expand Down Expand Up @@ -746,6 +760,9 @@ public static class Builder extends GoogleCredentials.Builder {
private String iamEndpointOverride;
private Calendar calendar = Calendar.getInstance();

private int connectTimeout = 20000; // Default to 20000ms = 20s
private int readTimeout = 20000; // Default to 20000ms = 20s

protected Builder() {}

/**
Expand All @@ -769,6 +786,8 @@ protected Builder(ImpersonatedCredentials credentials) {
this.lifetime = credentials.lifetime;
this.transportFactory = credentials.transportFactory;
this.iamEndpointOverride = credentials.iamEndpointOverride;
this.connectTimeout = credentials.connectTimeout;
this.readTimeout = credentials.readTimeout;
}

@CanIgnoreReturnValue
Expand Down Expand Up @@ -860,6 +879,20 @@ public Builder setCalendar(Calendar calendar) {
return this;
}

/** Warning: Not for public use and can be removed at any time. */
@InternalApi
public Builder setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
return this;
}

/** Warning: Not for public use and can be removed at any time. */
@InternalApi
public Builder setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
return this;
}

public Calendar getCalendar() {
return this.calendar;
}
Expand Down
49 changes: 32 additions & 17 deletions oauth2_http/java/com/google/auth/oauth2/StsRequestHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import com.google.api.client.json.JsonObjectParser;
import com.google.api.client.json.JsonParser;
import com.google.api.client.util.GenericData;
import com.google.api.core.InternalApi;
import com.google.common.base.Joiner;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.IOException;
Expand Down Expand Up @@ -73,26 +74,22 @@ public final class StsRequestHandler {
@Nullable private final HttpHeaders headers;
@Nullable private final String internalOptions;

private final int connectTimeout;
private final int readTimeout;

/**
* Internal constructor.
*
* @param tokenExchangeEndpoint the token exchange endpoint
* @param request the token exchange request
* @param headers optional additional headers to pass along the request
* @param internalOptions optional GCP specific STS options
* @return an StsTokenExchangeResponse instance if the request was successful
*/
private StsRequestHandler(
String tokenExchangeEndpoint,
StsTokenExchangeRequest request,
HttpRequestFactory httpRequestFactory,
@Nullable HttpHeaders headers,
@Nullable String internalOptions) {
this.tokenExchangeEndpoint = tokenExchangeEndpoint;
this.request = request;
this.httpRequestFactory = httpRequestFactory;
this.headers = headers;
this.internalOptions = internalOptions;
private StsRequestHandler(Builder builder) {
this.tokenExchangeEndpoint = builder.tokenExchangeEndpoint;
this.request = builder.request;
this.httpRequestFactory = builder.httpRequestFactory;
this.headers = builder.headers;
this.internalOptions = builder.internalOptions;
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
}

/**
Expand Down Expand Up @@ -120,6 +117,8 @@ public StsTokenExchangeResponse exchangeToken() throws IOException {
if (headers != null) {
httpRequest.setHeaders(headers);
}
httpRequest.setConnectTimeout(connectTimeout);
httpRequest.setReadTimeout(readTimeout);

try {
HttpResponse response = httpRequest.execute();
Expand Down Expand Up @@ -214,6 +213,9 @@ public static class Builder {
@Nullable private HttpHeaders headers;
@Nullable private String internalOptions;

private int connectTimeout = 20000; // Default to 20000ms = 20s
private int readTimeout = 20000; // Default to 20000ms = 20s

private Builder(
String tokenExchangeEndpoint,
StsTokenExchangeRequest stsTokenExchangeRequest,
Expand All @@ -235,9 +237,22 @@ public StsRequestHandler.Builder setInternalOptions(String internalOptions) {
return this;
}

/** Warning: Not for public use and can be removed at any time. */
@InternalApi
public StsRequestHandler.Builder setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
return this;
}

/** Warning: Not for public use and can be removed at any time. */
@InternalApi
public StsRequestHandler.Builder setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
return this;
}

public StsRequestHandler build() {
return new StsRequestHandler(
tokenExchangeEndpoint, request, httpRequestFactory, headers, internalOptions);
return new StsRequestHandler(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ public void getAccount_missing_throws() {
new MockMetadataServerTransport() {
@Override
public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
if (isGetServiceAccountsUrl(url)) {
if (isGetDefaultServiceAccountsUrl(url)) {
return new MockLowLevelHttpRequest(url) {
@Override
public LowLevelHttpResponse execute() throws IOException {
Expand Down Expand Up @@ -626,7 +626,7 @@ public void getAccount_emptyContent_throws() {
new MockMetadataServerTransport() {
@Override
public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
if (isGetServiceAccountsUrl(url)) {
if (isGetDefaultServiceAccountsUrl(url)) {
return new MockLowLevelHttpRequest(url) {
@Override
public LowLevelHttpResponse execute() throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ public LowLevelHttpRequest buildRequest(String method, String url) throws IOExce
if (url.startsWith(ComputeEngineCredentials.getTokenServerEncodedUrl())) {
this.request = getMockRequestForTokenEndpoint(url);
return this.request;
} else if (isGetServiceAccountsUrl(url)) {
this.request = getMockRequestForServiceAccount(url);
} else if (isGetDefaultServiceAccountsUrl(url)) {
this.request = getMockRequestForDefaultServiceAccount(url);
return this.request;
} else if (isSignRequestUrl(url)) {
this.request = getMockRequestForSign(url);
Expand Down Expand Up @@ -176,22 +176,13 @@ public LowLevelHttpResponse execute() throws IOException {
};
}

private MockLowLevelHttpRequest getMockRequestForServiceAccount(String url) {
private MockLowLevelHttpRequest getMockRequestForDefaultServiceAccount(String url) {
return new MockLowLevelHttpRequest(url) {
@Override
public LowLevelHttpResponse execute() throws IOException {
// Create the JSON response
GenericJson serviceAccountsContents = new GenericJson();
serviceAccountsContents.setFactory(OAuth2Utils.JSON_FACTORY);
GenericJson defaultAccount = new GenericJson();
defaultAccount.put("email", serviceAccountEmail);
serviceAccountsContents.put("default", defaultAccount);

String serviceAccounts = serviceAccountsContents.toPrettyString();

public LowLevelHttpResponse execute() {
return new MockLowLevelHttpResponse()
.setContentType(Json.MEDIA_TYPE)
.setContent(serviceAccounts);
.setContent(serviceAccountEmail);
}
};
}
Expand Down Expand Up @@ -341,8 +332,8 @@ public LowLevelHttpResponse execute() throws IOException {
};
}

protected boolean isGetServiceAccountsUrl(String url) {
return url.equals(ComputeEngineCredentials.getServiceAccountsUrl());
protected boolean isGetDefaultServiceAccountsUrl(String url) {
return url.equals(ComputeEngineCredentials.getDefaultServiceAccountUrl());
}

protected boolean isSignRequestUrl(String url) {
Expand Down
6 changes: 6 additions & 0 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
"ignorePaths": [
".kokoro/requirements.txt"
],
"vulnerabilityAlerts": {
"enabled": true
},
"maven": {
"enabled": false
},
"customManagers": [
{
"customType": "regex",
Expand Down