diff --git a/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java b/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java index 15ce8947d..c679a316c 100644 --- a/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java +++ b/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java @@ -122,6 +122,9 @@ public class ComputeEngineCredentials extends GoogleCredentials private final Collection scopes; + private final String transport; + private final String bindingEnforcement; + private transient HttpTransportFactory transportFactory; private transient String serviceAccountEmail; @@ -152,6 +155,8 @@ private ComputeEngineCredentials(ComputeEngineCredentials.Builder builder) { scopeList.removeAll(Arrays.asList("", null)); this.scopes = ImmutableSet.copyOf(scopeList); } + this.transport = builder.getTransport(); + this.bindingEnforcement = builder.getBindingEnforcement(); } @Override @@ -191,7 +196,10 @@ public final Collection getScopes() { } /** - * If scopes is specified, add "?scopes=comma-separated-list-of-scopes" to the token url. + * If scopes is specified, add "?scopes=comma-separated-list-of-scopes" to the token url. If + * transport is specified, add "?transport=xyz" to the token url; xyz is one of "alts" or "mtls". + * If bindingEnforcement is specified, add "?binding-enforcement=xyz" to the token url; xyz is one + * of "iam-policy" or "on". * * @return token url with the given scopes */ @@ -200,6 +208,12 @@ String createTokenUrlWithScopes() { if (!scopes.isEmpty()) { tokenUrl.set("scopes", Joiner.on(',').join(scopes)); } + if (!transport.isEmpty()) { + tokenUrl.set("transport", transport); + } + if (!bindingEnforcement.isEmpty()) { + tokenUrl.set("binding-enforcement", bindingEnforcement); + } return tokenUrl.toString(); } @@ -643,6 +657,9 @@ public static class Builder extends GoogleCredentials.Builder { private Collection scopes; private Collection defaultScopes; + private String transport = ""; + private String bindingEnforcement = ""; + protected Builder() { setRefreshMargin(COMPUTE_REFRESH_MARGIN); setExpirationMargin(COMPUTE_EXPIRATION_MARGIN); @@ -684,6 +701,18 @@ public Builder setQuotaProjectId(String quotaProjectId) { return this; } + @CanIgnoreReturnValue + public Builder setTransport(String transport) { + this.transport = transport; + return this; + } + + @CanIgnoreReturnValue + public Builder setBindingEnforcement(String bindingEnforcement) { + this.bindingEnforcement = bindingEnforcement; + return this; + } + public HttpTransportFactory getHttpTransportFactory() { return transportFactory; } @@ -696,6 +725,14 @@ public Collection getDefaultScopes() { return defaultScopes; } + public String getTransport() { + return transport; + } + + public String getBindingEnforcement() { + return bindingEnforcement; + } + @Override public ComputeEngineCredentials build() { return new ComputeEngineCredentials(this); diff --git a/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java b/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java index 10975d874..5d5326f45 100644 --- a/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java +++ b/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java @@ -190,6 +190,66 @@ public void buildTokenUrlWithScopes_defaultScopes() { assertEquals("bar", scopes.toArray()[1]); } + @Test + public void buildTokenUrlSoftMtlsBound_mtls_transport() { + ComputeEngineCredentials credentials = + ComputeEngineCredentials.newBuilder().setTransport("mtls").build(); + String softBoundTokenUrl = credentials.createTokenUrlWithScopes(); + + assertEquals(TOKEN_URL + "?transport=mtls", softBoundTokenUrl); + } + + @Test + public void buildTokenUrlSoftMtlsBound_iam_enforcement() { + ComputeEngineCredentials credentials = + ComputeEngineCredentials.newBuilder().setBindingEnforcement("iam-policy").build(); + String softBoundTokenUrl = credentials.createTokenUrlWithScopes(); + + assertEquals(TOKEN_URL + "?binding-enforcement=iam-policy", softBoundTokenUrl); + } + + @Test + public void buildTokenUrlSoftMtlsBound_mtls_transport_iam_enforcement() { + ComputeEngineCredentials credentials = + ComputeEngineCredentials.newBuilder() + .setTransport("mtls") + .setBindingEnforcement("iam-policy") + .build(); + String softBoundTokenUrl = credentials.createTokenUrlWithScopes(); + + assertEquals(TOKEN_URL + "?transport=mtls&binding-enforcement=iam-policy", softBoundTokenUrl); + } + + @Test + public void buildTokenUrlHardMtlsBound_always_enforced() { + ComputeEngineCredentials credentials = + ComputeEngineCredentials.newBuilder().setBindingEnforcement("on").build(); + String softBoundTokenUrl = credentials.createTokenUrlWithScopes(); + + assertEquals(TOKEN_URL + "?binding-enforcement=on", softBoundTokenUrl); + } + + @Test + public void buildTokenUrlHardMtlsBound_mtls_transport_always_enforced() { + ComputeEngineCredentials credentials = + ComputeEngineCredentials.newBuilder() + .setTransport("mtls") + .setBindingEnforcement("on") + .build(); + String softBoundTokenUrl = credentials.createTokenUrlWithScopes(); + + assertEquals(TOKEN_URL + "?transport=mtls&binding-enforcement=on", softBoundTokenUrl); + } + + @Test + public void buildTokenUrlHardDirectPathBound_alts_transport() { + ComputeEngineCredentials credentials = + ComputeEngineCredentials.newBuilder().setTransport("alts").build(); + String softBoundTokenUrl = credentials.createTokenUrlWithScopes(); + + assertEquals(TOKEN_URL + "?transport=alts", softBoundTokenUrl); + } + @Test public void buildScoped_scopesPresent() throws IOException { ComputeEngineCredentials credentials =