INTEGRITY Dokumentace

Terraform

Terraform je nástroj typu infrastructure as code, který umožňuje nasazovat služby od různých poskytovatelů pomocí standardizované konfigurační syntaxe. Při vytváření konfiguračního souboru Terraform definujete výsledný stav konfigurace, nikoli postup jednotlivých kroků. Díky tomu můžete snadno nasazovat, upravovat a spravovat své tunely spolu se zbytkem infrastruktury.

V tomto průvodci nasadíte pomocí Terraformu:

Předpoklady

Chcete-li dokončit následující postup, budete potřebovat:

1. Nainstalujte Terraform

Viz Průvodce instalací Terraformu pro váš operační systém.

2. Nainstalujte gcloud CLI

  1. Instalace gcloud CLI tak, aby Terraform mohl pracovat s vaším účtem GCP.

  2. Ověřte se pomocí CLI spuštěním:

    gcloud auth application-default login

3. Vytvořte token Cloudflare API

Vytvořte token API tak, aby Terraform mohl pracovat s vaším účtem Cloudflare. Token by měl obsahovat minimálně následující oprávnění:

Typ Položka Oprávnění
Účet Cloudflare Tunnel Úprava
Účet Access: aplikace a zásady Úprava
Zóna DNS Úprava

4. Vytvořte konfigurační adresář

Terraform funguje prostřednictvím pracovního adresáře, který obsahuje konfigurační soubory. Konfiguraci můžete uložit do více souborů nebo jen do jednoho: Terraform vyhodnotí všechny konfigurační soubory v adresáři, jako by byly v jediném dokumentu.

  1. Vytvořte složku pro konfiguraci Terraform:

    mkdir cloudflare-tf
  2. Přejděte do adresáře:

    cd cloudflare-tf

5. Vytvořte konfigurační soubory Terraform

Definujte vstupní proměnné

Následující proměnné budou předány do konfigurace GCP a Cloudflare.

  1. Ve svém konfiguračním adresáři vytvořte .tf soubor:

    touch variables.tf
  2. Otevřete soubor v textovém editoru a zkopírujte a vložte následující:

    # GCP variables
    variable "gcp_project_id" {
      description = "Google Cloud Platform (GCP) project ID"
      type        = string
    }
    
    variable "zone" {
      description = "Geographical zone for the GCP VM instance"
      type        = string
    }
    
    variable "machine_type" {
      description = "Machine type for the GCP VM instance"
      type        = string
    }
    
    # Cloudflare variables
    variable "cloudflare_zone" {
      description = "Domain used to expose the GCP VM instance to the Internet"
      type        = string
    }
    
    variable "cloudflare_zone_id" {
      description = "Zone ID for your domain"
      type        = string
    }
    
    variable "cloudflare_account_id" {
      description = "Account ID for your Cloudflare account"
      type        = string
      sensitive   = true
    }
    
    variable "cloudflare_email" {
      description = "Email address for your Cloudflare account"
      type        = string
      sensitive   = true
    }
    
    variable "cloudflare_token" {
      description = "Cloudflare API token"
      type        = string
      sensitive   = true
    }

Přiřaďte hodnoty proměnným

  1. Ve svém konfiguračním adresáři vytvořte .tfvars soubor:

    touch terraform.tfvars

    Terraform tyto proměnné automaticky použije, pokud je soubor pojmenován terraform.tfvars, jinak bude nutné soubor s proměnnými předat ručně.

  2. Přidejte následující proměnné do terraform.tfvars. Nezapomeňte upravit příklad podle svých vlastních hodnot.

    cloudflare_zone           = "example.com"
    cloudflare_zone_id        = "023e105f4ecef8ad9ca31a8372d0c353"
    cloudflare_account_id     = "372e67954025e0ba6aaa6d586b9e0b59"
    cloudflare_email          = "[email protected]"
    cloudflare_token          = "y3AalHS_E7Vabk3c3lX950F90_Xl7YtjSlzyFn_X"
    gcp_project_id            = "testvm-123"
    zone                      = "us-central1-a"
    machine_type              = "e2-medium"

