Skip to content
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

Add Resources for Vault Server in Roundtable #490

Merged
merged 13 commits into from
Feb 26, 2024
Merged
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"
}
}
10 changes: 9 additions & 1 deletion environment/deployments/roundtable/env/dev.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,13 @@ activate_apis = [
"sqladmin.googleapis.com"
]

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

vault_server_bucket_suffix = "vault-server-dev"
vault_server_backup_bucket_suffix = "vault-server-dev-backup"

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

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

vault_server_bucket_suffix = "vault-server"
vault_server_backup_bucket_suffix = "vault-server-backup"

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

100 changes: 100 additions & 0 deletions environment/deployments/roundtable/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,70 @@ 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 = {
vault-server = false
}
force_destroy = {
vault-server = false
}
labels = {
environment = var.environment
application = "vault"
}
}

// Vault Server Storage Bucket (Backup)
// Note that we don't need all the SA/WI access to this: the only thing it's
// going to be used for is a copy target. We may need a different SA to
// run the backups.
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_backup_bucket_suffix ]
prefix_name = "rubin"
versioning = {
vault-server = false
}
force_destroy = {
vault-server = false
}
labels = {
environment = var.environment
application = "vault"
}
}

// 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
}

# 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 +141,42 @@ resource "google_service_account_iam_binding" "git-lfs-ro-gcs-binding" {
]
}

# 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"
]
}

module "service_account_cluster" {
source = "terraform-google-modules/service-accounts/google"
version = "~> 2.0"
Expand Down
22 changes: 22 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,24 @@ 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"
}

variable "vault_server_backup_bucket_suffix" {
type = string
description = "Suffix for bucket used for Vault server storage backup"
}
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` |

98 changes: 98 additions & 0 deletions modules/kms/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
variable "project_id" {
description = "Project id where the keyring will be created."
type = string
}

variable "location" {
description = "Location for the keyring."
type = string
}

variable "keyring" {
description = "Keyring name."
type = string
}

variable "keys" {
description = "Key names."
type = list(string)
default = []
}

variable "set_decrypters_for" {
description = "Name of keys for which decrypters will be set."
type = list(string)
default = []
}

variable "set_encrypters_for" {
description = "Name of keys for which encrypters will be set."
type = list(string)
default = []
}

variable "set_owners_for" {
description = "Name of keys for which owners will be set."
type = list(string)
default = []
}

variable "decrypters" {
description = "List of comma-separated decrypters for each key declared in set_decrypters_for."
type = list(string)
default = []
}

variable "encrypters" {
description = "List of comma-separated encrypters for each key declared in set_encrypters_for."
type = list(string)
default = []
}

variable "owners" {
description = "List of comma-separated owners for each key declared in set_owners_for."
type = list(string)
default = []
}

variable "key_algorithm" {
description = "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."
type = string
default = "GOOGLE_SYMMETRIC_ENCRYPTION"
}

variable "key_destroy_scheduled_duration" {
description = "Set the period of time that versions of keys spend in the DESTROY_SCHEDULED state before transitioning to DESTROYED."
type = string
default = null
}

variable key_protection_level {
description = "The protection level to use when creating a version based on this template. Possible values are SOFTWARE and HSM."
type = string
default = "SOFTWARE"
}

variable "key_rotation_period" {
description = "Generate a new key every time this period passes."
type = string
default = "7776000s"
}

variable "labels" {
description = "Labels, provided as a map."
type = map(string)
default = {}
}

variable "prevent_destroy" {
description = "Set the prevent_destroy lifecycle attribute on keys."
type = bool
default = true
}

variable "purpose" {
description = "The immutable purpose of the CryptoKey. Possible values are ENCRYPT_DECRYPT, ASYMMETRIC_SIGN, and ASYMMETRIC_DECRYPT."
type = string
default = "ENCRYPT_DECRYPT"
}
Loading