Skip to content

Instantly share code, notes, and snippets.

@KengoTODA
Created September 23, 2022 06:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KengoTODA/68452b572894624494f268630a360284 to your computer and use it in GitHub Desktop.
Save KengoTODA/68452b572894624494f268630a360284 to your computer and use it in GitHub Desktop.
ファイル配信サイト構築サンプル
resource "google_artifact_registry_repository" "file_hosting" {
location = local.region
repository_id = "file-hosting"
description = "Docker registry for the file hosting service"
format = "DOCKER"
}
resource "google_artifact_registry_repository_iam_policy" "file_hosting" {
location = local.region
repository = google_artifact_registry_repository.file_hosting.name
policy_data = data.google_iam_policy.artifact_repository_admin.policy_data
}
resource "google_project_service_identity" "cloudrun_service_agent" {
provider = google-beta
service = "run.googleapis.com"
}
data "google_iam_policy" "artifact_repository_admin" {
binding {
role = "roles/artifactregistry.reader"
members = [
"serviceAccount:${google_project_service_identity.cloudrun_service_agent.email}"
]
}
}
resource "google_iam_workload_identity_pool" "circleci" {
provider = google-beta
workload_identity_pool_id = "circleci"
display_name = "Circle CI"
}
resource "google_iam_workload_identity_pool_provider" "circleci_oidc" {
provider = google-beta
workload_identity_pool_id = google_iam_workload_identity_pool.circleci.workload_identity_pool_id
workload_identity_pool_provider_id = "circleci"
display_name = "Circle CI"
oidc {
allowed_audiences = [local.circleci_organization_id]
issuer_uri = "https://oidc.circleci.com/org/${local.circleci_organization_id}"
}
attribute_mapping = {
"google.subject" = "assertion.sub"
"attribute.organization_id" = "assertion.aud"
"attribute.project_id" = "assertion['oidc.circleci.com/project-id']"
}
attribute_condition = "attribute.organization_id == '${local.circleci_organization_id}'"
}
resource "google_service_account" "circleci_oidc" {
account_id = "circleci"
display_name = "The service account to deploy files from Circle CI onto GCS bucket"
}
resource "google_service_account_iam_member" "circleci_oidc" {
service_account_id = google_service_account.circleci_oidc.name
role = "roles/iam.workloadIdentityUser"
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.circleci.name}/*"
}
# https://github.com/domZippilli/gcs-proxy-cloud-run
resource "google_service_account" "gcs_streaming_proxy" {
account_id = "gcs-streaming-proxy"
display_name = "gcs-streaming-proxy for the file hosting service"
description = "To fetch data from a GCS bucket to the gcs-streaming-proxy service"
}
resource "google_cloud_run_service" "proxy" {
name = "gcs-streaming-proxy"
location = local.region
autogenerate_revision_name = true
metadata {
annotations = {
"run.googleapis.com/ingress" = "internal-and-cloud-load-balancing"
}
}
template {
metadata {
annotations = {
"autoscaling.knative.dev/minScale" = 1
"autoscaling.knative.dev/maxScale" = 2
}
labels = {
"env" = "file-hosting"
"service_name" = "file-hosting"
}
}
spec {
service_account_name = google_service_account.gcs_streaming_proxy.email
containers {
image = "asia-northeast1-docker.pkg.dev/path/to/gcs-streaming-proxy"
env {
name = "BUCKET_NAME"
value = google_storage_bucket.file_hosting.name
}
resources {
limits = {
cpu = 2
memory = "512Mi"
}
}
ports {
container_port = 8080
name = "http1"
}
}
}
}
}
resource "google_cloud_run_service_iam_member" "website_visitor" {
for_each = toset([
"domain:${local.domain}",
])
location = local.region
service = google_cloud_run_service.proxy.name
role = "roles/run.invoker"
member = each.key
}
resource "google_iap_brand" "file_hosting" {
support_email = local.admin_email
application_title = "ファイル配信サイト サンプル"
}
# HTTPS Load Balancerを用いたIdentity-Aware Proxyによる認証
# https://cloud.google.com/blog/ja/products/serverless/serverless-load-balancing-terraform-hard-way
resource "google_compute_global_address" "file_hosting" {
name = "file-hosting"
}
resource "google_compute_managed_ssl_certificate" "file_hosting" {
name = "file-hosting"
managed {
domains = [
"docs.${local.domain}"
]
}
}
resource "google_compute_region_network_endpoint_group" "file_hosting" {
name = "file-hosting"
region = "asia-northeast1"
network_endpoint_type = "SERVERLESS"
cloud_run {
service = google_cloud_run_service.proxy.name
}
}
resource "google_iap_client" "file_hosting" {
display_name = "IAP-file-hosting"
brand = google_iap_brand.file_hosting.name
}
resource "google_compute_backend_service" "file_hosting" {
name = "file-hosting"
protocol = "HTTP"
port_name = "http"
timeout_sec = 30
backend {
group = google_compute_region_network_endpoint_group.file_hosting.id
}
iap {
oauth2_client_id = google_iap_client.file_hosting.client_id
oauth2_client_secret = google_iap_client.file_hosting.secret
}
}
resource "google_iap_web_backend_service_iam_binding" "file_hosting" {
web_backend_service = google_compute_backend_service.file_hosting.name
role = "roles/iap.httpsResourceAccessor"
members = [
"domain:${local.domain}",
]
}
resource "google_compute_url_map" "file_hosting" {
name = "file-hosting"
default_service = google_compute_backend_service.file_hosting.id
}
resource "google_compute_target_https_proxy" "file_hosting" {
name = "file-hosting"
url_map = google_compute_url_map.file_hosting.id
ssl_certificates = [
google_compute_managed_ssl_certificate.file_hosting.id
]
}
resource "google_compute_global_forwarding_rule" "file_hosting" {
name = "file-hosting"
target = google_compute_target_https_proxy.file_hosting.id
port_range = "443"
ip_address = google_compute_global_address.file_hosting.address
}
resource "google_compute_url_map" "file_hosting_https_redirect" {
name = "file-hosting-https-redirect"
default_url_redirect {
https_redirect = true
redirect_response_code = "MOVED_PERMANENTLY_DEFAULT"
strip_query = false
}
}
resource "google_compute_target_http_proxy" "file_hosting_https_redirect" {
name = "file-hosting-https-redirect"
url_map = google_compute_url_map.file_hosting_https_redirect.id
}
resource "google_compute_global_forwarding_rule" "file_hosting_https_redirect" {
name = "file-hosting-https-redirect"
target = google_compute_target_http_proxy.file_hosting_https_redirect.id
port_range = "80"
ip_address = google_compute_global_address.file_hosting.address
}
output "load_balancer_ip" {
value = google_compute_global_address.file_hosting.address
description = "The IP v4 address of the load balancer. Set this value to the DNS record for the hosting site."
}
resource "google_project_service" "project" {
for_each = toset([
"artifactregistry.googleapis.com",
"compute.googleapis.com",
"iam.googleapis.com",
"iamcredentials.googleapis.com",
"iap.googleapis.com",
"storage.googleapis.com",
"sts.googleapis.com",
"run.googleapis.com",
])
project = local.project_name
service = each.key
}
resource "google_storage_bucket" "file_hosting" {
name = local.bucket_name
location = local.region
uniform_bucket_level_access = true
lifecycle {
prevent_destroy = true
}
}
resource "google_storage_bucket_iam_policy" "file_hosting" {
bucket = google_storage_bucket.file_hosting.name
policy_data = data.google_iam_policy.file_hosting.policy_data
}
data "google_iam_policy" "file_hosting" {
binding {
role = "roles/storage.objectViewer"
members = [
"serviceAccount:${google_service_account.gcs_streaming_proxy.email}",
]
}
binding {
role = "roles/storage.objectAdmin"
members = [
"serviceAccount:${google_service_account.circleci_oidc.email}",
]
}
}
resource "google_storage_bucket_object" "index" {
name = "index.html"
bucket = google_storage_bucket.file_hosting.name
source = "files/index.html"
}
resource "google_storage_bucket_object" "favicon" {
name = "favicon.ico"
bucket = google_storage_bucket.file_hosting.name
source = "files/favicon.ico"
}
terraform {
backend "gcs" {
bucket = ...
prefix = ...
}
required_version = ">= 1.0"
required_providers {
google = {
source = "hashicorp/google"
version = "4.37.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = "4.37.0"
}
}
}
provider "google" {
project = local.project_name
region = local.region
}
provider "google-beta" {
project = local.project_name
region = local.region
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment