FAQ | This is a LIVE service | Changelog

Commit e13f2107 authored by Dr Abraham Martin's avatar Dr Abraham Martin
Browse files

Merge branch '20-direct-secret-loading' into 'master'

Resolve "Support loading secrets directly into services"

Closes #20

See merge request !25
parents 07374fd0 e2d18877
Pipeline #90736 passed with stage
in 47 seconds
......@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.0.0] - 2021-06-08
### Added
- Raised the provider to 3.70, adding the BETA requirement and the capability to
directly expose secrets manager secrets as files and env vars.
## [2.0.5] - 2021-05-28
### Changed
- Remove the requirement of BETA staging when the minimum instance number is above 0
......
......@@ -105,3 +105,59 @@ The static ip is configured with `prevent_destroy = true`, meaning that it canno
without removing it from terraform state using `terraform state rm` and then manually destroying
the resource within the GCP console. This is to prevent accidental destruction of an IP which
is likely to be whitelisted within firewall configuration that lives outside of our deployments.
## Secrets as Volumes and Env Vars
Secret Manager IDs can be directly referenced and exposed as environment variables
and volume mounts (files) in the running container.
At time of writing, the BETA Google Provider must be enabled.
Any number of items in the list is supported and not defining these variables
when calling this module is acceptable. The path of the mounted file will be
based on `path/name`.
For the example configuration below the files will be `/secrets-1/foobarfile1`
and `/secrets-2/foobarfile2`. A common `path` for multiple secrets is not supported, they must
be unique.
> Note: `name` should only have alphanumeric characters, hyphens and underscores.
Setting `version = ""` is equivalent to `version = "latest"` but the variable is not optional.
```tf
module "webapp" {
source = "git::https://gitlab.developers.cam.ac.uk/uis/devops/infra/terraform/gcp-cloud-run-app.git?ref=v3"
...
secrets_volume = [
{
name = "foobarfile1"
path = "/secret-1"
id = google_secret_manager_secret.secret-a.secret_id
version = "latest"
},
{
name = "foobarfile2"
path = "/secret-2"
id = google_secret_manager_secret.secret-b.secret_id
version = "2"
}
]
secrets_envars = [
{
name = "FOOBAR1"
id = google_secret_manager_secret.secret-c.secret_id
version = "latest"
},
{
name = "FOOBAR2"
id = google_secret_manager_secret.secret-d.secret_id
version = ""
}
]
...
```
......@@ -2,7 +2,7 @@
This is a simple example of deploying a Cloud Run hosted container into a
GCP project. Specify the project to deploy into and the sql instance to connect to
on the command line. The sql instance connection is optional, use an empty string
on the command line. The sql instance connection is optional, use an empty string
if you do not want to connect Cloud Run to a SQL instance.
So, for example, to deploy to the project ``my-project``:
......
......@@ -8,9 +8,9 @@ locals {
domain_mapping_present = var.dns_name != ""
# Do we need to enable the 'beta' launch stage - only required if certain beta
# functionality is being used, or if `enable_beta_launch_stage` is set downstream
# functionality is being used, or if `enable_beta_launch_stage` is set downstream.
enable_beta_launch_stage = (
var.enable_beta_launch_stage
var.enable_beta_launch_stage || length(var.secrets_volume) != 0 || length(var.secrets_envars) != 0
)
# Whether we should monitor the custom domain - only possible if there is a dns_name
......
......@@ -24,6 +24,9 @@ resource "google_cloud_run_service" "webapp" {
location = var.cloud_run_region
project = var.project
# Google Beta provider is required for mounting secrets AToW
provider = google-beta
autogenerate_revision_name = true
metadata {
......@@ -42,7 +45,7 @@ resource "google_cloud_run_service" "webapp" {
# Add the beta launch stage if required.
local.enable_beta_launch_stage ? {
# Required to be able to set ingress type.
# Required to be able to set ingress type and secrets volume mounts
"run.googleapis.com/launch-stage" : "BETA",
} : {},
......@@ -126,6 +129,41 @@ resource "google_cloud_run_service" "webapp" {
value = env.value
}
}
dynamic "env" {
for_each = var.secrets_envars
content {
name = env.value["name"]
value_from {
secret_key_ref {
name = env.value["id"]
key = coalesce(env.value["version"], "latest")
}
}
}
}
dynamic "volume_mounts" {
for_each = var.secrets_volume
content {
name = volume_mounts.value["name"]
mount_path = volume_mounts.value["path"]
}
}
}
dynamic "volumes" {
for_each = var.secrets_volume
content {
name = volumes.value["name"]
secret {
secret_name = volumes.value["id"]
items {
key = coalesce(volumes.value["version"], "latest")
path = volumes.value["name"]
}
}
}
}
timeout_seconds = var.timeout_seconds
......
......@@ -194,4 +194,34 @@ EOL
variable "static_egress_ip_cidr_range" {
default = "10.124.0.0/28"
description = "The cidr range used to create a subnet that this cloud run will use if assigned a static ip"
}
\ No newline at end of file
}
variable "secrets_volume" {
type = list(object({
name = string # name of the file that is going to be mounted
path = string # name of the directory of the volume mount. e.g. "/secrets". Must be unique for each secret.
id = string # id of the GCP Cloud Secret Manager secret
version = string # version of the GCP Cloud Secret Manager secret, defaults to "latest" if empty
}))
default = []
description = <<-EOL
Optional. If containing a list of maps specifying a Secret Manager secret ID,
a name and a secret version, will create named files from the secrets.
EOL
}
variable "secrets_envars" {
type = list(object({
name = string # name of the environment variables
id = string # id of the GCP Cloud Secret Manager secret
version = string # version of the GCP Cloud Secret Manager secret, defaults to "latest" if empty
}))
default = []
description = <<-EOL
Optional. If containing a list of maps specifying a Secret Manager secret ID,
a name and a secret version, will create named environment variables from the
secrets.
EOL
}
......@@ -2,7 +2,7 @@
terraform {
required_providers {
google = "~> 3.61"
google-beta = "~> 3.61"
google = "~> 3.70"
google-beta = "~> 3.70"
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment