feat: add kubernetes secrets engine with RBAC roles for au-syd1 cluster

- Add Kubernetes secrets engine at kubernetes/au/syd1 path
  - Create four RBAC roles with external YAML configuration:
    * media-apps-operator: namespaced role for media-apps with selective permissions
    * cluster-operator: cluster-wide read-only access to specific API groups
    * cluster-admin: cluster-wide full access to specific API groups
    * cluster-root: cluster-wide superuser access to all resources
  - Add Vault policies for credential generation for each role
  - Add admin policies for kubernetes auth backend configuration and role management
  - Refactor kubernetes auth backend to use shared locals for CA certificate
  - Update terraform-vault approle with required kubernetes policies
This commit is contained in:
Ben Vincent 2025-11-27 23:22:13 +11:00
parent ad1118af85
commit 6624f7aed1
15 changed files with 204 additions and 25 deletions

View File

@ -3,24 +3,27 @@ resource "vault_approle_auth_backend_role" "tf_vault" {
bind_secret_id = false
token_policies = [
"default_access",
"approle_token_create",
"auth/approle/approle_role_admin",
"auth/approle/approle_role_login",
"auth/kubernetes/k8s_auth_admin",
"auth/ldap/ldap_admin",
"auth/token/auth_token_create",
"auth/token/auth_token_self",
"auth/token/auth_token_roles_admin",
"auth/approle/approle_role_admin",
"auth/approle/approle_role_login",
"approle_token_create",
"auth/kubernetes/k8s_auth_admin",
"auth/ldap/ldap_admin",
"kubernetes/au/config_admin",
"kubernetes/au/roles_admin",
"kv/service/glauth/services/svc_vault_read",
"kv/service/kubernetes/au/syd1/token_reviewer_jwt/read",
"kv/service/kubernetes/au/syd1/service_account_jwt/read",
"pki_int/pki_int_roles_admin",
"pki_root/pki_root_roles_admin",
"ssh-host-signer/ssh-host-signer_roles_admin",
"sshca/sshca_roles_admin",
"kv/service/glauth/services/svc_vault_read",
"sys/sys_auth_admin",
"sys/sys_mounts_admin",
"sys/sys_policy_admin",
"transit/keys/admin",
"kv/service/kubernetes/au/syd1/token_reviewer_jwt/read",
]
token_ttl = 60
token_max_ttl = 120

View File

@ -6,23 +6,8 @@ resource "vault_auth_backend" "kubernetes" {
path = "kubernetes"
}
locals {
kubernetes_ca_cert = <<-EOT
-----BEGIN CERTIFICATE-----
MIIBejCCAR+gAwIBAgIBADAKBggqhkjOPQQDAjAkMSIwIAYDVQQDDBlya2UyLXNl
cnZlci1jYUAxNzU5MDI3NTg0MB4XDTI1MDkyODAyNDYyNFoXDTM1MDkyNjAyNDYy
NFowJDEiMCAGA1UEAwwZcmtlMi1zZXJ2ZXItY2FAMTc1OTAyNzU4NDBZMBMGByqG
SM49AgEGCCqGSM49AwEHA0IABKfsTD4tKzKcnHyubWseKjlIPphBVveV1n6RUxmi
a3H6s9qMmT3dldYJyaalZI0NctSdW4ucPhBN5THCUr8sOmejQjBAMA4GA1UdDwEB
/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRFb0pf+pC/voWvbs1z
fU/dqB0RxjAKBggqhkjOPQQDAgNJADBGAiEA/0zeJRrgwpHFPRsqgO+EhmwBx1Y8
NH3FcktF9J6PfPQCIQD4/IpOhdjf9rmo0ckG1npNEx5V8+OQ8ZTM7s1DL6+DfA==
-----END CERTIFICATE-----
EOT
}
# Data source to read the token_reviewer_jwt from Vault KV
data "vault_kv_secret_v2" "token_reviewer_jwt" {
data "vault_kv_secret_v2" "token_reviewer_jwt_au_syd1" {
mount = "kv"
name = "service/kubernetes/au/syd1/token_reviewer_jwt"
}
@ -31,8 +16,8 @@ data "vault_kv_secret_v2" "token_reviewer_jwt" {
resource "vault_kubernetes_auth_backend_config" "config" {
backend = vault_auth_backend.kubernetes.path
kubernetes_host = "https://api-k8s.service.consul:6443"
kubernetes_ca_cert = local.kubernetes_ca_cert
token_reviewer_jwt = data.vault_kv_secret_v2.token_reviewer_jwt.data["token"]
kubernetes_ca_cert = local.kubernetes_ca_cert_au_syd1
token_reviewer_jwt = data.vault_kv_secret_v2.token_reviewer_jwt_au_syd1.data["token"]
disable_iss_validation = true
use_annotations_as_alias_metadata = true
}

48
engine_k8s_au_syd1.tf Normal file
View File

@ -0,0 +1,48 @@
# Data source to read the service_token_jwt from Vault KV
data "vault_kv_secret_v2" "service_account_jwt_au_syd1" {
mount = "kv"
name = "service/kubernetes/au/syd1/service_account_jwt"
}
resource "vault_kubernetes_secret_backend" "kubernetes_au_syd1" {
path = "kubernetes/au/syd1"
description = "kubernetes secret engine for au-syd1 cluster"
default_lease_ttl_seconds = 600
max_lease_ttl_seconds = 86400
kubernetes_host = "https://api-k8s.service.consul:6443"
kubernetes_ca_cert = local.kubernetes_ca_cert_au_syd1
service_account_jwt = data.vault_kv_secret_v2.service_account_jwt_au_syd1.data["token"]
disable_local_ca_jwt = false
}
resource "vault_kubernetes_secret_backend_role" "media_apps_operator" {
backend = vault_kubernetes_secret_backend.kubernetes_au_syd1.path
name = "media-apps-operator"
allowed_kubernetes_namespaces = ["media-apps"]
generated_role_rules = file("${path.module}/resources/k8s/syd1/au/generated_role_rules/media-apps-operator.yaml")
}
resource "vault_kubernetes_secret_backend_role" "cluster_operator" {
backend = vault_kubernetes_secret_backend.kubernetes_au_syd1.path
name = "cluster-operator"
allowed_kubernetes_namespaces = ["*"]
generated_role_rules = file("${path.module}/resources/k8s/syd1/au/generated_role_rules/cluster-operator.yaml")
}
resource "vault_kubernetes_secret_backend_role" "cluster_admin" {
backend = vault_kubernetes_secret_backend.kubernetes_au_syd1.path
name = "cluster-admin"
allowed_kubernetes_namespaces = ["*"]
generated_role_rules = file("${path.module}/resources/k8s/syd1/au/generated_role_rules/cluster-admin.yaml")
}
resource "vault_kubernetes_secret_backend_role" "cluster_root" {
backend = vault_kubernetes_secret_backend.kubernetes_au_syd1.path
name = "cluster-root"
allowed_kubernetes_namespaces = ["*"]
generated_role_rules = file("${path.module}/resources/k8s/syd1/au/generated_role_rules/cluster-root.yaml")
}

View File

@ -0,0 +1,3 @@
path "kubernetes/au/+/config" {
capabilities = ["create", "update", "read", "delete", "list"]
}

View File

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

View File

@ -0,0 +1,3 @@
path "kubernetes/au/syd1/creds/cluster-admin" {
capabilities = ["update"]
}

View File

@ -0,0 +1,3 @@
path "kubernetes/au/syd1/creds/cluster-operator" {
capabilities = ["update"]
}

View File

@ -0,0 +1,3 @@
path "kubernetes/au/syd1/creds/cluster-root" {
capabilities = ["update"]
}

View File

@ -0,0 +1,3 @@
path "kubernetes/au/syd1/creds/media-apps-operator" {
capabilities = ["update"]
}

View File

@ -0,0 +1,3 @@
path "kv/data/service/kubernetes/au/syd1/service_account_jwt" {
capabilities = ["read"]
}

View File

@ -0,0 +1,23 @@
---
rules:
- apiGroups:
- ""
- "postgresql.cnpg.io"
- "cert-manager.io"
- "rbac.authorization.k8s.io"
- "batch"
- "secrets.hashicorp.com"
- "storage.k8s.io"
- "apps"
- "apiextensions.k8s.io"
- "externaldns.k8s.io"
- "autoscaling"
- "networking.k8s.io"
- "purelb.io"
- "nfd.k8s-sigs.io"
- "policy"
- "metrics.k8s.io"
resources:
- "*"
verbs:
- "*"

View File

@ -0,0 +1,25 @@
---
rules:
- apiGroups:
- ""
- "postgresql.cnpg.io"
- "cert-manager.io"
- "rbac.authorization.k8s.io"
- "batch"
- "secrets.hashicorp.com"
- "storage.k8s.io"
- "apps"
- "apiextensions.k8s.io"
- "externaldns.k8s.io"
- "autoscaling"
- "networking.k8s.io"
- "purelb.io"
- "nfd.k8s-sigs.io"
- "policy"
- "metrics.k8s.io"
resources:
- "*"
verbs:
- "get"
- "list"
- "watch"

View File

@ -0,0 +1,8 @@
---
rules:
- apiGroups:
- "*"
resources:
- "*"
verbs:
- "*"

View File

@ -0,0 +1,49 @@
---
rules:
- apiGroups:
- ""
resources:
- "pods"
- "services"
- "configmaps"
- "secrets"
- "endpoints"
- "persistentvolumeclaims"
verbs:
- "get"
- "list"
- "watch"
- apiGroups:
- ""
resources:
- "pods/log"
verbs:
- "get"
- "list"
- apiGroups:
- ""
resources:
- "pods/exec"
verbs:
- "create"
- apiGroups:
- "apps"
resources:
- "deployments"
- "replicasets"
- "statefulsets"
- "daemonsets"
verbs:
- "get"
- "list"
- "watch"
- "patch"
- apiGroups:
- "extensions"
- "networking.k8s.io"
resources:
- "ingresses"
verbs:
- "get"
- "list"
- "watch"

14
shared_locals.tf Normal file
View File

@ -0,0 +1,14 @@
locals {
kubernetes_ca_cert_au_syd1 = <<-EOT
-----BEGIN CERTIFICATE-----
MIIBejCCAR+gAwIBAgIBADAKBggqhkjOPQQDAjAkMSIwIAYDVQQDDBlya2UyLXNl
cnZlci1jYUAxNzU5MDI3NTg0MB4XDTI1MDkyODAyNDYyNFoXDTM1MDkyNjAyNDYy
NFowJDEiMCAGA1UEAwwZcmtlMi1zZXJ2ZXItY2FAMTc1OTAyNzU4NDBZMBMGByqG
SM49AgEGCCqGSM49AwEHA0IABKfsTD4tKzKcnHyubWseKjlIPphBVveV1n6RUxmi
a3H6s9qMmT3dldYJyaalZI0NctSdW4ucPhBN5THCUr8sOmejQjBAMA4GA1UdDwEB
/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRFb0pf+pC/voWvbs1z
fU/dqB0RxjAKBggqhkjOPQQDAgNJADBGAiEA/0zeJRrgwpHFPRsqgO+EhmwBx1Y8
NH3FcktF9J6PfPQCIQD4/IpOhdjf9rmo0ckG1npNEx5V8+OQ8ZTM7s1DL6+DfA==
-----END CERTIFICATE-----
EOT
}