From 223212dc91e8fc5e92ef08ebb3b4a803a977acdd Mon Sep 17 00:00:00 2001 From: Burcu Dogan Date: Sun, 11 May 2014 18:06:03 +0300 Subject: [PATCH] Adding token fetching implementing for Compute Engine. --- google/google.go | 52 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/google/google.go b/google/google.go index 6458c7e..a20480a 100644 --- a/google/google.go +++ b/google/google.go @@ -63,6 +63,11 @@ package google import ( + "encoding/json" + "net/http" + "path" + "time" + "github.com/rakyll/oauth2" ) @@ -72,9 +77,17 @@ const ( uriGoogleToken = "https://accounts.google.com/o/oauth2/token" ) +type metaTokenRespBody struct { + AccessToken string `json:"access_token"` + ExpiresIn time.Duration `json:"expires_in"` + TokenType string `json:"token_type"` +} + // ComputeEngineConfig represents a OAuth 2.0 consumer client // running on Google Compute Engine. -type ComputeEngineConfig struct{} +type ComputeEngineConfig struct { + account string +} // NewConfig creates a new OAuth2 config that uses Google // endpoints. @@ -89,10 +102,10 @@ func NewServiceAccountConfig(opts *oauth2.JWTOptions) (*oauth2.JWTConfig, error) } // NewComputeEngineConfig creates a new config that can fetch tokens -// from Google Compute Engine instance's metaserver. -func NewComputeEngineConfig() (*ComputeEngineConfig, error) { - // Should fetch an access token from the meta server. - return &ComputeEngineConfig{}, nil +// from Google Compute Engine instance's metaserver. If no account is +// provided, default is used. +func NewComputeEngineConfig(account string) (*ComputeEngineConfig, error) { + return &ComputeEngineConfig{account: account}, nil } // NewTransport creates an authorized transport. @@ -101,6 +114,31 @@ func (c *ComputeEngineConfig) NewTransport() (oauth2.Transport, error) { } // FetchToken retrieves a new access token via metadata server. -func (c *ComputeEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) { - panic("not yet implemented") +func (c *ComputeEngineConfig) FetchToken(existing *oauth2.Token) (token *oauth2.Token, err error) { + account := "default" + if c.account != "" { + account = c.account + } + u := "http://" + path.Join("metadata/computeMetadata/v1/instance/service-accounts", account, "token") + req, err := http.NewRequest("GET", u, nil) + if err != nil { + return + } + req.Header.Add("X-Google-Metadata-Request", "True") + resp, err := (&http.Client{Transport: oauth2.DefaultTransport}).Do(req) + if err != nil { + return + } + defer resp.Body.Close() + var tokenResp metaTokenRespBody + err = json.NewDecoder(resp.Body).Decode(&tokenResp) + if err != nil { + return + } + token = &oauth2.Token{ + AccessToken: tokenResp.AccessToken, + TokenType: tokenResp.TokenType, + Expiry: time.Now().Add(tokenResp.ExpiresIn * time.Second), + } + return }