From 08c2e2ce4498f9232007a9e09bceeb79dc164775 Mon Sep 17 00:00:00 2001 From: emily Date: Tue, 19 Sep 2017 05:44:05 -0700 Subject: [PATCH] Add GCE docs for GCP Auth Backend (#3341) --- website/source/api/auth/gcp/index.html.md | 112 +++++++++++- .../images/vault-gcp-gce-auth-workflow.svg | 170 ++++++++++++++++++ .../images/vault-gcp-iam-auth-workflow.svg | 138 +++++++++++++- website/source/docs/auth/gcp.html.md | 160 ++++++++++------- 4 files changed, 505 insertions(+), 75 deletions(-) create mode 100644 website/source/assets/images/vault-gcp-gce-auth-workflow.svg diff --git a/website/source/api/auth/gcp/index.html.md b/website/source/api/auth/gcp/index.html.md index 6650fc7151..cfedc24e9f 100644 --- a/website/source/api/auth/gcp/index.html.md +++ b/website/source/api/auth/gcp/index.html.md @@ -41,6 +41,10 @@ to confirm signed JWTs passed in during login. Vault will attempt to use [Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials) for that server's machine. +- `google_certs_endpoint` `(string: "")`: The Google OAuth2 endpoint to obtain public certificates for. This is used + primarily for testing and should generally not be set. If not set, will default to the [Google public certs + endpoint](https://www.googleapis.com/oauth2/v3/certs) + ### Sample Payload ```json @@ -84,7 +88,8 @@ $ curl \ "client_id":"...", "private_key":"-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----\n", "private_key_id":"...", - "project_id":"project-123456" + "project_id":"project-123456", + "google_certs_url": "" }, ... } @@ -136,22 +141,49 @@ entities attempting to login. value of this parameter. - `policies` `(array: [])` - Policies to be set on tokens issued using this role. +- `bound_service_accounts` `(array: [])` - Required for `iam` roles. + A comma-separated list of service account emails or ids. + Defines the service accounts that login is restricted to. If set to `\*`, all + service accounts are allowed (role will still be bound by project). Will be + inferred from service account used to issue metadata token for GCE instances. + +**`iam`-only params**: + - `max_jwt_exp` `(string: "")` - Optional, defaults to 900 (15min). Number of seconds past the time of authentication that the login param JWT must expire within. For example, if a user attempts to login with a token that expires within an hour and this is set to 15 minutes, Vault will return - an error prompting the user to create a new signed JWT with a shorter `exp`. - -**`iam`-only params**: + an error prompting the user to create a new signed JWT with a shorter `exp`. + The GCE metadata tokens currently do not allow the `exp` claim to be customized. + +- `allow_gce_inference` `(bool: true)` - A flag to determine if this role should + allow GCE instances to authenticate by inferring service accounts from the + GCE identity metadata token. - `service_accounts` `(array: [])` - Required for `iam` roles. A comma-separated list of service account emails or ids. Defines the service accounts that login is restricted to. If set to `*`, all service accounts are allowed (role will still be bound by project). +**`gce`-only params**: + +- `bound_zone` `(string: "")`: If set, determines the zone that a GCE instance must belong to. + If bound_instance_group is provided, it is assumed to be a zonal group and the group must belong to this zone. + +- `bound_region` `(string: "")`: If set, determines the region that a GCE instance must belong to. + If bound_instance_group is provided, it is assumed to be a regional group and the group must belong to this region. + **If bound_zone is provided, region will be ignored.** + +- `bound_instance_group` `(string: "")`: If set, determines the instance group that an authorized instance must belong to. + bound_zone or bound_region must also be set if bound_instance_group is set. + +- `bound_labels` `(array: [])`: A comma-separated list of Google Cloud Platform labels formatted as "$key:$value" strings that + must be set on authorized GCE instances. Because GCP labels are not currently ACL'd, we recommend that this be used in + conjunction with other restrictions. + ### Sample Payload -`iam` Role: +Example `iam` Role: ```json { @@ -167,7 +199,29 @@ entities attempting to login. "service_accounts": [ "dev-1@project-123456.iam.gserviceaccount.com", "dev-2@project-123456.iam.gserviceaccount.com", - "123456789", + "123456789" + ], + "allow_instance_migration": false +} +``` + +Example `gce` Role: + +```json +{ + "type": "gce", + "project": "project-123456", + "policies": [ + "default", + "dev", + "prod" + ], + "max_ttl": 1800000, + "max_jwt_exp": 10000, + "service_accounts": [ + "dev-1@project-123456.iam.gserviceaccount.com", + "dev-2@project-123456.iam.gserviceaccount.com", + "123456789" ], "allow_instance_migration": false } @@ -207,11 +261,51 @@ service accounts on the role. { "add": [ "dev-1@project-123456.iam.gserviceaccount.com", - "123456789", + "123456789" ], "remove": [ - "dev-2@project-123456.iam.gserviceaccount.com", + "dev-2@project-123456.iam.gserviceaccount.com" + ] +} +``` + +### Sample Request + +``` +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST \ + --data @payload.json \ + https://vault.rocks/v1/auth/gcp/role/dev-role +``` + +## Edit Labels For GCE Role + +Edit service accounts for an existing IAM role in the backend. +This allows you to add or remove service accounts from the list of +service accounts on the role. + +| Method | Path | Produces | +| :------- | :---------------------------------------| :------------------| +| `POST` | `/auth/gcp/role/:name/labels` | `204 (empty body)` | + +### Parameters +- `name` `(string: )` - Name of an existing `gce` role. Returns error if role is not an `gce` role. +- `add` `(array: [])` - List of `$key:$value` labels to add to the GCE role's bound labels. +- `remove` `(array: [])` - List of label keys to remove from the role's bound labels. + +### Sample Payload + +```json +{ + "add": [ + "foo:bar", + "env:dev", + "key:value" ], + "remove": [ + "keyInLabel1, keyInLabel2" + ] } ``` @@ -342,7 +436,7 @@ entity and then authorizes the entity for the given role. - `jwt` `(string: "")` - Signed [JSON Web Token](https://tools.ietf.org/html/rfc7519) (JWT). For `iam`, this is a JWT generated using the IAM API method [signJwt](https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/signJwt) - or a self-signed JWT. + or a self-signed JWT. For `gce`, this is an [identity metadata token](https://cloud.google.com/compute/docs/instances/verifying-instance-identity#request_signature). ### Sample Payload diff --git a/website/source/assets/images/vault-gcp-gce-auth-workflow.svg b/website/source/assets/images/vault-gcp-gce-auth-workflow.svg new file mode 100644 index 0000000000..0a376bbd9f --- /dev/null +++ b/website/source/assets/images/vault-gcp-gce-auth-workflow.svg @@ -0,0 +1,170 @@ + + + + Sequence Diagram 1@3x + Created with Sketch. + + + + + + + + + + + + + + + + + + + + Instance + + + Compute Engine + + + + + + + + + + + + + + + + + + + + + + + + Metadata Server + + + Compute Engine + + + + + + + + + + + + + + + + + + + + + + + + Google + OAuth2 API + + + + + + + + + Hashicorp Vault + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/website/source/assets/images/vault-gcp-iam-auth-workflow.svg b/website/source/assets/images/vault-gcp-iam-auth-workflow.svg index a45c5b6692..cd2fa18cba 100644 --- a/website/source/assets/images/vault-gcp-iam-auth-workflow.svg +++ b/website/source/assets/images/vault-gcp-iam-auth-workflow.svg @@ -1,4 +1,134 @@ - - - - + + + + Sequence Diagram 2@3x + Created with Sketch. + + + + + + + + + + + + + + + + + + + Hashicorp + Vault + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cloud IAM + + + + + + + + + + + + + + Developer + + + + + + \ No newline at end of file diff --git a/website/source/docs/auth/gcp.html.md b/website/source/docs/auth/gcp.html.md index 57698367e5..030ecb6398 100644 --- a/website/source/docs/auth/gcp.html.md +++ b/website/source/docs/auth/gcp.html.md @@ -17,6 +17,7 @@ different GCP APIs depending on the type of entity. Currently supports authentication for: * GCP IAM service accounts (`iam`) + * GCE IAM service accounts (`gce`) We will update the documentation as we introduce more supported entities. @@ -34,7 +35,7 @@ v0.8.0+ to use plugins. The Vault authentication workflow for IAM service accounts is as follows: 1. A client with IAM service account credentials generates a signed JWT using the IAM [projects.serviceAccounts.signJwt](https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/signJwt) method. See [usage](#the-iam-authentication-token) for the expected format and example code. - 2. The client sends this JWT to Vault in a login request with a role name. This role should have type `iam` + 2. The client sends this JWT to Vault in a login request with a role name. This role should have type `iam`. 3. Vault grabs the `kid` header value, which contains the ID of the key-pair used to generate the JWT, and the `sub` ID/email to find the service account key. If the service account does not exist or the key is not linked to the service account, Vault will deny authentication. 4. Vault authorizes the confirmed service account against the given role. See [authorization section](#authorization-workflow) to see how each type of role handles authorization. @@ -48,29 +49,70 @@ The expected format of the JWT payload is as follows: { "sub" : "[SERVICE ACCOUNT IDENTIFIER]", "aud" : "vault/[ROLE NAME]", - "exp" : "[EXPIRATION]", + "exp" : "[EXPIRATION]" } ``` * `[SERVICE ACCOUNT ID OR EMAIL]`: Either the email or the unique ID of a service account. -* `[ROLE NAME]`: Name of the role that this token will be used to login against. The full expected `aud` string should be "vault/$roleName". +* `[ROLE NAME]`: Name of the role that this token will be used to login against. The full expected `aud` string should end in "vault/$roleName". * `[EXPIRATION]` : A [NumericDate](https://tools.ietf.org/html/rfc7519#section-2) value (seconds from Epoch). This value must be before the max JWT expiration allowed for a role (see `max_jwt_exp` parameter for creating a role). This defaults to 15 minutes and cannot be more than a hour. **Note:** By default, we enforce a shorter `exp` period than the default length for a given token (1 hour) in order to make reuse of tokens difficult. You can customize this value for a given role but it will be capped at an hour. -To generate this token, we use the Google IAM API method. +To generate this token, we use the Google IAM API method [projects.serviceAccounts.signJwt](https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/signJwt). +See an [example of how to generate this token](#generating-iam-token). + +### GCE + +The Vault authentication workflow for GCE instances is as follows: + + 1. A client logins into a GCE instances and [obtains an instance identity metadata token](https://cloud.google.com/compute/docs/instances/verifying-instance-identity). + 2. The client request to login using this token (a JWT) and gives a role name to Vault. + 3. Vault uses the `kid` header value, which contains the ID of the key-pair used to generate the JWT, to find the OAuth2 public cert + to verify this JWT. + 4. Vault authorizes the confirmed instance against the given role. See the [authorization section](#authorization-workflow) to see how each type of role handles authorization. + +[![GCE Login Workflow](/assets/images/vault-gcp-gce-auth-workflow.svg)](/assets/images/vault-gcp-gce-auth-workflow.svg) + +#### The `gce` Authentication Token + +The token can be obtained from the `service-accounts/default/identity` endpoint for a instance's +[metadata server](https://cloud.google.com/compute/docs/storing-retrieving-metadata). You can use the +[example of how to obtain an instance metadata token](#generating-gce-token) to get started. + +Learn more about the JWT format from the +[documentation](https://cloud.google.com/compute/docs/instances/verifying-instance-identity#token_format) +for the identity metadata token. The params the user provides are: + +* `[AUD]`: The full expected `aud` string should end in "vault/$roleName". Note that Google requires the `aud` + claim to contain a scheme or authority but Vault will only check for a suffix. +* `[FORMAT]`: MUST BE `full` for Vault. Format of the metadata token generated (`standard` or `full`). + +### Examples for Obtaining Auth Tokens + +#### Generating IAM Token **HTTP Request Example** -This uses [Google API HTTP annotation](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto). Note the `$PAYLOAD` must be a marshaled JSON string with escaped double quotes. +This uses [Google API HTTP annotation](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto). +Note the `$PAYLOAD` must be a marshaled JSON string with escaped double quotes. ```sh +#!/bin/sh +# [START PARAMS] +ROLE="test-role" +PROJECT="project-123456" +SERVICE_ACCOUNT="my-account@project-123456.iam.gserviceaccount.com" +OAUTH_TOKEN=$(oauth2l header cloud-platform) +# [END PARAMS] -curl -H "Authorization: Bearer $OAUTH_TOKEN" \ + +PAYLOAD=$(echo "{ \"aud\": \"vault/$ROLE\", \"sub\": \"$SERVICE_ACCOUNT\"}" | sed -e 's/"/\\&/g') +curl -H "$OAUTH_TOKEN" \ -H "Content-Type: application/json" \ - -X POST -d '{"payload":"'$PAYLOAD'"}' https://iam.googleapis.com/v1/projects/$PROJECT/serviceAccounts/$SERVICE_ACCOUNT:signJwt + -X POST -d "{\"payload\":\"$PAYLOAD\"}" https://iam.googleapis.com/v1/projects/$PROJECT/serviceAccounts/$SERVICE_ACCOUNT:signJwt``` ``` **Golang Example** @@ -159,6 +201,27 @@ func main() { } ``` +#### Generating GCE Token + +**HTTP Request Example** + +This uses [Google API HTTP annotation](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto) +and must be run on a GCE instance. + +```sh +# [START PARAMS] +VAULT_ADDR="https://127.0.0.1:8200/" +ROLE="my-gce-role" +SERVICE_ACCOUNT="default" # replace with an instance's service account if needed +# [END PARAMS] + +curl -H "Metadata-Flavor: Google"\ + -G + --data-urlencode "audience=$VAULT_ADDR/vault/$ROLE"\ + --data-urlencode "format=full" \ + "http://metadata/computeMetadata/v1/instance/service-accounts/$SERVICE_ACCOUNT/identity" +``` + ## Authorization Workflow For `gcp`, login is per-role. Each role has a specific set of restrictions that @@ -167,53 +230,19 @@ to the role type. Currently supported role types are: -* `iam` +* `iam` (Supports both IAM and inference for GCE tokens) +* `gce` (Only supports GCE tokens) Vault validates an authenticated entity against the role and uses the role to determine information about the lease, including Vault policies assigned and -TTLs. For a full list of accepted arguments, see [role API docs](/api/auth/gcp/index.html#create-role). +TTLs. For a full list of accepted restrictions, see [role API docs](/api/auth/gcp/index.html#create-role). -### About `iam` Roles +If a GCE token is provided for login under an `iam` role, the service account associated with the token +(`sub` claim) is inferred and used to login. -`iam` roles support the following role restrictions: +## Usage - * `service_accounts`: A list of service accounts that are allowed to login as - this role. This list accepts either service account IDs or emails. - -**Note**: In the future we hope to support restrictions related to -IAM policies/permissions. With current IAM APIs, querying all IAM roles or permissions -(set or inherited) on an entity is very difficult to do and overall ends with not a -great story. We plan to wait until more functionality is supported before -attempting to add permission-based constraints. - -## Plugin Backend - -~> Note: The following section is only relevant if you decide to enable the gcp backend as -an external plugin. The gcp plugin backend is integrated into Vault as a builtin backend by default. - -### Plugin Setup - -Assuming you have saved the binary `vault-plugin-auth-gcp` to some folder -and configured the [plugin directory](/docs/internals/plugins.html#plugin-directory) -for your server at `path/to/plugins`: - -```sh -# Write plugin to catalog -$ vault write sys/plugins/catalog/gcp-auth command='vault-plugin-auth-gcp' sha_256= -Success! Data written to: sys/plugins/catalog/gcp-auth - -# Enable plugin backend for auth. -$ vault auth-enable -path=gcp -plugin-name=gcp-auth plugin -Successfully mounted plugin 'plugin' at 'gcp'! -``` - -### Contributing - -This plugin is developed in a separate Github repository: [`hashicorp/vault-plugin-auth-gcp`](https://github.com/hashicorp/vault-plugin-auth-gcp). Please file all feature requests, bugs, and pull requests specific to the GCP plugin under that repository. - -## Authentication - -### Via the CLI +### Via the CLI. #### Enable GCP authentication in Vault @@ -243,7 +272,7 @@ $ vault write auth/gcp/role/dev-role \ type="iam" \ project_id="project-123456" \ policies="prod,dev" \ - service_accounts="serviceaccount1@project1234.iam.gserviceaccount.com,uuid123,..." + bound_service_accounts="serviceaccount1@project1234.iam.gserviceaccount.com,uuid123,..." ... ``` @@ -252,18 +281,23 @@ Vault [policies](/docs/concepts/policies.html). Roles are configured with constr specific to the authentication type, as well as overall constraints and configuration for the generated auth tokens. -We also expose a helper path for updating the service accounts attached to -an existing `iam` role. +We also expose a helper path for updating the service accounts attached to an existing `iam` role: -```sh -vault write auth/gcp/role/dev-role/add-service-accounts \ - values='serviceAccountToAdd,...' - -vault write auth/gcp/role/dev-role/delete-service-accounts \ - values='serviceAccountToRemove,...' \ - ... -``` + ```sh + vault write auth/gcp/role/iam-role/service-accounts \ + add='serviceAccountToAdd,...' \ + remove='serviceAccountToRemove,...' \ + ``` +and for updating the labels attached to an existing `gce` role: + + ```sh + vault write auth/gcp/role/gce-role/labels \ + add='label1:value1,foo:bar,...' \ + remove='key1,key2,...' \ + ``` + + See [API docs](/api/auth/gcp/index.html#create-role) to view parameters for role creation and updates. @@ -319,7 +353,7 @@ $ curl $VAULT_ADDR/v1/auth/gcp/login \ The response will be in JSON. For example: -```javascript +```json { "auth":{ "client_token":"f33f8c72-924e-11f8-cb43-ac59d697597c", @@ -341,9 +375,11 @@ The response will be in JSON. For example: } ``` +## Contributing + +This plugin is developed in a separate Github repository: [`hashicorp/vault-plugin-auth-gcp`](https://github.com/hashicorp/vault-plugin-auth-gcp). Please file all feature requests, bugs, and pull requests specific to the GCP plugin under that repository. + ## API The GCP Auth Plugin has a full HTTP API. Please see the [API docs](/api/auth/gcp/index.html) for more details. - -