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