xds/client: Export a method to return bootstrap config. (#4033)

diff --git a/xds/internal/balancer/cdsbalancer/cdsbalancer.go b/xds/internal/balancer/cdsbalancer/cdsbalancer.go
index ab4b78e..b37cc73 100644
--- a/xds/internal/balancer/cdsbalancer/cdsbalancer.go
+++ b/xds/internal/balancer/cdsbalancer/cdsbalancer.go
@@ -35,6 +35,7 @@
 	"google.golang.org/grpc/resolver"
 	"google.golang.org/grpc/serviceconfig"
 	"google.golang.org/grpc/xds/internal/balancer/edsbalancer"
+	"google.golang.org/grpc/xds/internal/client/bootstrap"
 
 	xdsinternal "google.golang.org/grpc/xds/internal"
 	xdsclient "google.golang.org/grpc/xds/internal/client"
@@ -131,7 +132,7 @@
 // the cdsBalancer. This will be faked out in unittests.
 type xdsClientInterface interface {
 	WatchCluster(string, func(xdsclient.ClusterUpdate, error)) func()
-	CertProviderConfigs() map[string]*certprovider.BuildableConfig
+	BootstrapConfig() *bootstrap.Config
 	Close()
 }
 
@@ -241,13 +242,14 @@
 		return nil
 	}
 
-	cpc := b.xdsClient.CertProviderConfigs()
-	if cpc == nil {
+	bc := b.xdsClient.BootstrapConfig()
+	if bc == nil || bc.CertProviderConfigs == nil {
 		// Bootstrap did not find any certificate provider configs, but the user
 		// has specified xdsCredentials and the management server has sent down
 		// security configuration.
 		return errors.New("xds: certificate_providers config missing in bootstrap file")
 	}
+	cpc := bc.CertProviderConfigs
 
 	// A root provider is required whether we are using TLS or mTLS.
 	rootProvider, err := buildProvider(cpc, config.RootInstanceName, config.RootCertName, false, true)
diff --git a/xds/internal/balancer/cdsbalancer/cdsbalancer_security_test.go b/xds/internal/balancer/cdsbalancer/cdsbalancer_security_test.go
index a3f923d..972d16b 100644
--- a/xds/internal/balancer/cdsbalancer/cdsbalancer_security_test.go
+++ b/xds/internal/balancer/cdsbalancer/cdsbalancer_security_test.go
@@ -31,6 +31,7 @@
 	"google.golang.org/grpc/internal/testutils"
 	"google.golang.org/grpc/resolver"
 	xdsclient "google.golang.org/grpc/xds/internal/client"
+	"google.golang.org/grpc/xds/internal/client/bootstrap"
 	xdstestutils "google.golang.org/grpc/xds/internal/testutils"
 	"google.golang.org/grpc/xds/internal/testutils/fakeclient"
 )
@@ -43,7 +44,7 @@
 
 var (
 	fpb1, fpb2                   *fakeProviderBuilder
-	bootstrapCertProviderConfigs map[string]*certprovider.BuildableConfig
+	bootstrapConfig              *bootstrap.Config
 	cdsUpdateWithGoodSecurityCfg = xdsclient.ClusterUpdate{
 		ServiceName: serviceName,
 		SecurityCfg: &xdsclient.SecurityConfig{
@@ -64,9 +65,11 @@
 	fpb2 = &fakeProviderBuilder{name: fakeProvider2Name}
 	cfg1, _ := fpb1.ParseConfig(fakeConfig + "1111")
 	cfg2, _ := fpb2.ParseConfig(fakeConfig + "2222")
-	bootstrapCertProviderConfigs = map[string]*certprovider.BuildableConfig{
-		"default1": cfg1,
-		"default2": cfg2,
+	bootstrapConfig = &bootstrap.Config{
+		CertProviderConfigs: map[string]*certprovider.BuildableConfig{
+			"default1": cfg1,
+			"default2": cfg2,
+		},
 	}
 	certprovider.Register(fpb1)
 	certprovider.Register(fpb2)
@@ -326,7 +329,7 @@
 
 		if i == 0 {
 			// Set the bootstrap config used by the fake client.
-			xdsC.SetCertProviderConfigs(bootstrapCertProviderConfigs)
+			xdsC.SetBootstrapConfig(bootstrapConfig)
 		}
 
 		// Here we invoke the watch callback registered on the fake xdsClient. A bad
@@ -373,7 +376,7 @@
 	defer func() { buildProvider = origBuildProvider }()
 
 	// Set the bootstrap config used by the fake client.
-	xdsC.SetCertProviderConfigs(bootstrapCertProviderConfigs)
+	xdsC.SetBootstrapConfig(bootstrapConfig)
 
 	// Here we invoke the watch callback registered on the fake xdsClient. Even
 	// though the received update is good, the certprovider.Store is configured
@@ -409,7 +412,7 @@
 	}()
 
 	// Set the bootstrap config used by the fake client.
-	xdsC.SetCertProviderConfigs(bootstrapCertProviderConfigs)
+	xdsC.SetBootstrapConfig(bootstrapConfig)
 
 	// Here we invoke the watch callback registered on the fake xdsClient. A bad
 	// security config is passed here. So, we expect the CDS balancer to not
@@ -465,7 +468,7 @@
 	}()
 
 	// Set the bootstrap config used by the fake client.
-	xdsC.SetCertProviderConfigs(bootstrapCertProviderConfigs)
+	xdsC.SetBootstrapConfig(bootstrapConfig)
 
 	// Here we invoke the watch callback registered on the fake xdsClient. This
 	// will trigger the watch handler on the CDS balancer, which will attempt to
@@ -496,7 +499,7 @@
 	}()
 
 	// Set the bootstrap config used by the fake client.
-	xdsC.SetCertProviderConfigs(bootstrapCertProviderConfigs)
+	xdsC.SetBootstrapConfig(bootstrapConfig)
 
 	// Here we invoke the watch callback registered on the fake xdsClient. This
 	// will trigger the watch handler on the CDS balancer, which will attempt to
@@ -546,7 +549,7 @@
 	}()
 
 	// Set the bootstrap config used by the fake client.