Nakonfigurujte poskytovatele Terraform

Budete muset deklarovat poskytovatelé použitý k zajištění infrastruktury.

  1. Ve svém konfiguračním adresáři vytvořte .tf soubor:

    touch providers.tf
  2. Přidejte následující poskytovatele do providers.tf. random poskytovatel se používá k vygenerování tajného klíče tunelu.

    terraform {
    	required_providers {
    		cloudflare = {
    			source = "cloudflare/cloudflare"
    			version = ">= 5.8.2"
    		}
    		google = {
    			source = "hashicorp/google"
    		}
    	}
    	required_version = ">= 1.2"
    }
    
    # Providers
    provider "cloudflare" {
    	api_token    = var.cloudflare_token
    }
    provider "google" {
    	project    = var.gcp_project_id
    }
    provider "random" {
    }
    terraform {
    	required_providers {
    		cloudflare = {
    			source = "cloudflare/cloudflare"
    			version = ">= 4.40.0, < 5.0.0"
    		}
    		google = {
    			source = "hashicorp/google"
    		}
    		random = {
    			source = "hashicorp/random"
    		}
    	}
    	required_version = ">= 1.2"
    }
    
    # Providers
    provider "cloudflare" {
    	api_token    = var.cloudflare_token
    }
    provider "google" {
    	project    = var.gcp_project_id
    }
    provider "random" {
    }

Nakonfigurujte prostředky Cloudflare

