Skip to content

Commit ab69245

Browse files
committed
Refactor xDS bootstrapper to improve role separation between io.grpc.xds/io.grpc (grpc specific) and io.grpc.xds.client (generic) packages.
- Remove call credentials from BootstrapperImpl.ServerInfo. - Store call credentials in implSpecificConfig (Object) wrapped in a Map. - Move JwtTokenFileCallCredentials to io.grpc.xds package. - Remove ChannelCredentials fallback from GrpcXdsTransportFactory.
1 parent 0f14a55 commit ab69245

25 files changed

Lines changed: 493 additions & 508 deletions

xds/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ dependencies {
4949
project(':grpc-core'),
5050
project(':grpc-util'),
5151
project(':grpc-services'),
52-
project(':grpc-auth'),
5352
project(path: ':grpc-alts', configuration: 'shadow'),
5453
libraries.guava,
5554
libraries.gson,

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

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import com.google.errorprone.annotations.concurrent.GuardedBy;
2222
import io.grpc.CallCredentials;
2323
import io.grpc.ChannelCredentials;
24+
import io.grpc.CompositeCallCredentials;
25+
import io.grpc.internal.GrpcUtil;
2426
import io.grpc.internal.JsonUtil;
2527
import io.grpc.xds.client.AllowedGrpcServices;
2628
import io.grpc.xds.client.AllowedGrpcServices.AllowedGrpcService;
@@ -30,12 +32,17 @@
3032
import io.grpc.xds.client.XdsInitializationException;
3133
import io.grpc.xds.client.XdsLogger;
3234
import java.io.IOException;
35+
import java.util.ArrayList;
3336
import java.util.List;
3437
import java.util.Map;
3538
import java.util.Optional;
3639
import javax.annotation.Nullable;
3740

3841
class GrpcBootstrapperImpl extends BootstrapperImpl {
42+
@VisibleForTesting
43+
public static boolean enableXdsBootstrapCallCreds = GrpcUtil.getFlag(
44+
"GRPC_EXPERIMENTAL_XDS_BOOTSTRAP_CALL_CREDS", false);
45+
3946
private static final String BOOTSTRAP_PATH_SYS_ENV_VAR = "GRPC_XDS_BOOTSTRAP";
4047
private static final String BOOTSTRAP_PATH_SYS_PROPERTY = "io.grpc.xds.bootstrap";
4148
private static final String BOOTSTRAP_CONFIG_SYS_ENV_VAR = "GRPC_XDS_BOOTSTRAP_CONFIG";
@@ -104,7 +111,62 @@ protected String getJsonContent() throws XdsInitializationException, IOException
104111
protected Object getImplSpecificConfig(Map<String, ?> serverConfig, String serverUri)
105112
throws XdsInitializationException {
106113
ConfiguredChannelCredentials configuredChannel = getChannelCredentials(serverConfig, serverUri);
107-
return configuredChannel != null ? configuredChannel.channelCredentials() : null;
114+
ChannelCredentials channelCredentials = configuredChannel != null
115+
? configuredChannel.channelCredentials() : null;
116+
117+
CallCredentials callCredentials = null;
118+
List<?> rawCallCreds = JsonUtil.getList(serverConfig, "call_creds");
119+
if (enableXdsBootstrapCallCreds && rawCallCreds != null) {
120+
List<Map<String, ?>> callCredsList = JsonUtil.checkObjectList(rawCallCreds);
121+
callCredentials = parseCallCredentials(callCredsList, serverUri);
122+
}
123+
124+
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
125+
if (channelCredentials != null) {
126+
builder.put("grpc.channel_credentials", channelCredentials);
127+
}
128+
if (callCredentials != null) {
129+
builder.put("grpc.call_credentials", callCredentials);
130+
}
131+
return builder.buildOrThrow();
132+
}
133+
134+
@Nullable
135+
private CallCredentials parseCallCredentials(List<Map<String, ?>> jsonList, String serverUri)
136+
throws XdsInitializationException {
137+
List<CallCredentials> parsedCreds = new ArrayList<>();
138+
for (Map<String, ?> credJson : jsonList) {
139+
String type = JsonUtil.getString(credJson, "type");
140+
if (type == null) {
141+
throw new XdsInitializationException(
142+
"Invalid bootstrap: server " + serverUri + " with 'call_creds' type unspecified");
143+
}
144+
if ("jwt_token_file".equals(type)) {
145+
Map<String, ?> config = JsonUtil.getObject(credJson, "config");
146+
if (config == null) {
147+
throw new XdsInitializationException(
148+
"Invalid bootstrap: server " + serverUri + " with 'jwt_token_file' config missing");
149+
}
150+
String jwtTokenFile = JsonUtil.getString(config, "jwt_token_file");
151+
if (jwtTokenFile == null || jwtTokenFile.isEmpty()) {
152+
throw new XdsInitializationException(
153+
"Invalid bootstrap: server " + serverUri
154+
+ " with 'jwt_token_file' jwt_token_file missing or empty");
155+
}
156+
parsedCreds.add(new JwtTokenFileCallCredentials(jwtTokenFile));
157+
} else {
158+
logger.log(XdsLogger.XdsLogLevel.INFO,
159+
"Skipping unsupported call credential type: {0}", type);
160+
}
161+
}
162+
if (parsedCreds.isEmpty()) {
163+
return null;
164+
}
165+
CallCredentials combined = parsedCreds.get(0);
166+
for (int i = 1; i < parsedCreds.size(); i++) {
167+
combined = new CompositeCallCredentials(combined, parsedCreds.get(i));
168+
}
169+
return combined;
108170
}
109171

110172
@GuardedBy("GrpcBootstrapperImpl.class")
@@ -194,8 +256,8 @@ protected Optional<Object> parseImplSpecificObject(
194256
Optional<CallCredentials> callCredentials = Optional.empty();
195257
List<?> rawCallCredsList = JsonUtil.getList(serviceConfig, "call_creds");
196258
if (rawCallCredsList != null && !rawCallCredsList.isEmpty()) {
197-
callCredentials =
198-
parseCallCredentials(JsonUtil.checkObjectList(rawCallCredsList), targetUri);
259+
callCredentials = Optional.ofNullable(
260+
parseCallCredentials(JsonUtil.checkObjectList(rawCallCredsList), targetUri));
199261
}
200262

201263
AllowedGrpcService.Builder b = AllowedGrpcService.builder()
@@ -208,16 +270,7 @@ protected Optional<Object> parseImplSpecificObject(
208270
return Optional.of(customConfig);
209271
}
210272

211-
@SuppressWarnings("unused")
212-
private static Optional<CallCredentials> parseCallCredentials(List<Map<String, ?>> jsonList,
213-
String targetUri)
214-
throws XdsInitializationException {
215-
// TODO(sauravzg): Currently no xDS call credentials providers are implemented (no
216-
// XdsCallCredentialsRegistry).
217-
// As per A102/A97, we should just ignore unsupported call credentials types
218-
// without throwing an exception.
219-
return Optional.empty();
220-
}
273+
221274

222275
private static final class JsonChannelCredsConfig implements ChannelCredsConfig {
223276
private final String type;

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import io.grpc.Status;
3535
import io.grpc.xds.client.Bootstrapper;
3636
import io.grpc.xds.client.XdsTransportFactory;
37+
import java.util.Map;
3738
import java.util.concurrent.TimeUnit;
3839

3940
final class GrpcXdsTransportFactory implements XdsTransportFactory {
@@ -80,19 +81,26 @@ public GrpcXdsTransport(Bootstrapper.ServerInfo serverInfo,
8081
CallCredentials callCredentials,
8182
ChannelConfigurator channelConfigurator) {
8283
String target = serverInfo.target();
83-
ChannelCredentials channelCredentials = (ChannelCredentials) serverInfo.implSpecificConfig();
84+
Object implConfig = serverInfo.implSpecificConfig();
85+
ChannelCredentials channelCredentials = null;
86+
CallCredentials serverCallCredentials = null;
87+
if (implConfig instanceof Map) {
88+
Map<?, ?> configMap = (Map<?, ?>) implConfig;
89+
channelCredentials = (ChannelCredentials) configMap.get("grpc.channel_credentials");
90+
serverCallCredentials = (CallCredentials) configMap.get("grpc.call_credentials");
91+
}
8492
ManagedChannelBuilder<?> channelBuilder = Grpc.newChannelBuilder(target, channelCredentials)
8593
.keepAliveTime(5, TimeUnit.MINUTES);
8694
if (channelConfigurator != null) {
8795
channelConfigurator.configureChannelBuilder(channelBuilder);
8896
channelBuilder.childChannelConfigurator(channelConfigurator);
8997
}
9098
this.channel = channelBuilder.build();
91-
if (callCredentials != null && serverInfo.callCredentials() != null) {
99+
if (callCredentials != null && serverCallCredentials != null) {
92100
this.callCredentials = new CompositeCallCredentials(
93-
callCredentials, serverInfo.callCredentials());
94-
} else if (serverInfo.callCredentials() != null) {
95-
this.callCredentials = serverInfo.callCredentials();
101+
callCredentials, serverCallCredentials);
102+
} else if (serverCallCredentials != null) {
103+
this.callCredentials = serverCallCredentials;
96104
} else {
97105
this.callCredentials = callCredentials;
98106
}

xds/src/main/java/io/grpc/xds/client/JwtTokenFileCallCredentials.java renamed to xds/src/main/java/io/grpc/xds/JwtTokenFileCallCredentials.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.grpc.xds.client;
17+
package io.grpc.xds;
1818

1919
import static com.google.common.base.Preconditions.checkNotNull;
2020

xds/src/main/java/io/grpc/xds/client/Bootstrapper.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import com.google.common.annotations.VisibleForTesting;
2323
import com.google.common.collect.ImmutableList;
2424
import com.google.common.collect.ImmutableMap;
25-
import io.grpc.CallCredentials;
2625
import io.grpc.Internal;
2726
import io.grpc.xds.client.EnvoyProtoData.Node;
2827
import java.util.List;
@@ -69,23 +68,20 @@ public abstract static class ServerInfo {
6968

7069
public abstract boolean failOnDataErrors();
7170

72-
@Nullable public abstract CallCredentials callCredentials();
73-
7471
@VisibleForTesting
7572
public static ServerInfo create(String target, @Nullable Object implSpecificConfig) {
7673
return new AutoValue_Bootstrapper_ServerInfo(target, implSpecificConfig,
77-
false, false, false, false, null);
74+
false, false, false, false);
7875
}
7976

8077
@VisibleForTesting
8178
public static ServerInfo create(
8279
String target, Object implSpecificConfig,
8380
boolean ignoreResourceDeletion, boolean isTrustedXdsServer,
84-
boolean resourceTimerIsTransientError, boolean failOnDataErrors,
85-
@Nullable CallCredentials callCredentials) {
81+
boolean resourceTimerIsTransientError, boolean failOnDataErrors) {
8682
return new AutoValue_Bootstrapper_ServerInfo(target, implSpecificConfig,
8783
ignoreResourceDeletion, isTrustedXdsServer,
88-
resourceTimerIsTransientError, failOnDataErrors, callCredentials);
84+
resourceTimerIsTransientError, failOnDataErrors);
8985
}
9086
}
9187

xds/src/main/java/io/grpc/xds/client/BootstrapperImpl.java

Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
import com.google.common.annotations.VisibleForTesting;
2020
import com.google.common.collect.ImmutableList;
2121
import com.google.common.collect.ImmutableMap;
22-
import io.grpc.CallCredentials;
23-
import io.grpc.CompositeCallCredentials;
2422
import io.grpc.Internal;
2523
import io.grpc.InternalLogId;
2624
import io.grpc.internal.GrpcUtil;
@@ -33,7 +31,6 @@
3331
import java.nio.charset.StandardCharsets;
3432
import java.nio.file.Files;
3533
import java.nio.file.Paths;
36-
import java.util.ArrayList;
3734
import java.util.HashMap;
3835
import java.util.List;
3936
import java.util.Map;
@@ -68,9 +65,6 @@ public abstract class BootstrapperImpl extends Bootstrapper {
6865
@VisibleForTesting
6966
static boolean enableXdsFallback = GrpcUtil.getFlag(GRPC_EXPERIMENTAL_XDS_FALLBACK, true);
7067

71-
@VisibleForTesting
72-
public static boolean enableXdsBootstrapCallCreds = GrpcUtil.getFlag(
73-
"GRPC_EXPERIMENTAL_XDS_BOOTSTRAP_CALL_CREDS", false);
7468

7569
@VisibleForTesting
7670
public static boolean xdsDataErrorHandlingEnabled
@@ -290,58 +284,15 @@ private List<ServerInfo> parseServerInfos(List<?> rawServerConfigs, XdsLogger lo
290284
failOnDataErrors = xdsDataErrorHandlingEnabled
291285
&& serverFeatures.contains(SERVER_FEATURE_FAIL_ON_DATA_ERRORS);
292286
}
293-
CallCredentials callCredentials = null;
294-
List<?> rawCallCreds = JsonUtil.getList(serverConfig, "call_creds");
295-
if (enableXdsBootstrapCallCreds && rawCallCreds != null) {
296-
List<Map<String, ?>> callCredsList = JsonUtil.checkObjectList(rawCallCreds);
297-
callCredentials = parseCallCredentials(callCredsList, serverUri);
298-
}
299287
servers.add(
300288
ServerInfo.create(serverUri, implSpecificConfig, ignoreResourceDeletion,
301289
serverFeatures != null
302290
&& serverFeatures.contains(SERVER_FEATURE_TRUSTED_XDS_SERVER),
303-
resourceTimerIsTransientError, failOnDataErrors, callCredentials));
291+
resourceTimerIsTransientError, failOnDataErrors));
304292
}
305293
return servers.build();
306294
}
307295

308-
@Nullable
309-
private CallCredentials parseCallCredentials(List<Map<String, ?>> jsonList, String serverUri)
310-
throws XdsInitializationException {
311-
List<CallCredentials> parsedCreds = new ArrayList<>();
312-
for (Map<String, ?> credJson : jsonList) {
313-
String type = JsonUtil.getString(credJson, "type");
314-
if (type == null) {
315-
throw new XdsInitializationException(
316-
"Invalid bootstrap: server " + serverUri + " with 'call_creds' type unspecified");
317-
}
318-
if ("jwt_token_file".equals(type)) {
319-
Map<String, ?> config = JsonUtil.getObject(credJson, "config");
320-
if (config == null) {
321-
throw new XdsInitializationException(
322-
"Invalid bootstrap: server " + serverUri + " with 'jwt_token_file' config missing");
323-
}
324-
String jwtTokenFile = JsonUtil.getString(config, "jwt_token_file");
325-
if (jwtTokenFile == null || jwtTokenFile.isEmpty()) {
326-
throw new XdsInitializationException(
327-
"Invalid bootstrap: server " + serverUri
328-
+ " with 'jwt_token_file' jwt_token_file missing or empty");
329-
}
330-
parsedCreds.add(new JwtTokenFileCallCredentials(jwtTokenFile));
331-
} else {
332-
logger.log(XdsLogLevel.INFO, "Skipping unsupported call credential type: {0}", type);
333-
}
334-
}
335-
if (parsedCreds.isEmpty()) {
336-
return null;
337-
}
338-
CallCredentials combined = parsedCreds.get(0);
339-
for (int i = 1; i < parsedCreds.size(); i++) {
340-
combined = new CompositeCallCredentials(combined, parsedCreds.get(i));
341-
}
342-
return combined;
343-
}
344-
345296
@VisibleForTesting
346297
public void setFileReader(FileReader reader) {
347298
this.reader = reader;

xds/src/test/java/io/grpc/xds/ExtAuthzConfigParserTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ private static BootstrapInfo dummyBootstrapInfo() {
6565

6666
private static ServerInfo dummyServerInfo() {
6767
return ServerInfo.create(
68-
"test_target", Collections.emptyMap(), false, true, false, false, null);
68+
"test_target", Collections.emptyMap(), false, true, false, false);
6969
}
7070

7171
private ExtAuthz.Builder extAuthzBuilder;

xds/src/test/java/io/grpc/xds/ExternalProcessorClientInterceptorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ public void setUp() throws Exception {
246246

247247
serverInfo =
248248
Bootstrapper.ServerInfo.create(
249-
"test_target", Collections.emptyMap(), false, true, false, false, null);
249+
"test_target", Collections.emptyMap(), false, true, false, false);
250250

251251
filterContext = Filter.FilterConfigParseContext.builder()
252252
.bootstrapInfo(bootstrapInfo)

xds/src/test/java/io/grpc/xds/ExternalProcessorFilterTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public void setUp() throws Exception {
7777

7878
serverInfo =
7979
Bootstrapper.ServerInfo.create(
80-
"test_target", Collections.emptyMap(), false, true, false, false, null);
80+
"test_target", Collections.emptyMap(), false, true, false, false);
8181

8282
filterContext = Filter.FilterConfigParseContext.builder()
8383
.bootstrapInfo(bootstrapInfo)

xds/src/test/java/io/grpc/xds/FaultFilterTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ private static Filter.FilterConfigParseContext getFilterContext() {
114114
.node(Node.newBuilder().build())
115115
.build())
116116
.serverInfo(ServerInfo.create(
117-
"test_target", Collections.emptyMap(), false, true, false, false, null))
117+
"test_target", Collections.emptyMap(), false, true, false, false))
118118
.build();
119119
}
120120
}

0 commit comments

Comments
 (0)