-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Terraform for GCP CI base #144
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
terraform { | ||
source = "${get_repo_root()}/deployment/modules/gcp//example-gcp" | ||
} | ||
|
||
include "root" { | ||
path = find_in_parent_folders() | ||
expose = true | ||
} | ||
|
||
inputs = merge( | ||
include.root.locals, | ||
{ | ||
example_gcp_docker_image = "us-central1-docker.pkg.dev/trillian-tessera/docker-prod/example-gcp:latest" | ||
log_origin = "example-gcp" | ||
} | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
terraform { | ||
backend "gcs" {} | ||
} | ||
|
||
## Call the Tessera GCP module | ||
## | ||
## This will configure all the storage infrastructure required to run a Tessera log on GCP. | ||
module "gcs" { | ||
source = "..//gcs" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the double slash needed here? I think this is one of those cases where there is something needed about the 2 slashes but best to check. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yup, same as above. |
||
|
||
base_name = var.base_name | ||
env = var.env | ||
location = var.location | ||
project_id = var.project_id | ||
} | ||
|
||
## | ||
## Resources | ||
## | ||
|
||
# Enable Cloud Run API | ||
resource "google_project_service" "cloudrun_api" { | ||
service = "run.googleapis.com" | ||
disable_on_destroy = false | ||
} | ||
resource "google_project_service" "cloudkms_googleapis_com" { | ||
service = "cloudkms.googleapis.com" | ||
} | ||
|
||
## | ||
## KMS for log signing | ||
## | ||
resource "google_kms_key_ring" "log_signer" { | ||
location = var.location | ||
name = var.base_name | ||
} | ||
|
||
resource "google_kms_crypto_key" "log_signer" { | ||
key_ring = google_kms_key_ring.log_signer.id | ||
name = "log_signer" | ||
purpose = "ASYMMETRIC_SIGN" | ||
version_template { | ||
algorithm = "EC_SIGN_ED25519" | ||
} | ||
} | ||
resource "google_kms_crypto_key_version" "log_signer" { | ||
crypto_key = google_kms_crypto_key.log_signer.id | ||
} | ||
|
||
### | ||
### Set up Cloud Run service | ||
### | ||
resource "google_service_account" "cloudrun_service_account" { | ||
account_id = "cloudrun-${var.env}-sa" | ||
display_name = "Service Account for Cloud Run (${var.env})" | ||
} | ||
Comment on lines
+53
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't strictly necessary as there's a default service account you could use. It's good practice though. We should probably write in some docs our approach to the example on how to balance best practice vs minimalism. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, guidance is a good idea. I'll merge this as-is while we chew on that. |
||
|
||
resource "google_project_iam_member" "iam_act_as" { | ||
project = var.project_id | ||
role = "roles/iam.serviceAccountUser" | ||
member = "serviceAccount:${google_service_account.cloudrun_service_account.email}" | ||
} | ||
resource "google_project_iam_member" "iam_metrics_writer" { | ||
project = var.project_id | ||
role = "roles/monitoring.metricWriter" | ||
member = "serviceAccount:${google_service_account.cloudrun_service_account.email}" | ||
} | ||
resource "google_spanner_database_iam_binding" "iam_spanner_database_user" { | ||
project = var.project_id | ||
instance = module.gcs.log_spanner_instance.name | ||
database = module.gcs.log_spanner_db.name | ||
role = "roles/spanner.databaseUser" | ||
|
||
members = [ | ||
"serviceAccount:${google_service_account.cloudrun_service_account.email}" | ||
] | ||
} | ||
resource "google_project_iam_member" "iam_service_agent" { | ||
project = var.project_id | ||
role = "roles/run.serviceAgent" | ||
member = "serviceAccount:${google_service_account.cloudrun_service_account.email}" | ||
} | ||
|
||
locals { | ||
spanner_db_full = "projects/${var.project_id}/instances/${module.gcs.log_spanner_instance.name}/databases/${module.gcs.log_spanner_db.name}" | ||
} | ||
|
||
resource "google_cloud_run_v2_service" "default" { | ||
name = "example-service-${var.env}" | ||
location = var.location | ||
launch_stage = "GA" | ||
|
||
template { | ||
service_account = google_service_account.cloudrun_service_account.email | ||
containers { | ||
image = var.example_gcp_docker_image | ||
name = "example-gcp" | ||
args = [ | ||
"--logtostderr", | ||
"--v=1", | ||
"--bucket=${module.gcs.log_bucket.id}", | ||
"--spanner=${local.spanner_db_full}", | ||
"--project=${var.project_id}", | ||
"--listen=:8080", | ||
"--kms_key=${google_kms_crypto_key_version.log_signer.id}", | ||
"--origin=${var.log_origin}", | ||
] | ||
ports { | ||
container_port = 8080 | ||
} | ||
|
||
startup_probe { | ||
initial_delay_seconds = 1 | ||
timeout_seconds = 1 | ||
period_seconds = 10 | ||
failure_threshold = 3 | ||
tcp_socket { | ||
port = 8080 | ||
} | ||
} | ||
} | ||
} | ||
client = "terraform" | ||
depends_on = [ | ||
module.gcs, | ||
google_project_service.cloudrun_api, | ||
google_project_iam_member.iam_act_as, | ||
google_project_iam_member.iam_metrics_writer, | ||
google_project_iam_member.iam_service_agent, | ||
google_spanner_database_iam_binding.iam_spanner_database_user, | ||
] | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
variable "project_id" { | ||
description = "GCP project ID where the log is hosted" | ||
type = string | ||
} | ||
|
||
variable "base_name" { | ||
description = "Base name to use when naming resources" | ||
type = string | ||
} | ||
|
||
variable "location" { | ||
description = "Location in which to create resources" | ||
type = string | ||
} | ||
|
||
variable "env" { | ||
description = "Environment name, e.g ci, prod, etc." | ||
type = string | ||
} | ||
|
||
variable "example_gcp_docker_image" { | ||
description = "The full image URL (path & tag) for the example-gcp Docker image to deploy" | ||
type = string | ||
} | ||
|
||
variable "log_origin" { | ||
description = "The origin string for the example log" | ||
type = string | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This double slash is a bit weird?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is how you tell terraform about module "boundaries", with the double slash it brings in anything under there, without them it fails when you try to reference the sibling
gcs
from within theexample-gc
module.This is a bit of a dusty corner in terraform, but it's why e.g. you had to put double slashes in for your distributor config which referenced other modules: https://github.com/transparency-dev/distributor/blob/main/deployment/modules/distributor/main.tf#L110