Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impersonating GCP service accounts #7064

Comments

@joe-a-t
Copy link

joe-a-t commented Aug 19, 2020

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment. If the issue is assigned to the "modular-magician" user, it is either in the process of being autogenerated, or is planned to be autogenerated soon. If the issue is assigned to a user, that user is claiming responsibility for the issue. If the issue is assigned to "hashibot", a community member has claimed the issue already.

Description

In a google provider configuration block, there isn't a good way to impersonate a service account within the scope of a single GCP provider. There are several options, but they all have substantial drawbacks, especially compared to the way the AWS provider implements assuming roles.

Workaround 1 - Multiple Credentials

In this workaround, you need to create local keys for any service accounts you would like to impersonate and put them at a file path where the terraform provider configuration is expecting them.

Example
provider "google" {
  credentials = file("account.json")
  project     = "my-project-id"
  region      = "us-central1"
  zone        = "us-central1-c"
}

The downside of this workaround is that you have to worry about creating local credentials files at a specific path for each service account you would like to use prior to running any terraform commands. The credentials can also be stored and passed in via environment variables, but this still has the same problems around needing to get, store, and pass in credentials for the service accounts you are trying to impersonate outside of terraform.

Example
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth --verbosity=error --impersonate-service-account="[email protected]" print-access-token)

When you have a more complicated terraform setup with multiple service accounts, this quickly falls apart unless you write your own custom wrapper or key provisioning script, which you then have to maintain and manage yourself. Even if you do write that additional tooling, you're still in a situation where you have a plethora of access keys that have been created and are living on disk, which is less than optimal from a security and manageability standpoint. This is a significantly worse experience than how AWS uses assume role to use a single set of access keys (which don't even need to be written to disk if you use aws-vault or an instance profile) to access an unlimited number of roles.

Workaround 2 - Access Tokens via Data Sources

Another workaround is described in this Google Cloud blog post so I won't rehash the implementation details.

The downsides of this workaround is that the access tokens the data sources generate are actually written to your terraform state file. This means that anyone who has access to view the state file could grab access tokens with the permissions required to apply the terraform, even if that person shouldn't be allowed to apply the terraform. This creates an unacceptable security risk even though the tokens have relatively short lifespans. It also prevents enabling less privileged users to plan locally since you can longer trust them to access the state file, which really hurts their ability to efficiently create their own terraform configurations via self service.

Proposed Solution

Implement a method for impersonating a service account that is similar to AWS' ability to assume a role just in the context of a single command or provider as described in this post without writing keys to disk or requiring an external to terraform wrapper or key provisioning script. I think this can be done in a similar manner to how gcloud uses the --impersonate-service-account.

New or Affected Resource(s)

  • The entire google provider

Potential Terraform Configuration

provider "google" {
  impersonate-service-account = var.service_account
  project                     = "my-project-id"
  region                      = "us-central1"
  zone                        = "us-central1-c"
}

variable "service_account" {
  default     = "[email protected]"
  description = "Email of the service account to use"
  type        = string
}

References

@ghost ghost added the enhancement label Aug 19, 2020
@upodroid
Copy link
Contributor

There is a new feature being developed in the golang google api client that should make this much easier.

googleapis/google-api-go-client#625

When this comes out, the provider should be able to accept this and use the ADC to acquire and renew an access token belonging to the impersonated service account.

provider "google" {
  impersonate-service-account = "[email protected]"
  project                     = "my-project-id"
  region                      = "us-central1"
  zone                        = "us-central1-c"
}

@ghost
Copy link

ghost commented Nov 15, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 [email protected]. Thanks!

@ghost ghost locked as resolved and limited conversation to collaborators Nov 15, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.