...
1
2
3
4
5 package internal
6
7 import (
8 "encoding/json"
9 "log"
10 "sync"
11 "time"
12
13 "cloud.google.com/go/compute/metadata"
14 )
15
16 const configEndpointSuffix = "instance/platform-security/auto-mtls-configuration"
17
18
19 var configExpiry = time.Hour
20
21
22 func GetS2AAddress() string {
23 c, err := getMetadataMTLSAutoConfig().Config()
24 if err != nil {
25 return ""
26 }
27 if !c.Valid() {
28 return ""
29 }
30 return c.S2A.PlaintextAddress
31 }
32
33 type mtlsConfigSource interface {
34 Config() (*mtlsConfig, error)
35 }
36
37
38 var (
39 mdsMTLSAutoConfigSource mtlsConfigSource
40 once sync.Once
41 )
42
43
44 func getMetadataMTLSAutoConfig() mtlsConfigSource {
45 once.Do(func() {
46 mdsMTLSAutoConfigSource = &reuseMTLSConfigSource{
47 src: &metadataMTLSAutoConfig{},
48 }
49 })
50 return mdsMTLSAutoConfigSource
51 }
52
53
54
55 type reuseMTLSConfigSource struct {
56 src mtlsConfigSource
57 mu sync.Mutex
58 config *mtlsConfig
59 }
60
61 func (cs *reuseMTLSConfigSource) Config() (*mtlsConfig, error) {
62 cs.mu.Lock()
63 defer cs.mu.Unlock()
64
65 if cs.config.Valid() {
66 return cs.config, nil
67 }
68 c, err := cs.src.Config()
69 if err != nil {
70 return nil, err
71 }
72 cs.config = c
73 return c, nil
74 }
75
76
77
78 type metadataMTLSAutoConfig struct{}
79
80 var httpGetMetadataMTLSConfig = func() (string, error) {
81 return metadata.Get(configEndpointSuffix)
82 }
83
84 func (cs *metadataMTLSAutoConfig) Config() (*mtlsConfig, error) {
85 resp, err := httpGetMetadataMTLSConfig()
86 if err != nil {
87 log.Printf("querying MTLS config from MDS endpoint failed: %v", err)
88 return defaultMTLSConfig(), nil
89 }
90 var config mtlsConfig
91 err = json.Unmarshal([]byte(resp), &config)
92 if err != nil {
93 log.Printf("unmarshalling MTLS config from MDS endpoint failed: %v", err)
94 return defaultMTLSConfig(), nil
95 }
96
97 if config.S2A == nil {
98 log.Printf("returned MTLS config from MDS endpoint is invalid: %v", config)
99 return defaultMTLSConfig(), nil
100 }
101
102
103 config.Expiry = time.Now().Add(configExpiry)
104 return &config, nil
105 }
106
107 func defaultMTLSConfig() *mtlsConfig {
108 return &mtlsConfig{
109 S2A: &s2aAddresses{
110 PlaintextAddress: "",
111 MTLSAddress: "",
112 },
113 Expiry: time.Now().Add(configExpiry),
114 }
115 }
116
117
118 type s2aAddresses struct {
119
120 PlaintextAddress string `json:"plaintext_address"`
121
122 MTLSAddress string `json:"mtls_address"`
123 }
124
125
126 type mtlsConfig struct {
127 S2A *s2aAddresses `json:"s2a"`
128 Expiry time.Time
129 }
130
131 func (c *mtlsConfig) Valid() bool {
132 return c != nil && c.S2A != nil && !c.expired()
133 }
134 func (c *mtlsConfig) expired() bool {
135 return c.Expiry.Before(time.Now())
136 }
137
View as plain text