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 0abe48fa03
commit c7c90dd595
2 changed files with 83 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 {

25
service_scope.go Normal file
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
}
}