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: Support transport and binding-enforcement MDS parameters. #1558

Merged
merged 19 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from 17 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
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,57 @@ public class ComputeEngineCredentials extends GoogleCredentials
static final int MAX_COMPUTE_PING_TRIES = 3;
static final int COMPUTE_PING_CONNECTION_TIMEOUT_MS = 500;

// Experimental Feature:
// Behavior of setting {@link GoogleAuthTransport} / {@link BindingEnforcement}:
// - MTLS-bound token where binding enforcement depends on IAM policy: MTLS / {}, {} / IAM_POLICY,
// MTLS / IAM_POLICY
// - MTLS-bound token where bindings are always enforced: {} / ON, MTLS / ON
// - DirectPath bound token: ALTS / {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you move this into the javadocs for GoogleAuthTransport so it can be referenced for users in the future?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


/**
* Experimental Feature.
*
* <p>{@link GoogleAuthTransport} specifies how to authenticate to Google APIs.
*/
public enum GoogleAuthTransport {
lqiu96 marked this conversation as resolved.
Show resolved Hide resolved
// Authenticating to Google APIs via DirectPath
ALTS("alts"),
// Authenticating to Google APIs via GFE
MTLS("mtls");

private final String label;

private GoogleAuthTransport(String label) {
this.label = label;
}

public String getLabel() {
return label;
}
}

/**
* Experimental Feature.
*
* <p>{@link BindingEnforcement} specifies how binding info in tokens will be enforced.
*/
public enum BindingEnforcement {
// Binding enforcement will always happen, irrespective of the IAM policy.
ON("on"),
// Binding enforcement will depend on IAM policy.
IAM_POLICY("iam-policy");

private final String label;

private BindingEnforcement(String label) {
this.label = label;
}

public String getLabel() {
return label;
}
}

private static final String METADATA_FLAVOR = "Metadata-Flavor";
private static final String GOOGLE = "Google";
private static final String WINDOWS = "windows";
Expand All @@ -122,6 +173,9 @@ public class ComputeEngineCredentials extends GoogleCredentials

private final Collection<String> scopes;

private final GoogleAuthTransport transport;
private final BindingEnforcement bindingEnforcement;

private transient HttpTransportFactory transportFactory;
private transient String serviceAccountEmail;

Expand Down Expand Up @@ -152,6 +206,8 @@ private ComputeEngineCredentials(ComputeEngineCredentials.Builder builder) {
scopeList.removeAll(Arrays.asList("", null));
this.scopes = ImmutableSet.<String>copyOf(scopeList);
}
this.transport = builder.getGoogleAuthTransport();
this.bindingEnforcement = builder.getBindingEnforcement();
}

@Override
Expand Down Expand Up @@ -191,7 +247,10 @@ public final Collection<String> 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".
lqiu96 marked this conversation as resolved.
Show resolved Hide resolved
*
* @return token url with the given scopes
*/
Expand All @@ -200,6 +259,12 @@ String createTokenUrlWithScopes() {
if (!scopes.isEmpty()) {
tokenUrl.set("scopes", Joiner.on(',').join(scopes));
}
if (transport != null) {
tokenUrl.set("transport", transport.getLabel());
}
if (bindingEnforcement != null) {
tokenUrl.set("binding-enforcement", bindingEnforcement.getLabel());
}
return tokenUrl.toString();
}

Expand Down Expand Up @@ -643,6 +708,9 @@ public static class Builder extends GoogleCredentials.Builder {
private Collection<String> scopes;
private Collection<String> defaultScopes;

private GoogleAuthTransport transport;
private BindingEnforcement bindingEnforcement;

protected Builder() {
setRefreshMargin(COMPUTE_REFRESH_MARGIN);
setExpirationMargin(COMPUTE_EXPIRATION_MARGIN);
Expand Down Expand Up @@ -684,6 +752,28 @@ public Builder setQuotaProjectId(String quotaProjectId) {
return this;
}

/**
* Set the {@code GoogleAuthTransport} type.
*
* @param transport the transport type over which to authenticate to Google APIs
*/
@CanIgnoreReturnValue
public Builder setGoogleAuthTransport(GoogleAuthTransport transport) {
this.transport = transport;
return this;
}

/**
* Set the {@code BindingEnforcement} type.
*
* @param bindingEnforcement the token binding enforcement policy.
*/
@CanIgnoreReturnValue
public Builder setBindingEnforcement(BindingEnforcement bindingEnforcement) {
this.bindingEnforcement = bindingEnforcement;
return this;
}

public HttpTransportFactory getHttpTransportFactory() {
return transportFactory;
}
Expand All @@ -696,6 +786,24 @@ public Collection<String> getDefaultScopes() {
return defaultScopes;
}

/**
* Get the {@code GoogleAuthTransport} type.
*
* @return the transport type over which to authenticate to Google APIs
*/
public GoogleAuthTransport getGoogleAuthTransport() {
return transport;
}

/**
* Get the {@code BindingEnforcement} type.
*
* @return the token binding enforcement policy.
*/
public BindingEnforcement getBindingEnforcement() {
return bindingEnforcement;
}

@Override
public ComputeEngineCredentials build() {
return new ComputeEngineCredentials(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,110 @@ public void buildTokenUrlWithScopes_defaultScopes() {
assertEquals("bar", scopes.toArray()[1]);
}

@Test
public void buildTokenUrl_nullTransport() {
lqiu96 marked this conversation as resolved.
Show resolved Hide resolved
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder()
.setGoogleAuthTransport(null)
.setBindingEnforcement(ComputeEngineCredentials.BindingEnforcement.ON)
.build();
String softBoundTokenUrl = credentials.createTokenUrlWithScopes();

assertEquals(TOKEN_URL + "?binding-enforcement=on", softBoundTokenUrl);
}

@Test
public void buildTokenUrl_nullBindingEnforcement() {
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder()
.setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.MTLS)
.setBindingEnforcement(null)
.build();
String softBoundTokenUrl = credentials.createTokenUrlWithScopes();

assertEquals(TOKEN_URL + "?transport=mtls", softBoundTokenUrl);
}

@Test
public void buildTokenUrl_nullTransport_nullBindingEnforcement() {
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder()
.setGoogleAuthTransport(null)
.setBindingEnforcement(null)
.build();
String softBoundTokenUrl = credentials.createTokenUrlWithScopes();

assertEquals(TOKEN_URL, softBoundTokenUrl);
}

@Test
public void buildTokenUrlSoftMtlsBound_mtls_transport() {
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder()
.setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.MTLS)
.build();
String softBoundTokenUrl = credentials.createTokenUrlWithScopes();

assertEquals(TOKEN_URL + "?transport=mtls", softBoundTokenUrl);
}

@Test
public void buildTokenUrlSoftMtlsBound_iam_enforcement() {
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder()
.setBindingEnforcement(ComputeEngineCredentials.BindingEnforcement.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()
.setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.MTLS)
.setBindingEnforcement(ComputeEngineCredentials.BindingEnforcement.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(ComputeEngineCredentials.BindingEnforcement.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()
.setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.MTLS)
.setBindingEnforcement(ComputeEngineCredentials.BindingEnforcement.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()
.setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.ALTS)
.build();
String softBoundTokenUrl = credentials.createTokenUrlWithScopes();

assertEquals(TOKEN_URL + "?transport=alts", softBoundTokenUrl);
}

@Test
public void buildScoped_scopesPresent() throws IOException {
ComputeEngineCredentials credentials =
Expand Down
Loading