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: ComputeEngineCredential supports specifying scopes #457

Closed
wants to merge 1 commit into from

Conversation

ahmedtd
Copy link

@ahmedtd ahmedtd commented Aug 6, 2020

The existing behavior of ComputeEngineCredentials is to not provide the ?scopes parameter in its access token request to the metadata server. This is workable on GCE, which has the concept of a scope lock / default scopes applied to the VM. However, neither new AppEngine nor GKE Workload Identity have this concept; they just return a hardcoded set of default scopes if no
specific scopes are requested. This makes usage of some Google APIs impossible using the Java client libraries.

This change adds scope support to ComputeEngineCredentials. It's optional, so the current behavior will stay the default.
However, if the user specifies scopes on the builder or using createScoped, then those scopes will be passed to the metadata server.

@ahmedtd ahmedtd requested a review from a team as a code owner August 6, 2020 00:43
@google-cla google-cla bot added the cla: yes This human has signed the Contributor License Agreement. label Aug 6, 2020
@ahmedtd
Copy link
Author

ahmedtd commented Aug 6, 2020

@chingor13 This is the patch we discussed.

Copy link
Contributor

@elharo elharo left a comment

Choose a reason for hiding this comment

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

It really helps if changes like this are associated with a detailed issue.

pom.xml Outdated Show resolved Hide resolved
@@ -117,13 +126,27 @@ private ComputeEngineCredentials(HttpTransportFactory transportFactory) {
* @return new ComputeEngineCredentials
*/
public static ComputeEngineCredentials create() {
return new ComputeEngineCredentials(null);
return new ComputeEngineCredentials(ImmutableSet.<String>of(), null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this default to null instead?

An empty collection of scopes might make the url something like https://some-url/?scopes= which may be correct if you ask for no scopes, but if you pass null, it should exclude the scopes param.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, you're right. I originally wrote this so that an empty collection would result in not sending the ?scopes param, but then changed it to null.

Copy link
Author

Choose a reason for hiding this comment

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

Done

@chingor13
Copy link
Contributor

cc @salrashid123

@chingor13 chingor13 added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Aug 6, 2020
@kokoro-team kokoro-team removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Aug 6, 2020
The existing behavior of ComputeEngineCredentials is to not provide the
`?scopes` parameter in its access token request to the metadata
server.  This is workable on GCE, which has the concept of a scope
lock / default scopes applied to the VM.  However, neither new
AppEngine nor GKE Workload Identity have this concept; they just
return a hardcoded set of default scopes if no specific scopes are
requested.  This makes usage of some Google APIs impossible using the
Java client libraries.

This change adds scope support to ComputeEngineCredentials.  It's
optional, so the current behavior will stay the default.  However, if
the user specifies scopes on the builder or using `createScoped`, then
those scopes will be passed to the metadata server.
@chingor13 chingor13 added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Aug 7, 2020
@kokoro-team kokoro-team removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Aug 7, 2020
Copy link
Contributor

@chingor13 chingor13 left a comment

Choose a reason for hiding this comment

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

Also please run mvn com.coveo:fmt-maven-plugin:format to appease the linter.

HttpResponse response = getMetadataResponse(getTokenServerEncodedUrl());
GenericUrl url = new GenericUrl(getTokenServerEncodedUrl());
if (scopes != null) {
url.set("scopes", String.join(",", scopes));
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like String.join was added in Java 8 and this library still currently support Java 7.

Copy link
Contributor

Choose a reason for hiding this comment

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

You can use Guava's Joiner in this class.

@ahmedtd
Copy link
Author

ahmedtd commented Aug 8, 2020

@elharo I opened #458 . I have some follow up work to confirm that this works the same way in the AppEngine flex environment.

HttpResponse response = getMetadataResponse(getTokenServerEncodedUrl());
GenericUrl url = new GenericUrl(getTokenServerEncodedUrl());
if (scopes != null) {
url.set("scopes", String.join(",", scopes));
Copy link
Contributor

Choose a reason for hiding this comment

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

You can use Guava's Joiner in this class.

@@ -411,12 +437,21 @@ public Builder setHttpTransportFactory(HttpTransportFactory transportFactory) {
return this;
}

public Builder setScopes(Collection<String> scopes) {
this.scopes = scopes;
Copy link
Contributor

Choose a reason for hiding this comment

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

You probably want a defensive copy to avoid exposing mutable internal state.

public HttpTransportFactory getHttpTransportFactory() {
return transportFactory;
}

public Collection<String> getScopes() {
Copy link
Contributor

Choose a reason for hiding this comment

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

You probably want a defensive copy to avoid exposing mutable internal state.

GenericUrl parsedURL = new GenericUrl(url);

if ("/computeMetadata/v1/instance/service-accounts/default/token".equals(parsedURL.getRawPath())) {
String scopes = (String)parsedURL.getFirst("scopes");
Copy link
Contributor

Choose a reason for hiding this comment

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

space after cast

@chingor13
Copy link
Contributor

Addressed in #514

@chingor13 chingor13 closed this Dec 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants