Update GCP secrets to be example-driven (#4539)

👍
This commit is contained in:
Seth Vargo 2018-05-10 21:58:22 +01:00 committed by Jeff Mitchell
parent 407550bd89
commit a4fa046730
2 changed files with 380 additions and 538 deletions

View File

@ -95,6 +95,9 @@ This method allows you to create a roleset or update an existing roleset. See [r
to learn more about what happens when you create or update a roleset.
**If you update a roleset's bindings, this will effectively revoke any secrets
generated under this roleset.**
### Parameters
- `name` (`string: <required>`): Required. Name of the role. Cannot be updated.

View File

@ -1,590 +1,429 @@
---
layout: "docs"
page_title: "GCP - Secrets Engines"
page_title: "Google Cloud - Secrets Engines"
sidebar_current: "docs-secrets-gcp"
description: |-
The GCP secrets engine for Vault generates service account keys and OAuth tokens dynamically based
on IAM policies.
The Google Cloud Vault secrets engine dynamically generates Google Cloud
service account keys and OAuth tokens based on IAM policies.
---
# GCP Secrets Engine
# Google Cloud Secrets Engine
The Google Cloud Platform secrets engine dynamically generates IAM service account
credentials based on IAM policies, allowing users to have access to GCP resources
without having to manage a new identity (service account).
The Google Cloud Vault secrets engine dynamically generates Google Cloud service
account keys and OAuth tokens based on IAM policies. This enables users to gain
access to Google Cloud resources without needing to create or manage a dedicated
service account.
## Quick Links:
* **[Things to Note](#things-to-note): If you are running into unexpected errors
(or wish to avoid doing so), please read this section! In particular, if you have used other Vault secrets engines
(i.e. the AWS engine), this covers important differences in behavior.**
* Contributing/Issues: This engine was written as a Vault plugin and thus
exists outside the main Vault repo. Please report issues, request features, or
submit contributions to the [plugin-specific repo on Github](https://github.com/hashicorp/vault-plugin-secrets-gcp)
(all are welcome!)
* Docs Quick Links:
* [GCP secrets engine HTTP API](/api/secret/gcp/index.html)
* [Expected `roleset` bindings format](#roleset-bindings)
The benefits of using this secrets engine to manage Google Cloud IAM service accounts are:
- **Automatic cleanup of GCP IAM service account keys** - each Service Account
key is associated with a Vault lease. When the lease expires (either during
normal revocation or through early revocation), the service account key is
automatically revoked.
## Background
- **Quick, short-term access** - users do not need to create new GCP Service
Accounts for short-term or one-off access (such as batch jobs or quick
introspection).
Benefits of using this Vault secrets engine to manage IAM service accounts and credentials:
- **Multi-cloud and hybrid cloud applications** - users authenticate to Vault
using a central identity service (such as LDAP) and generate GCP credentials
without the need to create or manage a new Service Account for that user.
* Automatic cleanup of long-lived IAM service account keys
* Vault associates leases with generated IAM service account keys s.t. they will
be automatically revoked when the lease expires.
* Users don't need to create a new service-account per one-off or short-term access.
* Multi-cloud applications:
* Users authenticate to Vault using some central identity (LDAP, AppRole, etc)
and can generate GCP credentials without having to create and manage a new
service account for that user.
## Setup
Most secrets engines must be configured in advance before they can perform their
functions. These steps are usually completed by an operator or configuration
management tool.
## Overview
1. Enable the Google Cloud secrets engine:
*Note*: The following docs assume that the secrets engine has been mounted at `gcp`,
the default mount path. Adjust your calls accordingly if you mount the engine at a
different path. All example calls in this doc will use the Vault CL tool - see [HTTP API](/api/secret/gcp/index.html)
for possible API calls.
### Setup
Initially, the secrets engine must be enabled in Vault.
```sh
```text
$ vault secrets enable gcp
Success! Enabled the gcp secrets engine at: gcp/
```
You will need to set up the secrets engine with:
By default, the secrets engine will mount at the name of the engine. To
enable the secrets engine at a different path, use the `-path` argument.
* **[Config](#config)**: General config, including credentials that Vault will need to make calls
to GCP APIs (either explicitly or using Application Default Credentials), lease defaults, etc.
1. Configure the secrets engine with account credentials and optionally tune the
default TTLs:
* **[Rolesets](#rolesets)**: Generated credentials will need to be associated with sets of
[IAM roles](https://cloud.google.com/iam/docs/understanding-roles) on specific GCP resources. Rolesets
have an associated `secret_type` that determines a secret type that can be generated
under this role set.
### Usage - Secret Generation
Once the secrets engine has been set up, you can generate two types of secrets in Vault:
* **[Access Tokens](#access-tokens)** (`secret_type`: `access_token`):
This endpoint generates non-renewable OAuth2 access tokens with a lifetime of an hour.
* **[Service Account Keys](#service-account-keys)** (`secret_type`: `service_account_key`): This endpoint generates long-lived
[IAM service account keys](https://cloud.google.com/iam/docs/service-accounts#service_account_keys).
Each secret is associated with a [Vault lease](/docs/concepts/lease.html) that
can be revoked and possibly renewed (see lease docs for how to do so). On revoking
a lease, the secret is no longer guaranteed to work.
Each secret is generated under a specified role set, which determine which permissions (IAM roles)
the generated credentials have on specific GCP resources. Note that a role set can only generate one
type of secret, specified at role set creation as `secret_type`
## Config
The `config/` endpoint is used to configure any information shared by the
entire GCP secrets engine. You can
Allowed Operations: `write`, `read`
Examples:
```bash
$ vault write gcp/config credentials="..." ttl=100 max_ttl=1000
$ vault read gcp/config
```text
$ vault write gcp/config \
credentials=@my-credentials.json \
ttl=4h \
max_ttl=30m
Success! Data written to: gcp/config
```
Parameters For Write:
If you are running Vault from inside [Google Compute Engine][gce] or [Google
Kubernetes Engine][gke], the instance or pod service account can be used in
place or specifying the credentials JSON file. For more information on authentication, see the [authentication section](#authentication) below.
* `credentials` (`string:""`) - JSON credentials (either file contents or '@path/to/file').
See next sections to learn more about required permissions and alternative ways to provide these credentials.
* `ttl` (`int: 0 || string:"0s"`) Specifies default config TTL for long-lived credentials
(i.e. service account keys). Accepts integer number of seconds or Go duration format string.
* `max_ttl` (`int: 0 || string:"0s"`) Specifies default config TTL for long-lived credentials
(i.e. service account keys). Accepts integer number of seconds or Go duration format string.
1. Configure a roleset. Rolesets determine the permissions that Service Account
credentials generated by Vault will have on GCP resources.
#### Passing Credentials To Vault
If you would rather not pass the IAM credentials using the payload `credentials` parameter,
there are multiple ways to pass IAM credentials to the Vault server. You can specify credentials
in the following ways (given in order of evaluation):
To configure a roleset that generates OAuth2 access tokens (preferred):
1. Static credential JSON provided to the API as a payload (i.e. `credentials` parameter)
2. Credentials in the environment variables `GOOGLE_CREDENTIALS` or `GOOGLE_CLOUD_KEYFILE_JSON`
3. Parse JSON file ~/.gcp/credentials
4. [Google Application Default Credentials](https://cloud.google.com/docs/authentication/production)
#### Required Permissions
At present, this endpoint does not confirm that the provided GCP credentials
are for existing IAM users or have valid permissions. However, they will need
the following permissions:
```
// Service Account + Key Admin
iam.serviceAccounts.create
iam.serviceAccounts.delete
iam.serviceAccounts.get
iam.serviceAccounts.list
iam.serviceAccountKeys.create
iam.serviceAccountKeys.delete
iam.serviceAccountKeys.get
iam.serviceAccountKeys.list
iam.serviceAccounts.update
// IAM Policy Changes
$service.$resource.getIamPolicy
$service.$resource.setIamPolicy
```
where `$service.$resource` refers to the GCP service/resources you wish to
assign credentials permissions on, e.g.
`cloudresourcemanager.projects.get/setIamPolicy` for GCP projects
You can either create a [custom role](https://cloud.google.com/iam/docs/creating-custom-roles)
with these permissions and assign it at a project-level to an IAM service account for Vault to use, or
assign `roles/iam.serviceAccountAdmin` and `roles/iam.serviceAccountKeyAdmin` to get the permissions other
than `get/setIamPolicy` permissions, and assign custom roles or global roles that include `get/setIamPolicy`
permissions for the resources that Vault will change policies for.
## Rolesets
Rolesets determine the permissions that service account credentials (secrets)
generated by Vault will have on given GCP resources.
Endpoint: `roleset/` (`rolesets/` for list)
Allowed Operations: `write`, `read`, `list`, `delete`, `rotate`, `rotate-key`
### Creating/Updating Rolesets
Each roleset will have an associated service account that is *created when the role set is created or updated*.
(see [things to note](#things-to-note) for background)
Parameters For Write:
* `name` (`string: <required>`): Required. Name of the role. Cannot be updated. Given as part of path.
* `secret_type` (`string: "access_token"`): Type of secret generated for this role set.
Accepted values: `access_token`, `service_account_key`. Cannot be updated.
* `project` (`string: <required>`): Name of the GCP project that this roleset's service account will belong to.
Cannot be updated.
* `bindings` (`string: <required>`): Bindings configuration string (expected HCL or JSON string, raw or base64-encoded)
* `token_scopes` (`array: []`): List of OAuth scopes to assign to `access_token` secrets generated under
this role set (`access_token` role sets only)
Update is the same call but will error if non-updatable fields are given with different values.
If you update a roleset's bindings, note this will effectively revoke any secrets generated under
this roleset.
Examples:
```bash
# secret type `access_token`
```text
$ vault write gcp/roleset/my-token-roleset \
project="mygcpproject" \
project="my-project" \
secret_type="access_token" \
token_scopes="https://www.googleapis.com/auth/cloud-platform"
bindings=@binds.hcl \
token_scopes="https://www.googleapis.com/auth/cloud-platform" \
bindings=-<<EOF
resource "projects/my-project" {
roles = ["roles/viewer"]
}
EOF
```
# secret type `service_account_key`
To configure a roleset that generates GCP Service Account keys:
```text
$ vault write gcp/roleset/my-key-roleset \
project="mygcpproject" \
project="my-project" \
secret_type="service_account_key" \
bindings="<base64-encoded-hcl-string>"
```
#### Roleset Bindings
The rolesets `binding` argument accepts bindings in the following format:
```hcl
resource "path/to/my/resource" {
roles = [
"roles/viewer",
"projects/X/roles/myprojCustomRole"
]
}
resource "//service.googleapis.com/path/to/another/resource" {
roles = [
"organizations/Y/roles/myprojCustomRole"
]
bindings=-<<EOF
resource "projects/my-project" {
roles = ["roles/viewer"]
}
EOF
```
The top-level blocks are `resource` blocks, defined as `resource "a/resource/name" {...}`. Each block
define IAM policy information to be bound to this resource.
For more information on role bindings and sample role bindings, please see
the [roleset bindings](#roleset-bindings) section below.
The following resource path formats are supported:
For more information on the differences between OAuth2 access tokens and
Service Account keys, see the [things to note](#things-to-note) section
below.
1. Project-level Self-Link (Specify Service and Version)
A URI with scheme and host. Generally the `self_link` attribute of some resource.
Must be resource with parent project (i.e. relative resource name `projects/$PROJECT/...`).
Examples:
* Compute alpha zone:
## Usage
```
https://www.googleapis.com/compute/alpha/projects/my-project/zones/us-central1-c
```
2. [Full resource name](https://cloud.google.com/apis/design/resource_names#full_resource_name) (Specify Service):
A scheme-less URI consisting of a DNS-compatible API service name and a resource path.
The resource path is the relative resource name (see next). Use to specify service but use
either the preferred service version or the only version for which this resource is IAM-enabled.
Examples:
* Compute snapshot:
```
//compute.googleapis.com/project/X/snapshots/Y
```
* Pubsub snapshot:
```
//pubsub.googleapis.com/project/X/snapshots/Y
```
3. [Relative Resource Name](https://cloud.google.com/apis/design/resource_names#relative_resource_name):
A [path-noscheme](https://tools.ietf.org/html/rfc3986#appendix-A) URI path. Use if version/service are
apparent from resource type (or you want to use only the preferred version of the service). General format is resource name
as accepted by the corresponding REST API, but we've added some exceptions (namely Storage).
Examples:
* Storage bucket object:
```
b/bucketname/o/objectname
buckets/bucketname/o/objectname
```
* Pubsub Topic:
```
projects/X/topics/Y
```
Each `resource` block accepts the following arguments:
* `roles`: An array of string names for [IAM roles](https://cloud.google.com/iam/docs/understanding-roles).
Each string must be a global role name (`roles/roleFoo`), a project-level custom role
(`projects/myproj/roles/roleFoo`) or an organization-level custom role (`organizations/myorg/roles/roleFoo`)
You can provide this as a plaintext string blob, the base64-encoded version of this string,
or using syntax `@path/to/bindings.hcl` to pass in a filename
#### Creation Workflow:
When an admin user creates a roleset or updates the role set bindings, Vault does the following:
1. Parses given bindings configuration file as described above.
2. Add [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) entries to clean-up:
- Current service account, key, and bindings in roleset if updating and update succeeds
- New service account, key, and bindings if create/update fails.
3. Attempt to create a new IAM service account.
* The new service account email is `"vault$rolesetName-$timestamp@..."`, where the roleset name might be
truncated to fit the IAM service account character limit)
* The new service account display name will contain the Vault roleset it belongs to.
4. For each resource in the bindings
a. call `getIamPolicy` method on the resource.
b. For each role in the resource's role list, add a binding to this policy with the email of the new
service account.
{ "role": "roles/theRoleToAssign", "member": "serviceAccount:$EMAIL" }
c. call `setIamPolicy` method on the resource
See [this section](#calling-iam-methods) to learn more about how we call IAM methods on various resources.
**Note: Because the service account and policies are assigned now, the
resources given must exist at roleset creation time.**
5. If the roleset generates access tokens (`secret_type = "access_token"`), create a new service account key for
this service account.
6. Save the new role set.
**Note:** If steps 2-6 fail, we return a error response and the new service account will not be saved. WAL entries
will have been added s.t. any entities will eventually get cleaned up, but you may need to manually delete these
if rollback fails and you want to free up quota immediately.
After step 6, the create/update operation will return a success, but we have a last cleanup step:
7. Try to delete the old service account (and any keys) and remove its old IAM policy bindings.
If any of these calls to GCP APIs fail, we added the WAL entries in step 2 so eventually these resources
will get cleaned up. We will return a warning in the response. In addition, we will try to delete the WAL entries
for the now in-use service account that we just created s.t. it does not attempt to clean up these entities later.
#### WAL Cleanup
As mentioned, Vault will create WAL entries, both for newly created service accounts/bindings,
which may not get used if update fails, and for old service account bindings, which may need to be deleted
if immediate cleanup fail.
Each WAL entry contains the name of the role set that was under update/creation. The WAL cleanup functions
work as follows:
1. Vault will attempt to get the role set (which may be missing because it was deleted or was never created).
2. For each type of WAL entry:
* **Service Account**: We try to delete the service account saved in the WAL entry.
* If the roleset is still using the service account: We do nothing and remove the WAL entry.
This happens if we failed to delete a WAL entry for a successful operation, or we preemptively
added a WAL entry to delete old service accounts for an update that ended up failing.
* **Service Account Key** (for `access_token` rolesets)
* If a key name is included in the WAL entry:
* We are attempting to clean up a previously created and saved key after a role set update.
* If the roleset still exists and uses the key, we do nothing and remove the WAL entry.
Otherwise, we delete the key.
* If no key name is included:
* We are attempting to clean up newly created keys for failed roleset updates. Because the key
name is generated by GCP, we do not know the key name when we create the WAL entry.
* Instead of deleting one key, we list all the user-managed keys under this service account
and delete any that are not being used by the current roleset, if it exists.
Since this service account is being controlled by Vault and the secrets are access tokens,
there should not be any other user-managed keys for this service account.
* **IAM Resource-Policy Bindings**:
* The entry contains the GCP resource name that may need policy bindings cleaned up,
and the bound roles and service account email that needs to be cleaned up.
We get the IAM policy, remove the necessary bindings, and set the IAM policy without these bindings.
* If the roleset exists and is still using this service account email, we remove only IAM policy bindings
not included in the current roleset's bindings.
### Other Roleset Operations
#### Rotation
If you want to reset the service account for a given roleset, or rotate the key used for `access_token` rolesets,
the GCP secrets engine has two endpoints for this:
Examples:
```bash
$ vault write gcp/roleset/my-key-roleset/rotate \
$ vault write gcp/roleset/my-token-roleset/rotate
$ vault write gcp/roleset/my-token-roleset/rotate-key # `access_token` only
```
The `rotate/` endpoint works similar to roleset update (i.e. see the create/update workflow above).
It replaces the roleset's service account with a new service account and replaceds any bindings with the new
email as the IAM policy binding member. This will in effect revoke any secrets generated under this roleset.
The `rotate-key/` endpoint only applies to `access_token` rolesets and simply rotates the key
saved in the roleset used to generate access tokens, while keeping the same service account.
Note that rotating the service account (`/rotate`) for an `access_token` roleset
will also effectively rotate the key.
#### Read and Delete
Examples:
```bash
$ vault read gcp/roleset/my-token-roleset
$ vault delete gcp/roleset/my-key-roleset
```
On read, you can get the associated service account, token scopes for `access_token` rolesets,
and other information.
On delete, the service account, bindings, and any keys associated with the roleset service account
will be deleted.
## Generating Secrets
After the secrets engine is configured and a user/machine has a Vault token with
the proper permission, it can generate credentials. Depending on how the roleset
was configured, you can generate OAuth2 tokens or service account keys.
### Access Tokens
You can only generate tokens under `access_token` rolesets.
To generate OAuth2 tokens, read from `gcp/token/...`. The roleset must have been
created as type `access_token`:
Example Call:
```bash
```text
$ vault read gcp/token/my-token-roleset
Key Value
--- -----
lease_id gcp/token/my-token-roleset/some-uuid
lease_duration 59m59s
lease_id gcp/token/my-token-roleset/a8e792ec-9080...
lease_duration 60m
lease_renewable false
token ya29.c.Ell9...
token ya29.c.Elq3BWCRTcuzAyjYDlJZ2tA1zx_7O5AOL...
```
This endpoint generates non-renewable OAuth2 access tokens with a lifetime of an hour. Vault will simply
return an access token (as `token` in output) that can be used in calls to GCP APIs as part of an
"Authorization: Bearer" header:
```bash
$ curl -H "Authorization: Bearer $TOKEN" ...
This endpoint generates a non-renewable OAuth2 access token with the specified TTL. The `token` is a GCP OAuth2 access token that can be used as a Bearer token as part of an API call to Google Cloud.
```sh
$ curl -H "Authorization: Bearer ya29.c.Elq3BWCRTcuzAyjYDlJZ2tA1zx_7O5AOL..."
```
### Service Account Keys
You can only generate tokens under `service_account_key` rolesets.
To generate service account keys, read from `gcp/key/...`. The roleset must have
been created as type `service_account_key`:
Example Call:
```bash
```text
$ vault read gcp/key/my-key-roleset
lease_id gcp/key/my-key-roleset/some-uuid
lease_duration 768h
Key Value
--- -----
lease_id gcp/key/my-key-roleset/ce563a99-5e55-389b...
lease_duration 30m
lease_renewable true
key_algorithm KEY_ALG_RSA_2048
key_type TYPE_GOOGLE_CREDENTIALS_FILE
private_key_data <base-64 encoded private key data>...
private_key_data ewogICJ0eXBlIjogInNlcnZpY2VfYWNjb3VudCIsC...
```
This endpoint generates [IAM service account keys](https://cloud.google.com/iam/docs/service-accounts#service_account_keys)
associated with the role set's service account. These keys are by default long-lived in GCP, but Vault
associates a lease (see output `lease_*` information). This lease can be renewed to extend the key lifetime,
or revoked. When the lease is revoked, the service account key will be deleted (thus freeing up quota).
This endpoint generates a new [GCP IAM service account key][iam-keys] associated
with the roleset's Service Account. When the lease expires (or is revoked
early), the Service Account key will be deleted.
As mentioned in [things to note](#things-to-note), there is a limit of 10 service account keys per
account and thus a limit of 10 secrets per `service_account_key` roleset. Read this section to learn about
how to get around this limit if you are running into issues.
**There is a default limit of 10 keys per Service Account.** For more
information on this limit and recommended mitigation, please see the [things to
note](#things-to-note) section below.
To learn how to use service account keys, see
[calling Google APIs](https://developers.google.com/identity/protocols/OAuth2ServiceAccount#callinganapi),
[how to authenticate in gcloud](https://cloud.google.com/sdk/gcloud/reference/auth/activate-service-account), or
[how to authenticate in Google Cloud client libraries](https://cloud.google.com/docs/authentication/getting-started).
## Roleset Bindings
Roleset bindings define a list of resources and the associated IAM roles on that
resource. Roleset bindings are used as the `binding` argument when creating or
updating a rolset and are specified in the following format using HCL:
```hcl
resource NAME {
roles = [ROLE, [ROLE...]]
}
```
For example:
```hcl
resource "buckets/my-bucket" {
roles = [
"roles/storage.objectAdmin",
"roles/storage.legacyBucketReader",
]
}
```
The top-level `resource` block defines the resource or resource path for which
IAM policy information will be bound. The resource path may be specified in a
few different formats:
- **Project-level self-link** - a URI with scheme and host, generally
corresponding to the `self_link` attribute of a resource in GCP. This must
include the resource nested in the parent project.
```text
# compute alpha zome
https://www.googleapis.com/compute/alpha/projects/my-project/zones/us-central1-c
```
- **Full resource name** - a schema-less URI consisting of a DNS-compatible API
service name and resource path. See the [full resource name API
documentation][resource-name-full] for more information.
```text
# Compute snapshot
//compute.googleapis.com/project/my-project/snapshots/my-compute-snapshot
# Pubsub snapshot
//pubsub.googleapis.com/project/my-project/snapshots/my-pubsub-snapshot
```
- **Relative resource name** - A path-noscheme URI path, usually as accepted by
the API. Use this if the version or service are apparent from the resource
type. Please see the [relative resource name API
documentation][resource-name-relative] for more information.
```text
# Storage bucket objects
buckets/my-bucket
buckets/my-bucket/objects/my-object
# PubSub topics
projects/my-project/topics/my-pubsub-topic
```
The nested `roles` attribute is an array of strings names of [GCP IAM
roles][iam-roles]. The roles may be specified in the following formats:
- **Global role name** - these are global roles built into Google Cloud. For the
full list of available roles, please see the [list of predefined GCP
roles][predefined-roles].
```text
roles/viewer
roles/bigquery.user
roles/billing.admin
```
- **Organization-level custom role** - these are roles that are created at the
organization level by organization owners.
```text
organizations/my-organization/roles/my-custom-role
```
For more information, please see the documentation on [GCP custom
roles][custom-roles].
- **Project-level custom role** - these are roles that are created at a
per-project level by project owners.
```text
projects/my-project/roles/my-custom-role
```
For more information, please see the documentation on [GCP custom
roles][custom-roles].
## Authentication
The Google Cloud Vault secrets backend uses the official Google Cloud Golang
SDK. This means it supports the common ways of [providing credentials to Google
Cloud][cloud-creds]. In addition to specifying `credentials` directly via Vault
configuration, you can also get configuration from the following values **on the
Vault server**:
1. The environment variables `GOOGLE_APPLICATION_CREDENTIALS`. This is specified
as the **path** to a Google Cloud credentials file, typically for a service
account. If this environment variable is present, the resulting credentials are
used. If the credentials are invalid, an error is returned.
1. Default instance credentials. When no environment variable is present, the
default service account credentials are used. This is useful when running Vault
on [Google Compute Engine][gce] or [Google Kubernetes Engine][gke]
For more information on service accounts, please see the [Google Cloud Service
Accounts documentation][service-accounts].
To use this storage backend, the service account must have the following
minimum scope(s):
```text
https://www.googleapis.com/auth/cloud-platform
https://www.googleapis.com/auth/iam
```
### Required Permissions
The credentials given to Vault must have the following permissions:
```text
# Service Account + Key Admin
iam.serviceAccounts.create
iam.serviceAccounts.delete
iam.serviceAccounts.get
iam.serviceAccounts.list
iam.serviceAccounts.update
iam.serviceAccountKeys.create
iam.serviceAccountKeys.delete
iam.serviceAccountKeys.get
iam.serviceAccountKeys.list
# IAM Policy Changes
<service>.<resource>.getIamPolicy
<service>.<resource>.setIamPolicy
```
where `<service>` and `<resource>` correspond to permissions which will be
granted, for example:
```text
# Projects
resourcemanager.projects.getIamPolicy
resourcemanager.projects.setIamPolicy
# All compute
compute.*.getIamPolicy
compute.*.setIamPolicy
```
You can either:
- Create a [custom role][custom-roles] using these permissions, and assign this
role at a project-level
- Assign the set of roles required to get resource-specific
`getIamPolicy/setIamPolicy` permissions. At a minimum you will need to assign
`roles/iam.serviceAccountAdmin` and `roles/iam.serviceAccountKeyAdmin` so
Vault can manage service accounts and keys.
## Things to Note
### Access Tokens vs Service Account Keys
### Access Tokens vs. Service Account Keys
While in general the IAM team prefers that you use short-term access tokens over long-lived, hard-to-manage service account keys
to authenticate calls to GCP APIs, this is currently impractical as several Google tools
require service account keys for authenticating calls (i.e. `gcloud` CLI tool, client libraries).
Thus, while we default to roleset `secret_type` = `access_token`, we also offer the option
to generate keys (set role set `secret_type` to `service_account_key`), but we caution that
these keys should still be carefully monitored even if they have been associated with
Vault leases.
OAuth2 access tokens are **strongly preferred** to Service Account keys, but
some Google services do not yet support OAuth2 access tokens. Due to the quotas
imposed on Service Account Keys, these keys should be strictly monitored even if
they have been associated with a Vault lease.
**NOTE**: `access_token` role sets will generate a service account key that is saved in Vault. Vault will be the only
place this key can be accessed (i.e. console or API users cannot access the private key data) and this data will
not be returned in output for reading the role set. However, **this key can and should be [rotated](#rotation) as
necessary to avoid possible theft.** Note that rotation does effectively invalidate all secrets previously generated
under the roleset.
Even when using Vault to generate OAuth2 access tokens, Vault will still
generate a dedicated Service Account key whose private key is stored in Vault.
This private key is never accessible to other users, and the underlying key can
be rotated. See the [GCP API documentation][api] for more information on
rotation.
### Service account are created **on roleset update/creation** rather than per secret.
### Service Accounts are Tied to Rolesets
(**NOTE: This is different than AWS!!**)
Service Accounts are created when the roleset is created (or updated) rather
than each time a secret is generated. This may be different from how other
secrets engines behave, but it is for good reasons:
There are a couple of reasons why we want service account creation to happen during role-set creation/updates (i.e.
during server set up) rather than on the fly, per secret generated:
- IAM Service Account creation and permission propagation can take up to 60
seconds to complete. By creating the Service Account in advance, we speed up
the timeliness of future operations and reduce the flakiness of automated
workflows.
* IAM service account creation and permissions propagation can take up to a minute. Because the service account is
created and permissions are assigned during set-up, secrets can be used immediately instead of after a
possible delay. This can make automated workflows slightly less complicated/flaky.
* **Service Account Quotas**: GCP projects by default have a limit on the number of IAM service accounts you can create
(currently 100, *including system-managed service accounts*). You can
[request additional quota](https://cloud.google.com/compute/quotas), which is better done
during a set-up step.
* If service accounts are created per secret, this limit would instead be on the number of issued secrets.
- Each GCP project has a limit on the number of IAM Service Accounts. You can
[request additional quota][quotas]. The quota increase is processed by humans,
so it is best to request this additional quota in advance. This limit is
currently 100, **including system-managed Service Accounts**. If Service
Accounts were created per secret, this quota limit would reduce the number of
secrets that can be generated.
### Service Account Keys Have Limits
However, there are a couple of caveats that come from generating per-role-set as well:
GCP IAM has a hard limit (currently 10) on the number of Service Account keys.
Attempts to generate more keys will result in an error. If you find yourself
running into this limit, consider the follwing:
* **Service account key limit**:
Because GCP IAM has set a hard limit (currently 10) on the number of service
account keys, attempts to generate more keys than the limit will result in an error -
Vault is notified *on the fly* when a user tries to create a new secret
and the GCP IAM service returns an error. Thus, if you are generating service account
keys, *for each `service_account_key` role set, there is a hard limit of of
10 secrets (keys)**
If you find yourself running into this limit, consider:
* Having shorter TTLs or revoking access earlier: If you're not using service
account keys created earlier, consider rotating and freeing quota earlier.
* Creating more role sets with the same set of permissions: Additional role-sets can
always be created with the same set of permissions, which adds service accounts and
thus effectively increases the number of key secrets you can generate.
* Using `access_token` role sets: If you need several, very short-term accesses to GCP
resources, consider instead requesting `access_token` secrets which have no limit and
are naturally short-lived.
- Have shorter TTLs or revoke access earlier. If you are not using past Service
Account keys, consider rotating and freeing quota earlier.
* **Resources must exist at role set creation time.** Because we set the bindings for the service account at this point,
if the resource does not exist, calls to getIamPolicy will fail on the resource and the role set creation will fail.
- Create additional rolesets which share the same set of permissions. Additional
rolesets can be created with the same set of permissions. This will create a
new service account and increases the number of keys you can create.
* **Role-set creation might take a while and partially fail.** Because every service account creation, key creation, and
IAM policy change per resource is a GCP API call and we can't do transactions through GCP, if one call fails, the roleset
creation fails and Vault will attempt to rollback all changes made. However, these rollback calls themselves are
API calls that also might fail. We add [WAL entries](#wal-cleanup) to ensure that any unused entities or bindings
get cleaned up eventually, but you may run into possible situations where you hit quota limits or have unused
IAM service accounts that have not been cleaned up. If you manually do this cleanup, the WAL entry will just
succeed without doing anything, so feel free to do this (carefully) if you need to immediately clean up issues.
- Where possible, use OAuth2 access tokens instead of Service Account keys.
### External Changes to Vault-owned IAM Accounts
While Vault will initially create
and assign permissions to IAM service accounts, it is possible that an external user deletes this service account
and/or Vault-managed keys (for `access_token` role sets), or adjusts this service account's permissions.
**We will deny secret generation in the first case until the role set has been rotated or updated,
but the second case is hard to detect on the fly.**
### Resources Must Exist at Roleset Creation
* If your credentials has unexpected permissions, consider the cases that the service account has been
either assigned new external permissions or has possibly inherited permissions from a parent resource policy.
* Consider just rotating this service account periodically anyways to avoid tampering.
* In general, you should not be changing these service accounts via console/API if you are using Vault.
Please warn your GCP project owners to avoid accidentally changing these Vault roleset service accounts.
* Vault role set accounts have emails with the format `vault<roleset-prefix>-<creation UNIX timestamp>@...`,
where `roleset-prefix` is the roleset name, possibly truncated to fit the character limit on rolesets. The
display name (description) will also have the full Vault roleset name.
* If the service account/key has been deleted, you will need to regenerate the role set account/key using the
`gcp/$roleset/rotate` or `gcp/$roleset/rotate-key` endpoints. Updates to the role set bindings
will also trigger service account recreation.
Because we the bindings for the Service Account are set during roleset creation,
resources that do not exist will fail the `getIamPolicy` API call.
### Roleset Creation May Partially Fail
### Calling IAM Methods
Every Service Account creation, key creation, and IAM policy change is a GCP API
call per resource. If an API call to one of these resources fails, the roleset
creation fails and Vault will attempt to rollback.
An IAM-enabled resource (under an arbitrary GCP service) supports the following three IAM methods:
These rollbacks are API calls, so they may also fail. The secrets engine uses a
WAL to ensure that unused bindings are cleaned up. In the case of quota limits,
you may need to clean these up manually.
* `getIamPolicy`
* `setIamPolicy`
* `testIamPermissions`
### Do Not Modify Vault-owned IAM Accounts
In the case of this secrets engine, we need to call `getIamPolicy` and `setIamPolicy` on
an arbitrary resource under an arbitrary service, which would be difficult using
the [generated Go google APIs](https://github.com/google/google-api-go-client). Instead,
we autogenerated a library, using the [Google API Discovery Service](https://developers.google.com/discovery/)
to find IAM-enabled resources and configure HTTP calls on arbitrary services/resources for IAM.
While Vault will initially create and assign permissions to IAM service
accounts, it is possible that an external user deletes or modifies this service
account. These changes are difficult to detect, and it is best to prevent this
type of modification through IAM permissions.
For each binding config resource block (with a resource name), we attempt to find the resource type based on the
relative resource name and match it to a service config as seen in this
[autogenerated config file](https://github.com/hashicorp/vault-plugin-secrets-gcp/blob/master/plugin/iamutil/iam_resources_generated.go)
To re-generate this file, run:
Vault roleset Service Accounts will have emails in the format:
```
go generate github.com/hashicorp/vault-plugin-secrets-gcp/plugin/iamutil
vault<roleset-prefix>-<creation-unix-timestamp>@...
```
Communicate with your teams (or use IAM permissions) to not modify these
resources.
In general, we try to make it so you can specify the resource as given in the HTTP API URL
(between base API URL and get/setIamPolicy suffix). For some possibly non-standard APIs, we have also
added exceptions to try to reach something more standard; a notable current example is the Google Cloud Storage API,
whose methods look like `https://www.googleapis.com/storage/v1/b/bucket/o/object` where we accept either
`b/bucket/o/object` or `buckets/bucket/objects/object` as valid relative resource names.
If you are having trouble during role set creation with errors suggesting the resource format is invalid or API calls
are failing for a resource you know exists, please [report any issues](https://github.com/hashicorp/vault-plugin-secrets-gcp/issues)
you run into. It could be that the API is a non-standard form or we need to re-generate our config file.
## Help &amp; Support
The Google Cloud Vault secrets engine is written as an external Vault plugin and
thus exists outside the main Vault repository. It is automatically bundled with
Vault releases, but the code is managed separately.
Please report issues, add feature requests, and submit contributions to the
[vault-plugin-secrets-gcp repo on GitHub][repo].
## API
The GCP secrets engine has a full HTTP API. Please see the [GCP secrets engine API docs](/api/secret/gcp/index.html)
The GCP secrets engine has a full HTTP API. Please see the [GCP secrets engine API docs][api]
for more details.
[api]: (/api/secret/gcp/index.html)
[cloud-creds]: https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application
[custom-roles]: https://cloud.google.com/iam/docs/creating-custom-roles
[gce]: https://cloud.google.com/compute/
[gke]: https://cloud.google.com/kubernetes-engine/
[iam-keys]: https://cloud.google.com/iam/docs/service-accounts#service_account_keys
[iam-roles]: https://cloud.google.com/iam/docs/understanding-roles
[predefined-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles
[repo]: https://github.com/hashicorp/vault-plugin-secrets-gcp
[resource-name-full]: https://cloud.google.com/apis/design/resource_names#full_resource_name
[resource-name-relative]: https://cloud.google.com/apis/design/resource_names#relative_resource_name
[quotas]: https://cloud.google.com/compute/quotas
[service-accounts]: https://cloud.google.com/compute/docs/access/service-accounts