Merge pull request 'neoloc/terraformvault' (#1) from neoloc/terraformvault into master

Reviewed-on: https://git.query.consul/unkin/terraform-vault/pulls/1
This commit is contained in:
Ben Vincent 2024-09-26 23:06:26 +10:00
commit 9e3cbce264
45 changed files with 551 additions and 1 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.terraform
.terraform.lock.hcl
env

View File

@ -1,3 +1,37 @@
# terraform-vault # terraform-vault
A repository to manage the configuration of Vault secret engines, authentication modes and policies. A repository to manage the configuration of Vault secret engines, authentication modes and policies.
# Usage
1. Initialize Terraform
Once you have your backend block configured, you need to initialize your Terraform working directory to configure the backend:
```bash
terraform init
```
This command initializes the backend and checks the connection to Consul. If everything is set up correctly, Terraform will start using Consul as its backend for storing the state.
2. Common terraform init Errors
If you encounter errors while running terraform init, check the following:
Consul server is reachable: Make sure that the address is correct and that you can connect to the Consul server.
Consul token (if using ACLs): Verify that the token has the correct permissions to write to the specified path in the Consul KV store.
3. Example Consul KV Structure
In Consul, the state file will be stored in the KV store under the specified path:
```bash
terraform/state
```
You can check the Consul KV store by accessing the Consul UI or using the consul kv command to see the stored Terraform state:
```bash
consul kv get terraform/state
```

View File

@ -0,0 +1,14 @@
resource "vault_approle_auth_backend_role" "certmanager" {
role_name = "certmanager"
bind_secret_id = false
token_policies = ["certmanager"]
token_ttl = 30
token_max_ttl = 30
token_bound_cidrs = [
"198.18.17.3/32",
"198.18.13.32/32",
"198.18.13.33/32",
"198.18.13.34/32",
"198.18.13.46/32"
]
}

View File

@ -0,0 +1,9 @@
resource "vault_approle_auth_backend_role" "rundeck-role" {
role_name = "rundeck-role"
bind_secret_id = true
token_policies = ["rundeck"]
token_ttl = 1 * 3600
token_max_ttl = 4 * 3600
token_bound_cidrs = ["198.18.13.59/32"]
secret_id_bound_cidrs = ["198.18.13.59/32"]
}

View File

@ -0,0 +1,14 @@
resource "vault_approle_auth_backend_role" "sshsign-host-role" {
role_name = "sshsign-host-role"
bind_secret_id = false
token_policies = ["sshsign-host-policy"]
token_ttl = 30
token_max_ttl = 30
token_bound_cidrs = [
"198.18.17.3/32",
"198.18.13.32/32",
"198.18.13.33/32",
"198.18.13.34/32",
"198.18.13.46/32"
]
}

17
auth_approle_sshsigner.tf Normal file
View File

@ -0,0 +1,17 @@
resource "vault_approle_auth_backend_role" "sshsigner" {
role_name = "sshsigner"
bind_secret_id = false
token_policies = [
"sshsigner",
"sshca_signhost"
]
token_ttl = 30
token_max_ttl = 30
token_bound_cidrs = [
"198.18.17.3/32",
"198.18.13.32/32",
"198.18.13.33/32",
"198.18.13.34/32",
"198.18.13.46/32"
]
}

27
auth_approle_tf_vault.tf Normal file
View File

@ -0,0 +1,27 @@
resource "vault_approle_auth_backend_role" "tf_vault" {
role_name = "tf_vault"
bind_secret_id = false
token_policies = [
"default_access",
"auth_token_create",
"auth_token_self",
"auth_token_roles_admin",
"approle_role_admin",
"approle_role_login",
"approle_token_create",
"ldap_admin",
"pki_int_roles_admin",
"pki_root_roles_admin",
"ssh-host-signer_roles_admin",
"sshca_roles_admin",
"svc_vault_read",
"sys_auth_admin",
"sys_mounts_admin",
"sys_policy_admin",
]
token_ttl = 60
token_max_ttl = 120
token_bound_cidrs = [
"10.10.12.200/32",
]
}

7
auth_backend_approle.tf Normal file
View File

@ -0,0 +1,7 @@
#----------------------------
# Enable approle auth method
#----------------------------
resource "vault_auth_backend" "approle" {
type = "approle"
path = "approle"
}

31
auth_backend_ldap.tf Normal file
View File

@ -0,0 +1,31 @@
#--------------------------------
# Enable ldap auth method
#--------------------------------
# retrieve the bindpass from Vault
data "vault_generic_secret" "svc_vault" {
path = "kv/service/glauth/services/svc_vault"
}
# create the ldap backend
resource "vault_ldap_auth_backend" "ldap" {
path = "ldap"
url = "ldap://ldap.service.consul"
userdn = "ou=people,ou=users,dc=main,dc=unkin,dc=net"
userattr = "uid"
upndomain = "users.main.unkin.net"
discoverdn = false
groupdn = "ou=users,dc=main,dc=unkin,dc=net"
groupfilter = "(&(objectClass=posixGroup)(memberUid={{.Username}}))"
groupattr = "uid"
binddn = data.vault_generic_secret.svc_vault.data["distinguishedName"]
bindpass = data.vault_generic_secret.svc_vault.data["pass"]
}
resource "vault_ldap_auth_backend_group" "vault_access" {
groupname = "vault_access"
policies = [
"default_access",
]
backend = vault_ldap_auth_backend.ldap.path
}

15
engine_kv.tf Normal file
View File

@ -0,0 +1,15 @@
#--------------------------------------------------------------
# kv
# create engine
#--------------------------------------------------------------
resource "vault_mount" "kv" {
path = "kv"
type = "kv"
listing_visibility = "hidden"
max_lease_ttl_seconds = 0
external_entropy_access = false
seal_wrap = false
options = {
version = "2"
}
}

49
engine_pki_int.tf Normal file
View File

@ -0,0 +1,49 @@
#--------------------------------------------------------------
# pki_int
# create engine
# generate intermediate csa
# sign the intermediate against rootca
# set the signed intermediate cert in the pki_int engine
#--------------------------------------------------------------
resource "vault_mount" "pki_int" {
path = "pki_int"
type = "pki"
description = "PKI Intermediate CA"
max_lease_ttl_seconds = 43800 * 3600 # 43800 hours
}
## Generate the intermediate CSR
#resource "vault_pki_secret_backend_intermediate_cert_request" "pki_int_intermediate" {
# backend = vault_mount.pki_int.path
# common_name = "unkin.net Intermediate Authority"
# format = "pem"
# type = "internal"
#}
#
## Sign the intermediate CSR using the root CA
#resource "vault_generic_endpoint" "pki_root_sign_intermediate" {
# path = "${vault_mount.pki_root.path}/root/sign-intermediate"
#
# data_json = jsonencode({
# csr = vault_pki_secret_backend_intermediate_cert_request.pki_int_intermediate.csr,
# format = "pem_bundle",
# ttl = "43800h",
# issuer_ref = "UNKIN_ROOTCA_2024"
# })
#}
#
## Decode the certificate from the response
#locals {
# intermediate_signed_cert = vault_generic_endpoint.pki_root_sign_intermediate.write_data["certificate"]
#}
#
## Set the signed intermediate certificate
#resource "vault_pki_secret_backend_intermediate_set_signed" "pki_int_set_signed" {
# backend = vault_mount.pki_int.path
# certificate = local.intermediate_signed_cert
#}
#data "vault_pki_secret_backend_issuer" "pki_int_issuer" {
# backend = vault_mount.pki_int.path
# issuer_ref = data.vault_pki_secret_backend_root_cert.root.issuer_id
#}

39
engine_pki_root.tf Normal file
View File

@ -0,0 +1,39 @@
#-------------------------------------------
# pki_root:
# create engine
# generate rootca certificate
# read the issuer
# configure the pki urls
#-------------------------------------------
resource "vault_mount" "pki_root" {
path = "pki_root"
type = "pki"
description = "PKI Root CA"
max_lease_ttl_seconds = 87600 * 3600 # 87600h
}
#resource "vault_pki_secret_backend_root_cert" "pki_root_root_cert" {
# backend = vault_mount.pki_root.path
# common_name = "unkin.net"
# issuer_name = "UNKIN_ROOTCA_2024"
# ttl = 87600 * 3600
# format = "pem"
# type = "internal"
#}
#
#output "root_certificate" {
# value = vault_pki_secret_backend_root_cert.pki_root_root_cert.certificate
# sensitive = true
#}
data "vault_pki_secret_backend_issuer" "pki_root_issuer" {
backend = vault_mount.pki_root.path
issuer_ref = "default"
}
resource "vault_pki_secret_backend_config_urls" "pki_root_urls" {
backend = vault_mount.pki_root.path
issuing_certificates = ["${local.vault_addr}/v1/pki_root/ca"]
crl_distribution_points = ["${local.vault_addr}/v1/pki_root/crl"]
}

14
engine_rundeck.tf Normal file
View File

@ -0,0 +1,14 @@
#--------------------------------------------------------------
# rundeck
# create engine
#--------------------------------------------------------------
resource "vault_mount" "rundeck" {
path = "rundeck"
type = "kv"
max_lease_ttl_seconds = 0
external_entropy_access = false
seal_wrap = false
options = {
version = "2"
}
}

18
engine_ssh-host-signer.tf Normal file
View File

@ -0,0 +1,18 @@
#--------------------------------------------------------------
# ssh-host-signer
# create engine
# generate ca cert
# tune the ssh engine
#--------------------------------------------------------------
#resource "vault_mount" "ssh_host_signer" {
# path = "ssh-host-signer"
# type = "ssh"
# description = "SSH Host Signing Engine"
# max_lease_ttl_seconds = 87600 * 3600
#}
#
#resource "vault_ssh_secret_backend_ca" "ssh_host_signer_ca" {
# backend = vault_mount.ssh_host_signer.path
# generate_signing_key = false # change to true for new configuration
# key_type = "ssh-rsa"
#}

18
engine_sshca.tf Normal file
View File

@ -0,0 +1,18 @@
#--------------------------------------------------------------
# ssh
# create engine
# generate ca cert
# tune the ssh engine
#--------------------------------------------------------------
resource "vault_mount" "sshca" {
path = "sshca"
type = "ssh"
description = "SSH CA Engine"
max_lease_ttl_seconds = 87600 * 3600
}
resource "vault_ssh_secret_backend_ca" "ssh_ca" {
backend = vault_mount.sshca.path
generate_signing_key = true
key_type = "ssh-rsa"
}

31
main.tf Normal file
View File

@ -0,0 +1,31 @@
#-------------------------------------------
# locals
#-------------------------------------------
locals {
vault_addr = "https://vault.service.consul:8200"
}
#-----------------------------------------------------------------------------
# Configure this provider through the environment variables:
# - VAULT_ADDR
# - VAULT_TOKEN
#-----------------------------------------------------------------------------
provider "vault" {
address = local.vault_addr
}
#------------------------------------------------------------------------------
# Use remote state file and encrypt it since your state files may contains
# sensitive data.
# export CONSUL_HTTP_TOKEN=<your-token>
#------------------------------------------------------------------------------
terraform {
backend "consul" {
address = "https://consul.service.consul"
path = "infra/terraform/state"
scheme = "https"
lock = true
ca_file = "/etc/pki/tls/certs/ca-bundle.crt"
}
}

36
policies.tf Normal file
View File

@ -0,0 +1,36 @@
# Define a list of directories that contain policy files
locals {
policy_directories = [
"policies",
"policies/sys",
"policies/auth/approle",
"policies/auth/ldap",
"policies/auth/token",
"policies/pki_int",
"policies/pki_root",
"policies/rundeck",
"policies/ssh-host-signer",
"policies/sshca",
"policies/kv/service/glauth/services"
]
}
# Load policy files from each directory
locals {
policy_files = flatten([
for path in local.policy_directories : [
for policy in fileset(path, "*.hcl") : {
name = trim(replace(policy, ".hcl", ""), "/")
path = "${path}/${policy}"
}
]
])
}
# Define Vault policies for all listed directories
resource "vault_policy" "policies" {
for_each = { for policy in local.policy_files : policy.name => policy }
name = each.value.name
policy = file(each.value.path)
}

View File

@ -0,0 +1,3 @@
path "auth/approle/role/*" {
capabilities = ["create", "update", "read", "delete", "list"]
}

View File

@ -0,0 +1,3 @@
path "auth/approle/login" {
capabilities = ["create"]
}

View File

@ -0,0 +1,3 @@
path "auth/ldap/*" {
capabilities = ["create", "update", "read", "delete", "list"]
}

View File

@ -0,0 +1,7 @@
path "auth/token/create" {
capabilities = ["create", "read", "update", "list"]
}
path "auth/token/*" {
capabilities = ["create", "update"]
}

View File

@ -0,0 +1,4 @@
# Allow listing and reading tokens
path "auth/token/lookup" {
capabilities = ["read", "list"]
}

View File

@ -0,0 +1,4 @@
# Allow renewing tokens
path "auth/token/renew" {
capabilities = ["update"]
}

View File

@ -0,0 +1,3 @@
path "auth/token/roles/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}

View File

@ -0,0 +1,14 @@
# Allow tokens to query themselves
path "auth/token/lookup-self" {
capabilities = ["read"]
}
# Allow tokens to renew themselves
path "auth/token/renew-self" {
capabilities = ["update"]
}
# Allow tokens to revoke themselves
path "auth/token/revoke-self" {
capabilities = ["update"]
}

View File

@ -0,0 +1,15 @@
path "pki_int/*" {
capabilities = ["list", "read"]
}
path "pki_root/*" {
capabilities = ["list", "read"]
}
path "ssh-host-signer/*" {
capabilities = ["list", "read"]
}
path "sshca/*" {
capabilities = ["list", "read"]
}

View File

@ -0,0 +1,3 @@
path "kv/data/service/glauth/services/svc_vault" {
capabilities = ["list", "read"]
}

View File

@ -0,0 +1,9 @@
path "pki_int/issue/*" {
capabilities = ["create", "update", "read"]
}
path "pki_int/renew/*" {
capabilities = ["update"]
}
path "pki_int/cert/*" {
capabilities = ["read"]
}

View File

@ -0,0 +1,3 @@
path "pki_int/roles/*" {
capabilities = ["create", "update", "read", "delete", "list"]
}

View File

@ -0,0 +1,3 @@
path "pki_root/roles/*" {
capabilities = ["create", "update", "read", "delete", "list"]
}

View File

@ -0,0 +1,7 @@
path "rundeck/data/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "rundeck/metadata/*" {
capabilities = ["list"]
}

View File

@ -0,0 +1,3 @@
path "ssh-host-signer/roles/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}

View File

@ -0,0 +1,3 @@
path "ssh-host-signer/sign/hostrole" {
capabilities = ["create", "update"]
}

View File

@ -0,0 +1,3 @@
path "ssh-host-signer/sign/hostrole" {
capabilities = ["create", "update"]
}

View File

@ -0,0 +1,3 @@
path "sshca/roles/*" {
capabilities = ["create", "update", "read", "delete", "list"]
}

View File

@ -0,0 +1,3 @@
path "sshca/sign/host" {
capabilities = ["create", "update"]
}

View File

@ -0,0 +1,3 @@
path "sshca/sign/user" {
capabilities = ["create", "update"]
}

View File

@ -0,0 +1,4 @@
# Allow reading audit logs related to secret engines
path "sys/audit" {
capabilities = ["read", "list"]
}

View File

@ -0,0 +1,4 @@
# Allow creating and management of authentication backends (AppRole, LDAP, etc.)
path "sys/auth/*" {
capabilities = ["create", "update", "delete", "read", "list"]
}

View File

@ -0,0 +1,14 @@
# Allow access to manage secret engines (mount, unmount, update)
path "sys/mounts/*" {
capabilities = ["create", "update", "delete", "read", "list"]
}
# Allow tuning existing secret engines
path "sys/mounts-tune/*" {
capabilities = ["update", "read"]
}
# Allow reaing and listing of enabled secret engines
path "sys/mounts" {
capabilities = ["read", "list"]
}

View File

@ -0,0 +1,9 @@
# Allow management of policies (create, update, delete, list, and read)
path "sys/policies/acl/*" {
capabilities = ["create", "update", "delete", "read", "list"]
}
# Allow listing of available policies
path "sys/policies/acl" {
capabilities = ["read", "list"]
}

View File

@ -0,0 +1,15 @@
resource "vault_pki_secret_backend_role" "servers_default" {
backend = "pki_int"
name = "servers_default"
#issuer_ref = data.vault_pki_secret_backend_issuer.pki_int_issuer.default
allow_ip_sans = true
allowed_domains = ["unkin.net", "*.unkin.net", "localhost"]
allow_subdomains = true
allow_glob_domains = true
allow_bare_domains = true
enforce_hostnames = true
allow_any_name = true
max_ttl = 2160 * 3600
key_bits = 4096
country = ["Australia"]
}

View File

@ -0,0 +1,6 @@
resource "vault_pki_secret_backend_role" "pki_root_2024_servers" {
backend = vault_mount.pki_root.path
name = "2024-servers"
issuer_ref = data.vault_pki_secret_backend_issuer.pki_root_issuer.issuer_ref
allow_any_name = true
}

View File

@ -0,0 +1,11 @@
resource "vault_ssh_secret_backend_role" "hostrole" {
backend = "ssh-host-signer"
name = "hostrole"
key_type = "ca"
algorithm_signer = "rsa-sha2-256"
ttl = 87600 * 3600
allow_host_certificates = true
allowed_domains = "*"
allow_subdomains = true
allow_bare_domains = false
}

12
role_sshca_signhost.tf Normal file
View File

@ -0,0 +1,12 @@
resource "vault_ssh_secret_backend_role" "sshca_signhost" {
backend = vault_mount.sshca.path
name = "sshca_signhost"
key_type = "ca"
algorithm_signer = "rsa-sha2-256"
ttl = 87600 * 3600
allow_host_certificates = true
allow_subdomains = true
allow_bare_domains = false
allowed_domains = "main.unkin.net,consul"
}