Skip to content

Latest commit

 

History

History

net-swp

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Google Cloud Secure Web Proxy

This module allows creation and management of Secure Web Proxy, and its URL lists and policy rules.

It also allows to deploy SWP as a Private Service Connect service. This means that a single SWP deployment can be used from across different VPCs, regardless of whether they are interconnected.

A Proxy-only subnet must exist in the VPC where SWP is deployed.

When deploying SWP, the required ad-hoc Cloud Router is also created.

Minimal Secure Web Proxy

(Note that this will not allow any request to pass.)

module "secure-web-proxy" {
  source     = "./fabric/modules/net-swp"
  project_id = "my-project"
  region     = "europe-west4"
  name       = "secure-web-proxy"
  network    = "projects/my-project/global/networks/my-network"
  subnetwork = "projects/my-project/regions/europe-west4/subnetworks/my-subnetwork"
  certificates = [
    "projects/my-project/locations/europe-west4/certificates/secure-web-proxy-cert"
  ]
  gateway_config = {
    addresses = ["10.142.68.3"]
    labels = {
      example = "value"
    }
  }
}
# tftest modules=1 resources=2 inventory=basic.yaml

PSC service attachments

The optional service_attachment variable allows deploying SWP as a Private Service Connect service attachment

module "secure-web-proxy" {
  source     = "./fabric/modules/net-swp"
  project_id = "my-project"
  region     = "europe-west4"
  name       = "secure-web-proxy"
  network    = "projects/my-project/global/networks/my-network"
  subnetwork = "projects/my-project/regions/europe-west4/subnetworks/my-subnetwork"
  certificates = [
    "projects/my-project/locations/europe-west4/certificates/secure-web-proxy-cert"
  ]
  gateway_config = {
    addresses = ["10.142.68.3"]
    labels = {
      example = "value"
    }
  }
  service_attachment = {
    nat_subnets = ["projects/my-project/regions/europe-west4/subnetworks/my-psc-subnetwork"]
    consumer_accept_lists = {
      "my-autoaccept-project-1" = 1,
      "my-autoaccept-project-2" = 1
    }
  }
}
# tftest modules=1 resources=3 inventory=psc.yaml

Secure Web Proxy with rules

This example shows different ways of defining policy rules, including how to leverage substitution for internally generated URL maps, or externally defined resources.

module "secure-web-proxy" {
  source     = "./fabric/modules/net-swp"
  project_id = "my-project"
  region     = "europe-west4"
  name       = "secure-web-proxy"
  network    = "projects/my-project/global/networks/my-network"
  subnetwork = "projects/my-project/regions/europe-west4/subnetworks/my-subnetwork"
  certificates = [
    "projects/my-project/locations/europe-west4/certificates/secure-web-proxy-cert"
  ]
  gateway_config = {
    addresses = ["10.142.68.3"]
    ports     = [80, 443]
    labels = {
      example = "value"
    }
  }
  policy_rules = {
    host-0 = {
      priority        = 1000
      allow           = false
      session_matcher = "host() == 'google.com'"
    }
    secure-tag-0 = {
      priority        = 1001
      session_matcher = <<END
        source.matchTag('tagValues/281484836404786') && host() == 'example.com'
      END
    }
    secure-tag-1 = {
      priority        = 1002
      session_matcher = <<END
        source.matchTag('tagValues/281484836404786') && host() != 'google.com'
      END
    }
    service-account-0 = {
      priority        = 1003
      session_matcher = <<END
        source.matchServiceAccount('%s') && host() == 'example.com'
      END
      matcher_args = {
        session = ["service_account:foo"]
      }
    }
    url-list-0 = {
      priority        = 1004
      session_matcher = <<END
        inUrlList(
          host(),
          'projects/my-project/locations/europe-west4/urlLists/my-url-list'
        )
      END
    }
    url-list-1 = {
      priority        = 1005
      session_matcher = "inUrlList(host(), '%s')"
      matcher_args = {
        session = [
          "url_list:projects/my-project/locations/europe-west4/urlLists/default"
        ]
      }
    }
  }
  policy_rules_contexts = {
    service_accounts = {
      foo = "[email protected]"
    }
  }
  url_lists = {
    default = {
      values = [
        "example.org"
      ]
    }
  }
}
# tftest modules=1 resources=9 inventory=rules.yaml

