-
Notifications
You must be signed in to change notification settings - Fork 9
/
main.tf
176 lines (147 loc) · 5.04 KB
/
main.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
terraform {
backend "gcs" {
bucket = "octo-sts-terraform-state"
prefix = "/octo-sts"
}
required_providers {
ko = { source = "ko-build/ko" }
}
}
provider "google" { project = var.project_id }
provider "google-beta" { project = var.project_id }
provider "ko" { docker_repo = "gcr.io/${var.project_id}" }
// Create a network with several regional subnets
module "networking" {
source = "chainguard-dev/common/infra//modules/networking"
name = var.name
project_id = var.project_id
regions = var.regions
}
// Create a keyring to hold our OIDC keys.
resource "google_kms_key_ring" "app-keyring" {
project = var.project_id
name = var.name
location = "global"
}
// Create an asymmetric signing key to use for signing tokens.
resource "google_kms_crypto_key" "app-key" {
name = "app-signing-key"
key_ring = google_kms_key_ring.app-keyring.id
purpose = "ASYMMETRIC_SIGN"
version_template {
algorithm = "RSA_SIGN_PKCS1_2048_SHA256"
}
import_only = true
skip_initial_version_creation = true
}
locals {
# To import a key, we need to run the following commands:
# gcloud kms import-jobs create app-import-job \
# --location global \
# --keyring octo-sts \
# --import-method rsa-oaep-4096-sha256-aes-256 \
# --protection-level software
# gcloud kms import-jobs describe app-import-job \
# --location global \
# --keyring octo-sts \
# --format="value(state)"
# openssl pkcs8 -topk8 -nocrypt -inform PEM -outform DER \
# -in key.pem -out key.data
# # Needs: pip3 install --user "cryptography>=2.2.0"
# CLOUDSDK_PYTHON_SITEPACKAGES=1 gcloud kms keys versions import \
# --import-job app-import-job \
# --location global \
# --keyring octo-sts \
# --key app-signing-key \
# --algorithm rsa-sign-pkcs1-2048-sha256 \
# --target-key-file key.data
kms_key = "${google_kms_crypto_key.app-key.id}/cryptoKeyVersions/1"
}
// Create a dedicated GSA for the IAM datastore service.
resource "google_service_account" "octo-sts" {
project = var.project_id
account_id = var.name
display_name = "Octo STS"
description = "Dedicated service account for the Octo STS service."
}
module "sts-service" {
source = "chainguard-dev/common/infra//modules/regional-go-service"
project_id = var.project_id
name = var.name
regions = module.networking.regional-networks
// Only accept traffic coming from GCLB.
ingress = "INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER"
// This needs to egress in order to talk to Github
egress = "PRIVATE_RANGES_ONLY"
service_account = google_service_account.octo-sts.email
containers = {
"sts" = {
source = {
working_dir = "${path.module}/.."
importpath = "./cmd/app"
}
ports = [{ container_port = 8080 }]
env = [
{
name = "GITHUB_APP_ID"
value = "801323" // https://github.com/settings/apps/octosts
},
{
name = "KMS_KEY"
value = local.kms_key
}
]
}
}
}
// Allow the STS service to call the sign method on the keys in the keyring.
resource "google_kms_key_ring_iam_binding" "signer-members" {
key_ring_id = google_kms_key_ring.app-keyring.id
role = "roles/cloudkms.signer"
members = [
"serviceAccount:${google_service_account.octo-sts.email}",
]
}
data "google_client_openid_userinfo" "me" {}
resource "google_monitoring_alert_policy" "anomalous-kms-access" {
# In the absence of data, incident will auto-close in 7 days
alert_strategy {
auto_close = "604800s"
notification_rate_limit {
period = "86400s" // re-alert once a day if condition still valid.
}
}
display_name = "Abnormal KMS Access"
combiner = "OR"
conditions {
display_name = "Unauthorized KMS access"
condition_matched_log {
filter = <<EOT
-- KMS operations
protoPayload.serviceName="cloudkms.googleapis.com"
-- Against our Github App's keyring
protoPayload.resourceName: "${google_kms_key_ring.app-keyring.id}/"
-- The application itself should only perform signing operations.
-(
protoPayload.authenticationInfo.principalEmail="${google_service_account.octo-sts.email}" AND
protoPayload.methodName=("AsymmetricSign")
)
-- Github IaC should only reconcile the keyring and keys.
-(
protoPayload.authenticationInfo.principalEmail="${data.google_client_openid_userinfo.me.email}" AND
protoPayload.methodName=("CreateKeyRing" OR "CreateCryptoKey" OR "SetIamPolicy")
)
-- If we were to filter out import events they would look like
-- this, but instead I am opting to explicitly have these alert,
-- to raise awareness of the rotation, since it means that a human
-- has interacted with an App key locally.
-- -(
-- protoPayload.authenticationInfo.principalEmail="...@chainguard.dev" AND
-- protoPayload.methodName=("CreateImportJob" OR "ImportCryptoKeyVersion")
-- )
EOT
}
}
enabled = "true"
project = var.project_id
}