- Create a named key used by a role to sign tokens.
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/identity/oidc/key/$DOMAIN_ID" -d '{"allowed_client_ids":["$DOMAIN_ID"]}'
resource "vault_identity_oidc_key" "domain_id" {
name = var.domain_id
algorithm = "RS256"
allowed_client_ids = tolist(var.domain_id)
}
NOTE: The allowed_client_ids
is to authorise which Identity-Role is allowed to use this key to sign an ID token.
- Create an Identity Role; ID tokens are generated against a role & signed against a named key.
Sample Template (string-ified JSON):
{
"username": {{identity.entity.aliases.accessor_id.metadata.userid}}
"group": {{identity.entity.groups.names}}
"arn": {{identity.entity.aliases.accessor_id.metadata.arn}}
"aws_account": {{identity.entity.aliases.accessor_id.metadata.account}}
}
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/identity/oidc/role/$DOMAIN_ID" -d '{"key":"$DOMAIN_ID", "client_id":"sts.amazonaws.com", "template":"base64adda234q3b3"}'
NOTE: the value of client_id will render as the value of aud in the rendered claims.
locals {
userid = format(
"{{identity.entity.aliases.%s.metadata.userid}}",
data.vault_auth_backend.default.accessor
)
arn = format(
"{{identity.entity.aliases.%s.metadata.arn}}",
data.vault_auth_backend.default.accessor
)
aws_account = format(
"{{identity.entity.aliases.%s.metadata.aws_account}}",
data.vault_auth_backend.default.accessor
)
template_hcl {
group = "{{identity.entity.groups.names}}"
username = local.username
arn = local.arn
aws_account = local.aws_account
}
template = base64encode(jsonencode(local.template_hcl))
}
resource "vault_identity_oidc_role" "domain_id" {
name = var.domain_id
key = vault_identity_oidc_key.domain_id.name
client_id = "sts.amazonaws.com"
template = local.template
}
- Create an ACL policy against the path for requesting a signed token:
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/sys/policy/$DOMAIN_ID" -d '{"policy":"path \"identity/oidc/token/$DOMAIN_ID\" {..."}'
data "vault_policy_document" "domain_id" {
rule {
path = format("identity/oidc/token/%s", var.domain_id)
capabilities = ["read"]
description = "allow generate signed id token named after metadata keys"
}
}
resource "vault_policy" "domain_id" {
name = var.domain_id
policy = data.vault_policy_document.domain_id.hcl
}
- Create a Vault Identity Group.
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/identity/group" -d '{"name":"$DOMAIN_ID", "policies":["aws"]}'
Sample Response:
{
"data": {
"id": "363926d8-dd8b-c9f0-21f8-7b248be80ce1",
"name": "$DOMAIN_ID"
}
}
Configure the way that Vault interacts with the Identity store. Generate the identity alias when using the iam auth method.
Sample Payload
{
"iam_alias": "unique_id"
}
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/aws/config/identity" -d '{"iam_alias":"unique_id"}'
- Create AWS auth role:
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/auth/aws/role/$USER_ID" -d '{"bound_iam_principal_arn":["$ARN_ID"], "resolve_aws_unique_ids":true}'
- Create an Entity with Metadata:
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/identity/entity" -d '{"name":"$USER_ID", "metadata":{"user-id":"$USER_ID"}}'
Sample Response:
{
"data": {
"id": "8d6a45e5-572f-8f13-d226-cd0d1ec57297",
"aliases": null
"metadata": {
"user-id": "$USER_ID"
}
}
}
- Create an Entity Alias:
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/identity/entity-alias" -d '{"name":"$IAM_ARN", "canonical_id":"entity_canonical_id", "mount_accessor":"auth_aws_123", "custom_metadata":{"user-id":"$USER_ID"}}'
Sample Response:
{
"data": {
"canonical_id": "404e57bc-a0b1-a80f-0a73-b6e92e8a52d3",
"id": "34982d3d-e3ce-5d8b-6e5f-b9bb34246c31"
}
}
- Update identity group with entity member:
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/identity/group/id/363926d8-dd8b-c9f0-21f8-7b248be80ce1" -d '{"member_entity_ids":["8d6a45e5-572f-8f13-d226-cd0d1ec57297"]}'
- Login to Vault with AWS IAM Role:
curl -X POST "http://127.0.0.1:8200/v1/auth/aws/login" -d '{"role":"$USER_ID", "iam_http_request_method": "POST", "iam_request_url": "aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8=", "iam_request_body": "QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNQ==", "iam_request_headers": "eyJDb250ZW50LUxlbmd0aCI6IFsiNDMiXSwgIlVzZXItQWdlbnQiOiBbImF3cy1zZGstZ28vMS40LjEyIChnbzEuNy4xOyBsaW51eDsgYW1kNjQpIl0sICJYLVZhdWx0LUFXU0lBTS1TZXJ2ZXItSWQiOiBbInZhdWx0LmV4YW1wbGUuY29tIl0sICJYLUFtei1EYXRlIjogWyIyMDE2MDkzMFQwNDMxMjFaIl0sICJDb250ZW50LVR5cGUiOiBbImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZDsgY2hhcnNldD11dGYtOCJdLCAiQXV0aG9yaXphdGlvbiI6IFsiQVdTNC1ITUFDLVNIQTI1NiBDcmVkZW50aWFsPWZvby8yMDE2MDkzMC91cy1lYXN0LTEvc3RzL2F3czRfcmVxdWVzdCwgU2lnbmVkSGVhZGVycz1jb250ZW50LWxlbmd0aDtjb250ZW50LXR5cGU7aG9zdDt4LWFtei1kYXRlO3gtdmF1bHQtc2VydmVyLCBTaWduYXR1cmU9YTY5ZmQ3NTBhMzQ0NWM0ZTU1M2UxYjNlNzlkM2RhOTBlZWY1NDA0N2YxZWI0ZWZlOGZmYmM5YzQyOGMyNjU1YiJdfQ==" }'
- Generate a signed ID token as the AWS IAM Role:
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/identity/oidc/token/$DOMAIN_ID"
Sample Response:
{
"data": {
"client_id": "P6CfCzyHsQY4pMcA6kWAOCItA7",
"token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjJkMGI4YjlkLWYwNGQtNzFlYy1iNjc0LWM3MzU4NDMyYmM1YiJ9.eyJhdWQiOiJQNkNmQ3p5SHNRWTRwTWNBNmtXQU9DSXRBNyIsImV4cCI6MTU2MTQ4ODQxMiwiaWF0IjoxNTYxNDAyMDEyLCJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tOjEyMzQiLCJzdWIiOiI2YzY1ZWFmNy1kNGY0LTEzMzMtMDJiYy0xYzc1MjE5YzMxMDIifQ.IcbWTmks7P5eVtwmIBl5rL1B88MI55a9JJuYVLIlwE9aP_ilXpX5fE38CDm5PixDDVJb8TI2Q_FO4GMMH0ymHDO25ZvA917WcyHCSBGaQlgcS-WUL2fYTqFjSh-pezszaYBgPuGvH7hJjlTZO6g0LPCyUWat3zcRIjIQdXZum-OyhWAelQlveEL8sOG_ldyZ8v7fy7GXDxfJOK1kpw5AX9DXJKylbwZTBS8tLb-7edq8uZ0lNQyWy9VPEW_EEIZvGWy0AHua-Loa2l59GRRP8mPxuMYxH_c88x1lsSw0vH9E3rU8AXLyF3n4d40PASXEjZ-7dnIf4w4hf2P4L0xs_g",
"ttl": 86400
}
}
- Introspect a signed ID token:
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/identity/oidc/introspect" -d '{"client_id":"sts.amazonaws.com", "token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjJkMGI4YjlkLWYwNGQtNzFlYy1iNjc0LWM3MzU4NDMyYmM1YiJ9.eyJhdWQiOiJQNkNmQ3p5SHNRWTRwTWNBNmtXQU9DSXRBNyIsImV4cCI6MTU2MTQ4ODQxMiwiaWF0IjoxNTYxNDAyMDEyLCJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tOjEyMzQiLCJzdWIiOiI2YzY1ZWFmNy1kNGY0LTEzMzMtMDJiYy0xYzc1MjE5YzMxMDIifQ.IcbWTmks7P5eVtwmIBl5rL1B88MI55a9JJuYVLIlwE9aP_ilXpX5fE38CDm5PixDDVJb8TI2Q_FO4GMMH0ymHDO25ZvA917WcyHCSBGaQlgcS-WUL2fYTqFjSh-pezszaYBgPuGvH7hJjlTZO6g0LPCyUWat3zcRIjIQdXZum-OyhWAelQlveEL8sOG_ldyZ8v7fy7GXDxfJOK1kpw5AX9DXJKylbwZTBS8tLb-7edq8uZ0lNQyWy9VPEW_EEIZvGWy0AHua-Loa2l59GRRP8mPxuMYxH_c88x1lsSw0vH9E3rU8AXLyF3n4d40PASXEjZ-7dnIf4w4hf2P4L0xs_g"}'
Sample Response:
{
"active": true,
"iss": "https://10.1.1.45:8200/v1/identity/oidc",
"sub": "a2cd63d3-5364-406f-980e-8d71bb0692f5",
"aud": "SxSouteCYPBoaTFy94hFghmekos",
"iat": 1561411915,
"exp": 1561412215,
"userid": "bob",
"groups": ["$DOMAIN_ID"],
"arn-id": "arn:aws:iam:111122223333:role/myRole",
}
- Configure an AWS IAM role for Vault OIDC identity provider.
The following example AWS IAM trust policy limits acess to the defined vault identity group.
data "tls_certificate" "default" {
url = "https://vault.example.org"
}
resource "aws_iam_openid_connect_provider" "default" {
url = "https://vault.example.org"
client_id_list = ["aws.workload.identity"]
thumbprint_list = [data.tls_certificate.default.certificates.0.sha1_fingerprint]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::012345678910:oidc-provider/token.vault.company.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.vault.company.com:aud": "sts.amazonaws.com",
}
"ForAllValues:StringEquals": {
"token.vault.company.com:groups": [
"$DOMAIN_ID"
]
}
}
}
]
}
data "aws_iam_policy_document" "default" {
version = "2012-10-17"
statement {
sid = "FederatedTrustVaultOIDC"
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]
principals {
type = "Federated"
identifiers = tolist(aws_iam_openid_connect_provider.default.arn)
}
condition {
test = "StringEquals"
variable = "vault.example.com:aud"
values = ["sts.amazonaws.com"]
}
condition {
test = "ForAllValues:StringEquals"
variable = "vault.example.com:groups"
values = [var.domain_id]
}
}
}
resource "aws_iam_policy" "default" {
name = "FederatedOIDC"
path = "/"
policy = data.aws_iam_policy_document.default.json
}