Update Documentation for GCP Static Account (#12027)

* Update API Docs for Static Account

* Update CHANGELOGs

* Update guide

* Clarify IAM

* More refinement

* Fix missing replace of roleset while copy/pasting

Co-authored-by: Austin Gebauer <34121980+austingebauer@users.noreply.github.com>

* Remove CHANGELOG

* Fix some double ticks

* Apply suggestions from code review

Co-authored-by: Austin Gebauer <34121980+austingebauer@users.noreply.github.com>

* Update examples

Co-authored-by: Austin Gebauer <34121980+austingebauer@users.noreply.github.com>
This commit is contained in:
Yong Wen Chua 2021-07-14 00:36:05 +08:00 committed by GitHub
parent b6f990d1b6
commit 7ea650bc06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 373 additions and 67 deletions

View File

@ -1,3 +1,8 @@
```release-note:feature
secrets/gcp: Adds ability to use existing service accounts for generation of service account keys and access tokens.
```
```release-note:deprecation
secrets/gcp: Deprecated the `/gcp/token/:roleset` and `/gcp/key/:roleset` paths for generating secrets for rolesets.
Use `/gcp/roleset/:roleset/token` and `/gcp/roleset/:roleset/key` instead.
```

View File

@ -115,7 +115,7 @@ $ curl \
| :----- | :------------------- |
| `POST` | `/gcp/roleset/:name` |
This method allows you to create a roleset or update an existing roleset. See [roleset docs](/docs/secrets/gcp#roleset-bindings) for the GCP secrets backend
This method allows you to create a roleset or update an existing roleset. See [docs](/docs/secrets/gcp#bindings) for the GCP secrets backend
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
@ -145,7 +145,7 @@ generated under this roleset.**
#### Sample Bindings:
See [bindings format docs](/docs/secrets/gcp#roleset-bindings) for more information.
See [bindings format docs](/docs/secrets/gcp#bindings) for more information.
```hcl
resource "//cloudresourcemanager.googleapis.com/projects/mygcpproject" {
@ -180,9 +180,9 @@ $ curl \
## Rotate Roleset Account
| Method | Path |
| :----- | :-------------------------- | ------------------- |
| `POST` | `/gcp/roleset/:name/rotate` | `204 (empty body)`` |
| Method | Path | |
| :----- | :-------------------------- | ------------------ |
| `POST` | `/gcp/roleset/:name/rotate` | `204 (empty body)` |
This will rotate the service account this roleset uses to generate secrets.
(this also replaces the key `access_token` roleset). This can be used to invalidate
@ -195,14 +195,14 @@ old secrets generated by the roleset or fix issues if a roleset's service accoun
$ curl \
--header "X-Vault-Token: ..." \
--request POST \
https://127.0.0.1:8200/v1/consul/gcp/roleset/my-token-roleset/rotate
https://127.0.0.1:8200/v1/gcp/roleset/my-token-roleset/rotate
```
## Rotate Roleset Account Key (`access_token` Roleset Only)
| Method | Path |
| :----- | :------------------------------ | ------------------- |
| `POST` | `/gcp/roleset/:name/rotate-key` | `204 (empty body)`` |
| Method | Path | |
| :----- | :------------------------------ | ------------------ |
| `POST` | `/gcp/roleset/:name/rotate-key` | `204 (empty body)` |
This will rotate the service account key this roleset uses to generate
access tokens. This does not recreate the roleset service account.
@ -213,7 +213,7 @@ access tokens. This does not recreate the roleset service account.
$ curl \
--header "X-Vault-Token: ..." \
--request POST \
https://127.0.0.1:8200/v1/consul/gcp/roleset/my-token-roleset/rotate-key
https://127.0.0.1:8200/v1/gcp/roleset/my-token-roleset/rotate-key
```
## Read Roleset
@ -232,7 +232,7 @@ $ curl \
$ curl \
--header "X-Vault-Token: ..." \
--request GET \
https://127.0.0.1:8200/v1/consul/gcp/roleset/my-token-roleset
https://127.0.0.1:8200/v1/gcp/roleset/my-token-roleset
```
### Sample Response
@ -301,13 +301,190 @@ $ curl \
https://127.0.0.1:8200/v1/gcp/roleset/my-token-roleset
```
## Create/Update Static Account
| Method | Path |
| :----- | :-------------------------- |
| `POST` | `/gcp/static-account/:name` |
This method allows you to create a static account or update an existing static account. See [docs](/docs/secrets/gcp#bindings) for the GCP secrets backend
to learn more about what happens when you create or update a static account.
**If you update a static account's bindings, this will effectively revoke any secrets
generated under this static account.**
### Parameters
- `name` (`string: <required>`): Name of the static account. Cannot be updated.
- `secret_type` (`string: "access_token"`): Type of secret generated for this static account. Accepted values: `access_token`, `service_account_key`. Cannot be updated.
- `service_account_email` (`string: <required>`): Email of the GCP service account to manage. Cannot be updated.
- `bindings` (`string`): Bindings configuration string (expects HCL or JSON format in raw or base64-encoded string). Optional.
- `token_scopes` (`array: []`): List of OAuth scopes to assign to `access_token` secrets generated under this static account (`access_token` static accounts only)
### Sample Payload
```json
{
"secret_type": "access_token",
"service_account_email": "example@mygcpproject.iam.gserviceaccount.com",
"bindings": "...",
"token_scopes": [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/bigquery"
]
}
```
#### Sample Bindings:
See [bindings format docs](/docs/secrets/gcp#bindings) for more information.
```hcl
resource "//cloudresourcemanager.googleapis.com/projects/mygcpproject" {
roles = [
"roles/viewer"
],
}
resource "//bigquery.googleapis.com/projects/my-project/datasets/mydataset" {
roles = [
"roles/bigquery.dataViewer"
],
}
resource "https://selflink/to/my/resource" {
roles = [
"project/mygcpproject/roles/projcustomrole",
"organizations/myorg/roles/orgcustomrole"
],
}
```
### Sample Request
```shell-session
$ curl \
--header "X-Vault-Token: ..." \
--request POST \
--data @payload.json \
https://127.0.0.1:8200/v1/gcp/static-account/my-token-account
```
## Rotate Static Account Key (`access_token` Static Account Only)
| Method | Path | |
| :----- | :------------------------------ | ------------------------- |
| `POST` | `/gcp/static-account/:name/rotate-key` | `204 (empty body)` |
This will rotate the service account key this static account uses to generate
access tokens. This does not recreate the service account.
### Sample Request
```shell-session
$ curl \
--header "X-Vault-Token: ..." \
--request POST \
https://127.0.0.1:8200/v1/gcp/static-account/my-token-account/rotate-key
```
## Read Static Account
| Method | Path |
| :----- | :-------------------------- |
| `GET` | `/gcp/static-account/:name` |
### Parameters
- `name` (`string:<required>`): Name of the static account to read.
This endpoint will only return bindings that are managed through the secrets engine. Bindings
manually managed outside of Vault will not be returned.
### Sample Request
```shell-session
$ curl \
--header "X-Vault-Token: ..." \
--request GET \
https://127.0.0.1:8200/v1/gcp/static-account/my-token-account
```
### Sample Response
```json
{
"data": {
"secret_type": "access_token",
"service_account_email": "example@mygcpproject.iam.gserviceaccount.com",
"service_account_project": "mygcpproject",
"bindings": {
"project/mygcpproject": ["roles/viewer"],
"https://selflink/to/my/resource": [
"project/mygcpproject/roles/projcustomrole",
"organizations/myorg/roles/orgcustomrole"
]
},
"token_scopes": ["https://www.googleapis.com/auth/cloud-platform"]
}
}
```
## List Static Accounts
| Method | Path |
| :----- | :--------------------- |
| `LIST` | `/gcp/static-accounts` |
### Sample Request
```shell-session
$ curl \
--header "X-Vault-Token: ..." \
--request LIST \
https://127.0.0.1:8200/v1/gcp/static-accounts
```
### Sample Response
```json
{
"data": {
"keys": ["my-token-account", "my-sakey-account"]
}
}
```
## Delete Static Account
This endpoint deletes an existing static account by the given name.
| Method | Path |
| :------- | :-------------------------- |
| `DELETE` | `/gcp/static-account/:name` |
### Parameters
- `name` (`string:<required>`): Name of the static account to delete.
### Sample Request
```shell-session
$ curl \
--header "X-Vault-Token: ..." \
--request DELETE \
https://127.0.0.1:8200/v1/gcp/static-account/my-token-account
```
## Generate Secret (IAM Service Account Creds): OAuth2 Access Token
| Method | Path |
| :------------- | :-------------------- |
| `GET` / `POST` | `/gcp/token/:roleset` |
| Method | Path |
| :------------- | :------------------------------------------ |
| `GET` / `POST` | `/gcp/roleset/:roleset/token` |
| `GET` / `POST` | `/gcp/static-account/:static-account/token` |
| `GET` / `POST` | `/gcp/token/:roleset` (deprecated) |
Generates an OAuth2 token with the scopes defined on the roleset. This OAuth access token can
Generates an OAuth2 token with the scopes defined on the roleset or static account. This OAuth access token can
be used in GCP API calls, e.g. `curl -H "Authorization: Bearer $TOKEN" ...`
Tokens are non-revocable and non-renewable and have a static TTL of an hour. The TTL configured
@ -317,6 +494,7 @@ do not apply.
### Parameters
- `roleset` (`string:<required>`): Name of an roleset with secret type `access_token` to generate access_token under.
- `static-account` (`string:<required>`): Name of the static account with secret type `access_token` to generate access_token under.
### Sample Request
@ -324,7 +502,7 @@ do not apply.
$ curl \
--header "X-Vault-Token: ..." \
--request GET \
https://127.0.0.1:8200/v1/gcp/token/my-token-roleset
https://127.0.0.1:8200/v1/gcp/roleset/my-token-roleset/token
```
### Sample Response
@ -345,9 +523,12 @@ $ curl \
## Generate Secret (IAM Service Account Creds): Service Account Key
| Method | Path |
| :------------- | :------------------ |
| `GET` / `POST` | `/gcp/key/:roleset` |
| Method | Path |
| :------------- | :---------------------------------------- |
| `GET` / `POST` | `/gcp/roleset/:roleset/key` |
| `GET` / `POST` | `/gcp/static-account/:static-account/key` |
| `GET` / `POST` | `/gcp/key/:roleset` (deprecated) |
If using `GET` ('read'), the optional parameters will be set to their defaults. Use `POST` if you
want to specify different values for these params.
@ -358,6 +539,7 @@ or the system default if config was not defined.
### Parameters
- `roleset` (`string:<required>`): Name of an roleset with secret type `service_account_key` to generate key under.
- `static-account` (`string:<required>`): Name of an static account with secret type `service_account_key` to generate key under.
- `key_algorithm` (`string:"KEY_ALG_RSA_2048"`): Key algorithm used to generate key. Defaults to 2k RSA key
You probably should not choose other values (i.e. 1k), but accepted values are
`enum(`[`ServiceAccountKeyAlgorithm`](https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts.keys#ServiceAccountKeyAlgorithm)`)`
@ -380,7 +562,7 @@ or the system default if config was not defined.
$ curl \
--header "X-Vault-Token: ..." \
--request GET \
https://127.0.0.1:8200/v1/gcp/key/my-key-roleset
https://127.0.0.1:8200/v1/gcp/roleset/my-key-roleset/key
```
```shell-session
@ -388,7 +570,7 @@ $ curl \
--header "X-Vault-Token: ..." \
--request POST \
--data @payload.json \
https://127.0.0.1:8200/v1/gcp/key/my-key-roleset
https://127.0.0.1:8200/v1/gcp/roleset/my-key-roleset/key
```
### Sample Response
@ -396,7 +578,7 @@ $ curl \
```json
{
"request_id": "<uuid>",
"lease_id": "gcp/key/my-key-roleset/<uuid>",
"lease_id": "gcp/roleset/my-key-roleset/key/<uuid>",
"renewable": true,
"lease_duration": 3600,
"data": {

View File

@ -62,50 +62,126 @@ management tool.
place of specifying the credentials JSON file.
For more information on authentication, see the [authentication section](#authentication) below.
1. Configure a roleset. Rolesets determine the permissions that Service Account
credentials generated by Vault will have on GCP resources.
1. Configure rolesets or static accounts. See the relevant sections below.
To configure a roleset that generates OAuth2 access tokens (preferred):
## Rolesets
```text
$ vault write gcp/roleset/my-token-roleset \
project="my-project" \
secret_type="access_token" \
token_scopes="https://www.googleapis.com/auth/cloud-platform" \
bindings=-<<EOF
resource "//cloudresourcemanager.googleapis.com/projects/my-project" {
roles = ["roles/viewer"]
}
EOF
```
A roleset consists of a Vault managed GCP Service account along with a set of IAM bindings
defined for that service account. The name of the service account is generated based on the time
of creation or update. You should not depend on the name of the service account being
fixed and should manage all IAM bindings for the service account through the `bindings` parameter
when creating or updating the roleset.
To configure a roleset that generates GCP Service Account keys:
For more information on the differences between rolesets and static accounts, see the
[things to note](#things-to-note) section below.
```text
$ vault write gcp/roleset/my-key-roleset \
project="my-project" \
secret_type="service_account_key" \
bindings=-<<EOF
resource "//cloudresourcemanager.googleapis.com/projects/my-project" {
roles = ["roles/viewer"]
}
EOF
```
### Examples
Alternatively, provide a file for the `bindings` argument like so:
To configure a roleset that generates OAuth2 access tokens (preferred):
```text
$ vault write gcp/roleset/my-roleset
bindings=@mybindings.hcl
...
```
```text
$ vault write gcp/roleset/my-token-roleset \
project="my-project" \
secret_type="access_token" \
token_scopes="https://www.googleapis.com/auth/cloud-platform" \
bindings=-<<EOF
resource "//cloudresourcemanager.googleapis.com/projects/my-project" {
roles = ["roles/viewer"]
}
EOF
```
For more information on role bindings and sample role bindings, please see
the [roleset bindings](#roleset-bindings) section below.
To configure a roleset that generates GCP Service Account keys:
For more information on the differences between OAuth2 access tokens and
Service Account keys, see the [things to note](#things-to-note) section
below.
```text
$ vault write gcp/roleset/my-key-roleset \
project="my-project" \
secret_type="service_account_key" \
bindings=-<<EOF
resource "//cloudresourcemanager.googleapis.com/projects/my-project" {
roles = ["roles/viewer"]
}
EOF
```
Alternatively, provide a file for the `bindings` argument like so:
```text
$ vault write gcp/roleset/my-roleset
bindings=@mybindings.hcl
...
```
For more information on role bindings and sample role bindings, please see
the [bindings](#bindings) section below.
For more information on the differences between OAuth2 access tokens and
Service Account keys, see the [things to note](#things-to-note) section
below.
For more information on creating and managing rolesets, see the
[GCP secrets engine API docs][api] docs.
## Static Accounts
Static accounts are GCP service accounts that are created outside of Vault and then provided to
Vault to generate access tokens or keys. You can also use Vault to optionally manage IAM bindings
for the service account.
For more information on the differences between rolesets and static accounts, see the
[things to note](#things-to-note) section below.
### Examples
Before configuring a static account, you need to create a
[Google Cloud Service Account][service-accounts]. Take note of the email address of the service
account you have created. Service account emails are of the format
`<service-account-id>@<project-id>.iam.gserviceaccount.com`.
To configure a static account that generates OAuth2 access tokens (preferred):
```text
$ vault write gcp/static-account/my-token-account \
service_account_email="account@my-project.iam.gserviceaccount.com" \
secret_type="access_token" \
token_scopes="https://www.googleapis.com/auth/cloud-platform" \
bindings=-<<EOF
resource "//cloudresourcemanager.googleapis.com/projects/my-project" {
roles = ["roles/viewer"]
}
EOF
```
To configure a static account that generates GCP Service Account keys:
```text
$ vault write gcp/static-account/my-key-account \
service_account_email="account@my-project.iam.gserviceaccount.com" \
secret_type="service_account_key" \
bindings=-<<EOF
resource "//cloudresourcemanager.googleapis.com/projects/my-project" {
roles = ["roles/viewer"]
}
EOF
```
Alternatively, provide a file for the `bindings` argument like so:
```text
$ vault write gcp/static-account/my-account
bindings=@mybindings.hcl
...
```
For more information on role bindings and sample role bindings, please see
the [bindings](#bindings) section below.
For more information on the differences between OAuth2 access tokens and
Service Account keys, see the [things to note](#things-to-note) section
below.
For more information on creating and managing static accounts, see the
[GCP secrets engine API docs][api] docs.
## Usage
@ -119,7 +195,7 @@ To generate OAuth2 tokens, read from `gcp/token/...`. The roleset must have been
created as type `access_token`:
```shell-session
$ vault read gcp/token/my-token-roleset
$ vault read gcp/roleset/my-token-roleset/token
Key Value
--- -----
@ -144,7 +220,7 @@ To generate service account keys, read from `gcp/key/...`. The roleset must have
been created as type `service_account_key`:
```shell-session
$ vault read gcp/key/my-key-roleset
$ vault read gcp/roleset/my-key-roleset/key
Key Value
--- -----
@ -164,11 +240,11 @@ early), the Service Account key will be deleted.
information on this limit and recommended mitigation, please see the [things to
note](#things-to-note) section below.
## Roleset Bindings
## 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 roleset and are specified in the following format using HCL:
Roleset or static account bindings define a list of resources and the associated IAM roles on that
resource. Bindings are used as the `binding` argument when creating or
updating a roleset or static account and are specified in the following format using HCL:
```hcl
resource NAME {
@ -318,7 +394,8 @@ https://www.googleapis.com/auth/cloud-platform
### Required Permissions
The credentials given to Vault must have the following permissions:
The credentials given to Vault must have the following permissions when using rolesets at the
project level:
```text
# Service Account + Key Admin
@ -331,7 +408,28 @@ iam.serviceAccountKeys.create
iam.serviceAccountKeys.delete
iam.serviceAccountKeys.get
iam.serviceAccountKeys.list
```
When using static accounts, Vault must have the following permissions at the service account level:
```text
# Service account key admin
# This is provided in the `roles/iam.serviceAccountKeyAdmin` role
iam.serviceAccounts.get
# For `access_token` secrets
iam.serviceAccounts.getAccessToken
# For `service_account_keys` secrets
iam.serviceAccountKeys.create
iam.serviceAccountKeys.delete
iam.serviceAccountKeys.get
iam.serviceAccountKeys.list
```
When using rolesets or static accounts with bindings, Vault must have the following permissions:
```text
# IAM Policy Changes
<service>.<resource>.getIamPolicy
<service>.<resource>.setIamPolicy
@ -378,6 +476,27 @@ details on this operation, please see the
## Things to Note
### Rolesets vs. Static Accounts
Advantages of rolesets:
- Service accounts and IAM bindings are fully managed by Vault
Disadvantages of rolesets:
- Cannot easily decouple IAM bindings from the ones managed in Vault
- Vault requires permissions to manage IAM bindings and service accounts
Advantages of static accounts:
- Can manage IAM bindings independently from the ones managed in Vault
- Vault does not require permissions to IAM bindings and service accounts and only permissions
related to the keys of the service account
Disadvantages of static accounts:
- Self management of service accounts is necessary.
### Access Tokens vs. Service Account Keys
Advantages of `access_tokens`:
@ -438,9 +557,9 @@ running into this limit, consider the following:
- Where possible, use OAuth2 access tokens instead of Service Account keys.
### Resources Must Exist at Roleset Creation
### Resources in IAM Bindings Must Exist at Roleset or Static Account Creation
Because the bindings for the Service Account are set during roleset creation,
Because the bindings for the Service Account are set during roleset/static account creation,
resources that do not exist will fail the `getIamPolicy` API call.
### Roleset Creation May Partially Fail