https://github.com/0opsops/terraform-vault-secmgmt
Terraform module to manage HashiCorp Vault Secrets!
https://github.com/0opsops/terraform-vault-secmgmt
aws-assume-role aws-iam-user aws-secret-engine hashicorp-terraform hashicorp-vault jwt-auth k8s-auth kv-secret-engine kv-store oidc-auth vault-policies vault-roles
Last synced: 2 months ago
JSON representation
Terraform module to manage HashiCorp Vault Secrets!
- Host: GitHub
- URL: https://github.com/0opsops/terraform-vault-secmgmt
- Owner: 0opsops
- Created: 2022-05-29T09:55:30.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2024-06-16T13:51:58.000Z (12 months ago)
- Last Synced: 2025-02-09T14:38:29.298Z (4 months ago)
- Topics: aws-assume-role, aws-iam-user, aws-secret-engine, hashicorp-terraform, hashicorp-vault, jwt-auth, k8s-auth, kv-secret-engine, kv-store, oidc-auth, vault-policies, vault-roles
- Language: HCL
- Homepage: https://registry.terraform.io/modules/0opsops/secmgmt/vault/latest
- Size: 5.12 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Managing HashiCorp Vault Secrets with **Terraform**
## Multi Kubernetes clusters authentication and Multi AWS accounts `assumed_role` and Generating `IAM Users` for CI/CD purpose on the top of pre-existing Vault!
## [Just like this!](https://github.com/0opsops/terraform-vault-secmgmt/tree/main/examples#senario-brief)### Auth Methods
- USERPASS (UI)
- OIDC (UI)
- AWS
- JWT (GitLab, GitHub)
- KUBERNETES### Secrets Engines
- KV-V2
- AWS## THIS MODULE DOWNSIDE IS ALL SECRETS VALUES WOULD BE INSIDE `TERRAFORM.TFVARS` THAT AIN'T PRETTY GOOD AND REALLY HARD MANAGING SECRETS IN LARGE SCALE! (WELL.... WHATEVER... YOU KNOW VERY WELL WHAT YOU DOING!)
________________________________________________________________
## Requirements
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= v1.6.5 |
| [vault](#requirement\_vault) | >= 4.2.0 |## Providers
| Name | Version |
|------|---------|
| [vault](#provider\_vault) | >= 4.2.0 |## Modules
No modules.
## Resources
| Name | Type |
|------|------|
| [vault_auth_backend.kubernetes](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/auth_backend) | resource |
| [vault_auth_backend.this](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/auth_backend) | resource |
| [vault_auth_backend.user](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/auth_backend) | resource |
| [vault_auth_backend.userpass](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/auth_backend) | resource |
| [vault_aws_auth_backend_sts_role.this](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/aws_auth_backend_sts_role) | resource |
| [vault_aws_auth_backend_sts_role.user](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/aws_auth_backend_sts_role) | resource |
| [vault_aws_secret_backend.this](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/aws_secret_backend) | resource |
| [vault_aws_secret_backend.user](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/aws_secret_backend) | resource |
| [vault_aws_secret_backend_role.this](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/aws_secret_backend_role) | resource |
| [vault_aws_secret_backend_role.user](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/aws_secret_backend_role) | resource |
| [vault_generic_endpoint.users](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/generic_endpoint) | resource |
| [vault_identity_group.oidc](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/identity_group) | resource |
| [vault_identity_group_alias.oidc](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/identity_group_alias) | resource |
| [vault_jwt_auth_backend.gh](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/jwt_auth_backend) | resource |
| [vault_jwt_auth_backend.oidc](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/jwt_auth_backend) | resource |
| [vault_jwt_auth_backend.this](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/jwt_auth_backend) | resource |
| [vault_jwt_auth_backend_role.account](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/jwt_auth_backend_role) | resource |
| [vault_jwt_auth_backend_role.actions](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/jwt_auth_backend_role) | resource |
| [vault_jwt_auth_backend_role.actions_sec](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/jwt_auth_backend_role) | resource |
| [vault_jwt_auth_backend_role.oidc](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/jwt_auth_backend_role) | resource |
| [vault_jwt_auth_backend_role.secret](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/jwt_auth_backend_role) | resource |
| [vault_kubernetes_auth_backend_config.kubernetes](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/kubernetes_auth_backend_config) | resource |
| [vault_kubernetes_auth_backend_role.kubernetes](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/kubernetes_auth_backend_role) | resource |
| [vault_kv_secret_v2.this](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/kv_secret_v2) | resource |
| [vault_mount.this](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/mount) | resource |
| [vault_policy.this](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/policy) | resource |## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| [access\_key](#input\_access\_key) | AWS Assumed Role access key | `string` | `"ACCESS_KEY"` | no |
| [access\_key\_user](#input\_access\_key\_user) | AWS Access Key with necessary permissions | `string` | `"ACCESS_KEY"` | no |
| [auth\_backend\_role](#input\_auth\_backend\_role) | Role that will be used by Vault authenticating AWS |map(object({|
account_id = number
sts_role = string
})){| no |
"key": {
"account_id": 123456789012,
"sts_role": "arn:aws:iam::123456789012:role/ROLE_NAME"
}
}
| [auth\_backend\_role\_user](#input\_auth\_backend\_role\_user) | If enabled, This Role that will be used by Vault authenticating and performing necessary actions |map(object({|
account_id = number
sts_role = string
})){| no |
"key": {
"account_id": 13456789012,
"sts_role": "value"
}
}
| [aws\_auth\_path](#input\_aws\_auth\_path) | AWS Authentication Methods path | `string` | `"aws"` | no |
| [aws\_auth\_path\_user](#input\_aws\_auth\_path\_user) | AWS IAM user Authentication Methods path | `string` | `"account_b"` | no |
| [aws\_secret\_path](#input\_aws\_secret\_path) | AWS Secret Engine path for Assumed Role | `string` | `"aws"` | no |
| [aws\_secret\_path\_user](#input\_aws\_secret\_path\_user) | AWS Secret engine path for IAM User | `string` | `"account_b"` | no |
| [bound\_issuer](#input\_bound\_issuer) | The value against which to match the iss claim in a JWT | `string` | `"gitlab.com"` | no |
| [create\_auth\_backend\_role](#input\_create\_auth\_backend\_role) | Enable STS role or not for Vault | `bool` | `false` | no |
| [create\_auth\_backend\_role\_user](#input\_create\_auth\_backend\_role\_user) | Enable STS role or not on Vault | `bool` | `false` | no |
| [create\_aws\_auth\_backend](#input\_create\_aws\_auth\_backend) | Enable AWS Auth method or not | `bool` | n/a | yes |
| [create\_aws\_auth\_backend\_user](#input\_create\_aws\_auth\_backend\_user) | Enable AWS Auth method or not | `bool` | n/a | yes |
| [create\_aws\_secret\_backend](#input\_create\_aws\_secret\_backend) | Enable AWS Secret Method or not for Vault | `bool` | `false` | no |
| [create\_aws\_secret\_backend\_user](#input\_create\_aws\_secret\_backend\_user) | Vault Enable AWS Secret Method or not | `bool` | `false` | no |
| [create\_gh\_acc\_role](#input\_create\_gh\_acc\_role) | Enable Account Role for GitHub JWT Auth Method | `bool` | n/a | yes |
| [create\_gh\_secret\_role](#input\_create\_gh\_secret\_role) | For GHA, Enable Secrets JWT Auth Method Role or not | `bool` | n/a | yes |
| [create\_gl\_acc\_role](#input\_create\_gl\_acc\_role) | Enable Account Role for GitHub JWT Auth Method | `bool` | n/a | yes |
| [create\_gl\_secret\_role](#input\_create\_gl\_secret\_role) | For GitLab, Enable Secrets JWT Auth Method Role or not | `bool` | n/a | yes |
| [create\_k8s](#input\_create\_k8s) | Enable Kubernetes Auth Method or not | `bool` | n/a | yes |
| [create\_kv\_engine](#input\_create\_kv\_engine) | Enable KV version 2 secret engine | `bool` | n/a | yes |
| [create\_kv\_v2](#input\_create\_kv\_v2) | Create KV Version 2 Secrets | `bool` | n/a | yes |
| [create\_policy](#input\_create\_policy) | Enable Vault policy or not | `bool` | n/a | yes |
| [create\_secret\_backend\_role](#input\_create\_secret\_backend\_role) | Enable a role on an AWS Secret Method or not for Vault | `bool` | `false` | no |
| [create\_secret\_backend\_role\_user](#input\_create\_secret\_backend\_role\_user) | Enable a role on an AWS Secret Method for Vault | `bool` | `false` | no |
| [create\_userpass](#input\_create\_userpass) | Authenticate Vault with Username/Password | `bool` | n/a | yes |
| [credential\_type](#input\_credential\_type) | AWS STS Assumed Role type | `string` | `"assumed_role"` | no |
| [credential\_type\_user](#input\_credential\_type\_user) | AWS IAM User type | `string` | `"iam_user"` | no |
| [default\_ttl\_aws](#input\_default\_ttl\_aws) | Default Time To Live for Assumed role | `string` | `1800` | no |
| [default\_ttl\_gh\_jwt](#input\_default\_ttl\_gh\_jwt) | Default Time To Live | `string` | `"1h"` | no |
| [default\_ttl\_gl\_jwt](#input\_default\_ttl\_gl\_jwt) | Default Time To Live | `string` | `"1h"` | no |
| [default\_ttl\_user](#input\_default\_ttl\_user) | Default Time To Live for AWS temporary account | `number` | `2700` | no |
| [delete\_version\_after](#input\_delete\_version\_after) | Old secrets version will be deleted after this seconds (7 days) | `number` | `604800` | no |
| [enabled\_gh\_jwt\_backend](#input\_enabled\_gh\_jwt\_backend) | Enable GitHub JWT Auth Method or not | `bool` | n/a | yes |
| [enabled\_gl\_jwt\_backend](#input\_enabled\_gl\_jwt\_backend) | Enable GitLab JWT Auth Method or not | `bool` | n/a | yes |
| [enabled\_oidc\_backend](#input\_enabled\_oidc\_backend) | Enable OIDC Auth Method or not | `bool` | n/a | yes |
| [gh\_acc\_bound\_aud](#input\_gh\_acc\_bound\_aud) | URL of the repository owner, eg: `https://github.com/OWNER`, such as the organization that owns the repository. This is the only claim that can be customized | `list(string)` |[| no |
""
]
| [gh\_acc\_bound\_claims](#input\_gh\_acc\_bound\_claims) | https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#understanding-the-oidc-token |map(object({|
role_name = string
bound_claims = optional(map(string))
token_ttl = number
token_max_ttl = number
})){| no |
"key1": {
"bound_claims": {
"": ""
},
"role_name": "value",
"token_max_ttl": 600,
"token_ttl": 300
}
}
| [gh\_acc\_bound\_sub](#input\_gh\_acc\_bound\_sub) | Defines the subject claim that is to be validated by the cloud provider | `string` | `""` | no |
| [gh\_acc\_token\_policies](#input\_gh\_acc\_token\_policies) | Vault policy name to attach on AWS Auth Method Role | `list(string)` |[| no |
"default"
]
| [gh\_jwt\_path](#input\_gh\_jwt\_path) | GitHub JWT Authentication path | `string` | `"jwt-gh"` | no |
| [gh\_jwt\_token\_type](#input\_gh\_jwt\_token\_type) | `service` token or `batch` token? Default is `service` token | `string` | `"service"` | no |
| [gh\_secret\_bound\_aud](#input\_gh\_secret\_bound\_aud) | URL of the repository owner, eg: `https://github.com/OWNER`, such as the organization that owns the repository. This is the only claim that can be customized | `list(string)` |[| no |
""
]
| [gh\_secret\_bound\_claims](#input\_gh\_secret\_bound\_claims) | JWT/OIDC auth Method role for Secrets values in a Vault server |map(object({|
role_name = string
bound_claims = optional(map(string))
token_ttl = number
token_max_ttl = number
})){| no |
"key": {
"bound_claims": {
"": ""
},
"role_name": "value",
"token_max_ttl": 7200,
"token_ttl": 3600
}
}
| [gh\_secret\_bound\_sub](#input\_gh\_secret\_bound\_sub) | Defines the subject claim that is to be validated by the cloud provider | `string` | `""` | no |
| [gh\_secret\_token\_policies](#input\_gh\_secret\_token\_policies) | Secrets policy name | `list(string)` |[| no |
"default"
]
| [gl\_acc\_bound\_claims](#input\_gl\_acc\_bound\_claims) | JWT/OIDC auth Method role for AWS Account in a Vault server |map(object({|
role_name = string
bound_claims = map(string)
bound_claims_type = string
})){| no |
"key": {
"bound_claims": {
"project_id": "12312312",
"ref": "main,develop",
"ref_type": "branch"
},
"bound_claims_type": "glob",
"role_name": "ROLE_NAME"
}
}
| [gl\_acc\_token\_policies](#input\_gl\_acc\_token\_policies) | Vault policy name to attach on AWS Auth Method Role | `list(string)` |[| no |
"account_b"
]
| [gl\_jwt\_path](#input\_gl\_jwt\_path) | GitLab JWT Authentication path | `string` | `"jwt-gl"` | no |
| [gl\_jwt\_token\_type](#input\_gl\_jwt\_token\_type) | `service` token or `batch` token? Default is `service` token | `string` | `"service"` | no |
| [gl\_secret\_bound\_claims](#input\_gl\_secret\_bound\_claims) | JWT/OIDC auth Method role for Secrets values in a Vault server |map(object({|
role_name = string
bound_claims = map(string)
})){| no |
"key": {
"bound_claims": {
"project_id": "123123",
"ref": "main,develop",
"ref_type": "branch"
},
"role_name": "reader-role"
}
}
| [gl\_secret\_token\_policies](#input\_gl\_secret\_token\_policies) | Secrets policy name | `list(string)` |[| no |
"read-acc_b_creds"
]
| [k8s\_config](#input\_k8s\_config) | Kubernetes Auth Backend configuration |map(object({|
backend = string
kubernetes_host = string
kubernetes_ca_cert = string
token_reviewer_jwt = string
issuer = string
})){| no |
"dev-k8s": {
"backend": "dev-k8s",
"issuer": "https://kubernetes.default.svc.cluster.local",
"kubernetes_ca_cert": "-----BEGIN CERTIFICATE-----\nASDFQWERQWERASDFASDQ@#RDFADFASDF\n-----END CERTIFICATE-----",
"kubernetes_host": "https://K8S_HOST_ADDR:6443",
"token_reviewer_jwt": "eyJhbGciOiJSUzI1NiIJASiadura56tIsImtpZCI6InRreml3.ASDFASOIDJFASDKLFLASDF"
}
}
| [k8s\_path](#input\_k8s\_path) | Kubernetes Authentication path (Support multi clusters with different paths) |map(object({|
path = string
})){| no |
"dev-k8s": {
"path": "dev-k8s"
}
}
| [k8s\_role](#input\_k8s\_role) | Kubernetes role to authenticate Vault |map(object({|
role_name = string
backend = string
bound_service_account_names = list(string)
bound_service_account_namespaces = list(string)
token_policies = list(string)
token_ttl_k8s = number
})){| no |
"dev-k8s": {
"backend": "dev-k8s",
"bound_service_account_names": [
"dev-k8s"
],
"bound_service_account_namespaces": [
"default"
],
"role_name": "dev-k8s",
"token_policies": [
"default"
],
"token_ttl_k8s": 3600
}
}
| [kv\_v2](#input\_kv\_v2) | Key/Value store |map(object({|
sub_path = string
disable_read = bool
delete_all_versions = bool
data_json = any
})){| no |
"key1": {
"data_json": " {\n \"key1\": \"value1\"\n }\n",
"delete_all_versions": true,
"disable_read": false,
"sub_path": "path1"
},
"key2": {
"data_json": " {\n \"key2\": \"value2\"\n }\n",
"delete_all_versions": true,
"disable_read": false,
"sub_path": "path2"
}
}
| [kv\_v2\_description](#input\_kv\_v2\_description) | Just a description | `string` | `"Mount path of KV-V2 secret engine"` | no |
| [kv\_v2\_path](#input\_kv\_v2\_path) | KV-V2 secret engine path | `string` | `"infra"` | no |
| [max\_ttl\_aws](#input\_max\_ttl\_aws) | Maximum Time To Live for Assumed role | `string` | `3600` | no |
| [max\_ttl\_gh\_jwt](#input\_max\_ttl\_gh\_jwt) | Maximum Time To Live | `string` | `"2h"` | no |
| [max\_ttl\_gl\_jwt](#input\_max\_ttl\_gl\_jwt) | Maximum Time To Live | `string` | `"2h"` | no |
| [max\_ttl\_user](#input\_max\_ttl\_user) | Maximum Time To Live for AWS temporary account | `number` | `3600` | no |
| [max\_versions](#input\_max\_versions) | Maximum versions of the secrets | `number` | `100` | no |
| [oidc\_alias](#input\_oidc\_alias) | Name of the OIDC group alias |map(object({|
group_alias_name = string
})){| no |
"gmail": {
"group_alias_name": "gmail"
}
}
| [oidc\_auth\_path](#input\_oidc\_auth\_path) | OIDC mount path |map(object({|
oidc_path = string
oidc_role = string
oidc_discovery_url = string
oidc_client_id = string
oidc_client_sec = string
})){| no |
"gmail": {
"oidc_client_id": "123456789012-5k3hfs5kvc1h82kjkar895ir6118io4bra8q.apps.googleusercontent.com",
"oidc_client_sec": "ASDFDF-xRG_MCY1Ulkr8Ke0cBU87yr_XDKR",
"oidc_discovery_url": "https://accounts.google.com",
"oidc_path": "oidc",
"oidc_role": "gmail"
}
}
| [oidc\_backend\_role](#input\_oidc\_backend\_role) | OIDC role to login to Vault |map(object({|
oidc_role_name = string
oidc_user_claim = string
oidc_token_type = string
oidc_scopes = list(string)
allowed_redirect_uris = list(string)
oidc_token_policies = list(string)
})){| no |
"gmail": {
"allowed_redirect_uris": [
"http://127.0.0.1:8250/oidc/callback",
"http://127.0.0.1:8200/ui/vault/auth/oidc/oidc/callback"
],
"oidc_role_name": "gmail",
"oidc_scopes": [
"openid",
"email"
],
"oidc_token_policies": [
"reader"
],
"oidc_token_type": "service",
"oidc_user_claim": "email"
}
}
| [oidc\_identity\_group](#input\_oidc\_identity\_group) | n/a |map(object({|
oidc_identity_group_name = string
oidc_identity_type = string
oidc_identity_group_policies = list(string)
tags = map(string)
})){| no |
"gmail": {
"oidc_identity_group_name": "gmail",
"oidc_identity_group_policies": [
"reader"
],
"oidc_identity_type": "external",
"tags": {
"Organization": "OSS"
}
}
}
| [region](#input\_region) | Region that Vault residing | `string` | `"us-east-1"` | no |
| [region\_user](#input\_region\_user) | Region that Vault residing | `string` | `"us-east-1"` | no |
| [secret\_backend\_role](#input\_secret\_backend\_role) | Create and use STS Assumed Role by Vault performing necessary actions respectively |map(object({|
name = string
role_arns = list(string)
})){| no |
"key": {
"name": "aws",
"role_arns": [
"arn:aws:iam::123456789012:role/ROLE_NAME"
]
}
}
| [secret\_backend\_role\_user](#input\_secret\_backend\_role\_user) | IAM User with defined IAM permission policy respectively |map(object({|
name = string
policy_document = any
})){| no |
"key": {
"name": "value",
"policy_document": {}
}
}
| [secret\_key](#input\_secret\_key) | AWS Assumed Role User secret key | `string` | `"SECRET_KEY"` | no |
| [secret\_key\_user](#input\_secret\_key\_user) | AWS Secret Key with necessary permissions | `string` | `"SECRET_KEY"` | no |
| [userpass\_path](#input\_userpass\_path) | Mount path for `Userpass` auth method | `string` | `"userpass"` | no |
| [users\_path](#input\_users\_path) | The full logical path with `username` suffix |map(object({|
path = string
data_json = any
})){| no |
"user1": {
"data_json": " {\n \"policies\": [\"POLICY\"],\n \"password\": \"PASSWORD\"\n }\n",
"path": "auth/userpass/users/USERNAME"
}
}
| [vault\_policy](#input\_vault\_policy) | Policy to read secret by path |map(object({|
name = string
policy = any
})){| no |
"key1": {
"name": "reader",
"policy": " ## Policy for only reading secrets in this path\n path \"tfvars/data/*\"\n {\n capabilities = [\"read\"]\n }\n"
}
}## Outputs
No outputs.