diff --git a/builtin/providers/google/config.go b/builtin/providers/google/config.go index edb7add16..009f00092 100644 --- a/builtin/providers/google/config.go +++ b/builtin/providers/google/config.go @@ -7,12 +7,13 @@ 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" + + "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. @@ -38,38 +39,52 @@ 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 client *http.Client - // 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) - } + if c.AccountFile != "" { + if err := loadJSON(&account, c.AccountFile); err != nil { + return fmt.Errorf( + "Error loading account file '%s': %s", + c.AccountFile, + 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)) + + 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...") + 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(""), + }, + } - // 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()) + var err error + c.clientCompute, err = compute.New(client) if err != nil { return err } diff --git a/builtin/providers/google/provider.go b/builtin/providers/google/provider.go index da52e0682..c63b29402 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), }, 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.