Skip to content

Commit

Permalink
Merge pull request #490 from lsst/tickets/DM-42884
Browse files Browse the repository at this point in the history
Add Resources for Vault Server in Roundtable
  • Loading branch information
athornton authored Feb 26, 2024
2 parents 599a789 + 5f14f10 commit 5c6f187
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 4 deletions.
4 changes: 2 additions & 2 deletions environment/deployments/roundtable/backend.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ terraform {
backend "gcs" {
}
required_providers {
google = "~> 3.51.0"
google-beta = "~> 3.51.0"
google = ">= 3.51.0"
google-beta = ">= 3.51.0"
}
}
9 changes: 8 additions & 1 deletion environment/deployments/roundtable/env/dev.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,12 @@ activate_apis = [
"sqladmin.googleapis.com"
]

# Vault service service account
vault_server_service_accounts = [
"serviceAccount:[email protected]"
]

vault_server_bucket_suffix = "vault-server-dev"

# Increase this number to force Terraform to update the dev environment.
# Serial: 5
# Serial: 6
10 changes: 9 additions & 1 deletion environment/deployments/roundtable/env/production.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,13 @@ activate_apis = [
"sqladmin.googleapis.com"
]

# Vault service service account
vault_server_service_accounts = [
"serviceAccount:[email protected]"
]

vault_server_bucket_suffix = "vault-server"

# Increase this number to force Terraform to update the prod environment.
# Serial: 5
# Serial: 6

156 changes: 156 additions & 0 deletions environment/deployments/roundtable/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,161 @@ module "iam_admin" {
member = "gcp-${var.application_name}[email protected]"
}

// Vault server key management
// prod
module "kms" {
source = "../../../modules/kms"
project_id = module.project_factory.project_id
location = "us-central1"
keyring = "vault-server"
keys = [ "vault-seal" ]
set_owners_for = [ "vault-seal" ]
decrypters = var.vault_server_service_accounts
encrypters = var.vault_server_service_accounts
owners = var.vault_server_service_accounts
}

// Vault Server Storage Bucket
module "storage_bucket" {
source = "../../../modules/bucket"
project_id = module.project_factory.project_id
storage_class = "REGIONAL"
location = "us-central1"
suffix_name = [ var.vault_server_bucket_suffix ]
prefix_name = "rubin"
versioning = {
(var.vault_server_bucket_suffix) = true
}
lifecycle_rules = [
{
action = {
type = "Delete"
}
condition = {
num_newer_versions = 3
}
}
]
force_destroy = {
(var.vault_server_bucket_suffix) = false
}
labels = {
environment = var.environment
application = "vault"
}
}

// Vault Server Storage Bucket (Backup)
module "storage_bucket_b" {
source = "../../../modules/bucket"
project_id = module.project_factory.project_id
storage_class = "REGIONAL"
location = "us-central1"
suffix_name = [ "${var.vault_server_bucket_suffix}-backup" ]
prefix_name = "rubin"
versioning = {
"${var.vault_server_bucket_suffix}-backup" = true
}
lifecycle_rules = [
{
action = {
type = "Delete"
}
condition = {
num_newer_versions = "20"
}
}
]
force_destroy = {
"${var.vault_server_bucket_suffix}-backup" = false
}
labels = {
environment = var.environment
application = "vault"
}
}

// Service account and bindings for Vault Server

// Service account for Vault Server
resource "google_service_account" "vault_server_sa" {
account_id = "vault-server"
display_name = "Vault Server"
description = "Terraform-managed service account for Vault server"
project = module.project_factory.project_id
}

// Use Workload Identity to have the service run as the appropriate service
// account (bound to a Kubernetes service account)
resource "google_service_account_iam_binding" "vault-server-sa-wi" {
service_account_id = google_service_account.vault_server_sa.name
role = "roles/iam.workloadIdentityUser"
members = [
"serviceAccount:${module.project_factory.project_id}.svc.id.goog[vault/vault]"
]
}

// The Vault service account must be granted the roles Cloud KMS Viewer and
// Cloud KMS CryptoKey Encrypter/Decrypter
resource "google_service_account_iam_binding" "vault-server-viewer-binding" {
service_account_id = google_service_account.vault_server_sa.name
role = "roles/cloudkms.viewer"
members = [
"serviceAccount:vault-server@${module.project_factory.project_id}.iam.gserviceaccount.com"
]
}

resource "google_service_account_iam_binding" "vault-server-cryptokey-binding" {
service_account_id = google_service_account.vault_server_sa.name
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
members = [
"serviceAccount:vault-server@${module.project_factory.project_id}.iam.gserviceaccount.com"
]
}

// RW storage access to Vault Server bucket
resource "google_storage_bucket_iam_binding" "vault-server-storage-binding" {
bucket = module.storage_bucket.name
role = "roles/storage.objectUser"
members = var.vault_server_service_accounts
}

// Admin storage access to Vault Server backup bucket
resource "google_storage_bucket_iam_binding" "vault-server-storage-backup-binding" {
bucket = module.storage_bucket_b.name
role = "roles/storage.admin"
members = var.vault_server_service_accounts
}

// Resources for Vault Server storage backups

resource "google_storage_transfer_job" "vault-server-storage-backup" {
description = "Nightly backup of Vault Server storage"
project = module.project_factory.project_id
transfer_spec {
gcs_data_source {
bucket_name = module.storage_bucket.name
}
gcs_data_sink {
bucket_name = module.storage_bucket_b.name
}
}
schedule {
schedule_start_date {
year = 2024
month = 1
day = 1
}
start_time_of_day { // UTC: 2 AM Pacific Standard Time
hours = 10
minutes = 0
seconds = 0
nanos = 0
}
}
depends_on = [ google_storage_bucket_iam_binding.vault-server-storage-backup-binding ]
}

