Commit 0bfb2b93 authored by Adam Robinson's avatar Adam Robinson
Browse files

Merge branch '3-shared-vpc-for-worker-notebooks' into 'master'

Resolve "Shared VPC for Worker Notebooks"

Closes #3

See merge request !41
parents 7408483d 042701ae
resource "google_bigquery_dataset" "audit_logs" {
for_each = { for v in local.all_projects : v => v }
dataset_id = "${replace(google_project.hipaa_project[each.key].name, "-", "_")}_audit_logs"
project = google_project.hipaa_project["audit"].project_id
# friendly_name = "${var.projectPrefix}-Data"
project = google_project.hipaa_project["audit"].project_id
description = "${google_project.hipaa_project[each.key].project_id} - Log Export BQ Dataset"
location = "US"
default_table_expiration_ms = 10368000000 #120 Days
......@@ -15,13 +14,7 @@ resource "google_bigquery_dataset" "audit_logs" {
access {
role = "READER"
group_by_email = local.auditor_group_email
}
# This doesn't work as it creates a circular dependency
# access{
# role = "WRITER"
# user_by_email = split(":", google_logging_project_sink.hipaa_audit_project_logs_bq_sink.writer_identity)[1]
# }
}
lifecycle {
//Since these are audit logs, they should not be destroyed
......@@ -44,17 +37,12 @@ resource "google_logging_project_sink" "audit_logs_bq" {
unique_writer_identity = true
}
resource "null_resource" "sink_writer_bq_access" {
for_each = { for v in local.all_projects : v => v }
triggers = {
writer_identity = google_logging_project_sink.audit_logs_bq[each.key].writer_identity
}
provisioner "local-exec" {
command = "${path.module}/set-sink-writer-bq-access.sh ${google_project.hipaa_project["audit"].project_id} ${google_bigquery_dataset.audit_logs[each.key].dataset_id} ${google_logging_project_sink.audit_logs_bq[each.key].writer_identity}"
}
depends_on = [ null_resource.install_gcloud_cli ]
resource "google_bigquery_dataset_access" "sink_writer_bq_access" {
for_each = { for v in local.all_projects : v => v }
project = google_project.hipaa_project["audit"].project_id
dataset_id = "${google_bigquery_dataset.audit_logs[each.key].dataset_id}"
role = "WRITER"
user_by_email = split(":", google_logging_project_sink.audit_logs_bq[each.key].writer_identity)[1]
}
resource "google_logging_project_sink" "audit_logs_gcs" {
......
......@@ -172,7 +172,7 @@ resource "google_bigquery_dataset" "hipaa_data_bq" {
//give datalab service accounts writer access to the corresponding worker dataset
dynamic "access" {
for_each = compact([ for v in keys(var.datalab_user_list) : var.datalab_user_list[v] == each.value ? google_service_account.datalab_service_account[v].email : "" ])
for_each = compact([ for v in var.datalab_user_list : v["project"] == each.value ? google_service_account.datalab_service_account[v["username"]].email : "" ])
content {
role = google_project_iam_custom_role.BigQueryDataEditor_NO_Export[each.key].id
user_by_email = access.value
......@@ -180,4 +180,4 @@ resource "google_bigquery_dataset" "hipaa_data_bq" {
}
depends_on = [ google_project_service.bq-api ]
}
\ No newline at end of file
}
resource "google_folder_organization_policy" "resource_locations" {
folder = google_folder.project_folder.id
constraint = "gcp.resourceLocations"
list_policy{
allow {
values = ["in:us-locations"]
}
}
}
......@@ -56,21 +56,3 @@ resource "google_logging_metric" "set_iam_permissions_change" {
value_type = "INT64"
}
}
resource "null_resource" "install_gcloud_cli" {
triggers = {
run_time = timestamp()
}
provisioner "local-exec" {
command = <<EOH
if [ `uname` != "Darwin" ]; then
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
sudo apt-get --assume-yes update && sudo apt-get --assume-yes install google-cloud-sdk google-cloud-sdk-datalab jq
echo $GOOGLE_CLOUD_KEYFILE_JSON > ~/key.json
gcloud auth activate-service-account --key-file ~/key.json
rm ~/key.json
fi
EOH
}
}
locals {
default_cidr = "10.255.0.0/16"
default_regions = ["us-central1", "us-east1", "us-east4", "us-west1"]
default_subnets = {for x in local.default_regions : x => cidrsubnet(local.default_cidr,4,index(local.default_regions, x))}
network_type = "worker"
}
# Create shared VPC in network project
resource "google_compute_network" "hipaa-shared-vpc" {
project = google_project.hipaa_project["network"].project_id
......@@ -8,4 +15,28 @@ resource "google_compute_network" "hipaa-shared-vpc" {
# Enable VPC Sharing in network project
resource "google_compute_shared_vpc_host_project" "hipaa-shared-vpc" {
project = google_project.hipaa_project["network"].project_id
}
\ No newline at end of file
}
resource "google_compute_shared_vpc_service_project" "hipaa-shared-vpc-worker" {
for_each = { for v in local.worker_projects : v => v }
host_project = google_compute_shared_vpc_host_project.hipaa-shared-vpc.project
service_project = google_project.hipaa_project[each.key].project_id
}
resource "google_compute_subnetwork" "worker_subnet" {
for_each = local.default_subnets
project = google_project.hipaa_project["network"].project_id
name = "${local.network_type}-${each.key}"
region = each.key
ip_cidr_range = each.value
network = google_compute_network.hipaa-shared-vpc.self_link
}
resource "google_compute_subnetwork_iam_binding" "worker_subnet_binding" {
for_each = local.default_subnets
project = google_project.hipaa_project["network"].project_id
region = each.key
subnetwork = google_compute_subnetwork.worker_subnet[each.key].name
role = "roles/compute.networkUser"
members = concat(compact([ for v in local.worker_projects : "serviceAccount:service-${google_project.hipaa_project[v].number}@gcp-sa-notebooks.iam.gserviceaccount.com"]), ["group:${local.all_workers_group_email}"])
}
# enable APIs required for OS patching
resource "google_project_service" "os-config-api" {
for_each = { for v in local.worker_projects : v => v }
project = google_project.hipaa_project[each.key].project_id
service = "osconfig.googleapis.com"
}
resource "google_project_service" "container-analysis-api" {
for_each = { for v in local.worker_projects : v => v }
project = google_project.hipaa_project[each.key].project_id
service = "containeranalysis.googleapis.com"
}
resource "google_project_service" "compute-scanning" {
for_each = { for v in local.worker_projects : v => v }
project = google_project.hipaa_project[each.key].project_id
service = "computescanning.googleapis.com"
}
# set GCE Metadata for OS patching
resource "google_compute_project_metadata" "os_patching" {
for_each = { for v in local.worker_projects : v => v }
project = google_project.hipaa_project[each.key].project_id
metadata = {
enable-guest-attributes = true
enable-osconfig = true
}
}
resource "google_project_service" "notebooks_api" {
for_each = { for v in local.worker_projects : v => v }
project = google_project.hipaa_project[each.key].project_id
service = "notebooks.googleapis.com"
}
resource "google_project_iam_binding" "datalab_service_account_iam_binding" {
for_each = { for v in local.worker_projects : v => v }
project = google_project.hipaa_project[each.key].project_id
role = "roles/bigquery.jobUser"
members = compact([ for v in keys(var.datalab_user_list) : var.datalab_user_list[v] == each.value ? "serviceAccount:${google_service_account.datalab_service_account[v].email}" : "" ])
members = compact([ for v in var.datalab_user_list : v["project"] == each.value ? "serviceAccount:${google_service_account.datalab_service_account[v["username"]].email}" : "" ])
}
# DO WE NEED THIS?
resource "google_project_service" "sourcerepo-api" {
for_each = { for v in local.worker_projects : v => v }
project = google_project.hipaa_project[each.key].project_id
......@@ -55,14 +91,23 @@ resource "google_project_iam_binding" "view_compute_instances" {
]
}
resource "google_project_iam_binding" "view_notebooks" {
for_each = { for v in local.worker_projects : v => v }
project = google_project.hipaa_project[each.key].project_id
role = "roles/notebooks.viewer"
members = [
"group:${local.worker_project_email[each.key]}",
]
}
resource "google_service_account" "datalab_service_account" {
for_each = var.datalab_user_list
for_each = { for v in var.datalab_user_list : v["username"] => v["project"] }
account_id = "datalab-${split("@", each.key)[0]}"
project = google_project.hipaa_project[each.value].project_id
}
resource "google_service_account_iam_binding" "datalab_service_account_iam_binding" {
for_each = var.datalab_user_list
for_each = { for v in var.datalab_user_list : v["username"] => v["username"] }
service_account_id = google_service_account.datalab_service_account[each.key].name
role = "roles/iam.serviceAccountUser"
members = [
......@@ -70,8 +115,8 @@ resource "google_service_account_iam_binding" "datalab_service_account_iam_bindi
]
}
data "google_iam_policy" "datalab_user_to_instance_policy" {
for_each = var.datalab_user_list
data "google_iam_policy" "notebook_user_to_instance_policy" {
for_each = { for v in var.datalab_user_list : v["username"] => v["username"] }
binding {
role = "roles/compute.instanceAdmin.v1"
......@@ -81,34 +126,37 @@ data "google_iam_policy" "datalab_user_to_instance_policy" {
}
}
resource "google_compute_instance_iam_policy" "datalab_user_to_instance_binding" {
for_each = var.datalab_user_list
instance_name = "datalab-${split("@", each.key)[0]}"
resource "google_compute_instance_iam_policy" "notebook_user_to_instance_binding" {
for_each = { for v in var.datalab_user_list : v["username"] => v["project"] }
instance_name = google_notebooks_instance.worker_nb[each.key].name
project = google_project.hipaa_project[each.value].project_id
zone = var.datalab_zone
policy_data = data.google_iam_policy.datalab_user_to_instance_policy[each.key].policy_data
depends_on = [ null_resource.datalab ]
zone = data.google_compute_zones.notebooks.names[0]
policy_data = data.google_iam_policy.notebook_user_to_instance_policy[each.key].policy_data
}
resource "null_resource" "datalab" {
for_each = var.datalab_user_list
triggers = {
user = each.key
project_id = google_project.hipaa_project[each.value].project_id
}
provisioner "local-exec" {
//command = "datalab create --project ${google_project.hipaa_project[each.value].project_id} --machine-type n1-standard-1 --zone us-central1-a --no-connect --for-user ${each.key} --service-account ${google_service_account.datalab_service_account[each.key].email} datalab-${split("@", each.key)[0]}"
command = "datalab create --project ${self.triggers.project_id} --machine-type n1-standard-1 --zone ${var.datalab_zone} --no-connect --for-user ${self.triggers.user} --service-account ${google_service_account.datalab_service_account[self.triggers.user].email} datalab-${split("@", self.triggers.user)[0]}"
resource "google_notebooks_instance" "worker_nb" {
provider = google-beta
for_each = { for v in var.datalab_user_list : v["username"] => v }
project = google_project.hipaa_project[each.value["project"]].project_id
name = "notebook-${split("@", each.key)[0]}"
location = data.google_compute_zones.notebooks.names[0]
network = google_compute_network.hipaa-shared-vpc.id
subnet = google_compute_subnetwork.worker_subnet[var.notebook_region].id
machine_type = each.value["machine_type"]
service_account = google_service_account.datalab_service_account[each.key].email
instance_owners = each.value["username"]
vm_image {
project = "deeplearning-platform-release" # needs a var?
image_family = "tf-latest-cpu" # needs a var?
}
# temporary - waiting on bug fix
lifecycle {
ignore_changes = [
subnet,
network,
instance_owners,
]
}
provisioner "local-exec" {
when = destroy
//command = "datalab delete --quiet --delete-disk --project ${google_project.hipaa_project[each.value].project_id} --zone us-central1-a datalab-${split("@", each.key)[0]}"
command = "datalab delete --quiet --delete-disk --project ${self.triggers.project_id} --zone ${var.datalab_zone} datalab-${split("@", self.triggers.user)[0]}"
}
depends_on = [ google_sourcerepo_repository.datalab-notebooks, google_compute_network.datalab-network, null_resource.install_gcloud_cli ]
}
\ No newline at end of file
depends_on = [ google_project_service.notebooks_api, google_compute_subnetwork_iam_binding.worker_subnet_binding ]
}
#!/bin/bash
set -e
if [[ -z "$1" || -z "$2" || -z "$3" ]]; then
echo "pass [project id] [dataset id] [writer identity]"
exit 1
fi
if ! [ -x "$(command -v bq)" ]; then
echo "bq cli (bigquery cli, from gcloud cli) is not available in path"
exit 1
fi
project=$1
dataset=$2
writer=${3#"serviceAccount:"}
temp_file=$(mktemp)
trap "rm -f ${temp_file}" EXIT
bq show --format=prettyjson --project ${project} ${dataset} \
| jq --arg writer ${writer} '.access | . += [{"role": "WRITER", "userByEmail": $writer }] | {"access": .}' > ${temp_file}
bq update --source ${temp_file} ${project}:${dataset}
\ No newline at end of file
......@@ -28,21 +28,26 @@ variable "dependencies" {
}
variable "datalab_user_list" {
type = map(string)
# type = map(string)
type = list(object({username = string, project = string, machine_type = string}))
description = "A map of users to create a datalab instance for. The key is the username and the value is the project id"
default = {}
default = []
}
variable "notebook_region" {
default = "us-central1"
}
variable "datalab_zone" {
description = "The zone to create datalab instances in"
default = "us-central1-a"
data "google_compute_zones" "notebooks" {
project = google_project.hipaa_project["network"].project_id
region = var.notebook_region
}
locals {
base_projects = ["audit", "data", "network", "monitor"]
projects_storing_data = concat(["data"], local.worker_projects)
projects_with_lien = ["audit", "data", "network", "monitor"]
worker_projects = [ for x in range(var.worker_count): "worker${x}" ]
worker_projects = [ for x in range(var.worker_count): "worker${x}" ]
bq_enabled_projects = concat(["audit", "data", "monitor"], local.worker_projects)
all_projects = concat(local.base_projects, local.worker_projects)
owners_group_email = "${var.project_prefix}-owners@${var.domain}"
......@@ -51,5 +56,6 @@ locals {
read-only_group_email = "${var.project_prefix}-read-only@${var.domain}"
alerts_group_email = "${var.project_prefix}-alerts@${var.domain}"
worker_project_email = { for x in local.worker_projects : x => "${var.project_prefix}-${x}@${var.domain}" }
datalab_service_account_readers = [ for x in keys(var.datalab_user_list) : google_service_account.datalab_service_account[x].email ]
all_workers_group_email = "${var.project_prefix}-workers@${var.domain}" # Add all worker emails to this MComm Group
datalab_service_account_readers = [ for x in var.datalab_user_list : google_service_account.datalab_service_account[x["username"]].email ]
}
\ No newline at end of file
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