Secure Web Proxy with TLS inspection

You can activate TLS inspection and let the module handle the TLS inspection policy creation.

resource "google_privateca_ca_pool" "pool" {
  project  = "my-project"
  location = "europe-west4"
  name     = "swp"
  tier     = "DEVOPS"
}

resource "google_privateca_certificate_authority" "ca" {
  project                  = "my-project"
  location                 = "europe-west4"
  pool                     = google_privateca_ca_pool.pool.name
  certificate_authority_id = "swp"
  deletion_protection      = "false"
  lifetime                 = "1209600s"
  config {
    subject_config {
      subject {
        organization = "Cloud Foundation Fabric"
        common_name  = "fabric"
      }
    }
    x509_config {
      ca_options {
        is_ca = true
      }
      key_usage {
        base_key_usage {
          cert_sign = true
          crl_sign  = true
        }
        extended_key_usage {
          server_auth = true
        }
      }
    }
  }
  key_spec {
    algorithm = "EC_P256_SHA256"
  }
}

resource "google_privateca_ca_pool_iam_member" "member" {
  ca_pool = google_privateca_ca_pool.pool.id
  role    = "roles/privateca.certificateManager"
  member  = "serviceAccount:[email protected]"
}

module "secure-web-proxy" {
  source     = "./fabric/modules/net-swp"
  project_id = "my-project"
  region     = "europe-west4"
  name       = "secure-web-proxy"
  network    = "projects/my-project/global/networks/my-network"
  subnetwork = "projects/my-project/regions/europe-west4/subnetworks/my-subnetwork"
  certificates = [
    "projects/my-project/locations/europe-west4/certificates/swp"
  ]
  gateway_config = {
    addresses = ["10.142.68.3"]
  }
  tls_inspection_config = {
    create_config = {
      ca_pool = google_privateca_ca_pool.pool.id
    }
  }
  policy_rules = {
    tls-0 = {
      priority            = 1000
      session_matcher     = "host() == 'google.com'"
      application_matcher = "request.path.contains('generate_204')"
      tls_inspect         = true
    }
  }
}
# tftest modules=1 resources=7 inventory=tls.yaml

You can also refer to existing TLS inspection policies (even cross-project).

module "secure-web-proxy" {
  source     = "./fabric/modules/net-swp"
  project_id = "my-project"
  region     = "europe-west4"
  name       = "secure-web-proxy"
  network    = "projects/my-project/global/networks/my-network"
  subnetwork = "projects/my-project/regions/europe-west4/subnetworks/my-subnetwork"
  certificates = [
    "projects/my-project/locations/europe-west4/certificates/swp"
  ]
  gateway_config = {
    addresses = ["10.142.68.3"]
  }
  tls_inspection_config = {
    id = "projects/another-project/locations/europe-west1/tlsInspectionPolicies/tls-ip-0"
  }
  policy_rules = {
    tls-0 = {
      priority            = 1000
      session_matcher     = "host() == 'google.com'"
      application_matcher = "request.path.contains('generate_204')"
      tls_inspect         = true
    }
  }
}
# tftest modules=1 resources=3 inventory=tls-no-ip.yaml

Secure Web Proxy as transparent proxy

To use Secure Web Proxy as transparent proxy, define it as a default gateway for the tag or create policy based routes as described in the documentation. Secure Web Proxy passes only traffic on the ports that it listens. Configure rules as documented in earlier sections.