Následující konfigurace upraví nastavení ve vašem účtu Cloudflare.

  1. Ve svém konfiguračním adresáři vytvořte .tf soubor:

    touch Cloudflare-config.tf
  2. Přidejte následující prostředky do Cloudflare-config.tf:

    
    # Creates a new remotely-managed tunnel for the GCP VM.
    resource "cloudflare_zero_trust_tunnel_cloudflared" "gcp_tunnel" {
    	account_id    = var.cloudflare_account_id
    	name          = "Terraform GCP tunnel"
    	config_src    = "cloudflare"
    }
    
    # Reads the token used to run the tunnel on the server.
    data "cloudflare_zero_trust_tunnel_cloudflared_token" "gcp_tunnel_token" {
    	account_id 	= var.cloudflare_account_id
    	tunnel_id 	= cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id
    }
    
    # Creates the CNAME record that routes http_app.${var.cloudflare_zone} to the tunnel.
    resource "cloudflare_dns_record" "http_app" {
    	zone_id = var.cloudflare_zone_id
    	name    = "http_app"
    	content = "${cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id}.cfargotunnel.com"
    	type    = "CNAME"
    	ttl     = 1
    	proxied = true
    }
    
    # Configures tunnel with a published application for clientless access.
    resource "cloudflare_zero_trust_tunnel_cloudflared_config" "gcp_tunnel_config" {
    	tunnel_id  = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id
    	account_id = var.cloudflare_account_id
    	config     = {
    		ingress 	= [
    			{
    				hostname = "http_app.${var.cloudflare_zone}"
    				service  = "http://httpbin:80"
    			},
    			{
    				service  = "http_status:404"
    			}
    		]
    	}
    }
    
    # (Optional) Routes internal IP of GCP instance through the tunnel for private network access using WARP.
    resource "cloudflare_zero_trust_tunnel_cloudflared_route" "example_tunnel_route" {
    account_id         = var.cloudflare_account_id
    tunnel_id          = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id
    network            = google_compute_instance.http_server.network_interface.0.network_ip
    comment            = "Example tunnel route"
    }
    
    # Creates a reusable Access policy.
    resource "cloudflare_zero_trust_access_policy" "allow_emails" {
    	account_id   = var.cloudflare_account_id
    	name         = "Allow email addresses"
    	decision     = "allow"
    	include      = [
    		{
    			email = {
    				email = var.cloudflare_email
    			}
    		},
    		{
    			email_domain = {
    				domain = "@example.com"
    			}
    		}
    	]
    }
    
    # Creates an Access application to control who can connect to the public hostname.
    resource "cloudflare_zero_trust_access_application" "http_app" {
    	account_id       = var.cloudflare_account_id
    	type             = "self_hosted"
    	name             = "Access application for http_app.${var.cloudflare_zone}"
    	domain           = "http_app.${var.cloudflare_zone}"
    	policies = [
    		{
    			id = cloudflare_zero_trust_access_policy.allow_emails.id
    			precedence = 1
    		}
    	]
    }
    # Generates a 32-byte secret for the tunnel.
    resource "random_bytes" "tunnel_secret" {
    	byte_length = 32
    }
    
    # Creates a new remotely-managed tunnel for the GCP VM.
    resource "cloudflare_zero_trust_tunnel_cloudflared" "gcp_tunnel" {
    	account_id = var.cloudflare_account_id
    	name       = "Terraform GCP tunnel"
    	secret     = random_bytes.tunnel_secret.base64
    }
    
    # Creates the CNAME record that routes http_app.${var.cloudflare_zone} to the tunnel.
    resource "cloudflare_record" "http_app" {
    	zone_id = var.cloudflare_zone_id
    	name    = "http_app"
    	content   = "${cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.cname}"
    	type    = "CNAME"
    	proxied = true
    }
    
    # Configures tunnel with a published application for clientless access.
    resource "cloudflare_zero_trust_tunnel_cloudflared_config" "gcp_tunnel_config" {
    	tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id
    	account_id = var.cloudflare_account_id
    	config {
    		ingress_rule {
    			hostname = "${cloudflare_record.http_app.hostname}"
    			service  = "http://httpbin:80"
    		}
    		ingress_rule {
    			service  = "http_status:404"
    		}
    	}
    }
    
    # (Optional) Route internal IP of GCP instance through the tunnel for private network access using WARP.
    resource "cloudflare_zero_trust_tunnel_route" "example_tunnel_route" {
    account_id         = var.cloudflare_account_id
    tunnel_id          = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id
    network            = google_compute_instance.http_server.network_interface.0.network_ip
    comment            = "Example tunnel route"
    }
    
    # Creates an Access application to control who can connect to the public hostname.
    resource "cloudflare_zero_trust_access_application" "http_app" {
    	account_id          = var.cloudflare_account_id
    	name             = "Access application for http_app.${var.cloudflare_zone}"
    	domain           = "http_app.${var.cloudflare_zone}"
    }
    
    # Creates a (legacy) Access policy for the Access application.
    resource "cloudflare_zero_trust_access_policy" "allow_emails" {
    	application_id = cloudflare_zero_trust_access_application.http_app.id
    	account_id        = var.cloudflare_account_id
    	name           = "Example policy for http_app.${var.cloudflare_zone}"
    	precedence     = "1"
    	decision       = "allow"
    	include {
    		email = [var.cloudflare_email]
    	}
    }

Chcete-li se dozvědět více o těchto zdrojích, přečtěte si Dokumentace poskytovatele Cloudflare.

Nakonfigurujte prostředky GCP

