default_cert.go raw

   1  // Copyright 2023 Google LLC
   2  //
   3  // Licensed under the Apache License, Version 2.0 (the "License");
   4  // you may not use this file except in compliance with the License.
   5  // You may obtain a copy of the License at
   6  //
   7  //      http://www.apache.org/licenses/LICENSE-2.0
   8  //
   9  // Unless required by applicable law or agreed to in writing, software
  10  // distributed under the License is distributed on an "AS IS" BASIS,
  11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12  // See the License for the specific language governing permissions and
  13  // limitations under the License.
  14  
  15  package cert
  16  
  17  import (
  18  	"crypto/tls"
  19  	"errors"
  20  	"sync"
  21  )
  22  
  23  // defaultCertData holds all the variables pertaining to
  24  // the default certificate provider created by [DefaultProvider].
  25  //
  26  // A singleton model is used to allow the provider to be reused
  27  // by the transport layer. As mentioned in [DefaultProvider] (provider nil, nil)
  28  // may be returned to indicate a default provider could not be found, which
  29  // will skip extra tls config in the transport layer .
  30  type defaultCertData struct {
  31  	once     sync.Once
  32  	provider Provider
  33  	err      error
  34  }
  35  
  36  var (
  37  	defaultCert defaultCertData
  38  )
  39  
  40  // Provider is a function that can be passed into crypto/tls.Config.GetClientCertificate.
  41  type Provider func(*tls.CertificateRequestInfo) (*tls.Certificate, error)
  42  
  43  // errSourceUnavailable is a sentinel error to indicate certificate source is unavailable.
  44  var errSourceUnavailable = errors.New("certificate source is unavailable")
  45  
  46  // DefaultProvider returns a certificate source using the preferred EnterpriseCertificateProxySource.
  47  // If EnterpriseCertificateProxySource is not available, fall back to the legacy SecureConnectSource.
  48  //
  49  // If neither source is available (due to missing configurations), a nil Source and a nil Error are
  50  // returned to indicate that a default certificate source is unavailable.
  51  func DefaultProvider() (Provider, error) {
  52  	defaultCert.once.Do(func() {
  53  		defaultCert.provider, defaultCert.err = NewWorkloadX509CertProvider("")
  54  		if errors.Is(defaultCert.err, errSourceUnavailable) {
  55  			defaultCert.provider, defaultCert.err = NewEnterpriseCertificateProxyProvider("")
  56  			if errors.Is(defaultCert.err, errSourceUnavailable) {
  57  				defaultCert.provider, defaultCert.err = NewSecureConnectProvider("")
  58  				if errors.Is(defaultCert.err, errSourceUnavailable) {
  59  					defaultCert.provider, defaultCert.err = nil, nil
  60  				}
  61  			}
  62  		}
  63  	})
  64  	return defaultCert.provider, defaultCert.err
  65  }
  66