Skip to content
Merged
Changes from 1 commit
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 @@ -22,11 +22,16 @@
import com.google.cloud.bigtable.gaxx.grpc.ChannelPrimer;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.protobuf.Any;
import com.google.rpc.ErrorInfo;
import com.google.rpc.PreconditionFailure;
import com.google.rpc.Status;
import io.grpc.Channel;
import io.grpc.ClientInterceptors;
import io.grpc.ManagedChannel;
import io.grpc.Status.Code;
import io.grpc.StatusRuntimeException;
import io.grpc.protobuf.StatusProto;
import java.util.Optional;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Level;
Expand Down Expand Up @@ -74,6 +79,46 @@ public boolean check(Channel channel) {
}
}

/** Checks if the exception is due to a VPC Service Controls policy violation. */
private boolean isVpcScViolation(StatusRuntimeException e) {
try {
Status status = StatusProto.fromThrowable(e);
if (status != null) {
for (Any detail : status.getDetailsList()) {
// Check for ErrorInfo reason
if (detail.is(ErrorInfo.class)) {
ErrorInfo errorInfo = detail.unpack(ErrorInfo.class);
if ("VPC_SERVICE_CONTROLS".equals(errorInfo.getReason())) {
return true;
}
}
// Check for PreconditionFailure violation type
if (detail.is(PreconditionFailure.class)) {
PreconditionFailure failure = detail.unpack(PreconditionFailure.class);
for (PreconditionFailure.Violation violation : failure.getViolationsList()) {
if ("VPC_SERVICE_CONTROLS".equals(violation.getType())) {
return true;
}
}
}
}
}
} catch (Exception ex) {
// Fall back silently to string matching if protobuf unpacking fails
}

// Check the error message if we can't parse ErrorDetails
String description = e.getStatus().getDescription();
String message = e.getMessage();

return (description != null
&& (description.contains("VPC Service Controls")
|| description.contains("VPC_SERVICE_CONTROLS")))
|| (message != null
&& (message.contains("VPC Service Controls")
|| message.contains("VPC_SERVICE_CONTROLS")));
}

/** Executes the underlying RPC and evaluates the eligibility. */
private boolean evaluateEligibility(Channel channel) {
MetadataExtractorInterceptor interceptor = createInterceptor();
Expand All @@ -91,8 +136,15 @@ private boolean evaluateEligibility(Channel channel) {
if (e.getStatus().getCode() != Code.PERMISSION_DENIED) {
throw e;
}
// Failed with permission error, resorting to ALTS check.
isEligible = sidebandData.isAlts();

if (isVpcScViolation(e)) {
LOG.log(
Level.WARNING,
"DirectPath is blocked by a VPC Service Controls perimeter policy violation.");
} else {
// Failed with standard permission error, resorting to ALTS check.
isEligible = sidebandData.isAlts();
}
Comment thread
mutianf marked this conversation as resolved.
Outdated
}

if (isEligible) {
Expand Down
Loading