Skip to content

Commit a2d0511

Browse files
sauravzgkannanjgithub
authored andcommitted
xds: Add configuration objects for ExtAuthz, GrpcService and Bootstrap changes for GrpcService (grpc#12492)
This commit introduces configuration objects for the external authorization (ExtAuthz) filter and the gRPC service and corresponding translations from XDS proto and Bootstrap. These classes provide a structured, immutable representation of the subset of the configuration defined in the xDS protobuf messages. This PR should mostly now (hopefully ) be compliant with grpc/proposal#510 but without - CallCredentials (since I don't see A97) being implemented yet and would prefer to do it in a followup , we return empty optional) - TlsCredentials( since it's non trivial to construct a TLS credentials object, we throw an exception) - LocalCredentials(Java does't support these, we throw an exception) The main new classes are: - `ExtAuthzConfig`: Represents the configuration for the `ExtAuthz` filter, including settings for the gRPC service, header mutation rules, and other filter behaviors. - `GrpcServiceConfig`: Represents the configuration for a gRPC service, including the target URI, credentials, and other settings. - `HeaderMutationRulesConfig`: Represents the configuration for header mutation rules. - `ChannelCredsConfig` and friends: To allow comparison between credential configuration , to allow caching based on creds which'll be needed in followup PRs for authz and proc. The relevant sections of the spec are - GrpcService: grpc/proposal#510 - ExtAuthz: https://github.com/grpc/proposal/pull/481/files#diff-6bb76a24aa142cc33db9218509688f01b30c8885d2fd8849f164244e68cd54eaR106-R190 This commit also includes parsers to create these configuration objects from the corresponding protobuf messages, as well as unit tests for the new classes.
1 parent 9a88c69 commit a2d0511

12 files changed

Lines changed: 1670 additions & 23 deletions
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright 2025 The gRPC Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.grpc.xds;
18+
19+
import com.google.common.collect.ImmutableList;
20+
import io.envoyproxy.envoy.extensions.filters.http.ext_authz.v3.ExtAuthz;
21+
import io.grpc.internal.GrpcUtil;
22+
import io.grpc.xds.client.Bootstrapper.BootstrapInfo;
23+
import io.grpc.xds.client.Bootstrapper.ServerInfo;
24+
import io.grpc.xds.internal.MatcherParser;
25+
import io.grpc.xds.internal.extauthz.ExtAuthzConfig;
26+
import io.grpc.xds.internal.extauthz.ExtAuthzParseException;
27+
import io.grpc.xds.internal.grpcservice.GrpcServiceConfig;
28+
import io.grpc.xds.internal.grpcservice.GrpcServiceParseException;
29+
import io.grpc.xds.internal.headermutations.HeaderMutationRulesParseException;
30+
import io.grpc.xds.internal.headermutations.HeaderMutationRulesParser;
31+
32+
33+
/**
34+
* Parser for {@link io.envoyproxy.envoy.extensions.filters.http.ext_authz.v3.ExtAuthz}.
35+
*/
36+
final class ExtAuthzConfigParser {
37+
38+
private ExtAuthzConfigParser() {}
39+
40+
/**
41+
* Parses the {@link io.envoyproxy.envoy.extensions.filters.http.ext_authz.v3.ExtAuthz} proto to
42+
* create an {@link ExtAuthzConfig} instance.
43+
*
44+
* @param extAuthzProto The ext_authz proto to parse.
45+
* @return An {@link ExtAuthzConfig} instance.
46+
* @throws ExtAuthzParseException if the proto is invalid or contains unsupported features.
47+
*/
48+
public static ExtAuthzConfig parse(
49+
ExtAuthz extAuthzProto, BootstrapInfo bootstrapInfo, ServerInfo serverInfo)
50+
throws ExtAuthzParseException {
51+
if (!extAuthzProto.hasGrpcService()) {
52+
throw new ExtAuthzParseException(
53+
"unsupported ExtAuthz service type: only grpc_service is supported");
54+
}
55+
GrpcServiceConfig grpcServiceConfig;
56+
try {
57+
grpcServiceConfig =
58+
GrpcServiceConfigParser.parse(extAuthzProto.getGrpcService(), bootstrapInfo, serverInfo);
59+
} catch (GrpcServiceParseException e) {
60+
throw new ExtAuthzParseException("Failed to parse GrpcService config: " + e.getMessage(), e);
61+
}
62+
ExtAuthzConfig.Builder builder = ExtAuthzConfig.builder().grpcService(grpcServiceConfig)
63+
.failureModeAllow(extAuthzProto.getFailureModeAllow())
64+
.failureModeAllowHeaderAdd(extAuthzProto.getFailureModeAllowHeaderAdd())
65+
.includePeerCertificate(extAuthzProto.getIncludePeerCertificate())
66+
.denyAtDisable(extAuthzProto.getDenyAtDisable().getDefaultValue().getValue());
67+
68+
if (extAuthzProto.hasFilterEnabled()) {
69+
try {
70+
builder.filterEnabled(
71+
MatcherParser.parseFractionMatcher(extAuthzProto.getFilterEnabled().getDefaultValue()));
72+
} catch (IllegalArgumentException e) {
73+
throw new ExtAuthzParseException(e.getMessage());
74+
}
75+
}
76+
77+
if (extAuthzProto.hasStatusOnError()) {
78+
builder.statusOnError(
79+
GrpcUtil.httpStatusToGrpcStatus(extAuthzProto.getStatusOnError().getCodeValue()));
80+
}
81+
82+
if (extAuthzProto.hasAllowedHeaders()) {
83+
builder.allowedHeaders(extAuthzProto.getAllowedHeaders().getPatternsList().stream()
84+
.map(MatcherParser::parseStringMatcher).collect(ImmutableList.toImmutableList()));
85+
}
86+
87+
if (extAuthzProto.hasDisallowedHeaders()) {
88+
builder.disallowedHeaders(extAuthzProto.getDisallowedHeaders().getPatternsList().stream()
89+
.map(MatcherParser::parseStringMatcher).collect(ImmutableList.toImmutableList()));
90+
}
91+
92+
if (extAuthzProto.hasDecoderHeaderMutationRules()) {
93+
try {
94+
builder.decoderHeaderMutationRules(
95+
HeaderMutationRulesParser.parse(extAuthzProto.getDecoderHeaderMutationRules()));
96+
} catch (HeaderMutationRulesParseException e) {
97+
throw new ExtAuthzParseException(e.getMessage(), e);
98+
}
99+
}
100+
101+
return builder.build();
102+
}
103+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2025 The gRPC Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.grpc.xds;
18+
19+
import com.google.auto.value.AutoValue;
20+
import io.grpc.Internal;
21+
import io.grpc.xds.client.AllowedGrpcServices;
22+
23+
/**
24+
* Custom configuration for gRPC xDS bootstrap implementation.
25+
*/
26+
@Internal
27+
@AutoValue
28+
public abstract class GrpcBootstrapImplConfig {
29+
public abstract AllowedGrpcServices allowedGrpcServices();
30+
31+
public static GrpcBootstrapImplConfig create(AllowedGrpcServices services) {
32+
return new AutoValue_GrpcBootstrapImplConfig(services);
33+
}
34+
}

xds/src/main/java/io/grpc/xds/GrpcBootstrapperImpl.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
import io.grpc.CallCredentials;
2323
import io.grpc.ChannelCredentials;
2424
import io.grpc.internal.JsonUtil;
25+
import io.grpc.xds.client.AllowedGrpcServices;
26+
import io.grpc.xds.client.AllowedGrpcServices.AllowedGrpcService;
2527
import io.grpc.xds.client.BootstrapperImpl;
28+
import io.grpc.xds.client.ConfiguredChannelCredentials;
29+
import io.grpc.xds.client.ConfiguredChannelCredentials.ChannelCredsConfig;
2630
import io.grpc.xds.client.XdsInitializationException;
2731
import io.grpc.xds.client.XdsLogger;
28-
import io.grpc.xds.internal.grpcservice.AllowedGrpcService;
29-
import io.grpc.xds.internal.grpcservice.AllowedGrpcServices;
30-
import io.grpc.xds.internal.grpcservice.ChannelCredsConfig;
31-
import io.grpc.xds.internal.grpcservice.ConfiguredChannelCredentials;
3232
import java.io.IOException;
3333
import java.util.List;
3434
import java.util.Map;
@@ -173,11 +173,11 @@ private static ConfiguredChannelCredentials parseChannelCredentials(List<Map<Str
173173
}
174174

175175
@Override
176-
protected Optional<Object> parseAllowedGrpcServices(
176+
protected Optional<Object> parseImplSpecificObject(
177177
@Nullable Map<String, ?> rawAllowedGrpcServices)
178178
throws XdsInitializationException {
179179
if (rawAllowedGrpcServices == null || rawAllowedGrpcServices.isEmpty()) {
180-
return Optional.of(AllowedGrpcServices.empty());
180+
return Optional.of(GrpcBootstrapImplConfig.create(AllowedGrpcServices.empty()));
181181
}
182182

183183
ImmutableMap.Builder<String, AllowedGrpcService> builder =
@@ -203,7 +203,9 @@ protected Optional<Object> parseAllowedGrpcServices(
203203
callCredentials.ifPresent(b::callCredentials);
204204
builder.put(targetUri, b.build());
205205
}
206-
return Optional.of(AllowedGrpcServices.create(builder.build()));
206+
GrpcBootstrapImplConfig customConfig =
207+
GrpcBootstrapImplConfig.create(AllowedGrpcServices.create(builder.build()));
208+
return Optional.of(customConfig);
207209
}
208210

209211
@SuppressWarnings("unused")

0 commit comments

Comments
 (0)