From aa009516b7c3f64288d1be255278b063faf39fd4 Mon Sep 17 00:00:00 2001 From: Dave Cunningham Date: Fri, 30 Jan 2015 14:53:09 -0500 Subject: [PATCH 1/4] Port to oauth2, fix #606 --- builtin/providers/google/config.go | 59 +++++++++++++++------------- builtin/providers/google/provider.go | 2 +- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/builtin/providers/google/config.go b/builtin/providers/google/config.go index edb7add16..d08ab9406 100644 --- a/builtin/providers/google/config.go +++ b/builtin/providers/google/config.go @@ -7,9 +7,12 @@ import ( "net/http" "os" - "code.google.com/p/goauth2/oauth" - "code.google.com/p/goauth2/oauth/jwt" "code.google.com/p/google-api-go-client/compute/v1" + // oauth2 "github.com/rasa/oauth2-fork-b3f9a68" + "github.com/rasa/oauth2-fork-b3f9a68" + + // oauth2 "github.com/rasa/oauth2-fork-b3f9a68/google" + "github.com/rasa/oauth2-fork-b3f9a68/google" ) const clientScopes string = "https://www.googleapis.com/auth/compute" @@ -38,38 +41,40 @@ func (c *Config) loadAndValidate() error { c.Region = os.Getenv("GOOGLE_REGION") } - if err := loadJSON(&account, c.AccountFile); err != nil { - return fmt.Errorf( - "Error loading account file '%s': %s", - c.AccountFile, - err) + var f *oauth2.Options + var err error + + if c.AccountFile != "" { + if err := loadJSON(&account, c.AccountFile); err != nil { + return fmt.Errorf( + "Error loading account file '%s': %s", + c.AccountFile, + err) + } + + // Get the token for use in our requests + log.Printf("[INFO] Requesting Google token...") + log.Printf("[INFO] -- Email: %s", account.ClientEmail) + log.Printf("[INFO] -- Scopes: %s", clientScopes) + log.Printf("[INFO] -- Private Key Length: %d", len(account.PrivateKey)) + + f, err = oauth2.New( + oauth2.JWTClient(account.ClientEmail, []byte(account.PrivateKey)), + oauth2.Scope(clientScopes), + google.JWTEndpoint()) + + } else { + log.Printf("[INFO] Requesting Google token via GCE Service Role...") + f, err = oauth2.New(google.ComputeEngineAccount("")) + } - // Get the token for use in our requests - log.Printf("[INFO] Requesting Google token...") - log.Printf("[INFO] -- Email: %s", account.ClientEmail) - log.Printf("[INFO] -- Scopes: %s", clientScopes) - log.Printf("[INFO] -- Private Key Length: %d", len(account.PrivateKey)) - jwtTok := jwt.NewToken( - account.ClientEmail, - clientScopes, - []byte(account.PrivateKey)) - token, err := jwtTok.Assert(new(http.Client)) if err != nil { return fmt.Errorf("Error retrieving auth token: %s", err) } - // Instantiate the transport to communicate to Google - transport := &oauth.Transport{ - Config: &oauth.Config{ - ClientId: account.ClientId, - Scope: clientScopes, - }, - Token: token, - } - log.Printf("[INFO] Instantiating GCE client...") - c.clientCompute, err = compute.New(transport.Client()) + c.clientCompute, err = compute.New(&http.Client{Transport: f.NewTransport()}) if err != nil { return err } diff --git a/builtin/providers/google/provider.go b/builtin/providers/google/provider.go index 3a16dc0a0..4ad5a9a9f 100644 --- a/builtin/providers/google/provider.go +++ b/builtin/providers/google/provider.go @@ -11,7 +11,7 @@ func Provider() terraform.ResourceProvider { Schema: map[string]*schema.Schema{ "account_file": &schema.Schema{ Type: schema.TypeString, - Required: true, + Optional: true, DefaultFunc: schema.EnvDefaultFunc("GOOGLE_ACCOUNT_FILE", nil), }, From 1d41800cd2173798339be882f19b6ad83a178c41 Mon Sep 17 00:00:00 2001 From: Dave Cunningham Date: Fri, 30 Jan 2015 15:12:13 -0500 Subject: [PATCH 2/4] Add docs --- website/source/docs/providers/google/index.html.markdown | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/website/source/docs/providers/google/index.html.markdown b/website/source/docs/providers/google/index.html.markdown index 3014125cf..cacf7599b 100644 --- a/website/source/docs/providers/google/index.html.markdown +++ b/website/source/docs/providers/google/index.html.markdown @@ -34,9 +34,11 @@ resource "google_compute_instance" "default" { The following keys can be used to configure the provider. -* `account_file` - (Required) Path to the JSON file used to describe - your account credentials, downloaded from Google Cloud Console. More - details on retrieving this file are below. +* `account_file` - (Required) Path to the JSON file used to describe your + account credentials, downloaded from Google Cloud Console. More details on + retrieving this file are below. The _account file_ can be "" if you + are running terraform from a GCE instance with a properly-configured [Compute + Engine Service Account](https://cloud.google.com/compute/docs/authentication). * `project` - (Required) The name of the project to apply any resources to. From 106a1c62f5a9a8d0209f935f6fd2a95de163198a Mon Sep 17 00:00:00 2001 From: Dave Cunningham Date: Wed, 11 Feb 2015 01:44:52 -0500 Subject: [PATCH 3/4] Revert to upstream oauth2 --- builtin/providers/google/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builtin/providers/google/config.go b/builtin/providers/google/config.go index d08ab9406..3d61ad6be 100644 --- a/builtin/providers/google/config.go +++ b/builtin/providers/google/config.go @@ -9,10 +9,10 @@ import ( "code.google.com/p/google-api-go-client/compute/v1" // oauth2 "github.com/rasa/oauth2-fork-b3f9a68" - "github.com/rasa/oauth2-fork-b3f9a68" + "github.com/golang/oauth2" // oauth2 "github.com/rasa/oauth2-fork-b3f9a68/google" - "github.com/rasa/oauth2-fork-b3f9a68/google" + "github.com/golang/oauth2/google" ) const clientScopes string = "https://www.googleapis.com/auth/compute" From 4d280f093130980dd0ac085844c3cbaa4aa472e2 Mon Sep 17 00:00:00 2001 From: Dave Cunningham Date: Wed, 11 Feb 2015 21:21:24 -0500 Subject: [PATCH 4/4] Use new oauth2 golang library --- builtin/providers/google/config.go | 44 ++++++++++++++++++------------ 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/builtin/providers/google/config.go b/builtin/providers/google/config.go index 3d61ad6be..009f00092 100644 --- a/builtin/providers/google/config.go +++ b/builtin/providers/google/config.go @@ -8,14 +8,12 @@ import ( "os" "code.google.com/p/google-api-go-client/compute/v1" - // oauth2 "github.com/rasa/oauth2-fork-b3f9a68" - "github.com/golang/oauth2" - // oauth2 "github.com/rasa/oauth2-fork-b3f9a68/google" - "github.com/golang/oauth2/google" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + "golang.org/x/oauth2/jwt" ) -const clientScopes string = "https://www.googleapis.com/auth/compute" // Config is the configuration structure used to instantiate the Google // provider. @@ -41,8 +39,7 @@ func (c *Config) loadAndValidate() error { c.Region = os.Getenv("GOOGLE_REGION") } - var f *oauth2.Options - var err error + var client *http.Client if c.AccountFile != "" { if err := loadJSON(&account, c.AccountFile); err != nil { @@ -52,29 +49,42 @@ func (c *Config) loadAndValidate() error { err) } + clientScopes := []string{"https://www.googleapis.com/auth/compute"} + // Get the token for use in our requests log.Printf("[INFO] Requesting Google token...") log.Printf("[INFO] -- Email: %s", account.ClientEmail) log.Printf("[INFO] -- Scopes: %s", clientScopes) log.Printf("[INFO] -- Private Key Length: %d", len(account.PrivateKey)) - f, err = oauth2.New( - oauth2.JWTClient(account.ClientEmail, []byte(account.PrivateKey)), - oauth2.Scope(clientScopes), - google.JWTEndpoint()) + conf := jwt.Config{ + Email: account.ClientEmail, + PrivateKey: []byte(account.PrivateKey), + Scopes: clientScopes, + TokenURL: "https://accounts.google.com/o/oauth2/token", + } + + // Initiate an http.Client. The following GET request will be + // authorized and authenticated on the behalf of + // your service account. + client = conf.Client(oauth2.NoContext) } else { log.Printf("[INFO] Requesting Google token via GCE Service Role...") - f, err = oauth2.New(google.ComputeEngineAccount("")) + client = &http.Client{ + Transport: &oauth2.Transport{ + // Fetch from Google Compute Engine's metadata server to retrieve + // an access token for the provided account. + // If no account is specified, "default" is used. + Source: google.ComputeTokenSource(""), + }, + } } - if err != nil { - return fmt.Errorf("Error retrieving auth token: %s", err) - } - log.Printf("[INFO] Instantiating GCE client...") - c.clientCompute, err = compute.New(&http.Client{Transport: f.NewTransport()}) + var err error + c.clientCompute, err = compute.New(client) if err != nil { return err }