locals {
  swp_address = "10.0.2.2"
}
module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "swp-network"
  routes = {
    gateway = {
      dest_range    = "0.0.0.0/0",
      priority      = 100
      tags          = ["swp"] # only traffic from instances tagged 'swp' will be inspected
      next_hop_type = "ilb",
      next_hop      = local.swp_address # resource doesn't allow to obtain address
    }
  }
  subnets_proxy_only = [ # SWP requires proxy-only subnet
    {
      ip_cidr_range = "10.0.1.0/24"
      name          = "regional-proxy"
      region        = var.region
      active        = true
    }
  ]
  subnets = [
    {
      ip_cidr_range = "10.0.2.0/24"
      name          = "production"
      region        = var.region
    }
  ]
}

module "secure-web-proxy" {
  source     = "./fabric/modules/net-swp"
  project_id = var.project_id
  region     = var.region
  name       = "secure-web-proxy"
  network    = module.vpc.id
  subnetwork = module.vpc.subnets["${var.region}/production"].id
  gateway_config = {
    addresses             = [local.swp_address] # SWP allows only providing unreserved addresses, must provide address to avoid drift
    next_hop_routing_mode = true
    ports                 = [80, 443] # specify all ports to be intercepted
  }
  policy_rules = {
    proxy-rule = {
      priority        = 100
      session_matcher = "true" # pass all traffic
      tls_inspect     = false
    }
  }
}

# tftest inventory=transparent-proxy.yaml e2e

Factories

URL lists and policies rules can also be defined via YAML-based factories, similarly to several other modules. Data coming from factories is internally merged with variables data, with factories having precedence in case duplicate keys are present in both.

module "secure-web-proxy" {
  source     = "./fabric/modules/net-swp"
  project_id = "my-project"
  region     = "europe-west4"
  name       = "secure-web-proxy"
  network    = "projects/my-project/global/networks/my-network"
  subnetwork = "projects/my-project/regions/europe-west4/subnetworks/my-subnetwork"
  certificates = [
    "projects/my-project/locations/europe-west4/certificates/secure-web-proxy-cert"
  ]
  factories_config = {
    policy_rules = "data/policy-rules"
    url_lists    = "data/url-lists"
  }
  gateway_config = {
    addresses = ["10.142.68.3"]
    ports     = [80, 443]
    labels = {
      example = "value"
    }
  }
  policy_rules_contexts = {
    service_accounts = {
      foo = "[email protected]"
    }
  }
}
# tftest modules=1 resources=5 files=0,1,2 inventory=factories.yaml

URL list definitions:

description: URL list 0
values:
  - www.example.com
  - about.example.com
  - "*.google.com"
  - "github.com/example-org/*"
# tftest-file id=0 path=data/url-lists/list-0.yaml schema=url-list.schema.json

Policy rule definitions:

priority: 1000
session_matcher: "inUrlList(host(), '%s')"
matcher_args:
  session:
    - url_list:list-0
# tftest-file id=1 path=data/policy-rules/url-list-0.yaml schema=policy-rule.schema.json
priority: 1001
session_matcher: "source.matchServiceAccount('%s')"
matcher_args:
  session:
    - service_account:foo
# tftest-file id=2 path=data/policy-rules/service-account-0.yaml schema=policy-rule.schema.json

Variables

name description type required default
gateway_config Optional Secure Web Gateway configuration. object({…})
name Name of the Secure Web Proxy resource. string
network Name of the network the Secure Web Proxy is deployed into. string
project_id Project id of the project that holds the network. string
region Region where resources will be created. string
subnetwork Name of the subnetwork the Secure Web Proxy is deployed into. string
certificates List of certificates to be used for Secure Web Proxy. list(string) []
description Optional description for the created resources. string "Managed by Terraform."
factories_config Path to folder with YAML resource description data files. object({…}) {}
policy_rules Policy rules definitions. Merged with policy rules defined via the factory. map(object({…})) {}
policy_rules_contexts Replacement contexts for policy rules matcher arguments. object({…}) {}
service_attachment PSC service attachment configuration. object({…}) null
tls_inspection_config TLS inspection configuration. object({…}) {}
url_lists URL lists. map(object({…})) {}

Outputs

name description sensitive
gateway The gateway resource.
gateway_security_policy The gateway security policy resource.
id ID of the gateway resource.
service_attachment ID of the service attachment resource, if created.