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

feat!: adds support to multiple service projects and Shared VPC #115

14 changes: 7 additions & 7 deletions examples/secure_cloud_run_standalone/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ resource "random_id" "random_folder_suffix" {
}

module "secure_harness" {
source = "../../modules/secure-cloud-serverless-harness"
source = "../../modules/secure-serverless-harness"
billing_account = var.billing_account
security_project_name = "prj-kms-secure-cloud-run"
serverless_project_name = "prj-secure-cloud-run"
serverless_project_names = ["prj-secure-cloud-run"]
org_id = var.org_id
parent_folder_id = var.parent_folder_id
serverless_folder_suffix = random_id.random_folder_suffix.hex
Expand Down Expand Up @@ -65,18 +65,18 @@ module "secure_cloud_run" {
source = "../../modules/secure-cloud-run"
location = local.location
region = local.region
serverless_project_id = module.secure_harness.serverless_project_id
vpc_project_id = module.secure_harness.serverless_project_id
serverless_project_id = module.secure_harness.serverless_project_ids[0]
vpc_project_id = module.secure_harness.network_project_id[0]
kms_project_id = module.secure_harness.security_project_id
key_name = "key-secure-cloud-run"
keyring_name = "krg-secure-cloud-run"
service_name = "srv-secure-cloud-run"
image = "${local.location}-docker.pkg.dev/${module.secure_harness.security_project_id}/${module.secure_harness.artifact_registry_repository_name}/hello:latest"
cloud_run_sa = module.secure_harness.service_account_email
cloud_run_sa = module.secure_harness.service_account_email[module.secure_harness.serverless_project_ids[0]]
connector_name = "con-secure-cloud-run"
subnet_name = module.secure_harness.service_subnet
subnet_name = module.secure_harness.service_subnet[0]
create_subnet = false
shared_vpc_name = module.secure_harness.service_vpc.network_name
shared_vpc_name = module.secure_harness.service_vpc[0].network_name
ip_cidr_range = "10.0.0.0/28"
prevent_destroy = false
artifact_registry_repository_location = local.location
Expand Down
12 changes: 6 additions & 6 deletions examples/secure_cloud_run_standalone/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
*/

output "serverless_project_id" {
value = module.secure_harness.serverless_project_id
value = module.secure_harness.serverless_project_ids[0]
description = "The serverless project id."
}

output "serverless_project_number" {
value = module.secure_harness.serverless_project_number
value = module.secure_harness.serverless_project_numbers[module.secure_harness.serverless_project_ids[0]]
description = "The serverless project number."
}

Expand All @@ -35,22 +35,22 @@ output "security_project_number" {
}

output "service_account_email" {
value = module.secure_harness.service_account_email
value = module.secure_harness.service_account_email[module.secure_harness.serverless_project_ids[0]]
description = "The service account email created to be used by Cloud Run."
}

output "service_vpc_self_link" {
value = module.secure_harness.service_vpc.network.self_link
value = module.secure_harness.service_vpc[0].network.self_link
description = "The Network self-link created in harness."
}

output "service_vpc_name" {
value = module.secure_harness.service_vpc.network_name
value = module.secure_harness.service_vpc[0].network_name
description = "The Network self-link created in harness."
}

output "service_vpc_subnet_name" {
value = module.secure_harness.service_subnet
value = module.secure_harness.service_subnet[0]
description = "The sub-network name created in harness."
}

Expand Down
3 changes: 2 additions & 1 deletion modules/secure-cloud-run/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ module "vpc_project_apis" {
}

module "cloud_run_network" {
source = "../secure-cloud-serverless-net"
source = "../secure-serverless-net"

connector_name = var.connector_name
subnet_name = var.subnet_name
Expand All @@ -56,6 +56,7 @@ module "cloud_run_network" {
ip_cidr_range = var.ip_cidr_range
create_subnet = var.create_subnet
resource_names_suffix = var.resource_names_suffix
serverless_type = "CLOUD_RUN"

serverless_service_identity_email = google_project_service_identity.serverless_sa.email

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ module "secure_cloud_run_harness" {
| key\_rotation\_period | Period of key rotation in seconds. Default value is equivalent to 30 days. | `string` | `"2592000s"` | no |
| keyring\_name | Keyring name. | `string` | n/a | yes |
| location | The location where resources are going to be deployed. | `string` | n/a | yes |
| network\_project\_name | The name to give the shared vpc project. | `string` | `""` | no |
| org\_id | The organization ID. | `string` | n/a | yes |
| owners | List of comma-separated owners for each key declared in set\_owners\_for. | `list(string)` | `[]` | no |
| parent\_folder\_id | The ID of a folder to host the infrastructure created in this module. | `string` | `""` | no |
Expand All @@ -78,10 +79,11 @@ module "secure_cloud_run_harness" {
| region | The region in which the subnetwork will be created. | `string` | n/a | yes |
| security\_project\_name | The name to give the security project. | `string` | n/a | yes |
| serverless\_folder\_suffix | The suffix to be concat in the Serverless folder name fldr-serverless-<SUFFIX>. | `string` | `""` | no |
| serverless\_project\_name | The name to give the Cloud Run project. | `string` | n/a | yes |
| serverless\_project\_names | The name to give the Cloud Serverless project. | `list(string)` | n/a | yes |
| serverless\_type | The type of resource to be used. It supports only CLOUD\_RUN or CLOUD\_FUNCTION | `string` | n/a | yes |
| service\_account\_project\_roles | Common roles to apply to the Cloud Run service account in the serverless project. | `list(string)` | `[]` | no |
| service\_account\_project\_roles | Common roles to apply to the Cloud Serverless service account in the serverless project. | `map(list(string))` | `{}` | no |
| subnet\_ip | The CDIR IP range of the subnetwork. | `string` | n/a | yes |
| use\_shared\_vpc | Defines if the network created will be a single or shared vpc. | `bool` | `false` | no |
| vpc\_name | The name of the network. | `string` | n/a | yes |

## Outputs
Expand All @@ -90,17 +92,19 @@ module "secure_cloud_run_harness" {
|------|-------------|
| artifact\_registry\_repository\_id | The Artifact Registry Repository full identifier where the images should be stored. |
| artifact\_registry\_repository\_name | The Artifact Registry Repository last part of the repository name where the images should be stored. |
| cloud\_run\_service\_identity\_email | The Cloud Run Service Identity email. |
| cloud\_serverless\_service\_identity\_email | The Cloud Run Service Identity email. |
| cloudfunction\_source\_bucket | Cloud Function Source Bucket. |
| network\_project\_id | Project ID of the project created to host the Cloud Run Network. |
| restricted\_access\_level\_name | Access level name. |
| restricted\_service\_perimeter\_name | Service Perimeter name. |
| security\_project\_id | Project ID of the project created for KMS and Artifact Register. |
| security\_project\_number | Project number of the project created for KMS and Artifact Register. |
| serverless\_folder\_id | The folder created to alocate Serverless infra. |
| serverless\_project\_id | Project ID of the project created to deploy Cloud Run. |
| serverless\_project\_number | Project number of the project created to deploy Cloud Run. |
| service\_account\_email | The email of the Service Account created to be used by Cloud Run. |
| serverless\_project\_ids | Project ID of the projects created to deploy Cloud Run. |
| serverless\_project\_numbers | Project number of the projects created to deploy Cloud Run. |
| service\_account\_email | The email of the Service Account created to be used by Cloud Serverless. |
| service\_subnet | The sub-network name created in harness. |
| service\_vpc | The network created for Cloud Run. |
| service\_vpc | The network created for Cloud Serverless. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,33 @@
*/

locals {
api = var.serverless_type == "CLOUD_RUN" ? "run" : "cloudfunctions"
serverless_apis = [
api = var.serverless_type == "CLOUD_FUNCTION" ? ["cloudfunctions.googleapis.com", "cloudbuild.googleapis.com", "eventarc.googleapis.com", "eventarcpublishing.googleapis.com"] : []
serverless_apis = concat([
"vpcaccess.googleapis.com",
"compute.googleapis.com",
"container.googleapis.com",
"artifactregistry.googleapis.com",
"${local.api}.googleapis.com",
"run.googleapis.com",
"cloudkms.googleapis.com",
"dns.googleapis.com"
]
], local.api)
kms_apis = [
"cloudkms.googleapis.com",
"artifactregistry.googleapis.com"
]

decrypters = join(",", concat(["serviceAccount:${google_project_service_identity.artifact_sa.email}"], var.decrypters))
encrypters = join(",", concat(["serviceAccount:${google_project_service_identity.artifact_sa.email}"], var.encrypters))
network_apis = [
"vpcaccess.googleapis.com",
"compute.googleapis.com",
"dns.googleapis.com"
]

network_project_id = var.use_shared_vpc ? module.network_project[0].project_id : ""

eventarc_identities = [for project in module.serverless_project : "serviceAccount:${project.services_identities["eventarc"]}"]
gcs_identities = [for project in module.serverless_project : "serviceAccount:${project.services_identities["gcs"]}"]
decrypters = join(",", concat(["serviceAccount:${google_project_service_identity.artifact_sa.email}"], local.eventarc_identities, local.gcs_identities, var.decrypters))
encrypters = join(",", concat(["serviceAccount:${google_project_service_identity.artifact_sa.email}"], local.eventarc_identities, local.gcs_identities, var.encrypters))

}

Expand All @@ -40,82 +50,45 @@ resource "google_folder" "fld_serverless" {
parent = var.parent_folder_id == "" ? "organizations/${var.org_id}" : "folders/${var.parent_folder_id}"
}

module "security_project" {
module "network_project" {
count = var.use_shared_vpc ? 1 : 0
source = "terraform-google-modules/project-factory/google"
version = "~> 13.0"
version = "~> 14.2"
random_project_id = "true"
activate_apis = local.kms_apis
name = var.security_project_name
activate_apis = local.network_apis
name = var.network_project_name
org_id = var.org_id
billing_account = var.billing_account
folder_id = google_folder.fld_serverless.name

enable_shared_vpc_host_project = true
}

module "serverless_project" {
module "security_project" {
source = "terraform-google-modules/project-factory/google"
version = "~> 13.0"
version = "~> 14.2"
random_project_id = "true"
activate_apis = local.serverless_apis
name = var.serverless_project_name
activate_apis = local.kms_apis
name = var.security_project_name
org_id = var.org_id
billing_account = var.billing_account
folder_id = google_folder.fld_serverless.name
}

module "service_accounts" {
source = "terraform-google-modules/service-accounts/google"
version = "~> 3.0"
project_id = module.serverless_project.project_id
prefix = "sa"
names = ["serverless-${local.api}"]

depends_on = [
time_sleep.wait_90_seconds
]
}

resource "google_project_iam_member" "cloud_run_sa_roles" {
for_each = toset(var.service_account_project_roles)
project = module.serverless_project.project_id
role = each.value
member = module.service_accounts.iam_email

depends_on = [
time_sleep.wait_90_seconds
]
}

resource "google_project_service_identity" "serverless_sa" {
provider = google-beta

project = module.serverless_project.project_id
service = "${local.api}.googleapis.com"

depends_on = [
time_sleep.wait_90_seconds
]
}
module "serverless_project" {
source = "../service-project-factory"

resource "google_service_account_iam_member" "identity_service_account_user" {
service_account_id = module.service_accounts.service_account.id
role = "roles/iam.serviceAccountUser"
member = "serviceAccount:${google_project_service_identity.serverless_sa.email}"
for_each = toset(var.serverless_project_names)

depends_on = [
time_sleep.wait_90_seconds
]
billing_account = var.billing_account
serverless_type = var.serverless_type
org_id = var.org_id
activate_apis = local.serverless_apis
folder_name = google_folder.fld_serverless.name
project_name = each.value
service_account_project_roles = length(var.service_account_project_roles) > 0 ? var.service_account_project_roles[each.value] : []
}

resource "google_project_service_identity" "artifact_sa" {
provider = google-beta

project = module.security_project.project_id
service = "artifactregistry.googleapis.com"

depends_on = [
time_sleep.wait_90_seconds
]
}

resource "google_artifact_registry_repository" "repo" {
project = module.security_project.project_id
Expand All @@ -126,19 +99,20 @@ resource "google_artifact_registry_repository" "repo" {
kms_key_name = module.artifact_registry_kms.keys[var.key_name]

depends_on = [
time_sleep.wait_90_seconds
time_sleep.wait_180_seconds
]
}

resource "google_artifact_registry_repository_iam_member" "member" {
for_each = module.serverless_project
project = module.security_project.project_id
location = var.location
repository = google_artifact_registry_repository.repo.repository_id
role = "roles/artifactregistry.reader"
member = "serviceAccount:${google_project_service_identity.serverless_sa.email}"
member = "serviceAccount:${each.value.cloud_serverless_service_identity_email}"

depends_on = [
time_sleep.wait_90_seconds
time_sleep.wait_180_seconds
]
}

Expand All @@ -161,6 +135,38 @@ module "artifact_registry_kms" {
key_protection_level = var.key_protection_level

depends_on = [
time_sleep.wait_90_seconds
time_sleep.wait_180_seconds
]
}

resource "google_project_service_identity" "artifact_sa" {
provider = google-beta

project = module.security_project.project_id
service = "artifactregistry.googleapis.com"

depends_on = [
time_sleep.wait_180_seconds
]
}

module "cloudfunction_source_bucket" {
for_each = var.serverless_type == "CLOUD_RUN" ? {} : module.serverless_project
source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket"
version = "~>3.4"

project_id = each.value.project_id
name = "bkt-${var.location}-${each.value.project_number}-cfv2-zip-files"
location = var.location
storage_class = "REGIONAL"
force_destroy = true

encryption = {
default_kms_key_name = module.artifact_registry_kms.keys[var.key_name]
}

depends_on = [
module.artifact_registry_kms,
time_sleep.wait_180_seconds
]
}
Loading