...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package transport
16
17 import (
18 "encoding/json"
19 "log"
20 "os"
21 "strconv"
22 "sync"
23 "time"
24
25 "cloud.google.com/go/auth/internal/transport/cert"
26 "cloud.google.com/go/compute/metadata"
27 )
28
29 const (
30 configEndpointSuffix = "instance/platform-security/auto-mtls-configuration"
31 )
32
33 var (
34
35 configExpiry = time.Hour
36
37
38 mtlsOnce sync.Once
39 )
40
41
42
43 func GetS2AAddress() string {
44 c, err := getMetadataMTLSAutoConfig().Config()
45 if err != nil {
46 return ""
47 }
48 if !c.Valid() {
49 return ""
50 }
51 return c.S2A.PlaintextAddress
52 }
53
54 type mtlsConfigSource interface {
55 Config() (*mtlsConfig, error)
56 }
57
58
59 type mtlsConfig struct {
60 S2A *s2aAddresses `json:"s2a"`
61 Expiry time.Time
62 }
63
64 func (c *mtlsConfig) Valid() bool {
65 return c != nil && c.S2A != nil && !c.expired()
66 }
67 func (c *mtlsConfig) expired() bool {
68 return c.Expiry.Before(time.Now())
69 }
70
71
72 type s2aAddresses struct {
73
74 PlaintextAddress string `json:"plaintext_address"`
75
76 MTLSAddress string `json:"mtls_address"`
77 }
78
79
80 func getMetadataMTLSAutoConfig() mtlsConfigSource {
81 mtlsOnce.Do(func() {
82 mdsMTLSAutoConfigSource = &reuseMTLSConfigSource{
83 src: &metadataMTLSAutoConfig{},
84 }
85 })
86 return mdsMTLSAutoConfigSource
87 }
88
89
90
91 type reuseMTLSConfigSource struct {
92 src mtlsConfigSource
93 mu sync.Mutex
94 config *mtlsConfig
95 }
96
97 func (cs *reuseMTLSConfigSource) Config() (*mtlsConfig, error) {
98 cs.mu.Lock()
99 defer cs.mu.Unlock()
100
101 if cs.config.Valid() {
102 return cs.config, nil
103 }
104 c, err := cs.src.Config()
105 if err != nil {
106 return nil, err
107 }
108 cs.config = c
109 return c, nil
110 }
111
112
113
114 type metadataMTLSAutoConfig struct{}
115
116 var httpGetMetadataMTLSConfig = func() (string, error) {
117 return metadata.Get(configEndpointSuffix)
118 }
119
120 func (cs *metadataMTLSAutoConfig) Config() (*mtlsConfig, error) {
121 resp, err := httpGetMetadataMTLSConfig()
122 if err != nil {
123 log.Printf("querying MTLS config from MDS endpoint failed: %v", err)
124 return defaultMTLSConfig(), nil
125 }
126 var config mtlsConfig
127 err = json.Unmarshal([]byte(resp), &config)
128 if err != nil {
129 log.Printf("unmarshalling MTLS config from MDS endpoint failed: %v", err)
130 return defaultMTLSConfig(), nil
131 }
132
133 if config.S2A == nil {
134 log.Printf("returned MTLS config from MDS endpoint is invalid: %v", config)
135 return defaultMTLSConfig(), nil
136 }
137
138
139 config.Expiry = time.Now().Add(configExpiry)
140 return &config, nil
141 }
142
143 func defaultMTLSConfig() *mtlsConfig {
144 return &mtlsConfig{
145 S2A: &s2aAddresses{
146 PlaintextAddress: "",
147 MTLSAddress: "",
148 },
149 Expiry: time.Now().Add(configExpiry),
150 }
151 }
152
153 func shouldUseS2A(clientCertSource cert.Provider, opts *Options) bool {
154
155 if clientCertSource != nil {
156 return false
157 }
158
159 if !isGoogleS2AEnabled() {
160 return false
161 }
162
163 if opts.DefaultMTLSEndpoint == "" || opts.Endpoint != "" {
164 return false
165 }
166
167 if opts.Client != nil {
168 return false
169 }
170
171 return !opts.EnableDirectPath && !opts.EnableDirectPathXds
172 }
173
174 func isGoogleS2AEnabled() bool {
175 b, err := strconv.ParseBool(os.Getenv(googleAPIUseS2AEnv))
176 if err != nil {
177 return false
178 }
179 return b
180 }
181
View as plain text