open-vault/website/content/docs/auth/jwt/oidc_providers.mdx
2022-05-06 12:24:36 -07:00

517 lines
22 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
layout: docs
page_title: OIDC Provider Setup - Auth Methods
description: OIDC provider configuration quick starts
---
# OIDC Provider Configuration
This page collects high-level setup steps on how to configure an OIDC
application for various providers. For more general usage and operation
information, see the [Vault JWT/OIDC method documentation](/docs/auth/jwt).
OIDC providers are often highly configurable and you should become familiar with
their recommended settings and best practices. The instructions below are
largely community-driven and intended to help you get started. Corrections
and additions may be submitted via the [Vault Github repository](https://github.com/hashicorp/vault).
## Azure Active Directory (AAD)
~> **Note:** Azure Active Directory Applications that have custom signing keys as a result of using
the [claims-mapping](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-claims-mapping)
feature are currently not supported for OIDC authentication.
Reference: [Azure Active Directory v2.0 and the OpenID Connect protocol](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc)
1. Choose your Azure tenant.
1. Go to **Azure Active Directory** and
[register an application](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app)
for Vault.
1. Add Redirect URIs with the "Web" type. You may include two redirect URIs,
one for CLI access another one for Vault UI access.
- `http://localhost:8250/oidc/callback`
- `https://hostname:port_number/ui/vault/auth/oidc/oidc/callback`
1. Record the "Application (client) ID" as you will need it as the `oidc_client_id`.
1. Under **Endpoints**, copy the OpenID Connect metadata document URL, omitting the `/well-known...` portion.
- The endpoint URL (`oidc_discovery_url`) will look like: https://login.microsoftonline.com/tenant-guid-dead-beef-aaaa-aaaa/v2.0
1. Under **Certificates & secrets**,
[add a client secret](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#add-a-client-secret)
Record the secret's value as you will need it as the `oidc_client_secret` for Vault.
### Connect AD group with Vault external group
Reference: [Azure Active Directory with OIDC Auth Method and External Groups](https://learn.hashicorp.com/tutorials/vault/oidc-auth-azure)
To connect the AD group with a [Vault external groups](/docs/secrets/identity#external-vs-internal-groups),
you will need
[Azure AD v2.0 endpoints](https://docs.microsoft.com/en-gb/azure/active-directory/develop/azure-ad-endpoint-comparison).
You should set up a [Vault policy](https://learn.hashicorp.com/tutorials/vault/policies) for the Azure AD group to use.
1. Go to **Azure Active Directory** and choose your Vault application.
1. Go to **Token configuration** and **Add groups claim**. Select "All" or "SecurityGroup" based on
[which groups for a user](https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-fed-group-claims)
you want returned in the claim.
1. In Vault, enable the OIDC auth method.
1. Configure the OIDC auth method with the `oidc_client_id` (application ID), `oidc_client_secret`
(client secret), and `oidc_discovery_url` (endpoint URL) you recorded from Azure.
```shell
vault write auth/oidc/config \
oidc_client_id="your_client_id" \
oidc_client_secret="your_client_secret" \
default_role="your_default_role" \
oidc_discovery_url="https://login.microsoftonline.com/tenant_id/v2.0"
```
1. Configure the [OIDC Role](/api-docs/auth/jwt#create-role) with the following:
- `user_claim` should be `"email"`.
- `allowed_redirect_uris` should be the two redirect URIs for Vault CLI and UI access.
- `groups_claim` should be set to `"groups"`.
- `oidc_scopes` should be set to `"https://graph.microsoft.com/.default"`.
```shell
vault write auth/oidc/role/your_default_role \
user_claim="email" \
allowed_redirect_uris="http://localhost:8250/oidc/callback,https://online_version_hostname:port_number/ui/vault/auth/oidc/oidc/callback" \
groups_claim="groups" \
oidc_scopes="https://graph.microsoft.com/.default" \
policies=default
```
1. In Vault, create the [external group](/api-docs/secret/identity/group).
Record the group ID as you will need it for the group alias.
1. From Vault, retrieve the [OIDC accessor ID](/api-docs/system/auth#list-auth-methods)
from the OIDC auth method as you will need it for the group alias's `mount_accessor`.
1. Go to the Azure AD Group you want to attach to Vault's external group. Record the `objectId`
as you will need it as the group alias name in Vault.
1. In Vault, create a [group alias](/api-docs/secret/identity/group-alias)
for the external group and set the `objectId` as the group alias name.
```shell
vault write identity/group-alias \
name="your_ad_group_object_id" \
mount_accessor="vault_oidc_accessor_id" \
canonical_id="vault_external_group_id"
```
### Optional Azure-specific Configuration
If a user is a member of more than 200 groups (directly or indirectly), extra configuration
is required so that Vault can fetch the groups properly.
- In Azure, under the applications **API Permissions**, grant the following permissions:
- Microsoft Graph API permission [Directory.Read.All](https://docs.microsoft.com/en-us/graph/permissions-reference#application-permissions-19)
- In Vault, set `"provider_config"` to Azure.
```shell
vault write auth/oidc/config -<<"EOH"
{
"oidc_client_id": "your_client_id",
"oidc_client_secret": "your_client_secret",
"default_role": "your_default_role",
"oidc_discovery_url": "https://login.microsoftonline.com/tenant_id/v2.0",
"provider_config": {
"provider": "azure"
}
}
EOH
```
- In Vault, add `"profile"` to `oidc_scopes` so the user's id comes back on the JWT.
```shell
vault write auth/oidc/role/your_default_role \
user_claim="email" \
allowed_redirect_uris="http://localhost:8250/oidc/callback,https://online_version_hostname:port_number/ui/vault/auth/oidc/oidc/callback" \
groups_claim="groups" \
oidc_scopes="profile" \
policies="default"
```
## Auth0
1. Select Create Application (Regular Web App).
1. Configure Allowed Callback URLs.
1. Copy client ID and secret.
1. If you see Vault errors involving signature, check the application's Advanced > OAuth settings
and verify that signing algorithm is "RS256".
## ForgeRock
1. Navigate to Applications -> OAuth 2.0 -> Clients in ForgeRock Access Management.
1. Create new client.
1. Configure Client ID, Client Secret, Scopes and Redirection URIs.
- `client ID`
- `client secret`
- `allowed_redirect_uris` should be the two redirect URIs for Vault CLI and UI access.
- `oidc_scopes` should be set to the OIDC scopes.
1. Save Client ID and Client Secret.
### Configuration
1. In Vault, enable the OIDC auth method.
1. Configure the OIDC auth method with the `oidc_client_id` (client ID), `oidc_client_secret`
(client secret), and `oidc_discovery_url` (endpoint URL) from ForgeRock.
```shell
vault write auth/oidc/config \
oidc_client_id="your_client_id" \
oidc_client_secret="your_client_secret" \
default_role="your_default_role" \
oidc_discovery_url="https://openam.example.com:8443/openam/oauth2"
```
1. Configure the [OIDC Role](/api-docs/auth/jwt) with the following:
- `user_claim` should be `"sub"`.
- `allowed_redirect_uris` should be the two redirect URIs for Vault CLI and UI access.
- `oidc_scopes` should be set to the OIDC scopes.
```shell
vault write auth/oidc/role/your_default_role \
user_claim="sub" \
allowed_redirect_uris="http://localhost:8250/oidc/callback,https://online_version_hostname:port_number/ui/vault/auth/oidc/oidc/callback" \
oidc_scopes="your_oidc_scopes" \
policies=default
```
## Gitlab
1. Visit Settings > Applications.
1. Fill out Name and Redirect URIs.
1. Making sure to select the "openid" scope.
1. Copy client ID and secret.
## Google
Main reference: [Using OAuth 2.0 to Access Google APIs](https://developers.google.com/identity/protocols/OAuth2)
1. Visit the [Google API Console](https://console.developers.google.com).
1. Create or a select a project.
1. Create a new credential via Credentials > Create Credentials > OAuth Client ID.
1. Configure the OAuth Consent Screen. Application Name is required. Save.
1. Select application type: "Web Application".
1. Configure Authorized Redirect URIs.
1. Save client ID and secret.
### Optional Google-specific Configuration
Google-specific configuration is available when using Google as an identity provider from the
Vault JWT/OIDC auth method. The configuration allows Vault to obtain Google Workspace group membership and
user information during the JWT/OIDC authentication flow. The group membership obtained from Google Workspace
may be used for Identity group alias association. The user information obtained from Google Workspace can be
used to copy claims data into resulting auth token and alias metadata via [claim_mappings](/api-docs/auth/jwt#claim_mappings).
#### Setup
To set up the Google-specific handling, you'll need:
- A Google Workspace account with the [super admin role](https://support.google.com/a/answer/2405986?hl=en)
for granting domain-wide delegation API client access.
- The ability to create a service account in [Google Cloud Platform](https://console.developers.google.com/iam-admin/serviceaccounts).
The Google-specific handling that's used to fetch Google Workspace groups and user information in Vault uses
[Google Workspace Domain-Wide Delegation of Authority](https://developers.google.com/admin-sdk/directory/v1/guides/delegation)
for authentication and authorization. You need to follow **all steps** in the [guide](https://developers.google.com/admin-sdk/directory/v1/guides/delegation)
to obtain the key file for a Google service account capable of making requests to the Google Workspace
[User Accounts](https://developers.google.com/admin-sdk/directory/v1/guides/manage-users) and
[Groups](https://developers.google.com/admin-sdk/directory/v1/guides/manage-groups) APIs.
In **step 5** within the section titled
[Delegate domain-wide authority to your service account](https://developers.google.com/admin-sdk/directory/v1/guides/delegation#delegate_domain-wide_authority_to_your_service_account),
the only OAuth scopes that should be granted are:
- `https://www.googleapis.com/auth/admin.directory.group.readonly`
- `https://www.googleapis.com/auth/admin.directory.user.readonly`
~> This is an **important security step** in order to give the service account the least set of privileges
that enable the feature.
The Google service account key file obtained from the steps in the guide must be made available on the
host that Vault is running on.
#### Configuration
- `provider` `(string: <required>)` - Name of the provider. Must be set to "gsuite".
- `gsuite_service_account` `(string: <required>)` - Either the path to or the contents of a Google service
account key file in JSON format. If given as a file path, it must refer to a file that's readable on
the host that Vault is running on. If given directly as JSON contents, the JSON must be properly escaped.
- `gsuite_admin_impersonate` `(string: <required>)` - Email address of a Google Workspace admin to impersonate.
- `fetch_groups` `(bool: false)` - If set to true, groups will be fetched from Google Workspace.
- `fetch_user_info` `(bool: false)` - If set to true, user info will be fetched from Google Workspace using the configured [user_custom_schemas](#user_custom_schemas).
- `groups_recurse_max_depth` `(int: <optional>)` - Group membership recursion max depth. Defaults to 0, which means don't recurse.
- `user_custom_schemas` `(string: <optional>)` - Comma-separated list of Google Workspace [custom schemas](https://developers.google.com/admin-sdk/directory/v1/guides/manage-schemas).
Values set for Google Workspace users using custom schema fields will be fetched and made available as claims that can be used with [claim_mappings](/api-docs/auth/jwt#claim_mappings). Required if [fetch_user_info](#fetch_user_info) is set to true.
Example configuration:
```
vault write auth/oidc/config -<<EOF
{
"oidc_discovery_url": "https://accounts.google.com",
"oidc_client_id": "your_client_id",
"oidc_client_secret": "your_client_secret",
"default_role": "your_default_role",
"provider_config": {
"provider": "gsuite",
"gsuite_service_account": "/path/to/service-account.json",
"gsuite_admin_impersonate": "admin@gsuitedomain.com",
"fetch_groups": true,
"fetch_user_info": true,
"groups_recurse_max_depth": 5,
"user_custom_schemas": "Education,Preferences"
}
}
EOF
```
Example role:
```
vault write auth/oidc/role/your_default_role \
allowed_redirect_uris="http://localhost:8200/ui/vault/auth/oidc/oidc/callback,http://localhost:8250/oidc/callback" \
user_claim="sub" \
groups_claim="groups" \
claim_mappings="/Education/graduation_date"="graduation_date" \
claim_mappings="/Preferences/shirt_size"="shirt_size"
```
## Keycloak
1. Select/create a Realm and Client. Select a Client and visit Settings.
1. Client Protocol: openid-connect
1. Access Type: confidential
1. Standard Flow Enabled: On
1. Configure Valid Redirect URIs.
1. Save.
1. Visit Credentials. Select Client ID and Secret and note the generated secret.
## Kubernetes
Kubernetes can function as an OIDC provider such that Vault can validate its
service account tokens using JWT/OIDC auth.
-> **Note:** The JWT auth engine does **not** use Kubernetes' `TokenReview` API
during authentication, and instead uses public key cryptography to verify the
contents of JWTs. This means tokens that have been revoked by Kubernetes will
still be considered valid by Vault until their expiry time. To mitigate this
risk, use short TTLs for service account tokens or use
[Kubernetes auth](/docs/auth/kubernetes) which _does_ use the `TokenReview` API.
### Using service account issuer discovery
When using service account issuer discovery, you only need to provide the JWT
auth mount with an OIDC discovery URL, and sometimes a TLS certificate authority
to trust. This makes it the most straightforward method to configure if your
Kubernetes cluster meets the requirements.
Kubernetes cluster requirements:
* [`ServiceAccountIssuerDiscovery`][k8s-sa-issuer-discovery] feature enabled.
* Present from 1.18, defaults to enabled from 1.20.
* kube-apiserver's `--service-account-issuer` flag is set to a URL that is
reachable from Vault. Public by default for most managed Kubernetes solutions.
* Must use short-lived service account tokens when logging in.
* Tokens mounted into pods default to short-lived from 1.21.
Configuration steps:
1. Ensure OIDC discovery URLs do not require authentication, as detailed
[here][k8s-sa-issuer-discovery]:
```bash
kubectl create clusterrolebinding oidc-reviewer \
--clusterrole=system:service-account-issuer-discovery \
--group=system:unauthenticated
```
1. Find the issuer URL of the cluster.
```bash
kubectl proxy &
ISSUER="$(curl --fail --silent --show-error 127.0.0.1:8001/.well-known/openid-configuration | jq -r '.issuer')"
# Kill the background proxy process when you're done
kill %%
```
1. Enable and configure JWT auth in Vault.
1. If Vault is running in Kubernetes:
```bash
kubectl exec vault-0 -- vault auth enable jwt
kubectl exec vault-0 -- vault write auth/jwt/config \
oidc_discovery_url=https://kubernetes.default.svc.cluster.local \
oidc_discovery_ca_pem=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
```
1. Alternatively, if Vault is _not_ running in Kubernetes:
-> **Note:** When Vault is outside the cluster, the `$ISSUER` endpoint below may
or may not be reachable. If not, you can configure JWT auth using
[`jwt_validation_pubkeys`](#using-jwt-validation-public-keys) instead.
```bash
vault auth enable jwt
vault write auth/jwt/config oidc_discovery_url="${ISSUER}"
```
1. Configure a role and log in as detailed [below](#creating-a-role-and-logging-in).
[k8s-sa-issuer-discovery]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-issuer-discovery
### Using JWT validation public keys
This method can be useful if Kubernetes' API is not reachable from Vault or if
you would like a single JWT auth mount to service multiple Kubernetes clusters
by chaining their public signing keys.
Kubernetes cluster requirements:
* [`ServiceAccountIssuerDiscovery`][k8s-sa-issuer-discovery] feature enabled.
* Present from 1.18, defaults to enabled from 1.20.
* This requirement can be avoided if you can access the Kubernetes master
nodes to read the public signing key directly from disk at
`/etc/kubernetes/pki/sa.pub`. In this case, you can skip the steps to
retrieve and then convert the key as it will already be in PEM format.
* Must use short-lived service account tokens when logging in.
* Tokens mounted into pods default to short-lived from 1.21.
Configuration steps:
1. Fetch the service account signing public key from your cluster's JWKS URI.
```bash
# 1. Find the issuer URL of the cluster.
kubectl proxy &
ISSUER="$(curl --fail --silent --show-error 127.0.0.1:8001/.well-known/openid-configuration | jq -r '.issuer')"
# 2. Query the jwks_uri specified in /.well-known/openid-configuration
# NB: You may need to run this from a pod within the cluster if the $ISSUER
# URL is not available outside the cluster.
curl "$(curl --fail --silent --show-error "${ISSUER}/.well-known/openid-configuration" | jq -r '.jwks_uri')"
# Kill the background proxy process when you're done
kill %%
```
1. Convert the keys from JWK format to PEM. You can use a CLI tool or an online
converter such as [this one][jwk-to-pem].
1. Configure the JWT auth mount with those public keys.
```bash
vault write auth/jwt/config \
jwt_validation_pubkeys="-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9...
-----END PUBLIC KEY-----","-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9...
-----END PUBLIC KEY-----"
```
1. Configure a role and log in as detailed [below](#creating-a-role-and-logging-in).
[jwk-to-pem]: https://8gwifi.org/jwkconvertfunctions.jsp
### Creating a role and logging in
Once your JWT auth mount is configured, you're ready to configure a role and
log in.
1. Create a role for JWT auth that the `default` service account from the
`default` namespace can use. The audience of tokens defaults to the same as
the issuer, but it is configurable.
```bash
vault write auth/jwt/role/my-role \
role_type="jwt" \
bound_audiences="${ISSUER}" \
user_claim="sub" \
bound_subject="system:serviceaccount:default:default" \
policies="default" \
ttl="1h"
```
1. Pods or other clients with access to a service account JWT can then log in.
```bash
vault write auth/jwt/login \
role=my-role \
jwt=@/var/run/secrets/kubernetes.io/serviceaccount/token
# OR equivalent to:
curl \
--fail \
--request POST \
--header "X-Vault-Request: true" \
--data '{"jwt":"<JWT-TOKEN-HERE>","role":"my-role"}' \
"${VAULT_ADDR}/v1/auth/jwt/login"
```
### Specifying TTL and audience
If you would like to specify a custom TTL or audience for service account tokens,
the following pod spec illustrates a volume mount that overrides the default
admission injected token. This is especially relevant if you are unable to
disable the [--service-account-extend-token-expiration][k8s-extended-tokens]
flag for `kube-apiserver` and want to use short TTLs.
When using the resulting token, you will need to set `bound_audiences=vault`
when creating roles in Vault's JWT auth mount.
```yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
# automountServiceAccountToken is redundant in this example because the
# mountPath overlapping with the default path below will already stop the
# default admission injected token from being created. Use this option if you
# choose a different mount path.
automountServiceAccountToken: false
containers:
- name: nginx
image: nginx
volumeMounts:
- name: custom-token
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
volumes:
- name: custom-token
projected:
defaultMode: 420
sources:
- serviceAccountToken:
path: token
expirationSeconds: 600 # 10 minutes is the minimum TTL
audience: vault
- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
```
[k8s-extended-tokens]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/#options
## Okta
1. Make sure an Authorization Server has been created. The "Issuer" field shown on the Setting page
will be used as the `oidc_discovery_url`.
1. Visit Applications > Add Application (Web).
1. Configure Login redirect URIs. Save.
1. Save client ID and secret.
Note your policy will need `oidc_scopes` to include `profile` to get a full profile ("[Fat Token](https://support.okta.com/help/s/article/Okta-Groups-or-Attribute-Missing-from-Id-Token)"). You will also need to configure bound audience along the lines of `"bound_audiences": ["api://default", "0a4........."]` if you are using the default authorization server.