-	xdsC.SetCertProviderConfigs(bootstrapCertProviderConfigs)
+	xdsC.SetBootstrapConfig(bootstrapConfig)
 
 	// Here we invoke the watch callback registered on the fake xdsClient. This
 	// will trigger the watch handler on the CDS balancer, which will attempt to
@@ -617,7 +620,7 @@
 	defer func() { buildProvider = origBuildProvider }()
 
 	// Set the bootstrap config used by the fake client.
-	xdsC.SetCertProviderConfigs(bootstrapCertProviderConfigs)
+	xdsC.SetBootstrapConfig(bootstrapConfig)
 
 	// Here we invoke the watch callback registered on the fake xdsClient. This
 	// will trigger the watch handler on the CDS balancer, which will attempt to
diff --git a/xds/internal/client/client.go b/xds/internal/client/client.go
index aa715f5..09729ec 100644
--- a/xds/internal/client/client.go
+++ b/xds/internal/client/client.go
@@ -30,7 +30,7 @@
 	v2corepb "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
 	v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
 	"github.com/golang/protobuf/proto"
-	"google.golang.org/grpc/credentials/tls/certprovider"
+
 	"google.golang.org/grpc/xds/internal/client/load"
 
 	"google.golang.org/grpc"
@@ -390,11 +390,10 @@
 	return c, nil
 }
 
-// CertProviderConfigs returns the certificate provider configuration from the
-// "certificate_providers" field of the bootstrap file. The key in the returned
-// map is the plugin_instance_name. Callers must not modify the returned map.
-func (c *Client) CertProviderConfigs() map[string]*certprovider.BuildableConfig {
-	return c.config.CertProviderConfigs
+// BootstrapConfig returns the configuration read from the bootstrap file.
+// Callers must treat the return value as read-only.
+func (c *Client) BootstrapConfig() *bootstrap.Config {
+	return c.config
 }
 
 // run is a goroutine for all the callbacks.
diff --git a/xds/internal/testutils/fakeclient/client.go b/xds/internal/testutils/fakeclient/client.go
index c540b57..0978125 100644
--- a/xds/internal/testutils/fakeclient/client.go
+++ b/xds/internal/testutils/fakeclient/client.go
@@ -22,9 +22,9 @@
 import (
 	"context"
 
-	"google.golang.org/grpc/credentials/tls/certprovider"
 	"google.golang.org/grpc/internal/testutils"
 	xdsclient "google.golang.org/grpc/xds/internal/client"
+	"google.golang.org/grpc/xds/internal/client/bootstrap"
 	"google.golang.org/grpc/xds/internal/client/load"
 )
 
@@ -43,7 +43,7 @@
 	loadReportCh *testutils.Channel
 	closeCh      *testutils.Channel
 	loadStore    *load.Store
-	certConfigs  map[string]*certprovider.BuildableConfig
+	bootstrapCfg *bootstrap.Config
 
 	ldsCb func(xdsclient.ListenerUpdate, error)
 	rdsCb func(xdsclient.RouteConfigUpdate, error)
@@ -223,14 +223,14 @@
 	return err
 }
 
-// CertProviderConfigs returns the configured certificate provider configs.
-func (xdsC *Client) CertProviderConfigs() map[string]*certprovider.BuildableConfig {
-	return xdsC.certConfigs
+// BootstrapConfig returns the bootstrap config.
+func (xdsC *Client) BootstrapConfig() *bootstrap.Config {
+	return xdsC.bootstrapCfg
 }
 
-// SetCertProviderConfigs updates the certificate provider configs.
-func (xdsC *Client) SetCertProviderConfigs(configs map[string]*certprovider.BuildableConfig) {
-	xdsC.certConfigs = configs
+// SetBootstrapConfig updates the bootstrap config.
+func (xdsC *Client) SetBootstrapConfig(cfg *bootstrap.Config) {
+	xdsC.bootstrapCfg = cfg
 }
 
 // Name returns the name of the xds client.