-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsecrets.tf
127 lines (108 loc) · 4.23 KB
/
secrets.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
locals {
input_secrets = merge(local.cap_secrets, var.secrets)
input_secret_keys = nonsensitive(concat(keys(local.cap_secrets), keys(var.secrets)))
}
// ns_secret_keys.this is used to calculate a set of secrets to add to gcp secrets manager
// The resulting `secret_keys` attribute must be known at plan time
// This doesn't need to do a full interpolation because we only care about which inputs need to be added to gcp secrets manager
// ns_secret_keys.input_env_variables should contain only var.env_vars since they could contain interpolation that promotes them to sensitive
// We exclude `local.cap_env_vars` because capabilities must use `cap_secrets` to create secrets
data "ns_secret_keys" "this" {
input_env_variables = var.env_vars
input_secret_keys = local.input_secret_keys
}
// "existing" adds support for the `secret(...)` syntax
// This only supports `secret(...)` specified by the user
data "ns_env_variables" "existing" {
input_env_variables = var.env_vars
input_secrets = {}
}
locals {
base_secret_keys = data.ns_secret_keys.this.secret_keys
existing_secret_keys = keys(data.ns_env_variables.existing.secret_refs)
all_secret_keys = toset(concat(tolist(local.base_secret_keys), local.existing_secret_keys))
}
resource "google_secret_manager_secret" "app_secret" {
for_each = local.base_secret_keys
// Valid secret_id: [[a-zA-Z_0-9]+]
secret_id = lower(replace("${local.resource_name}_${each.value}", "/[^a-zA-Z_0-9]/", "_"))
labels = local.tags
replication {
auto {}
}
}
resource "google_secret_manager_secret_version" "app_secret" {
for_each = local.base_secret_keys
secret = google_secret_manager_secret.app_secret[each.value].id
secret_data = local.all_secrets[each.value]
}
locals {
// Valid metadata name: [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*
app_secret_store_name = "${local.resource_name}-gsm-secrets"
// secret refs are prepared as a map in the form name:"<secret-id>"
// base => user-injected + capability secrets
// existing => user-injected with format `secret(...)`
base_secret_refs = { for key in local.base_secret_keys : key => google_secret_manager_secret.app_secret[key].secret_id }
existing_secret_refs = data.ns_env_variables.existing.secret_refs
all_secret_refs = merge(local.base_secret_refs, local.existing_secret_refs)
}
// The secret store defines "how" to access google secrets manager
// This secret store is only responsible for establishing authentication config
resource "kubernetes_manifest" "gsm_secret_store" {
manifest = {
apiVersion = "external-secrets.io/v1beta1"
kind = "SecretStore"
metadata = {
namespace = local.app_namespace
name = local.app_secret_store_name
labels = local.labels
}
spec = {
provider = {
gcpsm = {
projectID = local.project_id
auth = {
workloadIdentity = {
clusterLocation = local.region
clusterName = local.cluster_name
serviceAccountRef = {
name = kubernetes_service_account_v1.app.metadata.0.name
}
}
}
}
}
}
}
}
// The `ExternalSecret` resource creates a single k8s Secret
// with all secrets from capabilities and `secrets` var for this application pod
// Each `key` in this secret maps directly to an env var to inject into the app pod
resource "kubernetes_manifest" "secrets_from_gsm" {
depends_on = [kubernetes_manifest.gsm_secret_store]
count = signum(length(local.all_secret_keys))
manifest = {
apiVersion = "external-secrets.io/v1beta1"
kind = "ExternalSecret"
metadata = {
namespace = local.app_namespace
name = local.app_secret_store_name
labels = local.labels
}
spec = {
secretStoreRef = {
kind = "SecretStore"
name = local.app_secret_store_name
}
target = {
name = local.app_secret_store_name
}
data = [for key, value in local.all_secret_refs : {
secretKey = key
remoteRef = {
key = value
}
}]
}
}
}