Následující konfigurace definuje specifikace virtuálního počítače GCP a nastavuje spouštěcí skript, který se spustí při startu.

  1. Ve svém konfiguračním adresáři vytvořte .tf soubor:

    touch GCP-config.tf
  2. Přidejte následující obsah do GCP-config.tf:

    # OS the server will use
    data "google_compute_image" "image" {
    	family  = "ubuntu-2204-lts"
    	project = "ubuntu-os-cloud"
    }
    
    # GCP Instance resource
    resource "google_compute_instance" "http_server" {
    	name         = "test"
    	machine_type = var.machine_type
    	zone         = var.zone
    	tags         = []
    	boot_disk {
    		initialize_params {
    			image = data.google_compute_image.image.self_link
    		}
    	}
    
    	network_interface {
    		network = "default"
    		access_config {
    			//Ephemeral IP
    		}
    	}
    	// Optional config to make instance ephemeral
    /*  scheduling {
    		preemptible       = true
    		automatic_restart = false
    	} */
    
    	// Pass the tunnel token to the GCP server so that the server can install and run the tunnel upon startup.
    	metadata_startup_script = templatefile("./install-tunnel.tftpl",
    		{
    			tunnel_token = data.cloudflare_zero_trust_tunnel_cloudflared_token.gcp_tunnel_token.token
    		})
    }
    # OS the server will use
    data "google_compute_image" "image" {
    	family  = "ubuntu-2204-lts"
    	project = "ubuntu-os-cloud"
    }
    
    # GCP Instance resource
    resource "google_compute_instance" "http_server" {
    	name         = "test"
    	machine_type = var.machine_type
    	zone         = var.zone
    	tags         = []
    	boot_disk {
    		initialize_params {
    			image = data.google_compute_image.image.self_link
    		}
    	}
    
    	network_interface {
    		network = "default"
    		access_config {
    			//Ephemeral IP
    		}
    	}
    	// Optional config to make instance ephemeral
    /*  scheduling {
    		preemptible       = true
    		automatic_restart = false
    	} */
    
    	// Pass the tunnel token to the GCP server so that the server can install and run the tunnel upon startup.
    	metadata_startup_script = templatefile("./install-tunnel.tftpl",
    		{
    			tunnel_token = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.tunnel_token
    		})
    }

Vytvořit spouštěcí skript

Následující skript nainstaluje cloudflared a spusťte tunel jako službu. Tento příklad také nainstaluje odlehčenou aplikaci HTTP, kterou můžete použít k otestování konektivity.

  1. Ve svém konfiguračním adresáři vytvořte soubor šablony Terraform:

    touch install-tunnel.tftpl
  2. Otevřete soubor v textovém editoru a zkopírujte a vložte následující bash skript:

    # Script to install Cloudflare Tunnel and Docker resources
    
    # Docker configuration
    cd /tmp
    sudo apt-get install software-properties-common
    # Retrieving the docker repository for this OS
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
    # The OS is updated and docker is installed
    sudo apt update -y && sudo apt upgrade -y
    sudo apt install docker docker-compose -y
    # Add the HTTPBin application and run it on localhost:8080.
    cat > /tmp/docker-compose.yml << "EOF"
    version: '3'
    services:
      httpbin:
        image: kennethreitz/httpbin
        restart: always
        container_name: httpbin
        ports:
          - 8080:80
    
      cloudflared:
        image: cloudflare/cloudflared:latest
        restart: always
        container_name: cloudflared
        command: tunnel run --token ${tunnel_token}
    EOF
    cd /tmp
    sudo docker-compose up -d

6. Nasaďte Terraform

Chcete-li nasadit konfigurační soubory:

  1. Inicializujte svůj konfigurační adresář:

    terraform init
  2. Zobrazte náhled všeho, co bude vytvořeno:

    terraform plan
  3. Použijte konfiguraci:

    terraform apply

Aktivace instance GCP a tunelu může trvat několik minut. Nový tunel si můžete zobrazit na kartě Cloudflare dashboard v části Sítě > Tunnels, a vaši aplikaci Access a zásadu v části Zero Trust > Řízení přístupu > Aplikace. Nové DNS záznamy najdete na DNS záznamy stránka.

7. Otestujte připojení

  1. V Sítě > Tunnels, ověřte, že je váš tunel aktivní.

  2. V Řízení přístupu > Aplikace, ověřte, že váš e-mail Cloudflare je zásadou Access povolen.

  3. Z libovolného zařízení otevřete prohlížeč a přejděte na http_app.<CLOUDFLARE_ZONE> (například http_app.example.com).

    Pokud jste se v poslední době nepřihlásili, zobrazí se přihlašovací stránka Access.

  4. Přihlaste se pomocí svého e-mailu Cloudflare.

    Měli byste vidět HTTPBin domovská stránka.