credentials/xds: Move non-user facing functionality to an internal package (#4117)

This commit is contained in:
Easwar Swaminathan 2020-12-16 15:46:56 -08:00 committed by GitHub
parent 644d506ebb
commit d79063fdde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 268 additions and 229 deletions

View File

@ -32,21 +32,13 @@ import (
"errors"
"fmt"
"net"
"sync"
"time"
"google.golang.org/grpc/attributes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/tls/certprovider"
"google.golang.org/grpc/internal"
credinternal "google.golang.org/grpc/internal/credentials"
"google.golang.org/grpc/resolver"
xdsinternal "google.golang.org/grpc/internal/credentials/xds"
)
func init() {
internal.GetXDSHandshakeInfoForTesting = getHandshakeInfo
}
// ClientOptions contains parameters to configure a new client-side xDS
// credentials implementation.
type ClientOptions struct {
@ -97,193 +89,6 @@ type credsImpl struct {
fallback credentials.TransportCredentials
}
// handshakeAttrKey is the type used as the key to store HandshakeInfo in
// the Attributes field of resolver.Address.
type handshakeAttrKey struct{}
// SetHandshakeInfo returns a copy of addr in which the Attributes field is
// updated with hInfo.
func SetHandshakeInfo(addr resolver.Address, hInfo *HandshakeInfo) resolver.Address {
addr.Attributes = addr.Attributes.WithValues(handshakeAttrKey{}, hInfo)
return addr
}
// getHandshakeInfo returns a pointer to the HandshakeInfo stored in attr.
func getHandshakeInfo(attr *attributes.Attributes) *HandshakeInfo {
v := attr.Value(handshakeAttrKey{})
hi, _ := v.(*HandshakeInfo)
return hi
}
// HandshakeInfo wraps all the security configuration required by client and
// server handshake methods in credsImpl. The xDS implementation will be
// responsible for populating these fields.
//
// Safe for concurrent access.
//
// TODO(easwars): Move this type and any other non-user functionality to an
// internal package.
type HandshakeInfo struct {
mu sync.Mutex
rootProvider certprovider.Provider
identityProvider certprovider.Provider
acceptedSANs map[string]bool // Only on the client side.
requireClientCert bool // Only on server side.
}
// SetRootCertProvider updates the root certificate provider.
func (hi *HandshakeInfo) SetRootCertProvider(root certprovider.Provider) {
hi.mu.Lock()
hi.rootProvider = root
hi.mu.Unlock()
}
// SetIdentityCertProvider updates the identity certificate provider.
func (hi *HandshakeInfo) SetIdentityCertProvider(identity certprovider.Provider) {
hi.mu.Lock()
hi.identityProvider = identity
hi.mu.Unlock()
}
// SetAcceptedSANs updates the list of accepted SANs.
func (hi *HandshakeInfo) SetAcceptedSANs(sans []string) {
hi.mu.Lock()
hi.acceptedSANs = make(map[string]bool, len(sans))
for _, san := range sans {
hi.acceptedSANs[san] = true
}
hi.mu.Unlock()
}
// SetRequireClientCert updates whether a client cert is required during the
// ServerHandshake(). A value of true indicates that we are performing mTLS.
func (hi *HandshakeInfo) SetRequireClientCert(require bool) {
hi.mu.Lock()
hi.requireClientCert = require
hi.mu.Unlock()
}
// UseFallbackCreds returns true when fallback credentials are to be used based
// on the contents of the HandshakeInfo.
func (hi *HandshakeInfo) UseFallbackCreds() bool {
if hi == nil {
return true
}
hi.mu.Lock()
defer hi.mu.Unlock()
return hi.identityProvider == nil && hi.rootProvider == nil
}
func (hi *HandshakeInfo) makeClientSideTLSConfig(ctx context.Context) (*tls.Config, error) {
hi.mu.Lock()
// On the client side, rootProvider is mandatory. IdentityProvider is
// optional based on whether the client is doing TLS or mTLS.
if hi.rootProvider == nil {
return nil, errors.New("xds: CertificateProvider to fetch trusted roots is missing, cannot perform TLS handshake. Please check configuration on the management server")
}
// Since the call to KeyMaterial() can block, we read the providers under
// the lock but call the actual function after releasing the lock.
rootProv, idProv := hi.rootProvider, hi.identityProvider
hi.mu.Unlock()
// InsecureSkipVerify needs to be set to true because we need to perform
// custom verification to check the SAN on the received certificate.
// Currently the Go stdlib does complete verification of the cert (which
// includes hostname verification) or none. We are forced to go with the
// latter and perform the normal cert validation ourselves.
cfg := &tls.Config{InsecureSkipVerify: true}
km, err := rootProv.KeyMaterial(ctx)
if err != nil {
return nil, fmt.Errorf("xds: fetching trusted roots from CertificateProvider failed: %v", err)
}
cfg.RootCAs = km.Roots
if idProv != nil {
km, err := idProv.KeyMaterial(ctx)
if err != nil {
return nil, fmt.Errorf("xds: fetching identity certificates from CertificateProvider failed: %v", err)
}
cfg.Certificates = km.Certs
}
return cfg, nil
}
func (hi *HandshakeInfo) makeServerSideTLSConfig(ctx context.Context) (*tls.Config, error) {
cfg := &tls.Config{ClientAuth: tls.NoClientCert}
hi.mu.Lock()
// On the server side, identityProvider is mandatory. RootProvider is
// optional based on whether the server is doing TLS or mTLS.
if hi.identityProvider == nil {
return nil, errors.New("xds: CertificateProvider to fetch identity certificate is missing, cannot perform TLS handshake. Please check configuration on the management server")
}
// Since the call to KeyMaterial() can block, we read the providers under
// the lock but call the actual function after releasing the lock.
rootProv, idProv := hi.rootProvider, hi.identityProvider
if hi.requireClientCert {
cfg.ClientAuth = tls.RequireAndVerifyClientCert
}
hi.mu.Unlock()
// identityProvider is mandatory on the server side.
km, err := idProv.KeyMaterial(ctx)
if err != nil {
return nil, fmt.Errorf("xds: fetching identity certificates from CertificateProvider failed: %v", err)
}
cfg.Certificates = km.Certs
if rootProv != nil {
km, err := rootProv.KeyMaterial(ctx)
if err != nil {
return nil, fmt.Errorf("xds: fetching trusted roots from CertificateProvider failed: %v", err)
}
cfg.ClientCAs = km.Roots
}
return cfg, nil
}
func (hi *HandshakeInfo) matchingSANExists(cert *x509.Certificate) bool {
if len(hi.acceptedSANs) == 0 {
// An empty list of acceptedSANs means "accept everything".
return true
}
var sans []string
// SANs can be specified in any of these four fields on the parsed cert.
sans = append(sans, cert.DNSNames...)
sans = append(sans, cert.EmailAddresses...)
for _, ip := range cert.IPAddresses {
sans = append(sans, ip.String())
}
for _, uri := range cert.URIs {
sans = append(sans, uri.String())
}
hi.mu.Lock()
defer hi.mu.Unlock()
for _, san := range sans {
if hi.acceptedSANs[san] {
return true
}
}
return false
}
// NewHandshakeInfo returns a new instance of HandshakeInfo with the given root
// and identity certificate providers.
func NewHandshakeInfo(root, identity certprovider.Provider, sans ...string) *HandshakeInfo {
acceptedSANs := make(map[string]bool, len(sans))
for _, san := range sans {
acceptedSANs[san] = true
}
return &HandshakeInfo{
rootProvider: root,
identityProvider: identity,
acceptedSANs: acceptedSANs,
}
}
// ClientHandshake performs the TLS handshake on the client-side.
//
// It looks for the presence of a HandshakeInfo value in the passed in context
@ -314,7 +119,7 @@ func (c *credsImpl) ClientHandshake(ctx context.Context, authority string, rawCo
if chi.Attributes == nil {
return c.fallback.ClientHandshake(ctx, authority, rawConn)
}
hi := getHandshakeInfo(chi.Attributes)
hi := xdsinternal.GetHandshakeInfo(chi.Attributes)
if hi.UseFallbackCreds() {
return c.fallback.ClientHandshake(ctx, authority, rawConn)
}
@ -331,7 +136,7 @@ func (c *credsImpl) ClientHandshake(ctx context.Context, authority string, rawCo
// 4. Key usage to match whether client/server usage.
// 5. A `VerifyPeerCertificate` function which performs normal peer
// cert verification using configured roots, and the custom SAN checks.
cfg, err := hi.makeClientSideTLSConfig(ctx)
cfg, err := hi.ClientSideTLSConfig(ctx)
if err != nil {
return nil, nil, err
}
@ -362,7 +167,7 @@ func (c *credsImpl) ClientHandshake(ctx context.Context, authority string, rawCo
}
// The SANs sent by the MeshCA are encoded as SPIFFE IDs. We need to
// only look at the SANs on the leaf cert.
if !hi.matchingSANExists(certs[0]) {
if !hi.MatchingSANExists(certs[0]) {
return fmt.Errorf("SANs received in leaf certificate %+v does not match any of the accepted SANs", certs[0])
}
return nil
@ -410,7 +215,9 @@ func (c *credsImpl) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.Aut
// passed to this function does not implement this interface, or if the
// `HandshakeInfo` does not contain the information we are looking for, we
// delegate the handshake to the fallback credentials.
hiConn, ok := rawConn.(interface{ XDSHandshakeInfo() *HandshakeInfo })
hiConn, ok := rawConn.(interface {
XDSHandshakeInfo() *xdsinternal.HandshakeInfo
})
if !ok {
return c.fallback.ServerHandshake(rawConn)
}
@ -430,7 +237,7 @@ func (c *credsImpl) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.Aut
}
ctx, cancel := context.WithDeadline(context.Background(), deadline)
defer cancel()
cfg, err := hi.makeServerSideTLSConfig(ctx)
cfg, err := hi.ServerSideTLSConfig(ctx)
if err != nil {
return nil, nil, err
}

View File

@ -33,6 +33,7 @@ import (
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/tls/certprovider"
"google.golang.org/grpc/internal"
xdsinternal "google.golang.org/grpc/internal/credentials/xds"
"google.golang.org/grpc/internal/grpctest"
"google.golang.org/grpc/internal/testutils"
"google.golang.org/grpc/resolver"
@ -217,8 +218,8 @@ func newTestContextWithHandshakeInfo(parent context.Context, root, identity cert
// Creating the HandshakeInfo and adding it to the attributes is very
// similar to what the CDS balancer would do when it intercepts calls to
// NewSubConn().
info := NewHandshakeInfo(root, identity, sans...)
addr := SetHandshakeInfo(resolver.Address{}, info)
info := xdsinternal.NewHandshakeInfo(root, identity, sans...)
addr := xdsinternal.SetHandshakeInfo(resolver.Address{}, info)
// Moving the attributes from the resolver.Address to the context passed to
// the handshaker is done in the transport layer. Since we directly call the
@ -529,12 +530,12 @@ func (s) TestClientCredsProviderSwitch(t *testing.T) {
// Create a root provider which will fail the handshake because it does not
// use the correct trust roots.
root1 := makeRootProvider(t, "x509/client_ca_cert.pem")
handshakeInfo := NewHandshakeInfo(root1, nil, defaultTestCertSAN)
handshakeInfo := xdsinternal.NewHandshakeInfo(root1, nil, defaultTestCertSAN)
// We need to repeat most of what newTestContextWithHandshakeInfo() does
// here because we need access to the underlying HandshakeInfo so that we
// can update it before the next call to ClientHandshake().
addr := SetHandshakeInfo(resolver.Address{}, handshakeInfo)
addr := xdsinternal.SetHandshakeInfo(resolver.Address{}, handshakeInfo)
contextWithHandshakeInfo := internal.NewClientHandshakeInfoContext.(func(context.Context, credentials.ClientHandshakeInfo) context.Context)
ctx = contextWithHandshakeInfo(ctx, credentials.ClientHandshakeInfo{Attributes: addr.Attributes})
if _, _, err := creds.ClientHandshake(ctx, authority, conn); err == nil {

View File

@ -32,6 +32,7 @@ import (
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/tls/certprovider"
xdsinternal "google.golang.org/grpc/internal/credentials/xds"
"google.golang.org/grpc/testdata"
)
@ -94,11 +95,11 @@ func (s) TestServerCredsWithoutFallback(t *testing.T) {
type wrapperConn struct {
net.Conn
xdsHI *HandshakeInfo
xdsHI *xdsinternal.HandshakeInfo
deadline time.Time
}
func (wc *wrapperConn) XDSHandshakeInfo() *HandshakeInfo {
func (wc *wrapperConn) XDSHandshakeInfo() *xdsinternal.HandshakeInfo {
return wc.xdsHI
}
@ -106,7 +107,7 @@ func (wc *wrapperConn) GetDeadline() time.Time {
return wc.deadline
}
func newWrappedConn(conn net.Conn, xdsHI *HandshakeInfo, deadline time.Time) *wrapperConn {
func newWrappedConn(conn net.Conn, xdsHI *xdsinternal.HandshakeInfo, deadline time.Time) *wrapperConn {
return &wrapperConn{Conn: conn, xdsHI: xdsHI, deadline: deadline}
}
@ -120,7 +121,7 @@ func (s) TestServerCredsInvalidHandshakeInfo(t *testing.T) {
t.Fatalf("NewServerCredentials(%v) failed: %v", opts, err)
}
info := NewHandshakeInfo(&fakeProvider{}, nil)
info := xdsinternal.NewHandshakeInfo(&fakeProvider{}, nil)
conn := newWrappedConn(nil, info, time.Time{})
if _, _, err := creds.ServerHandshake(conn); err == nil {
t.Fatal("ServerHandshake succeeded without identity certificate provider in HandshakeInfo")
@ -156,7 +157,7 @@ func (s) TestServerCredsProviderFailure(t *testing.T) {
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
info := NewHandshakeInfo(test.rootProvider, test.identityProvider)
info := xdsinternal.NewHandshakeInfo(test.rootProvider, test.identityProvider)
conn := newWrappedConn(nil, info, time.Time{})
if _, _, err := creds.ServerHandshake(conn); err == nil || !strings.Contains(err.Error(), test.wantErr) {
t.Fatalf("ServerHandshake() returned error: %q, wantErr: %q", err, test.wantErr)
@ -178,7 +179,7 @@ func (s) TestServerCredsHandshakeTimeout(t *testing.T) {
// Create a test server which uses the xDS server credentials created above
// to perform TLS handshake on incoming connections.
ts := newTestServerWithHandshakeFunc(func(rawConn net.Conn) handshakeResult {
hi := NewHandshakeInfo(makeRootProvider(t, "x509/client_ca_cert.pem"), makeIdentityProvider(t, "x509/server2_cert.pem", "x509/server2_key.pem"))
hi := xdsinternal.NewHandshakeInfo(makeRootProvider(t, "x509/client_ca_cert.pem"), makeIdentityProvider(t, "x509/server2_cert.pem", "x509/server2_key.pem"))
hi.SetRequireClientCert(true)
// Create a wrapped conn which can return the HandshakeInfo created
@ -231,7 +232,7 @@ func (s) TestServerCredsHandshakeFailure(t *testing.T) {
ts := newTestServerWithHandshakeFunc(func(rawConn net.Conn) handshakeResult {
// Create a HandshakeInfo which has a root provider which does not match
// the certificate sent by the client.
hi := NewHandshakeInfo(makeRootProvider(t, "x509/server_ca_cert.pem"), makeIdentityProvider(t, "x509/client2_cert.pem", "x509/client2_key.pem"))
hi := xdsinternal.NewHandshakeInfo(makeRootProvider(t, "x509/server_ca_cert.pem"), makeIdentityProvider(t, "x509/client2_cert.pem", "x509/client2_key.pem"))
hi.SetRequireClientCert(true)
// Create a wrapped conn which can return the HandshakeInfo and
@ -313,7 +314,7 @@ func (s) TestServerCredsHandshakeSuccess(t *testing.T) {
// created above to perform TLS handshake on incoming connections.
ts := newTestServerWithHandshakeFunc(func(rawConn net.Conn) handshakeResult {
// Create a HandshakeInfo with information from the test table.
hi := NewHandshakeInfo(test.rootProvider, test.identityProvider)
hi := xdsinternal.NewHandshakeInfo(test.rootProvider, test.identityProvider)
hi.SetRequireClientCert(test.requireClientCert)
// Create a wrapped conn which can return the HandshakeInfo and
@ -390,11 +391,11 @@ func (s) TestServerCredsProviderSwitch(t *testing.T) {
// to perform TLS handshake on incoming connections.
ts := newTestServerWithHandshakeFunc(func(rawConn net.Conn) handshakeResult {
cnt++
var hi *HandshakeInfo
var hi *xdsinternal.HandshakeInfo
if cnt == 1 {
// Create a HandshakeInfo which has a root provider which does not match
// the certificate sent by the client.
hi = NewHandshakeInfo(makeRootProvider(t, "x509/server_ca_cert.pem"), makeIdentityProvider(t, "x509/client2_cert.pem", "x509/client2_key.pem"))
hi = xdsinternal.NewHandshakeInfo(makeRootProvider(t, "x509/server_ca_cert.pem"), makeIdentityProvider(t, "x509/client2_cert.pem", "x509/client2_key.pem"))
hi.SetRequireClientCert(true)
// Create a wrapped conn which can return the HandshakeInfo and
@ -409,7 +410,7 @@ func (s) TestServerCredsProviderSwitch(t *testing.T) {
return handshakeResult{}
}
hi = NewHandshakeInfo(makeRootProvider(t, "x509/client_ca_cert.pem"), makeIdentityProvider(t, "x509/server1_cert.pem", "x509/server1_key.pem"))
hi = xdsinternal.NewHandshakeInfo(makeRootProvider(t, "x509/client_ca_cert.pem"), makeIdentityProvider(t, "x509/server1_cert.pem", "x509/server1_key.pem"))
hi.SetRequireClientCert(true)
// Create a wrapped conn which can return the HandshakeInfo and

View File

@ -0,0 +1,230 @@
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package xds contains non-user facing functionality of the xds credentials.
package xds
import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"sync"
"google.golang.org/grpc/attributes"
"google.golang.org/grpc/credentials/tls/certprovider"
"google.golang.org/grpc/internal"
"google.golang.org/grpc/resolver"
)
func init() {
internal.GetXDSHandshakeInfoForTesting = GetHandshakeInfo
}
// handshakeAttrKey is the type used as the key to store HandshakeInfo in
// the Attributes field of resolver.Address.
type handshakeAttrKey struct{}
// SetHandshakeInfo returns a copy of addr in which the Attributes field is
// updated with hInfo.
func SetHandshakeInfo(addr resolver.Address, hInfo *HandshakeInfo) resolver.Address {
addr.Attributes = addr.Attributes.WithValues(handshakeAttrKey{}, hInfo)
return addr
}
// GetHandshakeInfo returns a pointer to the HandshakeInfo stored in attr.
func GetHandshakeInfo(attr *attributes.Attributes) *HandshakeInfo {
v := attr.Value(handshakeAttrKey{})
hi, _ := v.(*HandshakeInfo)
return hi
}
// HandshakeInfo wraps all the security configuration required by client and
// server handshake methods in xds credentials. The xDS implementation will be
// responsible for populating these fields.
//
// Safe for concurrent access.
type HandshakeInfo struct {
mu sync.Mutex
rootProvider certprovider.Provider
identityProvider certprovider.Provider
acceptedSANs map[string]bool // Only on the client side.
requireClientCert bool // Only on server side.
}
// SetRootCertProvider updates the root certificate provider.
func (hi *HandshakeInfo) SetRootCertProvider(root certprovider.Provider) {
hi.mu.Lock()
hi.rootProvider = root
hi.mu.Unlock()
}
// SetIdentityCertProvider updates the identity certificate provider.
func (hi *HandshakeInfo) SetIdentityCertProvider(identity certprovider.Provider) {
hi.mu.Lock()
hi.identityProvider = identity
hi.mu.Unlock()
}
// SetAcceptedSANs updates the list of accepted SANs.
func (hi *HandshakeInfo) SetAcceptedSANs(sans []string) {
hi.mu.Lock()
hi.acceptedSANs = make(map[string]bool, len(sans))
for _, san := range sans {
hi.acceptedSANs[san] = true
}
hi.mu.Unlock()
}
// SetRequireClientCert updates whether a client cert is required during the
// ServerHandshake(). A value of true indicates that we are performing mTLS.
func (hi *HandshakeInfo) SetRequireClientCert(require bool) {
hi.mu.Lock()
hi.requireClientCert = require
hi.mu.Unlock()
}
// UseFallbackCreds returns true when fallback credentials are to be used based
// on the contents of the HandshakeInfo.
func (hi *HandshakeInfo) UseFallbackCreds() bool {
if hi == nil {
return true
}
hi.mu.Lock()
defer hi.mu.Unlock()
return hi.identityProvider == nil && hi.rootProvider == nil
}
// ClientSideTLSConfig constructs a tls.Config to be used in a client-side
// handshake based on the contents of the HandshakeInfo.
func (hi *HandshakeInfo) ClientSideTLSConfig(ctx context.Context) (*tls.Config, error) {
hi.mu.Lock()
// On the client side, rootProvider is mandatory. IdentityProvider is
// optional based on whether the client is doing TLS or mTLS.
if hi.rootProvider == nil {
return nil, errors.New("xds: CertificateProvider to fetch trusted roots is missing, cannot perform TLS handshake. Please check configuration on the management server")
}
// Since the call to KeyMaterial() can block, we read the providers under
// the lock but call the actual function after releasing the lock.
rootProv, idProv := hi.rootProvider, hi.identityProvider
hi.mu.Unlock()
// InsecureSkipVerify needs to be set to true because we need to perform
// custom verification to check the SAN on the received certificate.
// Currently the Go stdlib does complete verification of the cert (which
// includes hostname verification) or none. We are forced to go with the
// latter and perform the normal cert validation ourselves.
cfg := &tls.Config{InsecureSkipVerify: true}
km, err := rootProv.KeyMaterial(ctx)
if err != nil {
return nil, fmt.Errorf("xds: fetching trusted roots from CertificateProvider failed: %v", err)
}
cfg.RootCAs = km.Roots
if idProv != nil {
km, err := idProv.KeyMaterial(ctx)
if err != nil {
return nil, fmt.Errorf("xds: fetching identity certificates from CertificateProvider failed: %v", err)
}
cfg.Certificates = km.Certs
}
return cfg, nil
}
// ServerSideTLSConfig constructs a tls.Config to be used in a server-side
// handshake based on the contents of the HandshakeInfo.
func (hi *HandshakeInfo) ServerSideTLSConfig(ctx context.Context) (*tls.Config, error) {
cfg := &tls.Config{ClientAuth: tls.NoClientCert}
hi.mu.Lock()
// On the server side, identityProvider is mandatory. RootProvider is
// optional based on whether the server is doing TLS or mTLS.
if hi.identityProvider == nil {
return nil, errors.New("xds: CertificateProvider to fetch identity certificate is missing, cannot perform TLS handshake. Please check configuration on the management server")
}
// Since the call to KeyMaterial() can block, we read the providers under
// the lock but call the actual function after releasing the lock.
rootProv, idProv := hi.rootProvider, hi.identityProvider
if hi.requireClientCert {
cfg.ClientAuth = tls.RequireAndVerifyClientCert
}
hi.mu.Unlock()
// identityProvider is mandatory on the server side.
km, err := idProv.KeyMaterial(ctx)
if err != nil {
return nil, fmt.Errorf("xds: fetching identity certificates from CertificateProvider failed: %v", err)
}
cfg.Certificates = km.Certs
if rootProv != nil {
km, err := rootProv.KeyMaterial(ctx)
if err != nil {
return nil, fmt.Errorf("xds: fetching trusted roots from CertificateProvider failed: %v", err)
}
cfg.ClientCAs = km.Roots
}
return cfg, nil
}
// MatchingSANExists returns true if the SAN contained in the passed in
// certificate is present in the list of accepted SANs in the HandshakeInfo.
//
// If the list of accepted SANs in the HandshakeInfo is empty, this function
// returns true for all input certificates.
func (hi *HandshakeInfo) MatchingSANExists(cert *x509.Certificate) bool {
if len(hi.acceptedSANs) == 0 {
return true
}
var sans []string
// SANs can be specified in any of these four fields on the parsed cert.
sans = append(sans, cert.DNSNames...)
sans = append(sans, cert.EmailAddresses...)
for _, ip := range cert.IPAddresses {
sans = append(sans, ip.String())
}
for _, uri := range cert.URIs {
sans = append(sans, uri.String())
}
hi.mu.Lock()
defer hi.mu.Unlock()
for _, san := range sans {
if hi.acceptedSANs[san] {
return true
}
}
return false
}
// NewHandshakeInfo returns a new instance of HandshakeInfo with the given root
// and identity certificate providers.
func NewHandshakeInfo(root, identity certprovider.Provider, sans ...string) *HandshakeInfo {
acceptedSANs := make(map[string]bool, len(sans))
for _, san := range sans {
acceptedSANs[san] = true
}
return &HandshakeInfo{
rootProvider: root,
identityProvider: identity,
acceptedSANs: acceptedSANs,
}
}

View File

@ -27,17 +27,16 @@ import (
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/tls/certprovider"
"google.golang.org/grpc/credentials/xds"
"google.golang.org/grpc/internal/buffer"
xdsinternal "google.golang.org/grpc/internal/credentials/xds"
"google.golang.org/grpc/internal/grpclog"
"google.golang.org/grpc/internal/grpcsync"
"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"
"google.golang.org/grpc/xds/internal/client/bootstrap"
xdsclient "google.golang.org/grpc/xds/internal/client"
"google.golang.org/grpc/xds/internal/client/bootstrap"
)
const (
@ -81,7 +80,7 @@ func (cdsBB) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.
updateCh: buffer.NewUnbounded(),
closed: grpcsync.NewEvent(),
cancelWatch: func() {}, // No-op at this point.
xdsHI: xds.NewHandshakeInfo(nil, nil),
xdsHI: xdsinternal.NewHandshakeInfo(nil, nil),
}
b.logger = prefixLogger((b))
b.logger.Infof("Created")
@ -188,7 +187,7 @@ type cdsBalancer struct {
// a new provider is to be created.
cachedRoot certprovider.Provider
cachedIdentity certprovider.Provider
xdsHI *xds.HandshakeInfo
xdsHI *xdsinternal.HandshakeInfo
xdsCredsInUse bool
}
@ -506,7 +505,7 @@ type ccWrapper struct {
// The certificate providers in this HandshakeInfo are updated based on the
// received security configuration in the Cluster resource.
xdsHI *xds.HandshakeInfo
xdsHI *xdsinternal.HandshakeInfo
}
// NewSubConn intercepts NewSubConn() calls from the child policy and adds an
@ -515,7 +514,7 @@ type ccWrapper struct {
func (ccw *ccWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
newAddrs := make([]resolver.Address, len(addrs))
for i, addr := range addrs {
newAddrs[i] = xds.SetHandshakeInfo(addr, ccw.xdsHI)
newAddrs[i] = xdsinternal.SetHandshakeInfo(addr, ccw.xdsHI)
}
return ccw.ClientConn.NewSubConn(newAddrs, opts)
}

View File

@ -28,6 +28,7 @@ import (
"google.golang.org/grpc/credentials/tls/certprovider"
"google.golang.org/grpc/credentials/xds"
"google.golang.org/grpc/internal"
xdsinternal "google.golang.org/grpc/internal/credentials/xds"
"google.golang.org/grpc/internal/testutils"
"google.golang.org/grpc/resolver"
xdsclient "google.golang.org/grpc/xds/internal/client"
@ -188,7 +189,7 @@ func makeNewSubConn(ctx context.Context, edsCC balancer.ClientConn, parentCC *xd
if got, want := gotAddrs[0].Addr, addrs[0].Addr; got != want {
return fmt.Errorf("resolver.Address passed to parent ClientConn has address %q, want %q", got, want)
}
getHI := internal.GetXDSHandshakeInfoForTesting.(func(attr *attributes.Attributes) *xds.HandshakeInfo)
getHI := internal.GetXDSHandshakeInfoForTesting.(func(attr *attributes.Attributes) *xdsinternal.HandshakeInfo)
hi := getHI(gotAddrs[0].Attributes)
if hi == nil {
return errors.New("resolver.Address passed to parent ClientConn doesn't contain attributes")

View File

@ -29,9 +29,9 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/tls/certprovider"
"google.golang.org/grpc/credentials/xds"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/internal"
xdsinternal "google.golang.org/grpc/internal/credentials/xds"
internalgrpclog "google.golang.org/grpc/internal/grpclog"
"google.golang.org/grpc/internal/grpcsync"
xdsclient "google.golang.org/grpc/xds/internal/client"
@ -210,7 +210,7 @@ func (s *GRPCServer) newListenerWrapper(lis net.Listener) (*listenerWrapper, err
lw := &listenerWrapper{
Listener: lis,
closed: grpcsync.NewEvent(),
xdsHI: xds.NewHandshakeInfo(nil, nil),
xdsHI: xdsinternal.NewHandshakeInfo(nil, nil),
}
// This is used to notify that a good update has been received and that
@ -436,7 +436,7 @@ type listenerWrapper struct {
cachedIdentity certprovider.Provider
// Wraps all information required by the xds handshaker.
xdsHI *xds.HandshakeInfo
xdsHI *xdsinternal.HandshakeInfo
}
// Accept blocks on an Accept() on the underlying listener, and wraps the
@ -480,7 +480,7 @@ type conn struct {
// This is the same HandshakeInfo as stored in the listenerWrapper that
// created this conn. The former updates the HandshakeInfo whenever it
// receives new security configuration.
xdsHI *xds.HandshakeInfo
xdsHI *xdsinternal.HandshakeInfo
// The connection deadline as configured by the grpc.Server on the rawConn
// that is returned by a call to Accept(). This is set to the connection
@ -512,6 +512,6 @@ func (c *conn) GetDeadline() time.Time {
// XDSHandshakeInfo returns a pointer to the HandshakeInfo stored in conn. This
// will be invoked by the ServerHandshake() method of the XdsCredentials.
func (c *conn) XDSHandshakeInfo() *xds.HandshakeInfo {
func (c *conn) XDSHandshakeInfo() *xdsinternal.HandshakeInfo {
return c.xdsHI
}