@@ -76,6 +76,10 @@ type UnsealResponse struct {
7676 Progress int `json:"progress"`
7777}
7878
79+ type metadataAccessTokenResponse struct {
80+ AccessToken string `json:"access_token"`
81+ }
82+
7983func main () {
8084 log .Println ("Starting the vault-init service..." )
8185
@@ -166,7 +170,14 @@ func main() {
166170 stop ()
167171 default :
168172 }
169- response , err := httpClient .Head (vaultAddr + "/v1/sys/health" )
173+ request , err := newVaultRequest (http .MethodHead , vaultAddr + "/v1/sys/health" , nil )
174+ if err != nil {
175+ log .Println (err )
176+ time .Sleep (checkInterval )
177+ continue
178+ }
179+
180+ response , err := httpClient .Do (request )
170181
171182 if response != nil && response .Body != nil {
172183 response .Body .Close ()
@@ -238,7 +249,7 @@ func initialize() {
238249 }
239250
240251 r := bytes .NewReader (initRequestData )
241- request , err := http .NewRequest ( "PUT" , vaultAddr + "/v1/sys/init" , r )
252+ request , err := newVaultRequest ( http .MethodPut , vaultAddr + "/v1/sys/init" , r )
242253 if err != nil {
243254 log .Println (err )
244255 return
@@ -384,7 +395,7 @@ func unsealOne(key string) (bool, error) {
384395 }
385396
386397 r := bytes .NewReader (unsealRequestData )
387- request , err := http . NewRequest (http .MethodPut , vaultAddr + "/v1/sys/unseal" , r )
398+ request , err := newVaultRequest (http .MethodPut , vaultAddr + "/v1/sys/unseal" , r )
388399 if err != nil {
389400 return false , err
390401 }
@@ -461,6 +472,58 @@ func processTLSConfig(cfg *tls.Config, serverName, caCert, caPath string) error
461472 return nil
462473}
463474
475+ func newVaultRequest (method , url string , body io.Reader ) (* http.Request , error ) {
476+ request , err := http .NewRequest (method , url , body )
477+ if err != nil {
478+ return nil , err
479+ }
480+
481+ accessToken , err := accessTokenFromMetadata ()
482+ if err != nil {
483+ return nil , fmt .Errorf ("failed to get access token from metadata server: %w" , err )
484+ }
485+
486+ request .Header .Set ("X-Admin-Token" , accessToken )
487+ request .Header .Set ("Accept" , "application/json" )
488+ if method == http .MethodPut {
489+ request .Header .Set ("Content-Type" , "application/json" )
490+ }
491+
492+ return request , nil
493+ }
494+
495+ func accessTokenFromMetadata () (string , error ) {
496+ const metadataTokenURL = "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"
497+
498+ request , err := http .NewRequest (http .MethodGet , metadataTokenURL , nil )
499+ if err != nil {
500+ return "" , err
501+ }
502+ request .Header .Set ("Metadata-Flavor" , "Google" )
503+
504+ client := & http.Client {Timeout : 5 * time .Second }
505+ response , err := client .Do (request )
506+ if err != nil {
507+ return "" , err
508+ }
509+ defer response .Body .Close ()
510+
511+ if response .StatusCode != http .StatusOK {
512+ return "" , fmt .Errorf ("unexpected status code: %d" , response .StatusCode )
513+ }
514+
515+ var tokenResponse metadataAccessTokenResponse
516+ if err := json .NewDecoder (response .Body ).Decode (& tokenResponse ); err != nil {
517+ return "" , err
518+ }
519+
520+ if tokenResponse .AccessToken == "" {
521+ return "" , fmt .Errorf ("metadata server returned empty access token" )
522+ }
523+
524+ return tokenResponse .AccessToken , nil
525+ }
526+
464527func boolFromEnv (env string , def bool ) bool {
465528 val := os .Getenv (env )
466529 if val == "" {
0 commit comments