-
Notifications
You must be signed in to change notification settings - Fork 70
feat: Enable MTLS_S2A bound token by default for gRPC S2A enabled flows #3591
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
Changes from 7 commits
a091561
152ed13
39fa157
7c20422
3864db8
d8b2959
3c8da4e
8c060dc
c8528b8
2c41813
c487491
0fe5134
52ef3de
50d3ae2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,7 @@ | |
import com.google.common.io.Files; | ||
import io.grpc.CallCredentials; | ||
import io.grpc.ChannelCredentials; | ||
import io.grpc.CompositeChannelCredentials; | ||
import io.grpc.Grpc; | ||
import io.grpc.InsecureChannelCredentials; | ||
import io.grpc.ManagedChannel; | ||
|
@@ -69,6 +70,7 @@ | |
import java.nio.charset.StandardCharsets; | ||
import java.security.GeneralSecurityException; | ||
import java.security.KeyStore; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
@@ -146,7 +148,7 @@ public final class InstantiatingGrpcChannelProvider implements TransportChannelP | |
@VisibleForTesting final ImmutableMap<String, ?> directPathServiceConfig; | ||
@Nullable private final MtlsProvider mtlsProvider; | ||
@Nullable private final SecureSessionAgent s2aConfigProvider; | ||
@Nullable private final List<HardBoundTokenTypes> allowedHardBoundTokenTypes; | ||
private final List<HardBoundTokenTypes> allowedHardBoundTokenTypes; | ||
@VisibleForTesting final Map<String, String> headersWithDuplicatesRemoved = new HashMap<>(); | ||
|
||
@Nullable | ||
|
@@ -175,7 +177,10 @@ private InstantiatingGrpcChannelProvider(Builder builder) { | |
this.headerProvider = builder.headerProvider; | ||
this.useS2A = builder.useS2A; | ||
this.endpoint = builder.endpoint; | ||
this.allowedHardBoundTokenTypes = builder.allowedHardBoundTokenTypes; | ||
this.allowedHardBoundTokenTypes = | ||
builder.allowedHardBoundTokenTypes == null | ||
? new ArrayList<>() | ||
: builder.allowedHardBoundTokenTypes; | ||
lqiu96 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
this.mtlsProvider = builder.mtlsProvider; | ||
this.s2aConfigProvider = builder.s2aConfigProvider; | ||
this.envProvider = builder.envProvider; | ||
|
@@ -592,6 +597,35 @@ ChannelCredentials createS2ASecuredChannelCredentials() { | |
} | ||
} | ||
|
||
boolean isMtlsS2AHardBoundTokensEnabled() { | ||
|
||
if (!useS2A | ||
// If S2A cannot be used, {@code HardBoundTokenTypes.MTLS_S2A} hard bound tokens should not | ||
// be used | ||
lqiu96 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|| allowedHardBoundTokenTypes.isEmpty() | ||
|| credentials == null | ||
|| !(credentials instanceof ComputeEngineCredentials)) { | ||
return false; | ||
} | ||
return allowedHardBoundTokenTypes.stream() | ||
.anyMatch(val -> val.equals(HardBoundTokenTypes.MTLS_S2A)); | ||
} | ||
|
||
CallCredentials createHardBoundTokensCallCredentials( | ||
ComputeEngineCredentials.GoogleAuthTransport googleAuthTransport, | ||
ComputeEngineCredentials.BindingEnforcement bindingEnforcement) { | ||
ComputeEngineCredentials.Builder credsBuilder = | ||
((ComputeEngineCredentials) credentials).toBuilder(); | ||
// We only set scopes and HTTP transport factory from the original credentials because | ||
// only those are used in gRPC CallCredentials to fetch request metadata. | ||
return MoreCallCredentials.from( | ||
ComputeEngineCredentials.newBuilder() | ||
.setScopes(credsBuilder.getScopes()) | ||
.setHttpTransportFactory(credsBuilder.getHttpTransportFactory()) | ||
.setGoogleAuthTransport(googleAuthTransport) | ||
.setBindingEnforcement(bindingEnforcement) | ||
lqiu96 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
lqiu96 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
.build()); | ||
} | ||
|
||
private ManagedChannel createSingleChannel() throws IOException { | ||
GrpcHeaderInterceptor headerInterceptor = | ||
new GrpcHeaderInterceptor(headersWithDuplicatesRemoved); | ||
|
@@ -648,6 +682,15 @@ private ManagedChannel createSingleChannel() throws IOException { | |
} | ||
if (channelCredentials != null) { | ||
// Create the channel using S2A-secured channel credentials. | ||
if (isMtlsS2AHardBoundTokensEnabled()) { | ||
// Set a {@code ComputeEngineCredentials} instance to be per-RPC call credentials, | ||
// which will be used to fetch MTLS_S2A hard bound tokens from the metdata server. | ||
CallCredentials callCreds = | ||
createHardBoundTokensCallCredentials( | ||
ComputeEngineCredentials.GoogleAuthTransport.MTLS, | ||
ComputeEngineCredentials.BindingEnforcement.ON); | ||
channelCredentials = CompositeChannelCredentials.create(channelCredentials, callCreds); | ||
} | ||
builder = Grpc.newChannelBuilder(endpoint, channelCredentials); | ||
} else { | ||
// Use default if we cannot initialize channel credentials via DCA or S2A. | ||
|
@@ -818,7 +861,7 @@ public static final class Builder { | |
@Nullable private Boolean attemptDirectPathXds; | ||
@Nullable private Boolean allowNonDefaultServiceAccount; | ||
@Nullable private ImmutableMap<String, ?> directPathServiceConfig; | ||
@Nullable private List<HardBoundTokenTypes> allowedHardBoundTokenTypes; | ||
private List<HardBoundTokenTypes> allowedHardBoundTokenTypes; | ||
|
||
private Builder() { | ||
processorCount = Runtime.getRuntime().availableProcessors(); | ||
|
@@ -846,6 +889,7 @@ private Builder(InstantiatingGrpcChannelProvider provider) { | |
this.attemptDirectPath = provider.attemptDirectPath; | ||
this.attemptDirectPathXds = provider.attemptDirectPathXds; | ||
this.allowNonDefaultServiceAccount = provider.allowNonDefaultServiceAccount; | ||
this.allowedHardBoundTokenTypes = provider.allowedHardBoundTokenTypes; | ||
this.directPathServiceConfig = provider.directPathServiceConfig; | ||
this.mtlsProvider = provider.mtlsProvider; | ||
this.s2aConfigProvider = provider.s2aConfigProvider; | ||
|
@@ -914,7 +958,10 @@ Builder setUseS2A(boolean useS2A) { | |
*/ | ||
@InternalApi | ||
public Builder setAllowHardBoundTokenTypes(List<HardBoundTokenTypes> allowedValues) { | ||
this.allowedHardBoundTokenTypes = allowedValues; | ||
this.allowedHardBoundTokenTypes = | ||
Preconditions.checkNotNull( | ||
allowedValues, "Illegal Argument, allowedValues cannot be null"); | ||
lqiu96 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
; | ||
return this; | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.