Support service accounts on GCE instances

Update the Google Compute Engine provider to add support for service
accounts on `google_compute_instance`. Both gcloud shorthand (`compute-ro`,
`storage-ro`, etc.) and OAuth2 API endpoints are supported.

This feature is currently limited to a single service account (supporting
multiple scopes) and an automatically-generated service account email.
This commit is contained in:
Jeff Goldschrafe 2014-10-07 04:16:50 -04:00
parent f61b7af815
commit d3081e0da8
3 changed files with 94 additions and 12 deletions

View File

@ -124,6 +124,33 @@ func resourceComputeInstance() *schema.Resource {
},
},
"service_account": &schema.Schema{
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"email": &schema.Schema{
Type: schema.TypeString,
Computed: true,
ForceNew: true,
},
"scopes": &schema.Schema{
Type: schema.TypeList,
Required: true,
ForceNew: true,
Elem: &schema.Schema{
Type: schema.TypeString,
StateFunc: func(v interface{}) string {
return canonicalizeServiceScope(v.(string))
},
},
},
},
},
},
"tags": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
@ -259,6 +286,26 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err
networks = append(networks, &iface)
}
serviceAccountsCount := d.Get("service_account.#").(int)
serviceAccounts := make([]*compute.ServiceAccount, 0, serviceAccountsCount)
for i := 0; i < serviceAccountsCount; i++ {
prefix := fmt.Sprintf("service_account.%d", i)
scopesCount := d.Get(prefix + ".scopes.#").(int)
scopes := make([]string, 0, scopesCount)
for j := 0; j < scopesCount; j++ {
scope := d.Get(fmt.Sprintf(prefix + ".scopes.%d", j)).(string)
scopes = append(scopes, canonicalizeServiceScope(scope))
}
serviceAccount := &compute.ServiceAccount {
Email: "default",
Scopes: scopes,
}
serviceAccounts = append(serviceAccounts, serviceAccount)
}
// Create the instance information
instance := compute.Instance{
CanIpForward: d.Get("can_ip_forward").(bool),
@ -269,18 +316,7 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err
Name: d.Get("name").(string),
NetworkInterfaces: networks,
Tags: resourceInstanceTags(d),
/*
ServiceAccounts: []*compute.ServiceAccount{
&compute.ServiceAccount{
Email: "default",
Scopes: []string{
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/devstorage.full_control",
},
},
},
*/
ServiceAccounts: serviceAccounts,
}
log.Printf("[INFO] Requesting instance creation")
@ -339,6 +375,16 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
d.Set("can_ip_forward", instance.CanIpForward)
// Set the service accounts
for i, serviceAccount := range instance.ServiceAccounts {
prefix := fmt.Sprintf("service_account.%d", i)
d.Set(prefix + ".email", serviceAccount.Email)
d.Set(prefix + ".scopes.#", len(serviceAccount.Scopes))
for j, scope := range serviceAccount.Scopes {
d.Set(fmt.Sprintf("%s.scopes.%d", prefix, j), scope)
}
}
// Set the networks
externalIP := ""
for i, iface := range instance.NetworkInterfaces {

View File

@ -0,0 +1,25 @@
package google
func canonicalizeServiceScope(scope string) string {
// This is a convenience map of short names used by the gcloud tool
// to the GCE auth endpoints they alias to.
scopeMap := map[string]string{
"bigquery": "https://www.googleapis.com/auth/bigquery",
"compute-ro": "https://www.googleapis.com/auth/compute.readonly",
"compute-rw": "https://www.googleapis.com/auth/compute",
"datastore": "https://www.googleapis.com/auth/datastore",
"sql": "https://www.googleapis.com/auth/sqlservice",
"sql-admin": "https://www.googleapis.com/auth/sqlservice.admin",
"storage-full": "https://www.googleapis.com/auth/devstorage.full_control",
"storage-ro": "https://www.googleapis.com/auth/devstorage.read_only",
"storage-rw": "https://www.googleapis.com/auth/devstorage.read_write",
"taskqueue": "https://www.googleapis.com/auth/taskqueue",
"userinfo-email": "https://www.googleapis.com/auth/userinfo.email",
}
if matchedUrl, ok := scopeMap[scope]; ok {
return matchedUrl
} else {
return scope
}
}

View File

@ -30,6 +30,10 @@ resource "google_compute_instance" "default" {
metadata {
foo = "bar"
}
service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}
```
@ -60,6 +64,8 @@ The following arguments are supported:
specified multiple times for multiple networks. Structure is documented
below.
* `service_account` - (Optional) Service account to attach to the instance.
* `tags` - (Optional) Tags to attach to the instance.
The `disk` block supports:
@ -82,6 +88,11 @@ The `network` block supports:
* `address` - (Optional) The IP address of a reserved IP address to assign
to this interface.
The `service_account` block supports:
* `scopes` - (Required) A list of service scopes. Both OAuth2 URLs and gcloud
short names are supported.
## Attributes Reference
The following attributes are exported: