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
- PSC service attachments
- Secure Web Proxy with rules
- Secure Web Proxy with TLS inspection
- Secure Web Proxy as transparent proxy
- Factories
- Variables
- Outputs
(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
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
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
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
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
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
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({…})) |
{} |
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. |