feat: major restructuring in migration to terragrunt

- migrate from individual terraform files to config-driven terragrunt module structure
- add vault_cluster module with config discovery system
- replace individual .tf files with centralized config.hcl
- restructure auth and secret backends as configurable modules
- move auth roles and secret backends to yaml-based configuration
- convert policies from .hcl to .yaml format, add rules/auth definition
- add pre-commit hooks for yaml formatting and file cleanup
- add terragrunt cache to gitignore
- update makefile with terragrunt commands and format target
This commit is contained in:
2026-01-04 23:31:42 +11:00
parent bd112181f5
commit 8070b6f66b
245 changed files with 3943 additions and 985 deletions
@@ -0,0 +1,11 @@
resource "vault_auth_backend" "approle" {
type = "approle"
path = var.path
tune {
default_lease_ttl = var.default_lease_ttl
max_lease_ttl = var.max_lease_ttl
listing_visibility = var.listing_visibility
}
}
@@ -0,0 +1,4 @@
output "backend" {
description = "The created auth backend"
value = vault_auth_backend.approle
}
@@ -0,0 +1,37 @@
variable "country" {
description = "Country identifier"
type = string
}
variable "region" {
description = "Region identifier"
type = string
}
variable "path" {
description = "Mount path of the AppRole auth backend"
type = string
default = "approle"
}
variable "listing_visibility" {
description = "Specifies whether to show this mount in the UI-specific listing endpoint. Valid values are 'unauth' or 'hidden'"
type = string
default = null
validation {
condition = var.listing_visibility == null || contains(["unauth", "hidden"], var.listing_visibility)
error_message = "listing_visibility must be either 'unauth' or 'hidden'."
}
}
variable "default_lease_ttl" {
description = "Specifies the default time-to-live. If set, this overrides the global default. Must be a valid duration string"
type = string
default = null
}
variable "max_lease_ttl" {
description = "Specifies the maximum time-to-live. If set, this overrides the global default. Must be a valid duration string"
type = string
default = null
}
@@ -0,0 +1,36 @@
# Expected keys in KV secret for salt: salt
data "vault_kv_secret_v2" "salt_config" {
mount = "kv"
name = "service/vault/${var.country}/${var.region}/auth_backend/${var.mount_path}"
}
# Expected keys in KV secret for role_id: role_id (when use_deterministic_role_id = false)
data "vault_kv_secret_v2" "role_config" {
count = var.use_deterministic_role_id ? 0 : 1
mount = "kv"
name = "service/vault/${var.country}/${var.region}/auth_approle_role/${var.mount_path}/${var.approle_name}"
}
locals {
salt = data.vault_kv_secret_v2.salt_config.data["salt"]
role_id_input = "${local.salt}-${var.approle_name}-${var.mount_path}"
deterministic_role_id = uuidv5("dns", "${local.role_id_input}")
# Use deterministic role-id by default, or read from KV if specified
role_id = var.use_deterministic_role_id ? local.deterministic_role_id : data.vault_kv_secret_v2.role_config[0].data["role_id"]
}
resource "vault_approle_auth_backend_role" "role" {
backend = var.mount_path
role_name = var.approle_name
role_id = local.role_id
token_policies = var.token_policies
token_ttl = var.token_ttl
token_max_ttl = var.token_max_ttl
bind_secret_id = var.bind_secret_id
secret_id_ttl = var.secret_id_ttl
token_bound_cidrs = var.token_bound_cidrs
alias_metadata = var.alias_metadata
}
@@ -0,0 +1,68 @@
variable "country" {
description = "Country identifier"
type = string
}
variable "region" {
description = "Region identifier"
type = string
}
variable "approle_name" {
description = "Name of the AppRole role"
type = string
}
variable "mount_path" {
description = "Mount path of the AppRole auth backend"
type = string
default = "approle"
}
variable "token_policies" {
description = "List of policies to assign to the role (passed from policy_auth_map)"
type = list(string)
}
variable "token_ttl" {
description = "The TTL period of tokens issued using this role"
type = number
default = null
}
variable "token_max_ttl" {
description = "The maximum TTL period of tokens issued using this role"
type = number
default = null
}
variable "bind_secret_id" {
description = "Whether or not to require secret_id to be presented when logging in using this AppRole"
type = bool
default = false
}
variable "secret_id_ttl" {
description = "The TTL period of SecretIDs generated against this AppRole"
type = number
default = null
}
variable "token_bound_cidrs" {
description = "List of CIDR blocks that can authenticate using this role"
type = list(string)
default = []
}
variable "alias_metadata" {
description = "The metadata to be tied to generated entity alias. This should be a list or map containing the metadata in key value pairs"
type = map(string)
default = null
}
variable "use_deterministic_role_id" {
description = "Whether to use deterministic role-id generation (true) or read pre-generated role-id from KV (false)"
type = bool
default = true
}
@@ -0,0 +1,25 @@
# Expected keys in KV secret: kubernetes_ca_cert, token_reviewer_jwt
data "vault_kv_secret_v2" "auth_backend_config" {
mount = "kv"
name = "service/vault/${var.country}/${var.region}/auth_backend/${var.path}"
}
resource "vault_auth_backend" "kubernetes" {
type = "kubernetes"
path = var.path
tune {
default_lease_ttl = var.default_lease_ttl
max_lease_ttl = var.max_lease_ttl
listing_visibility = var.listing_visibility
}
}
resource "vault_kubernetes_auth_backend_config" "config" {
backend = vault_auth_backend.kubernetes.path
kubernetes_host = var.kubernetes_host
kubernetes_ca_cert = data.vault_kv_secret_v2.auth_backend_config.data["kubernetes_ca_cert"]
token_reviewer_jwt = data.vault_kv_secret_v2.auth_backend_config.data["token_reviewer_jwt"]
disable_iss_validation = var.disable_iss_validation
use_annotations_as_alias_metadata = var.use_annotations_as_alias_metadata
}
@@ -0,0 +1,54 @@
variable "country" {
description = "Country identifier"
type = string
}
variable "region" {
description = "Region identifier"
type = string
}
variable "path" {
description = "Mount path of the Kubernetes auth backend"
type = string
default = "kubernetes"
}
variable "disable_iss_validation" {
description = "Disable JWT issuer validation"
type = bool
default = true
}
variable "use_annotations_as_alias_metadata" {
description = "Use annotations as alias metadata"
type = bool
default = true
}
variable "listing_visibility" {
description = "Specifies whether to show this mount in the UI-specific listing endpoint. Valid values are 'unauth' or 'hidden'"
type = string
default = null
validation {
condition = var.listing_visibility == null || contains(["unauth", "hidden"], var.listing_visibility)
error_message = "listing_visibility must be either 'unauth' or 'hidden'."
}
}
variable "default_lease_ttl" {
description = "Specifies the default time-to-live. If set, this overrides the global default. Must be a valid duration string"
type = string
default = null
}
variable "max_lease_ttl" {
description = "Specifies the maximum time-to-live. If set, this overrides the global default. Must be a valid duration string"
type = string
default = null
}
variable "kubernetes_host" {
description = "Host must be a host string, a host:port pair, or a URL to the base of the Kubernetes API server"
type = string
}
@@ -0,0 +1,9 @@
resource "vault_kubernetes_auth_backend_role" "role" {
backend = var.backend
role_name = var.role_name
bound_service_account_names = var.bound_service_account_names
bound_service_account_namespaces = var.bound_service_account_namespaces
token_ttl = var.token_ttl
token_policies = var.token_policies
audience = var.audience
}
@@ -0,0 +1,36 @@
variable "backend" {
description = "The unique path of the Kubernetes auth backend to configure"
type = string
}
variable "role_name" {
description = "The name of the role"
type = string
}
variable "bound_service_account_names" {
description = "List of service account names able to access this role"
type = list(string)
}
variable "bound_service_account_namespaces" {
description = "List of namespaces allowed to access this role"
type = list(string)
}
variable "token_ttl" {
description = "The TTL period of tokens issued using this role, in seconds"
type = number
default = 3600
}
variable "token_policies" {
description = "List of policies to assign to the role (passed from policy_auth_map)"
type = list(string)
}
variable "audience" {
description = "Audience claim to verify in the JWT"
type = string
default = "vault"
}
@@ -0,0 +1,27 @@
# Expected keys in KV secret: url, binddn, bindpass
data "vault_kv_secret_v2" "auth_backend_config" {
mount = "kv"
name = "service/vault/${var.country}/${var.region}/auth_backend/${var.path}"
}
resource "vault_ldap_auth_backend" "ldap" {
path = var.path
url = data.vault_kv_secret_v2.auth_backend_config.data["url"]
userdn = var.userdn
userattr = var.userattr
upndomain = var.upndomain
discoverdn = var.discoverdn
groupdn = var.groupdn
groupfilter = var.groupfilter
groupattr = var.groupattr
binddn = data.vault_kv_secret_v2.auth_backend_config.data["binddn"]
bindpass = data.vault_kv_secret_v2.auth_backend_config.data["bindpass"]
alias_metadata = var.alias_metadata
username_as_alias = var.username_as_alias
tune {
default_lease_ttl = var.default_lease_ttl
max_lease_ttl = var.max_lease_ttl
listing_visibility = var.listing_visibility
}
}
@@ -0,0 +1,91 @@
variable "country" {
description = "Country identifier"
type = string
}
variable "region" {
description = "Region identifier"
type = string
}
variable "path" {
description = "Mount path of the LDAP auth backend"
type = string
default = "ldap"
}
variable "userdn" {
description = "Base DN under which to perform user search"
type = string
}
variable "userattr" {
description = "Attribute on user objects matching the username"
type = string
default = "uid"
}
variable "upndomain" {
description = "UPN domain for users"
type = string
default = null
}
variable "discoverdn" {
description = "Use anonymous bind to discover the bind DN of a user"
type = bool
default = false
}
variable "groupdn" {
description = "Base DN under which to perform group search"
type = string
default = null
}
variable "groupfilter" {
description = "Go template for querying group membership"
type = string
default = null
}
variable "groupattr" {
description = "LDAP attribute to follow on objects returned by groupfilter"
type = string
default = "cn"
}
variable "listing_visibility" {
description = "Specifies whether to show this mount in the UI-specific listing endpoint. Valid values are 'unauth' or 'hidden'"
type = string
default = null
validation {
condition = var.listing_visibility == null || contains(["unauth", "hidden"], var.listing_visibility)
error_message = "listing_visibility must be either 'unauth' or 'hidden'."
}
}
variable "default_lease_ttl" {
description = "Specifies the default time-to-live. If set, this overrides the global default. Must be a valid duration string"
type = string
default = null
}
variable "max_lease_ttl" {
description = "Specifies the maximum time-to-live. If set, this overrides the global default. Must be a valid duration string"
type = string
default = null
}
variable "alias_metadata" {
description = "The metadata to be tied to generated entity alias. This should be a list or map containing the metadata in key value pairs"
type = map(string)
default = null
}
variable "username_as_alias" {
description = "Force the auth method to use the username passed by the user as the alias name"
type = bool
default = true
}
@@ -0,0 +1,5 @@
resource "vault_ldap_auth_backend_group" "group" {
groupname = var.groupname
policies = var.policies
backend = var.backend
}
@@ -0,0 +1,14 @@
variable "groupname" {
description = "Name of the LDAP group"
type = string
}
variable "policies" {
description = "List of policies to assign to the LDAP group"
type = list(string)
}
variable "backend" {
description = "Path of the LDAP auth backend"
type = string
}
@@ -0,0 +1,21 @@
# Expected keys in KV secret: token (if not bootstrapping)
data "vault_kv_secret_v2" "secret_backend_config" {
count = var.bootstrap ? 0 : 1
mount = "kv"
name = "service/vault/${var.country}/${var.region}/secret_backend/${var.path}"
}
resource "vault_consul_secret_backend" "consul" {
path = var.path
description = var.description
address = var.address
token = var.bootstrap ? null : data.vault_kv_secret_v2.secret_backend_config[0].data["token"]
bootstrap = var.bootstrap
scheme = var.scheme
ca_cert = var.ca_cert
client_cert = var.client_cert
client_key = var.client_key
default_lease_ttl_seconds = var.default_lease_ttl_seconds
max_lease_ttl_seconds = var.max_lease_ttl_seconds
}
@@ -0,0 +1,67 @@
variable "country" {
description = "Country identifier"
type = string
}
variable "region" {
description = "Region identifier"
type = string
}
variable "path" {
description = "Mount path of the Consul secrets engine"
type = string
}
variable "description" {
description = "Human-friendly description of the mount"
type = string
default = null
}
variable "address" {
description = "The address of the Consul instance"
type = string
}
variable "bootstrap" {
description = "Whether to bootstrap the Consul backend"
type = bool
default = false
}
variable "scheme" {
description = "The scheme to use when connecting to Consul"
type = string
default = "https"
}
variable "ca_cert" {
description = "CA certificate for TLS verification"
type = string
default = null
}
variable "client_cert" {
description = "Client certificate for TLS authentication"
type = string
default = null
}
variable "client_key" {
description = "Client key for TLS authentication"
type = string
default = null
}
variable "default_lease_ttl_seconds" {
description = "Default lease TTL in seconds"
type = number
default = null
}
variable "max_lease_ttl_seconds" {
description = "Maximum lease TTL in seconds"
type = number
default = null
}
@@ -0,0 +1,8 @@
resource "vault_consul_secret_backend_role" "role" {
backend = var.backend
name = var.name
consul_roles = var.consul_roles
ttl = var.ttl
max_ttl = var.max_ttl
local = var.local
}
@@ -0,0 +1,35 @@
variable "backend" {
description = "The unique path where the Consul backend is mounted"
type = string
}
variable "name" {
description = "The name of the role"
type = string
}
variable "consul_roles" {
description = "List of Consul roles to attach to tokens"
type = list(string)
default = []
}
variable "ttl" {
description = "TTL for generated tokens"
type = number
default = null
}
variable "max_ttl" {
description = "Maximum TTL for generated tokens"
type = number
default = null
}
variable "local" {
description = "Whether tokens should be local to the datacenter"
type = bool
default = false
}
@@ -0,0 +1,16 @@
# Expected keys in KV secret: service_account_jwt, kubernetes_ca_cert
data "vault_kv_secret_v2" "secret_backend_config" {
mount = "kv"
name = "service/vault/${var.country}/${var.region}/secret_backend/${var.path}"
}
resource "vault_kubernetes_secret_backend" "kubernetes" {
path = var.path
description = var.description
default_lease_ttl_seconds = var.default_lease_ttl_seconds
max_lease_ttl_seconds = var.max_lease_ttl_seconds
kubernetes_host = var.kubernetes_host
kubernetes_ca_cert = data.vault_kv_secret_v2.secret_backend_config.data["kubernetes_ca_cert"]
service_account_jwt = data.vault_kv_secret_v2.secret_backend_config.data["service_account_jwt"]
disable_local_ca_jwt = var.disable_local_ca_jwt
}
@@ -0,0 +1,43 @@
variable "country" {
description = "Country identifier"
type = string
}
variable "region" {
description = "Region identifier"
type = string
}
variable "path" {
description = "Mount path of the Kubernetes secrets engine"
type = string
}
variable "description" {
description = "Human-friendly description of the mount"
type = string
default = null
}
variable "default_lease_ttl_seconds" {
description = "Default lease TTL in seconds"
type = number
default = 600
}
variable "max_lease_ttl_seconds" {
description = "Maximum lease TTL in seconds"
type = number
default = 86400
}
variable "kubernetes_host" {
description = "The Kubernetes API server URL"
type = string
}
variable "disable_local_ca_jwt" {
description = "Whether to disable local CA JWT validation"
type = bool
default = false
}
@@ -0,0 +1,19 @@
locals {
# Auto-generate role rules path: resources/secret_backend/{backend_path}/roles/{role_name}.yaml
role_rules_file = "resources/secret_backend/${var.backend}/roles/${var.name}.yaml"
# Auto-generate extra labels based on country/region and role name
auto_labels = merge(var.extra_labels, {
vault-region = "${var.country}-${var.region}"
vault-role = var.name
})
}
resource "vault_kubernetes_secret_backend_role" "role" {
backend = var.backend
name = var.name
allowed_kubernetes_namespaces = var.allowed_kubernetes_namespaces
kubernetes_role_type = var.kubernetes_role_type
generated_role_rules = file("${path.module}/../../../../../../../../${local.role_rules_file}")
extra_labels = local.auto_labels
}
@@ -0,0 +1,37 @@
variable "country" {
description = "Country identifier"
type = string
}
variable "region" {
description = "Region identifier"
type = string
}
variable "backend" {
description = "The unique path where the Kubernetes backend is mounted"
type = string
}
variable "name" {
description = "The name of the role"
type = string
}
variable "allowed_kubernetes_namespaces" {
description = "List of allowed Kubernetes namespaces"
type = list(string)
default = ["*"]
}
variable "kubernetes_role_type" {
description = "Type of Kubernetes role (Role or ClusterRole)"
type = string
default = "Role"
}
variable "extra_labels" {
description = "Additional labels to apply to generated Kubernetes objects"
type = map(string)
default = {}
}
@@ -0,0 +1,17 @@
resource "vault_mount" "kv" {
path = var.path
type = "kv"
description = var.description
options = {
version = var.kv_version
type = var.type
}
}
resource "vault_kv_secret_backend_v2" "config" {
count = var.type == "kv-v2" && var.max_versions != null ? 1 : 0
mount = vault_mount.kv.path
max_versions = var.max_versions
}
@@ -0,0 +1,28 @@
variable "path" {
description = "Mount path of the KV secrets engine"
type = string
}
variable "type" {
description = "Type of the secrets engine"
type = string
default = "kv-v2"
}
variable "description" {
description = "Human-friendly description of the mount"
type = string
default = null
}
variable "kv_version" {
description = "KV secrets engine version"
type = string
default = "2"
}
variable "max_versions" {
description = "Maximum number of versions to keep per key"
type = number
default = null
}
@@ -0,0 +1,38 @@
resource "vault_mount" "pki" {
path = var.path
type = "pki"
description = var.description
max_lease_ttl_seconds = var.max_lease_ttl_seconds
}
data "vault_pki_secret_backend_issuer" "issuer" {
backend = vault_mount.pki.path
issuer_ref = var.issuer_ref
}
resource "vault_pki_secret_backend_config_urls" "config_urls" {
backend = vault_mount.pki.path
issuing_certificates = var.issuing_certificates
crl_distribution_points = var.crl_distribution_points
ocsp_servers = var.ocsp_servers
enable_templating = var.enable_templating
}
resource "vault_pki_secret_backend_config_issuers" "issuers" {
count = var.default_issuer_ref != null ? 1 : 0
backend = vault_mount.pki.path
default = var.default_issuer_ref
default_follows_latest_issuer = var.default_follows_latest_issuer
}
resource "vault_pki_secret_backend_crl_config" "crl" {
backend = vault_mount.pki.path
expiry = var.crl_expiry
disable = var.crl_disable
ocsp_disable = var.ocsp_disable
auto_rebuild = var.auto_rebuild
enable_delta = var.enable_delta
delta_rebuild_interval = var.delta_rebuild_interval
}
@@ -0,0 +1,92 @@
variable "path" {
description = "Path where the PKI backend will be mounted"
type = string
}
variable "description" {
description = "Description of the PKI mount"
type = string
}
variable "max_lease_ttl_seconds" {
description = "Maximum possible lease duration for tokens and secrets in seconds"
type = number
}
variable "issuer_ref" {
description = "Reference to the PKI issuer (default, or issuer ID/name)"
type = string
default = "default"
}
variable "issuing_certificates" {
description = "List of URLs for issuing certificates"
type = list(string)
default = []
}
variable "crl_distribution_points" {
description = "List of URLs for CRL distribution points"
type = list(string)
default = []
}
variable "ocsp_servers" {
description = "List of OCSP server URLs"
type = list(string)
default = []
}
variable "enable_templating" {
description = "Whether to enable URL templating"
type = bool
default = false
}
variable "default_issuer_ref" {
description = "Default issuer reference"
type = string
default = null
}
variable "default_follows_latest_issuer" {
description = "Whether the default issuer follows the latest issuer"
type = bool
default = false
}
variable "crl_expiry" {
description = "CRL expiry time"
type = string
default = "72h"
}
variable "crl_disable" {
description = "Whether to disable CRL"
type = bool
default = false
}
variable "ocsp_disable" {
description = "Whether to disable OCSP"
type = bool
default = false
}
variable "auto_rebuild" {
description = "Whether to enable auto rebuild of CRL"
type = bool
default = false
}
variable "enable_delta" {
description = "Whether to enable delta CRL"
type = bool
default = false
}
variable "delta_rebuild_interval" {
description = "Delta CRL rebuild interval"
type = string
default = null
}
@@ -0,0 +1,54 @@
resource "vault_mount" "pki" {
path = var.path
type = "pki"
description = var.description
max_lease_ttl_seconds = var.max_lease_ttl_seconds
}
resource "vault_pki_secret_backend_root_cert" "root_cert" {
backend = vault_mount.pki.path
common_name = var.common_name
issuer_name = var.issuer_name
ttl = var.ttl
format = var.format
type = "internal"
}
data "vault_pki_secret_backend_issuer" "issuer" {
backend = vault_mount.pki.path
issuer_ref = vault_pki_secret_backend_root_cert.root_cert.issuer_id
depends_on = [vault_pki_secret_backend_root_cert.root_cert]
}
resource "vault_pki_secret_backend_config_urls" "urls" {
backend = vault_mount.pki.path
issuing_certificates = var.issuing_certificates
crl_distribution_points = var.crl_distribution_points
ocsp_servers = var.ocsp_servers
enable_templating = var.enable_templating
}
resource "vault_pki_secret_backend_config_issuers" "issuers" {
backend = vault_mount.pki.path
default = data.vault_pki_secret_backend_issuer.issuer.issuer_id
default_follows_latest_issuer = var.default_follows_latest_issuer
depends_on = [
vault_pki_secret_backend_root_cert.root_cert,
data.vault_pki_secret_backend_issuer.issuer
]
}
resource "vault_pki_secret_backend_crl_config" "crl" {
backend = vault_mount.pki.path
expiry = var.crl_expiry
disable = var.crl_disable
ocsp_disable = var.ocsp_disable
auto_rebuild = var.auto_rebuild
enable_delta = var.enable_delta
delta_rebuild_interval = var.delta_rebuild_interval
depends_on = [vault_pki_secret_backend_root_cert.root_cert]
}
@@ -0,0 +1,110 @@
variable "path" {
description = "Mount path of the PKI secrets engine"
type = string
}
variable "description" {
description = "Human-friendly description of the mount"
type = string
default = null
}
variable "max_lease_ttl_seconds" {
description = "Maximum lease TTL in seconds"
type = number
default = 315360000 # 87600 * 3600
}
variable "common_name" {
description = "Common name for the root certificate"
type = string
}
variable "issuer_name" {
description = "Name for the root CA issuer"
type = string
}
variable "ttl" {
description = "TTL for the root certificate in seconds"
type = number
default = 315360000 # 87600 * 3600
}
variable "format" {
description = "Format for the certificate"
type = string
default = "pem"
}
variable "issuing_certificates" {
description = "List of issuing certificate URLs"
type = list(string)
default = []
}
variable "crl_distribution_points" {
description = "List of CRL distribution point URLs"
type = list(string)
default = []
}
variable "ocsp_servers" {
description = "List of OCSP server URLs"
type = list(string)
default = []
}
variable "enable_templating" {
description = "Whether to enable templating for URL configuration"
type = bool
default = false
}
variable "default_issuer_ref" {
description = "Reference to the default issuer"
type = string
default = null
}
variable "default_follows_latest_issuer" {
description = "Whether the default issuer should follow the latest issuer"
type = bool
default = false
}
variable "crl_expiry" {
description = "CRL expiration time"
type = string
default = "72h"
}
variable "crl_disable" {
description = "Whether to disable CRL"
type = bool
default = false
}
variable "ocsp_disable" {
description = "Whether to disable OCSP"
type = bool
default = false
}
variable "auto_rebuild" {
description = "Whether to auto-rebuild CRL"
type = bool
default = false
}
variable "enable_delta" {
description = "Whether to enable delta CRL"
type = bool
default = false
}
variable "delta_rebuild_interval" {
description = "Delta CRL rebuild interval"
type = string
default = null
}
@@ -0,0 +1,16 @@
resource "vault_pki_secret_backend_role" "role" {
backend = var.backend
name = var.name
allow_ip_sans = var.allow_ip_sans
allowed_domains = var.allowed_domains
allow_subdomains = var.allow_subdomains
allow_glob_domains = var.allow_glob_domains
allow_bare_domains = var.allow_bare_domains
enforce_hostnames = var.enforce_hostnames
allow_any_name = var.allow_any_name
max_ttl = var.max_ttl
key_bits = var.key_bits
country = var.country
use_csr_common_name = var.use_csr_common_name
use_csr_sans = var.use_csr_sans
}
@@ -0,0 +1,81 @@
variable "backend" {
description = "The unique path where the PKI backend is mounted"
type = string
}
variable "name" {
description = "The name of the role"
type = string
}
variable "allow_ip_sans" {
description = "Whether IP Subject Alternative Names are allowed"
type = bool
default = false
}
variable "allowed_domains" {
description = "List of allowed domains for certificates"
type = list(string)
default = []
}
variable "allow_subdomains" {
description = "Whether subdomains are allowed"
type = bool
default = false
}
variable "allow_glob_domains" {
description = "Whether glob domains are allowed"
type = bool
default = false
}
variable "allow_bare_domains" {
description = "Whether bare domains are allowed"
type = bool
default = false
}
variable "enforce_hostnames" {
description = "Whether to enforce hostnames"
type = bool
default = false
}
variable "allow_any_name" {
description = "Whether any name is allowed"
type = bool
default = false
}
variable "max_ttl" {
description = "Maximum TTL for certificates in seconds"
type = number
default = null
}
variable "key_bits" {
description = "Number of bits for the key"
type = number
default = 4096
}
variable "country" {
description = "List of countries for certificate subject"
type = list(string)
default = []
}
variable "use_csr_common_name" {
description = "Whether to use CSR common name"
type = bool
default = false
}
variable "use_csr_sans" {
description = "Whether to use CSR Subject Alternative Names"
type = bool
default = false
}
@@ -0,0 +1,14 @@
resource "vault_mount" "ssh" {
path = var.path
type = "ssh"
description = var.description
max_lease_ttl_seconds = var.max_lease_ttl_seconds
}
resource "vault_ssh_secret_backend_ca" "ssh_ca" {
count = var.generate_signing_key != null ? 1 : 0
backend = vault_mount.ssh.path
generate_signing_key = var.generate_signing_key
key_type = var.key_type
}
@@ -0,0 +1,28 @@
variable "path" {
description = "Mount path of the SSH secrets engine"
type = string
}
variable "description" {
description = "Human-friendly description of the mount"
type = string
default = null
}
variable "max_lease_ttl_seconds" {
description = "Maximum lease TTL in seconds"
type = number
default = 315360000 # 87600 * 3600
}
variable "generate_signing_key" {
description = "Whether to generate a signing key for the CA"
type = bool
default = null
}
variable "key_type" {
description = "Type of key to generate for the CA"
type = string
default = "ssh-rsa"
}
@@ -0,0 +1,12 @@
resource "vault_ssh_secret_backend_role" "role" {
backend = var.backend
name = var.name
key_type = var.key_type
algorithm_signer = var.algorithm_signer
ttl = var.ttl
allow_host_certificates = var.allow_host_certificates
allow_user_certificates = var.allow_user_certificates
allowed_domains = var.allowed_domains
allow_subdomains = var.allow_subdomains
allow_bare_domains = var.allow_bare_domains
}
@@ -0,0 +1,57 @@
variable "backend" {
description = "The unique path where the SSH backend is mounted"
type = string
}
variable "name" {
description = "The name of the role"
type = string
}
variable "key_type" {
description = "The type of key used by this role"
type = string
default = "ca"
}
variable "algorithm_signer" {
description = "Algorithm used to sign certificates"
type = string
default = "rsa-sha2-256"
}
variable "ttl" {
description = "TTL for certificates issued by this role"
type = number
default = 315360000 # 87600 * 3600
}
variable "allow_host_certificates" {
description = "Whether this role can issue host certificates"
type = bool
default = false
}
variable "allow_user_certificates" {
description = "Whether this role can issue user certificates"
type = bool
default = false
}
variable "allowed_domains" {
description = "List of allowed domains for certificates"
type = string
default = null
}
variable "allow_subdomains" {
description = "Whether subdomains are allowed"
type = bool
default = false
}
variable "allow_bare_domains" {
description = "Whether bare domains are allowed"
type = bool
default = false
}
@@ -0,0 +1,7 @@
resource "vault_mount" "transit" {
path = var.path
type = "transit"
description = var.description
default_lease_ttl_seconds = var.default_lease_ttl_seconds
max_lease_ttl_seconds = var.max_lease_ttl_seconds
}
@@ -0,0 +1,22 @@
variable "path" {
description = "Mount path of the transit secrets engine"
type = string
}
variable "description" {
description = "Human-friendly description of the mount"
type = string
default = null
}
variable "default_lease_ttl_seconds" {
description = "Default lease TTL in seconds"
type = number
default = 3600
}
variable "max_lease_ttl_seconds" {
description = "Maximum lease TTL in seconds"
type = number
default = 86400
}
@@ -0,0 +1,10 @@
resource "vault_transit_secret_backend_key" "key" {
backend = var.backend
name = var.name
type = var.type
deletion_allowed = var.deletion_allowed
derived = var.derived
exportable = var.exportable
allow_plaintext_backup = var.allow_plaintext_backup
auto_rotate_period = var.auto_rotate_period
}
@@ -0,0 +1,45 @@
variable "backend" {
description = "The unique path where the transit backend is mounted"
type = string
}
variable "name" {
description = "The name of the encryption key"
type = string
}
variable "type" {
description = "The type of key to create"
type = string
default = "aes256-gcm96"
}
variable "deletion_allowed" {
description = "Whether the key is allowed to be deleted"
type = bool
default = false
}
variable "derived" {
description = "Whether the key supports key derivation"
type = bool
default = false
}
variable "exportable" {
description = "Whether the key is exportable"
type = bool
default = false
}
variable "allow_plaintext_backup" {
description = "Whether the key supports plaintext backup"
type = bool
default = false
}
variable "auto_rotate_period" {
description = "Period for automatic key rotation"
type = string
default = null
}
@@ -0,0 +1,11 @@
locals {
policy_hcl = join("\n", [
for rule in var.policy_rules :
"path \"${rule.path}\" {\n capabilities = ${jsonencode(rule.capabilities)}\n}"
])
}
resource "vault_policy" "this" {
name = var.policy_name
policy = local.policy_hcl
}
@@ -0,0 +1,12 @@
variable "policy_name" {
description = "Name of the Vault policy"
type = string
}
variable "policy_rules" {
description = "List of policy rules for this policy"
type = list(object({
path = string
capabilities = list(string)
}))
}