From 01ccf580d871b1c2af61ea7490690d4c400e131c Mon Sep 17 00:00:00 2001 From: vinay-gopalan <86625824+vinay-gopalan@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:16:56 -0700 Subject: [PATCH 1/4] Add WIF documentation for GCP Auth and Secrets engines (#27170) Co-authored-by: Sarah Chavis <62406755+schavis@users.noreply.github.com> --- website/content/api-docs/auth/gcp.mdx | 33 +++++++- website/content/api-docs/secret/gcp.mdx | 39 ++++++++- website/content/docs/auth/gcp.mdx | 92 ++++++++++++++++++++- website/content/docs/secrets/gcp.mdx | 103 ++++++++++++++++++++++-- 4 files changed, 256 insertions(+), 11 deletions(-) diff --git a/website/content/api-docs/auth/gcp.mdx b/website/content/api-docs/auth/gcp.mdx index dddeb9594e03..6c1dc99f8b27 100644 --- a/website/content/api-docs/auth/gcp.mdx +++ b/website/content/api-docs/auth/gcp.mdx @@ -21,7 +21,25 @@ at any location, please update your API calls accordingly. Configures the credentials required for the plugin to perform API calls to Google Cloud. These credentials will be used to query the status of IAM entities and get service account or other Google public certificates -to confirm signed JWTs passed in during login. +to confirm signed JWTs passed in during login. You can configure +credentials either with Application Credentials for a privileged service account, +or using Plugin Workload Identity Federation (WIF). + +### IAM +Vault uses the official Google Cloud SDK to source credentials from environment variables and shared files. + +From the highest precedence to lowest, you can pass root credentials to the Vault server in the following ways: + +1. Provide static credentials to the API as a payload. + +1. Use [plugin workload identity federation](/vault/docs/auth/gcp#plugin-workload-identity-federation-wif) credentials. + +1. Set [application default credentials](https://cloud.google.com/docs/authentication/application-default-credentials) +as environment variables on the Vault server. + + + Passing Vault new root credentials overwrites any preexisting root credentials. + | Method | Path | | :----- | :----------------- | @@ -33,7 +51,18 @@ to confirm signed JWTs passed in during login. service account credentials file. The service account associated with the credentials file must have the following [permissions](/vault/docs/auth/gcp#required-gcp-permissions). If this value is empty, Vault will try to use [Application Default Credentials][gcp-adc] - from the machine on which the Vault server is running. + from the machine on which the Vault server is running. Mutually exclusive with `identity_token_audience`. + +- `service_account_email` `(string: "")` – Service Account + to impersonate for plugin workload identity federation. Required with `identity_token_audience`. + +- `identity_token_audience` `(string: "")` - The + audience claim value for plugin identity tokens. Must match an allowed audience configured + for the target [Workload Identity Pool](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#prepare). + Mutually exclusive with `credentials`. + +- `identity_token_ttl` `(string/int: 3600)` - The + TTL of generated tokens. Defaults to 1 hour. Uses [duration format strings](/vault/docs/concepts/duration-format). - `iam_alias` `(string: "role_id")` - Must be either `unique_id` or `role_id`. If `unique_id` is specified, the service account's unique ID will be used for diff --git a/website/content/api-docs/secret/gcp.mdx b/website/content/api-docs/secret/gcp.mdx index 6b4fdce3b526..52819278b637 100644 --- a/website/content/api-docs/secret/gcp.mdx +++ b/website/content/api-docs/secret/gcp.mdx @@ -16,18 +16,53 @@ update your API calls accordingly. ## Write config +Use the endpoint to configure shared information for the secrets engine. You can configure +credentials for a privileged service account either with Application Credentials or using +Plugin Workload Identity Federation (WIF). + +### IAM +Vault uses the official Google Cloud SDK to source credentials from environment +variables and shared files. + +From the highest precedence to lowest, you can pass root credentials to the Vault +server in the following ways: + +1. Provide static credentials to the API as a payload. + +1. Use [plugin workload identity federation](/vault/docs/secrets/gcp#plugin-workload-identity-federation-wif) +credentials. + +1. Set [application default credentials](https://cloud.google.com/docs/authentication/application-default-credentials) +as environment variables on the Vault server. + +1. Define credentials in shared credential files. + + + Passing Vault new root credential overwrites any preexisting root credentials. + + | Method | Path | | :----- | :------------ | | `POST` | `/gcp/config` | -This endpoint configures shared information for the secrets engine. ### Parameters - `credentials` (`string:""`) - JSON credentials (either file contents or '@path/to/file') See docs for [alternative ways](/vault/docs/secrets/gcp#setup) to pass in to this parameter, as well as the - [required permissions](/vault/docs/secrets/gcp#required-permissions). + [required permissions](/vault/docs/secrets/gcp#required-permissions). Mutually exclusive with `identity_token_audience`. + +- `service_account_email` `(string: "")` – Service Account +to impersonate for plugin workload identity federation. Required with `identity_token_audience`. + +- `identity_token_audience` `(string: "")` - The +audience claim value for plugin identity tokens. Must match an allowed audience configured +for the target [Workload Identity Pool](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#prepare). +Mutually exclusive with `credentials`. + +- `identity_token_ttl` `(string/int: 3600)` - The +TTL of generated tokens. Defaults to 1 hour. Uses [duration format strings](/vault/docs/concepts/duration-format). - `ttl` (`int: 0 || string:"0s"`) – Specifies default config TTL for long-lived credentials (i.e. service account keys). Uses [duration format strings](/vault/docs/concepts/duration-format). diff --git a/website/content/docs/auth/gcp.mdx b/website/content/docs/auth/gcp.mdx index c276cab2e953..d35550d5f465 100644 --- a/website/content/docs/auth/gcp.mdx +++ b/website/content/docs/auth/gcp.mdx @@ -100,6 +100,41 @@ management tool. environment, you will additionally need to configure your environment’s custom endpoints via the [custom_endpoint](/vault/api-docs/auth/gcp#custom_endpoint) configuration parameter. + In some cases, you cannot set sensitive IAM security credentials in your + Vault configuration. For example, your organization may require that all + security credentials are short-lived or explicitly tied to a machine identity. + + To provide IAM security credentials to Vault, we recommend using Vault + [plugin workload identity federation](#plugin-workload-identity-federation-wif) + (WIF) as shown below. + +1. Alternatively, configure the audience claim value and the service account email to assume for plugin workload identity federation: + + ```text + $ vault write auth/gcp/config \ + identity_token_audience="" \ + service_account_email="" + ``` + + Vault's identity token provider signs the plugin identity token JWT internally. + If a trust relationship exists between Vault and GCP through WIF, the auth + method can exchange the Vault identity token for a + [federated access token](https://cloud.google.com/docs/authentication/token-types#access). + + To configure a trusted relationship between Vault and GCP: + - You must configure the [identity token issuer backend](/vault/api-docs/secret/identity/tokens#configure-the-identity-tokens-backend) + for Vault. + - GCP must have a + [workload identity pool and provider](https://cloud.google.com/iam/docs/manage-workload-identity-pools-providers) + configured with information about the fully qualified and network-reachable + issuer URL for the Vault plugin's + [identity token provider](/vault/api-docs/secret/identity/tokens#read-plugin-identity-well-known-configurations). + + Establishing a trusted relationship between Vault and GCP ensures that GCP + can fetch JWKS + [public keys](/vault/api-docs/secret/identity/tokens#read-active-public-keys) + and verify the plugin identity token signature. + 1. Create a named role: For an `iam`-type role: @@ -224,6 +259,61 @@ account to impersonate any service account in the GCP project where it resides. See [Managing service account impersonation](https://cloud.google.com/iam/docs/impersonating-service-accounts) for more information. +## Plugin Workload Identity Federation (WIF) + + + +The GCP auth method supports the plugin WIF workflow and has a source of identity called +a plugin identity token. A plugin identity token is a JWT that is signed internally by the Vault +[plugin identity token issuer](/vault/api-docs/secret/identity/tokens#read-plugin-workload-identity-issuer-s-openid-configuration). + +If there is a trust relationship configured between Vault and GCP through +[workload identity federation](https://cloud.google.com/iam/docs/workload-identity-federation), +the auth method can exchange its identity token for short-lived access tokens needed to +perform its actions. + +Exchanging identity tokens for access tokens lets the GCP auth method +operate without configuring explicit access to sensitive IAM security +credentials. + +To configure the auth method to use plugin WIF: + +1. Ensure that Vault [openid-configuration](/vault/api-docs/secret/identity/tokens#read-plugin-identity-token-issuer-s-openid-configuration) +and [public JWKS](/vault/api-docs/secret/identity/tokens#read-plugin-identity-token-issuer-s-public-jwks) +APIs are network-reachable by GCP. We recommend using an API proxy or gateway +if you need to limit Vault API exposure. + +1. Create a + [workload identity pool and provider](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#create-pool-provider) + in GCP. + 1. The provider URL **must** point at your [Vault plugin identity token issuer](/vault/api-docs/secret/identity/tokens#read-plugin-workload-identity-issuer-s-openid-configuration) with the + `/.well-known/openid-configuration` suffix removed. For example: + `https://host:port/v1/identity/oidc/plugins`. + 1. Uniquely identify the recipient of the plugin identity token as the audience. + You can use the [default audience](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#prepare) + for the identity pool or a custom value less than 256 characters. + +1. [Authenticate a workload](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#authenticate) +in GCP by granting the identity pool access to a dedicated service account using service account impersonation. +Filter requests using the unique `sub` claim issued by plugin identity tokens so the GCP Auth method can +impersonate the service account. `sub` claims have the form: `plugin-identity::auth:`. + +1. Configure the GCP auth method with the OIDC audience value and service account +email. + + ```shell-session + $ vault write auth/gcp/config \ + identity_token_audience="//iam.googleapis.com/projects/410449834127/locations/global/workloadIdentityPools/vault-gcp-auth-43777a63/providers/vault-gcp-auth-wif-provider" \ + service_account_email="vault-plugin-wif-auth@hc-b712f250b4e04cacbadd258a90b.iam.gserviceaccount.com" + ``` + +Your auth method can now use plugin WIF for its configuration credentials. +By default, WIF [credentials](https://cloud.google.com/iam/docs/workload-identity-federation#access_management) +have a time-to-live of 1 hour and automatically refresh when they expire. + +Please see the [API documentation](/vault/api-docs/auth/gcp#configure) +for more details on the fields associated with plugin WIF. + ## Group aliases As of Vault 1.0, roles can specify an `add_group_aliases` boolean parameter @@ -275,7 +365,7 @@ for IAM service accounts looks like this: ### GCE login GCE login only applies to roles of type `gce` and **must be completed on an -infrastructure running on Google Cloud**. These steps will not work from your +infrastructure running on Google Cloud**. These steps will not work from your local laptop or another cloud provider. [![Vault Google Cloud GCE Login Workflow](/img/vault-gcp-gce-auth-workflow.svg)](/img/vault-gcp-gce-auth-workflow.svg) diff --git a/website/content/docs/secrets/gcp.mdx b/website/content/docs/secrets/gcp.mdx index 739c325514b9..8d7c4333a9f9 100644 --- a/website/content/docs/secrets/gcp.mdx +++ b/website/content/docs/secrets/gcp.mdx @@ -62,6 +62,42 @@ management tool. place of specifying the credentials JSON file. For more information on authentication, see the [authentication section](#authentication) below. + In some cases, you cannot set sensitive IAM security credentials in your + Vault configuration. For example, your organization may require that all + security credentials are short-lived or explicitly tied to a machine identity. + + To provide IAM security credentials to Vault, we recommend using Vault + [plugin workload identity federation](#plugin-workload-identity-federation-wif) + (WIF) as shown below. + + +1. Alternatively, configure the audience claim value and the service account email to assume for plugin workload identity federation: + + ```text + $ vault write gcp/config \ + identity_token_audience="" \ + service_account_email="" + ``` + + Vault's identity token provider signs the plugin identity token JWT internally. + If a trust relationship exists between Vault and GCP through WIF, the secrets + engine can exchange the Vault identity token for a + [federated access token](https://cloud.google.com/docs/authentication/token-types#access). + + To configure a trusted relationship between Vault and GCP: + - You must configure the [identity token issuer backend](/vault/api-docs/secret/identity/tokens#configure-the-identity-tokens-backend) + for Vault. + - GCP must have a + [workload identity pool and provider](https://cloud.google.com/iam/docs/manage-workload-identity-pools-providers) + configured with information about the fully qualified and network-reachable + issuer URL for the Vault plugin's + [identity token provider](/vault/api-docs/secret/identity/tokens#read-plugin-identity-well-known-configurations). + + Establishing a trusted relationship between Vault and GCP ensures that GCP + can fetch JWKS + [public keys](/vault/api-docs/secret/identity/tokens#read-active-public-keys) + and verify the plugin identity token signature. + 1. Configure rolesets or static accounts. See the relevant sections below. ## Rolesets @@ -77,11 +113,11 @@ For more information on the differences between rolesets and static accounts, se ### Roleset policy considerations -Starting with Vault 1.8.0, existing permissive policies containing globs -for the GCP Secrets Engine may grant additional privileges due to the introduction +Starting with Vault 1.8.0, existing permissive policies containing globs +for the GCP Secrets Engine may grant additional privileges due to the introduction of `/gcp/roleset/:roleset/token` and `/gcp/roleset/:roleset/key` endpoints. -The following policy grants a user the ability to read all rolesets, but would +The following policy grants a user the ability to read all rolesets, but would also allow them to generate tokens and keys. This type of policy is not recommended: ```hcl @@ -91,7 +127,7 @@ path "/gcp/roleset/*" { } ``` -The following example demonstrates how a wildcard can instead be used in a roleset policy to +The following example demonstrates how a wildcard can instead be used in a roleset policy to adhere to the principle of least privilege: ```hcl @@ -100,7 +136,7 @@ path "/gcp/roleset/+" { } ``` -For more more information on policy syntax, see the +For more more information on policy syntax, see the [policy documentation](/vault/docs/concepts/policies#policy-syntax). ### Examples @@ -217,7 +253,7 @@ Impersonated accounts are a way to generate an OAuth2 [access token](/vault/docs the permissions and accesses of another given service account. These access tokens do not have the same 10-key limit as service account keys do, yet they retain their short-lived nature. By default, their TTL in GCP is 1 hour, but -this may be configured to be up to 12 hours as explained in Google's +this may be configured to be up to 12 hours as explained in Google's [short-lived credentials documentation](https://cloud.google.com/iam/docs/create-short-lived-credentials-delegated#sa-credentials-oauth). For more information regarding service account impersonation in GCP, consider starting @@ -546,6 +582,61 @@ You can either: This means to update access on the dataset, Vault must be able to update the dataset's metadata. +## Plugin Workload Identity Federation (WIF) + + + +The GCP secrets engine supports the plugin WIF workflow and has a source of identity called +a plugin identity token. The plugin identity token is a JWT that is signed internally by Vault's +[plugin identity token issuer](/vault/api-docs/secret/identity/tokens#read-plugin-workload-identity-issuer-s-openid-configuration). + +If there is a trust relationship configured between Vault and GCP through +[workload identity federation](https://cloud.google.com/iam/docs/workload-identity-federation), +the secrets engine can exchange its identity token for short-lived access tokens needed to +perform its actions. + +Exchanging identity tokens for access tokens lets the GCP secrets engine +operate without configuring explicit access to sensitive IAM security +credentials. + +To configure the secrets engine to use plugin WIF: + +1. Ensure that Vault [openid-configuration](/vault/api-docs/secret/identity/tokens#read-plugin-identity-token-issuer-s-openid-configuration) +and [public JWKS](/vault/api-docs/secret/identity/tokens#read-plugin-identity-token-issuer-s-public-jwks) +APIs are network-reachable by GCP. We recommend using an API proxy or gateway +if you need to limit Vault API exposure. + +1. Create a + [workload identity pool and provider](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#create-pool-provider) + in GCP. + 1. The provider URL **must** point at your [Vault plugin identity token issuer](/vault/api-docs/secret/identity/tokens#read-plugin-workload-identity-issuer-s-openid-configuration) with the + `/.well-known/openid-configuration` suffix removed. For example: + `https://host:port/v1/identity/oidc/plugins`. + 1. Uniquely identify the recipient of the plugin identity token as the audience. + You can use the [default audience](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#prepare) + for the identity pool or a custom value less than 256 characters. + +1. [Authenticate a workload](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#authenticate) +in GCP by granting the identity pool access to a dedicated service account using service account impersonation. +Filter requests using the unique `sub` claim issued by plugin identity tokens so the GCP Auth engine can +impersonate the service account. `sub` claims have the form: `plugin-identity::secret:`. + +1. Configure the GCP secrets engine with the OIDC audience value and service account +email. + + ```shell-session + $ vault write gcp/config \ + identity_token_audience="//iam.googleapis.com/projects/410449834127/locations/global/workloadIdentityPools/vault-gcp-secrets-43777a63/providers/vault-gcp-secrets-wif-provider" \ + service_account_email="vault-plugin-wif-secrets@hc-b712f250b4e04cacbadd258a90b.iam.gserviceaccount.com" + ``` + +Your secrets engine can now use plugin WIF for its configuration credentials. +By default, WIF [credentials](https://cloud.google.com/iam/docs/workload-identity-federation#access_management) +have a time-to-live of 1 hour and automatically refresh when they expire. + +Please see the [API documentation](/vault/api-docs/secret/gcp#write-config) +for more details on the fields associated with plugin WIF. + ### Root credential rotation If the mount is configured with credentials directly, the credential's key may be From 5acc4331ea74efb37d90d53b1e104eecb71e8458 Mon Sep 17 00:00:00 2001 From: vinay-gopalan <86625824+vinay-gopalan@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:17:13 -0700 Subject: [PATCH 2/4] Add WIF documentation for Azure Auth and Secrets engines (#27185) --- website/content/api-docs/auth/azure.mdx | 12 +++- website/content/api-docs/secret/azure.mdx | 10 +++ website/content/docs/auth/azure.mdx | 84 ++++++++++++++++++++++ website/content/docs/secrets/azure.mdx | 86 +++++++++++++++++++++++ 4 files changed, 191 insertions(+), 1 deletion(-) diff --git a/website/content/api-docs/auth/azure.mdx b/website/content/api-docs/auth/azure.mdx index 3f8eef4e2a57..98ebc9f2c996 100644 --- a/website/content/api-docs/auth/azure.mdx +++ b/website/content/api-docs/auth/azure.mdx @@ -22,6 +22,9 @@ Configures the credentials required for the plugin to perform API calls to Azure. These credentials will be used to query the metadata about the virtual machine. +You can configure the auth engine with account credentials or plugin workload +identity federation (WIF). + | Method | Path | | :----- | :------------------- | | `POST` | `/auth/azure/config` | @@ -41,7 +44,14 @@ virtual machine. This value can also be provided with the `AZURE_CLIENT_ID` environment variable. - `client_secret` `(string: '')` - The client secret for credentials to query the Azure APIs. This value can also be provided with the `AZURE_CLIENT_SECRET` environment variable. -- `max_retries` `(int: 3)` - The maximum number of attempts a failed operation will be + Mutually exclusive with `identity_token_audience`. +- `identity_token_audience` `(string: "")` - The + audience claim value for plugin identity tokens. Must match the allowed audiences configured + for the target [Federated Identity Credential](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp#configure-a-federated-identity-credential-on-an-app). + Mutually exclusive with `client_secret`. +- `identity_token_ttl` `(string/int: 3600)` - The + TTL of generated tokens. Defaults to 1 hour. Uses [duration format strings](/vault/docs/concepts/duration-format). +- `max_retries` `(int: 3)` - The maximum number of attempts a failed operation will be retried before producing an error. - `max_retry_delay` `(string: '60s')` - The maximum delay, in seconds, allowed before retrying an operation. - `retry_delay` `(string: '4s')` - The initial amount of delay, in seconds, to use before retrying an operation. Increases exponentially. diff --git a/website/content/api-docs/secret/azure.mdx b/website/content/api-docs/secret/azure.mdx index 4c5d202a434a..70e95c34c566 100644 --- a/website/content/api-docs/secret/azure.mdx +++ b/website/content/api-docs/secret/azure.mdx @@ -20,6 +20,9 @@ Configures the credentials required for the plugin to perform API calls to Azure. These credentials will be used to query roles and create/delete service principals. Environment variables will override any parameters set in the config. +You can configure the secrets engine with account credentials or using +plugin workload identity federation (WIF). + | Method | Path | | :----- | :-------------- | | `POST` | `/azure/config` | @@ -32,6 +35,13 @@ service principals. Environment variables will override any parameters set in th with the AZURE_CLIENT_ID environment variable. See [authentication](/vault/docs/secrets/azure#authentication) for more details. - `client_secret` (`string:""`) - The OAuth2 client secret to connect to Azure. This value can also be provided with the AZURE_CLIENT_SECRET environment variable. See [authentication](/vault/docs/secrets/azure#authentication) for more details. + Mutually exclusive with `identity_token_audience`. +- `identity_token_audience` `(string: "")` - The + audience claim value for plugin identity tokens. Must match the allowed audiences configured + for the target [Federated Identity Credential](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp#configure-a-federated-identity-credential-on-an-app). + Mutually exclusive with `client_secret`. +- `identity_token_ttl` `(string/int: 3600)` - The + TTL of generated tokens. Defaults to 1 hour. Uses [duration format strings](/vault/docs/concepts/duration-format). - `environment` (`string:""`) - The Azure environment. This value can also be provided with the AZURE_ENVIRONMENT environment variable. If not specified, Vault will use Azure Public Cloud. - `root_password_ttl` `(string: 182d)` - Specifies how long the root password is valid for in Azure when diff --git a/website/content/docs/auth/azure.mdx b/website/content/docs/auth/azure.mdx index dae629a2ed66..e6e3487975a6 100644 --- a/website/content/docs/auth/azure.mdx +++ b/website/content/docs/auth/azure.mdx @@ -151,6 +151,41 @@ tool. For the complete list of configuration options, please see the API documentation. + In some cases, you cannot set sensitive account credentials in your + Vault configuration. For example, your organization may require that all + security credentials are short-lived or explicitly tied to a machine identity. + + To provide managed identity security credentials to Vault, we recommend using Vault + [plugin workload identity federation](#plugin-workload-identity-federation-wif) + (WIF) as shown below. + +1. Alternatively, configure the audience claim value and the Client, Tenant IDs for plugin workload identity federation: + + ```text + $ vault write azure/config \ + tenant_id=7cd1f227-ca67-4fc6-a1a4-9888ea7f388c \ + client_id=dd794de4-4c6c-40b3-a930-d84cd32e9699 \ + identity_token_audience=vault.example/v1/identity/oidc/plugins + ``` + + The Vault identity token provider signs the plugin identity token JWT internally. + If a trust relationship exists between Vault and Azure through WIF, the auth + method can exchange the Vault identity token for a federated access token. + + To configure a trusted relationship between Vault and Azure: + - You must configure the [identity token issuer backend](/vault/api-docs/secret/identity/tokens#configure-the-identity-tokens-backend) + for Vault. + - Azure must have a + [federated identity credential](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp#configure-a-federated-identity-credential-on-an-app) + configured with information about the fully qualified and network-reachable + issuer URL for the Vault plugin + [identity token provider](/vault/api-docs/secret/identity/tokens#read-plugin-identity-well-known-configurations). + + Establishing a trusted relationship between Vault and Azure ensures that Azure + can fetch JWKS + [public keys](/vault/api-docs/secret/identity/tokens#read-active-public-keys) + and verify the plugin identity token signature. + 1. Create a role: ```shell-session @@ -229,6 +264,55 @@ server: AZURE_GO_SDK_LOG_LEVEL=DEBUG ``` +## Plugin Workload Identity Federation (WIF) + + + +The Azure auth method supports the plugin WIF workflow, and has a source of identity called +a plugin identity token. A plugin identity token is a JWT that is signed internally by Vault's +[plugin identity token issuer](/vault/api-docs/secret/identity/tokens#read-plugin-workload-identity-issuer-s-openid-configuration). + +If there is a trust relationship configured between Vault and Azure through +[workload identity federation](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation), +the auth method can exchange its identity token for short-lived access tokens needed to +perform its actions. + +Exchanging identity tokens for access tokens lets the Azure auth method +operate without configuring explicit access to sensitive client credentials. + +To configure the auth method to use plugin WIF: + +1. Ensure that Vault [openid-configuration](/vault/api-docs/secret/identity/tokens#read-plugin-identity-token-issuer-s-openid-configuration) + and [public JWKS](/vault/api-docs/secret/identity/tokens#read-plugin-identity-token-issuer-s-public-jwks) + APIs are network-reachable by Azure. We recommend using an API proxy or gateway + if you need to limit Vault API exposure. + +1. Configure a + [federated identity credential](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp#configure-a-federated-identity-credential-on-an-app) + on a dedicated application registration in Azure to establish a trust relationship with Vault. + 1. The issuer URL **must** point at your [Vault plugin identity token issuer](/vault/api-docs/secret/identity/tokens#read-plugin-workload-identity-issuer-s-openid-configuration) with the + `/.well-known/openid-configuration` suffix removed. For example: + `https://host:port/v1/identity/oidc/plugins`. + 1. The subject identifier **must** match the unique `sub` claim issued by plugin identity tokens. + The subject identifier should have the form `plugin-identity::auth:`. + 1. The audience should be under 600 characters. The default value in Azure is `api://AzureADTokenExchange`. + +1. Configure the Azure auth method with the client and tenant IDs and the OIDC audience value. + + ```shell-session + $ vault write azure/config \ + tenant_id=7cd1f227-ca67-4fc6-a1a4-9888ea7f388c \ + client_id=dd794de4-4c6c-40b3-a930-d84cd32e9699 \ + identity_token_audience=vault.example/v1/identity/oidc/plugins + ``` + +Your auth method can now use plugin WIF for its configuration credentials. +By default, WIF [credentials](https://learn.microsoft.com/en-us/entra/identity-platform/access-tokens#token-lifetime) +have a time-to-live of 1 hour and automatically refresh when they expire. + +Please see the [API documentation](/vault/api-docs/auth/azure#configure) +for more details on the fields associated with plugin WIF. + ## API The Azure Auth Plugin has a full HTTP API. Please see the [API documentation](/vault/api-docs/auth/azure) for more details. diff --git a/website/content/docs/secrets/azure.mdx b/website/content/docs/secrets/azure.mdx index 0e3eedb05895..96a1956dd4bb 100644 --- a/website/content/docs/secrets/azure.mdx +++ b/website/content/docs/secrets/azure.mdx @@ -61,6 +61,42 @@ management tool. If you are running Vault inside an Azure VM with MSI enabled, `client_id` and `client_secret` may be omitted. For more information on authentication, see the [authentication](#authentication) section below. + In some cases, you cannot set sensitive account credentials in your + Vault configuration. For example, your organization may require that all + security credentials are short-lived or explicitly tied to a machine identity. + + To provide managed identity security credentials to Vault, we recommend using Vault + [plugin workload identity federation](#plugin-workload-identity-federation-wif) + (WIF) as shown below. + +1. Alternatively, configure the audience claim value and the Client, Tenant and Subscription IDs for plugin workload identity federation: + + ```text + $ vault write azure/config \ + subscription_id=$AZURE_SUBSCRIPTION_ID \ + tenant_id=$AZURE_TENANT_ID \ + client_id=$AZURE_CLIENT_ID \ + identity_token_audience=$TOKEN_AUDIENCE + ``` + + The Vault identity token provider signs the plugin identity token JWT internally. + If a trust relationship exists between Vault and Azure through WIF, the secrets + engine can exchange the Vault identity token for a federated access token. + + To configure a trusted relationship between Vault and Azure, : + - You must configure the [identity token issuer backend](/vault/api-docs/secret/identity/tokens#configure-the-identity-tokens-backend) + for Vault. + - Azure must have a + [federated identity credential](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp#configure-a-federated-identity-credential-on-an-app) + configured with information about the fully qualified and network-reachable + issuer URL for the Vault plugin + [identity token provider](/vault/api-docs/secret/identity/tokens#read-plugin-identity-well-known-configurations). + + Establishing a trusted relationship between Vault and Azure ensures that Azure + can fetch JWKS + [public keys](/vault/api-docs/secret/identity/tokens#read-active-public-keys) + and verify the plugin identity token signature. + 1. Configure a role. A role may be set up with either an existing service principal, or a set of Azure roles that will be assigned to a dynamically created service principal. @@ -266,6 +302,56 @@ principles it creates. |------------------------------------------------| ------------ | ------------------------------------------- | | [User Access Administrator][user_access_admin] | Subscription | Service Principal ID given in configuration | +## Plugin Workload Identity Federation (WIF) + + + +The Azure secrets engine supports the plugin WIF workflow, and has a source of identity called +a plugin identity token. The plugin identity token is a JWT that is signed internally by Vault's +[plugin identity token issuer](/vault/api-docs/secret/identity/tokens#read-plugin-workload-identity-issuer-s-openid-configuration). + +If there is a trust relationship configured between Vault and Azure through +[workload identity federation](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation), +the secrets engine can exchange its identity token for short-lived access tokens needed to +perform its actions. + +Exchanging identity tokens for access tokens lets the Azure secrets engine +operate without configuring explicit access to sensitive client credentials. + +To configure the secrets engine to use plugin WIF: + +1. Ensure that Vault [openid-configuration](/vault/api-docs/secret/identity/tokens#read-plugin-identity-token-issuer-s-openid-configuration) + and [public JWKS](/vault/api-docs/secret/identity/tokens#read-plugin-identity-token-issuer-s-public-jwks) + APIs are network-reachable by Azure. We recommend using an API proxy or gateway + if you need to limit Vault API exposure. + +1. Configure a + [federated identity credential](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp#configure-a-federated-identity-credential-on-an-app) + on a dedicated application registration in Azure to establish a trust relationship with Vault. + 1. The issuer URL **must** point at your [Vault plugin identity token issuer](/vault/api-docs/secret/identity/tokens#read-plugin-workload-identity-issuer-s-openid-configuration) with the + `/.well-known/openid-configuration` suffix removed. For example: + `https://host:port/v1/identity/oidc/plugins`. + 1. The subject identifier **must** match the unique `sub` claim issued by plugin identity tokens. + The subject identifier should have the form `plugin-identity::secret:`. + 1. The audience should be under 600 characters. The default value in Azure is `api://AzureADTokenExchange`. + +1. Configure the Azure secrets engine with the subscription, client and tenant IDs and the OIDC audience value. + + ```shell-session + $ vault write azure/config \ + subscription_id=$AZURE_SUBSCRIPTION_ID \ + tenant_id=$AZURE_TENANT_ID \ + client_id=$AZURE_CLIENT_ID \ + identity_token_audience="vault.example/v1/identity/oidc/plugins" + ``` + +Your secrets engine can now use plugin WIF for its configuration credentials. +By default, WIF [credentials](https://learn.microsoft.com/en-us/entra/identity-platform/access-tokens#token-lifetime) +have a time-to-live of 1 hour and automatically refresh when they expire. + +Please see the [API documentation](/vault/api-docs/secret/azure#configure-access) +for more details on the fields associated with plugin WIF. + ## Choosing between dynamic or existing service principals Dynamic service principals are preferred if the desired Azure resources can be provided From 1f64e6e9ca9cba5bbe98539925f3baa0cae03dec Mon Sep 17 00:00:00 2001 From: claire bontempo <68122737+hellobontempo@users.noreply.github.com> Date: Mon, 3 Jun 2024 17:20:09 -0700 Subject: [PATCH 3/4] UI: Allow repeat data wrapping for wrap tool (#27289) * update selectors * add tests * add tests * add explanations to true only args * allow token wrap to wrap again * update test wording * add wrap specific modules to tools acceptance test * add changelog * remove selectedAction * trim args and update tests --- changelog/27289.txt | 3 + ui/app/components/tool-actions-form.js | 23 +-- ui/app/components/tool-wrap.js | 37 ++--- .../components/tool-actions-form.hbs | 7 +- ui/app/templates/components/tool-hash.hbs | 4 +- ui/app/templates/components/tool-lookup.hbs | 12 +- ui/app/templates/components/tool-random.hbs | 2 +- ui/app/templates/components/tool-rewrap.hbs | 2 +- ui/app/templates/components/tool-unwrap.hbs | 6 +- ui/app/templates/components/tool-wrap.hbs | 37 ++--- ui/tests/acceptance/tools-test.js | 155 +++++++++++------- ui/tests/helpers/tools-selectors.ts | 11 ++ .../components/tools/tool-wrap-test.js | 81 +++++++++ 13 files changed, 253 insertions(+), 127 deletions(-) create mode 100644 changelog/27289.txt create mode 100644 ui/tests/helpers/tools-selectors.ts create mode 100644 ui/tests/integration/components/tools/tool-wrap-test.js diff --git a/changelog/27289.txt b/changelog/27289.txt new file mode 100644 index 000000000000..3e10cf0a02f6 --- /dev/null +++ b/changelog/27289.txt @@ -0,0 +1,3 @@ +```release-note:improvement +ui: Allow users to wrap inputted data again instead of resetting form +``` diff --git a/ui/app/components/tool-actions-form.js b/ui/app/components/tool-actions-form.js index 306bfb7c4e5b..b6407255b6b4 100644 --- a/ui/app/components/tool-actions-form.js +++ b/ui/app/components/tool-actions-form.js @@ -32,12 +32,12 @@ export default Component.extend(DEFAULTS, { flashMessages: service(), store: service(), // putting these attrs here so they don't get reset when you click back - //random + // random bytes: 32, - //hash + // hash format: 'base64', algorithm: 'sha2-256', - + data: '{\n}', tagName: '', didReceiveAttrs() { @@ -139,15 +139,18 @@ export default Component.extend(DEFAULTS, { this.reset(); }, - updateTtl(ttl) { - set(this, 'wrapTTL', ttl); + onBack(properties) { + // only reset specific properties so user can reuse input data and repeat the action + if (this.isDestroyed || this.isDestroying) { + return; + } + properties.forEach((prop) => { + set(this, prop, DEFAULTS[prop]); + }); }, - codemirrorUpdated(val, hasErrors) { - setProperties(this, { - buttonDisabled: hasErrors, - data: val, - }); + onChange(param, value) { + set(this, param, value); }, }, }); diff --git a/ui/app/components/tool-wrap.js b/ui/app/components/tool-wrap.js index 02eb0d6acfde..2435b14b247d 100644 --- a/ui/app/components/tool-wrap.js +++ b/ui/app/components/tool-wrap.js @@ -12,45 +12,36 @@ import { tracked } from '@glimmer/tracking'; * ToolWrap components are components that sys/wrapping/wrap functionality. Most of the functionality is passed through as actions from the tool-actions-form and then called back with properties. * * @example - * ```js * - * ``` - * @param onClear {Function} - parent action that is passed through. Must be passed as {{action "onClear"}} - * @param token=null {String} - property passed from parent to child and then passed back up to parent - * @param selectedAction="wrap" - passed in from parent. This is the wrap action, others include hash, etc. - * @param codemirrorUpdated {Function} - parent action that is passed through. Must be passed as {{action "codemirrorUpdated"}}. - * @param updateTtl {Function} - parent action that is passed through. Must be passed as {{action "updateTtl"}} - * @param buttonDisabled=false {Boolean} - false default and if there is an error on codemirror it turns to true. - * @param error=null {Object} - errors passed from parent as default then from child back to parent. + * @token={{@token}} + * /> + * + * @param {object} errors=null - errors returned if wrap fails + * @param {function} onBack - callback that only clears specific values so the action can be repeated. Must be passed as `{{action "onBack"}}` + * @param {function} onChange - callback that fires when inputs change and passes value and param name back to the parent + * @param {function} onClear - callback that resets all of values to defaults. Must be passed as `{{action "onClear"}}` + * @param {string} token=null - returned after user clicks "Wrap data", if there is a token value it displays instead of the JsonEditor */ export default class ToolWrap extends Component { - @tracked data = '{\n}'; @tracked buttonDisabled = false; - @action - onClear() { - this.args.onClear(); - } @action updateTtl(evt) { if (!evt) return; const ttl = evt.enabled ? `${evt.seconds}s` : '30m'; - this.args.updateTtl(ttl); + this.args.onChange('wrapTTL', ttl); } + @action codemirrorUpdated(val, codemirror) { codemirror.performLint(); const hasErrors = codemirror?.state.lint.marked?.length > 0; - this.data = val; this.buttonDisabled = hasErrors; - this.args.codemirrorUpdated(val, hasErrors); + this.args.onChange('data', val); } } diff --git a/ui/app/templates/components/tool-actions-form.hbs b/ui/app/templates/components/tool-actions-form.hbs index 53ae308392fc..fb88239f6ab8 100644 --- a/ui/app/templates/components/tool-actions-form.hbs +++ b/ui/app/templates/components/tool-actions-form.hbs @@ -54,12 +54,11 @@ {{else if (eq this.selectedAction "wrap")}} {{else}} diff --git a/ui/app/templates/components/tool-hash.hbs b/ui/app/templates/components/tool-hash.hbs index b1eed813cfae..cc244f3c42dd 100644 --- a/ui/app/templates/components/tool-hash.hbs +++ b/ui/app/templates/components/tool-hash.hbs @@ -30,7 +30,7 @@ />
- +
{{else}} @@ -80,7 +80,7 @@
- +
{{/if}} \ No newline at end of file diff --git a/ui/app/templates/components/tool-lookup.hbs b/ui/app/templates/components/tool-lookup.hbs index d01e071d8b8e..682ab7bf7fda 100644 --- a/ui/app/templates/components/tool-lookup.hbs +++ b/ui/app/templates/components/tool-lookup.hbs @@ -13,12 +13,12 @@ {{#if (or @creation_time @creation_ttl)}}
- - - + + + {{#if @expirationDate}} - - + + {{/if}}
@@ -42,7 +42,7 @@
- +
{{/if}} \ No newline at end of file diff --git a/ui/app/templates/components/tool-random.hbs b/ui/app/templates/components/tool-random.hbs index ac0556a06ab1..36f71ea16e8a 100644 --- a/ui/app/templates/components/tool-random.hbs +++ b/ui/app/templates/components/tool-random.hbs @@ -63,7 +63,7 @@
- +
{{/if}} \ No newline at end of file diff --git a/ui/app/templates/components/tool-rewrap.hbs b/ui/app/templates/components/tool-rewrap.hbs index 223a60a429e2..07fd050e40c8 100644 --- a/ui/app/templates/components/tool-rewrap.hbs +++ b/ui/app/templates/components/tool-rewrap.hbs @@ -56,7 +56,7 @@
- +
{{/if}} \ No newline at end of file diff --git a/ui/app/templates/components/tool-unwrap.hbs b/ui/app/templates/components/tool-unwrap.hbs index 0aa14feae2d3..3716ced3e415 100644 --- a/ui/app/templates/components/tool-unwrap.hbs +++ b/ui/app/templates/components/tool-unwrap.hbs @@ -13,8 +13,8 @@ {{#if @unwrap_data}} - Data - Wrap Details + Data + Wrap Details
- +
{{/if}} \ No newline at end of file diff --git a/ui/app/templates/components/tool-wrap.hbs b/ui/app/templates/components/tool-wrap.hbs index ef28aa91bac1..04fd967782ec 100644 --- a/ui/app/templates/components/tool-wrap.hbs +++ b/ui/app/templates/components/tool-wrap.hbs @@ -16,48 +16,41 @@
-