# Service account for Git LFS read/write
resource "google_service_account" "git_lfs_rw_sa" {
account_id = "git-lfs-rw"
Expand Down Expand Up @@ -77,6 +232,7 @@ resource "google_service_account_iam_binding" "git-lfs-ro-gcs-binding" {
]
}


module "service_account_cluster" {
source = "terraform-google-modules/service-accounts/google"
version = "~> 2.0"
Expand Down
17 changes: 17 additions & 0 deletions environment/deployments/roundtable/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ variable "activate_apis" {
description = "The api to activate for the GCP project"
type = list(string)
default = [
"cloudkms.googleapis.com",
"compute.googleapis.com",
"container.googleapis.com",
"stackdriver.googleapis.com",
Expand Down Expand Up @@ -176,3 +177,19 @@ variable "static_ip_name" {
type = string
default = "load-balancer"
}

# SERVICE ACCOUNTS

// Vault Server
variable "vault_server_service_accounts" {
type = list(string)
description = "Service accounts used for Vault-Server access"
default = []
}

# Buckets

variable "vault_server_bucket_suffix" {
type = string
description = "Suffix for bucket used for Vault server storage"
}
22 changes: 22 additions & 0 deletions modules/kms/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module "kms" {
source = "terraform-google-modules/kms/google"
version = ">= 2.0"

project_id = var.project_id
location = var.location
keyring = var.keyring
keys = var.keys
set_decrypters_for = var.set_decrypters_for
set_encrypters_for = var.set_encrypters_for
set_owners_for = var.set_owners_for
decrypters = var.decrypters
encrypters = var.encrypters
owners = var.owners
labels = var.labels
key_algorithm = var.key_algorithm
key_destroy_scheduled_duration = var.key_destroy_scheduled_duration
key_protection_level = var.key_protection_level
key_rotation_period = var.key_rotation_period
prevent_destroy = var.prevent_destroy
purpose = var.purpose
}
19 changes: 19 additions & 0 deletions modules/kms/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
output "keyring" {
description = "Self link of the keyring."
value = module.kms.keyring
}

output "keyring_name" {
description = "Name of the keyring."
value = module.kms.keyring_name
}

output "keyring_resource" {
description = "Keyring resource."
value = module.kms.keyring_resource
}

output "keys" {
description = "Map of key name => key self link."
value = module.kms.keys
}
37 changes: 37 additions & 0 deletions modules/kms/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Terraform module for KMS

This enables creation of a KMS keyring and one or more keys with linked owner/encrypter/decrypter service accounts.

It is used by Rubin Observatory to store seal keys for the Vault server that backs K8s vault-secrets-operator. In expected use, `project_id`, `location`, `keyring`, `keys`, and access information will be set, and everything else will be left at its default value.

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|----------|
| project\_id | Project id where the keyring will be created. | `string` | n/a | yes |
| location | Location for the keyring. | `string` | n/a | yes |
| keyring | Keyring name. | `string` | n/a | yes |
| keys | Key names. | `list(string)` | `[]` | no |
| set\_decrypters\_for | Name of keys for which decrypters will be set. | `list(str)` | `[]` | no |
| set\_encrypters\_for | Name of keys for which encrypters will be set. | `list(str)` | `[]` | no |
| set\_owners\_for | Name of keys for which owners will be set. | `list(str)` | `[]` | no |
| decrypters | List of comma-separated decrypters for each key declared in set\_decrypters\_for. | `list(str)` | `[]` | no |
| encrypters | List of comma-separated encrypters for each key declared in set\_encrypters\_for. | `list(str)` | `[]` | no |
| owners | List of comma-separated owners for each key declared in set\_owners\_for. | `list(str)` | `[]` | no |
| key\_algorithm | The algorithm to use when creating a version based on this template. See the https://cloud.google.com/kms/docs/reference/rest/v1/CryptoKeyVersionAlgorithm for possible inputs. | `string` | `"GOOGLE_SYMMETRIC_ENCRYPTION"` | no |
| key\_destroy\_scheduled\_duration | Set the period of time that versions of keys spend in the DESTROY_SCHEDULED state before transitioning to DESTROYED. | `string` | null | no |
| key\_protection\_level | The protection level to use when creating a version based on this template. Possible values are SOFTWARE and HSM. | `string` | `"SOFTWARE"` | no |
| key\_rotation\_peroid | Generate a new key every time this period passes. | `string` | `"7776000s"` | no |
| labels | Labels, provided as a map. | `map(string)` | `{}` | no |
| prevent\_destroy | Set the prevent\_destroy lifecycle attribute on keys. | `bool` | `true` | no |
| purpose | The immutable purpose of the CryptoKey. Possible values are ENCRYPT\_DECRYPT, ASYMMETRIC\_SIGN, and ASYMMETRIC\_DECRYPT. | `string` | `"ENCRYPT_DECRYPT"` | no |

## Outputs

| Name | Description | Value |
|------|-------------|-------|
| keyring | Self link of the keyring. | `module.kms.keyring` |
| keyring\_name | Name of the keyring. | `module.kms.keyring_name` |
| keyring\_resource | Keyring resource. | `module.kms.keyring_resource` |
| keys | Map of key name => key self link. | `module.kms.keys` |

Loading

0 comments on commit 5c6f187

Please sign in to comment.