main.tf (165 lines of code) (raw):

/** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ # Append all resource names to help with testing # buckets must be all lowercase for buckets resource "random_string" "random_name" { length = 4 min_lower = 4 special = false } locals { region = split("-", var.zone)[0] folder_trusted = "folders/${data.google_project.trusted_analytics.folder_id}" bootstrap_bkt_name = format("restricted-%s-%s", var.bootstrap_notebooks_bucket_name, random_string.random_name.result) } # The key ring holds data keys that encrypt any PII data at rest such as BQ, GCS, or boot images. # Initial key is HSM backed key rotates every 45 days. module "kms_data" { source = "terraform-google-modules/kms/google" version = "~> 1.2" project_id = var.project_trusted_kms location = local.region keyring = format("trusted-data-keyring-%s", random_string.random_name.result) keys = [var.notebook_key_name] key_protection_level = "HSM" key_rotation_period = "3888000s" # 45 days } module "bootstrap" { source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket" version = "~> 1.7" project_id = var.project_trusted_kms name = local.bootstrap_bkt_name location = local.region force_destroy = true encryption = { default_kms_key_name = module.kms_data.keys[var.notebook_key_name] } } # IAM for the AI Platform user service account to read the post startup script. resource "google_storage_bucket_iam_member" "member" { bucket = module.bootstrap.bucket.name role = "roles/storage.objectViewer" member = "serviceAccount:${google_service_account.sa_p_notebook_compute.email}" } resource "google_storage_bucket_object" "postscript" { name = "post_startup_script.sh" source = "${path.module}/bootstrap_files/post_startup_script.sh" bucket = module.bootstrap.bucket.name } # IAM policy for each user (ie. data scientist) resource "google_project_iam_member" "notebook_caip_user_iam" { project = var.project_trusted_analytics role = "roles/notebooks.viewer" for_each = toset(var.trusted_scientists) member = each.value } # Creates a trusted notebook per relevant user that has file # download disabled. Although some values are hard-coded, you can # customize them using variables. resource "google_notebooks_instance" "caip_nbk_p_trusted" { provider = google-beta project = var.project_trusted_analytics # var.trusted_scientists has users that are defined with the IAM type such as "user:aaa@example.com", "group:bbb@example.com", "serviceAccount:ccc@example.com". # Therefore, we need to remove the prefix type for_each = toset(split("\n",replace(join("\n",tolist(var.trusted_scientists)),"/\\S+:/",""))) service_account = google_service_account.sa_p_notebook_compute.email # replace characters with dash (-) from user identities not supported in GCE instance names such as period (.), apostrophe ('), underscore (_) name = format("caip-nbk-%s-%s-%s", var.notebook_name_prefix, split("@", replace(each.value, "/[.'_]+/", "-"))[0], random_string.random_name.result) location = var.zone machine_type = "n1-standard-1" vm_image { project = "deeplearning-platform-release" image_family = "tf-latest-cpu" } instance_owners = [each.value] post_startup_script = format("%s/%s", module.bootstrap.bucket.url, google_storage_bucket_object.postscript.name) install_gpu_driver = false boot_disk_type = "PD_SSD" boot_disk_size_gb = 110 disk_encryption = "CMEK" kms_key = module.kms_data.keys[var.notebook_key_name] # only allow network with private IP no_public_ip = true # If true, forces to use an SSH tunnel. no_proxy_access = false network = var.trusted_private_network subnet = var.trusted_private_subnet labels = { blueprint = "security" } metadata = { terraform = "true" proxy-mode = "mail" proxy-user-mail = each.value notebook-disable-root = "true" notebook-disable-downloads = "true" notebook-disable-nbconvert = "true" serial-port-enable = "FALSE" block-project-ssh-keys = "TRUE" } lifecycle { prevent_destroy = false ignore_changes = [ # Ignore changes to the following attributes to allow idempotent re-deployment # when re-applying, terraform cannot get the disk-encryption type even though it's already set to CMEK create_time, disk_encryption, kms_key, update_time, vm_image, ] } depends_on = [ module.kms_data, module.iam_grant_policy, google_storage_bucket_object.postscript, google_service_account.sa_p_notebook_compute, google_compute_subnetwork_iam_binding.subnet_binding, ] } module "access_level_members_higher_trust" { source = "terraform-google-modules/vpc-service-controls/google//modules/access_level" version = "~> 2.0" policy = var.default_policy_id name = format("higher_trust_notebooks_members_%s", random_string.random_name.result) members = var.trusted_scientists ip_subnetworks = var.vpc_perimeter_ip_subnetworks # Note: Below are additional policy attributes you should configure based on your security policies, which are additional context information part of endpoint verification configuration. # regions = var.vpc_perimeter_regions # allowed_encryption_statuses = ["ENCRYPTED"] # require_corp_owned = true # require_screen_lock = true } data "google_project" "trusted_data" { project_id = var.project_trusted_data } data "google_project" "trusted_analytics" { project_id = var.project_trusted_analytics } data "google_project" "trusted_kms" { project_id = var.project_trusted_kms } module "regular_service_perimeter_higher_trust" { source = "terraform-google-modules/vpc-service-controls/google//modules/regular_service_perimeter" version = "~> 2.0" policy = var.default_policy_id perimeter_name = format("higher_trust_notebooks_%s", random_string.random_name.result) description = "Perimeter shielding Notebook projects with PII data" resources = [ "${data.google_project.trusted_data.number}", "${data.google_project.trusted_analytics.number}", "${data.google_project.trusted_kms.number}", ] access_levels = [module.access_level_members_higher_trust.name] restricted_services = [ "compute.googleapis.com", "storage.googleapis.com", "notebooks.googleapis.com", "bigquery.googleapis.com", "datacatalog.googleapis.com", "dataflow.googleapis.com", "dlp.googleapis.com", "cloudkms.googleapis.com", "secretmanager.googleapis.com", "cloudasset.googleapis.com", "cloudfunctions.googleapis.com", "pubsub.googleapis.com", "monitoring.googleapis.com", "logging.googleapis.com" ] depends_on = [ google_notebooks_instance.caip_nbk_p_trusted, ] }