-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Terraform script for GCP Testing (#264)
* add Terraform script to make GCP VPC with firewall * make minor changes to README * add minor change to README * Update README * Update README * Update README * remove optional Terraform options * changed cloud NAT use to private subnet only * increase nat ports for more reliable connection
- Loading branch information
Showing
4 changed files
with
337 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# GCP VPC with firewall by Terraform for OSD Network Verifier Test | ||
This repository contains Terrafom scripts to set up a VPC in GCP with a public and private subnet. It also creates a cloud NAT for the private subnet and a firewall policy to block egress from certain domains. | ||
|
||
Use `dest_fqdns` to add the domains you want blocked to test with the osd-network-verifier. | ||
|
||
## Prerequisites | ||
- Terraform | ||
- GCP account | ||
|
||
## Usage | ||
### GCP Credentials | ||
Generate a GCP credentials file by running: | ||
``` | ||
gcloud auth application-default login | ||
``` | ||
Note the location of the credentials file. The default location and file is `$HOME/.config/gcloud/application_default_credentials.json`. | ||
|
||
### Configuration | ||
Before running the script, you need to configure script variables. A `terraform.tfvars.example` file is provided as a template. Here are the steps to configure the variables: | ||
1. Copy the example file: | ||
``` | ||
cp terraform.tfvars.example terraform.tfvars | ||
``` | ||
2. Use a text editor to set `project` and `credentials_file` in `terraform.tfvars` | ||
- `project`: name of your GCP project | ||
- `credentials_file`: path to your GCP credentials file you generated | ||
3. Set and uncomment any other variables you wish to configure | ||
- `region`: GCP region where resources will be created | ||
- `zone`: GCP zone where resources will be created | ||
- `public_ip_cidr_range`: CIDR block for public subnet within VPC | ||
- `private_ip_cidr_range`: CIDR block for private subnet within VPC | ||
- `dest_fqdns`: list of domains you wish to block | ||
|
||
Note: The default value for these variables are defined in `variables.tf` | ||
|
||
### Running the scripts | ||
1. Initialize Terraform | ||
``` | ||
terraform init | ||
``` | ||
2. Check execution plan | ||
``` | ||
terraform plan | ||
``` | ||
3. Apply changes | ||
``` | ||
terraform apply | ||
``` | ||
4. Destroy Terraform resources after running verifier | ||
``` | ||
terraform destroy | ||
``` | ||
## Outputs | ||
The script outputs the IDs of the created VPC and subnets. | ||
``` | ||
private_subnet_id = "my-private-subnet" | ||
public_subnet_id = "my-public-subnet" | ||
vpc_name = "my-vpc" | ||
``` | ||
|
||
## Test OSD Network Verifier | ||
``` | ||
osd-network-verifier/osd-network-verifier egress --platform gcp-classic --subnet-id $subnet_id --vpc-name $vpc_name | ||
``` | ||
Replace `$subnet_id` with `private_subnet_id` or `public_subnet_id` and `$vpc_name` with `vpc_name` from the terraform output value. | ||
|
||
Example: | ||
``` | ||
./osd-network-verifier/osd-network-verifier egress --platform gcp-classic --subnet-id my-private-subnet --vpc-name my-vpc | ||
Using Project ID emhammon-test | ||
Created instance with ID: verifier-4624 | ||
Applying labels | ||
Successfully applied labels | ||
ComputeService Instance: verifier-4624 RUNNING | ||
Gathering and parsing console log output... | ||
Summary: | ||
printing out failures: | ||
- egressURL error: https://cdn01.quay.io:443 (Failed to connect to cdn01.quay.io port 443: Connection timed out) | ||
- egressURL error: https://quay.io:443 (Failed to connect to quay.io port 443: Connection timed out) | ||
printing out exceptions preventing the verifier from running the specific test: | ||
printing out errors faced during the execution: | ||
Failure! | ||
``` | ||
Because we have configured the firewall rules to block `cdn01.quay.io` and `quay.io`, we can determine the network verifier is working correctly by identifying these domains have been blocked. | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# configure GCP provider | ||
provider "google" { | ||
credentials = file(var.credentials_file) | ||
project = var.project | ||
region = var.region | ||
zone = var.zone | ||
} | ||
|
||
# create a VPC | ||
resource "google_compute_network" "vpc_network" { | ||
name = var.vpc_name | ||
auto_create_subnetworks = var.auto_create_subnetworks | ||
routing_mode = var.routing_mode | ||
# maximum transmission unit in bytes | ||
# default is 1460 but ranges from 1300 to 8896 | ||
mtu = var.mtu | ||
} | ||
|
||
# create a public subnet | ||
resource "google_compute_subnetwork" "public_subnet" { | ||
name = var.public_subnet_name | ||
region = var.region | ||
network = google_compute_network.vpc_network.self_link | ||
ip_cidr_range = var.public_ip_cidr_range | ||
depends_on = [google_compute_network.vpc_network] | ||
} | ||
|
||
# create a private subnet | ||
resource "google_compute_subnetwork" "private_subnet" { | ||
name = var.private_subnet_name | ||
region = var.region | ||
network = google_compute_network.vpc_network.self_link | ||
ip_cidr_range = var.private_ip_cidr_range | ||
private_ip_google_access = var.private_ip_google_access | ||
depends_on = [google_compute_network.vpc_network] | ||
} | ||
|
||
# create cloud NAT | ||
resource "google_compute_router" "router" { | ||
name = var.router_name | ||
network = google_compute_network.vpc_network.name | ||
region = var.region | ||
bgp { | ||
asn = var.asn | ||
} | ||
} | ||
resource "google_compute_router_nat" "nat" { | ||
name = var.cloud_nat_name | ||
router = google_compute_router.router.name | ||
region = google_compute_router.router.region | ||
nat_ip_allocate_option = var.nat_ip_allocate_option | ||
enable_endpoint_independent_mapping = var.enable_endpoint_independent_mapping | ||
enable_dynamic_port_allocation = var.enable_dynamic_port_allocation | ||
min_ports_per_vm = var.min_ports_per_vm | ||
# how NAT should be configured per Subnetwork | ||
source_subnetwork_ip_ranges_to_nat = var.source_subnetwork_ip_ranges_to_nat | ||
subnetwork { | ||
name = google_compute_subnetwork.private_subnet.id | ||
source_ip_ranges_to_nat = [var.source_ip_ranges_to_nat] | ||
} | ||
} | ||
|
||
# create firewall policy | ||
resource "google_compute_network_firewall_policy" "fw-policy" { | ||
name = var.firewall_policy_name | ||
project = var.project | ||
} | ||
resource "google_compute_network_firewall_policy_rule" "rules" { | ||
project = var.project | ||
priority = var.priority | ||
direction = var.direction | ||
action = var.action | ||
rule_name = var.rule_name | ||
firewall_policy = google_compute_network_firewall_policy.fw-policy.name | ||
match { | ||
dest_fqdns = var.dest_fqdns | ||
layer4_configs { | ||
ip_protocol = var.ip_protocol | ||
} | ||
} | ||
} | ||
resource "google_compute_network_firewall_policy_association" "primary" { | ||
name = "my-association" | ||
attachment_target = google_compute_network.vpc_network.id | ||
firewall_policy = google_compute_network_firewall_policy.fw-policy.name | ||
project = var.project | ||
} | ||
|
||
# create outputs for network verifier | ||
output "vpc_name" { | ||
value = google_compute_network.vpc_network.name | ||
} | ||
output "public_subnet_id" { | ||
value = google_compute_subnetwork.public_subnet.name | ||
} | ||
output "private_subnet_id" { | ||
value = google_compute_subnetwork.private_subnet.name | ||
} |
28 changes: 28 additions & 0 deletions
28
examples/gcp/terraform/vpc-firewall/terraform.tfvars.example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
### necessary variables | ||
project = "<YOUR_PROJECT_NAME>" | ||
credentials_file = "<YOUR_CREDENTIALS_FILE>" | ||
|
||
### configure other variables if needed | ||
## GCP region where resources will be created | ||
#region = "us-east1" | ||
|
||
## GCP zone where resources will be created | ||
#zone = "us-east1a-a" | ||
|
||
## CIDR block for public subnet within VPC | ||
#public_ip_cidr_range = "10.0.1.0/24" | ||
|
||
## CIDR block for private subnet within VPC | ||
#private_ip_cidr_range = "10.0.2.0/24" | ||
|
||
## domains to block | ||
#dest_fqdns = ["quay.io", "cloud.redhat.com"] | ||
|
||
## VPC name | ||
#vpc_name = "vpc-name" | ||
|
||
## public subnet name | ||
#public_subnet_name = "public-subnet-name" | ||
|
||
## private subnet name | ||
#private_subnet_name = "private-subnet-name" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
## terraform variables | ||
# configure GCP provider | ||
variable "project" {} | ||
variable "credentials_file" {} | ||
variable "region" { | ||
type = string | ||
default = "us-east1" | ||
} | ||
variable "zone" { | ||
type = string | ||
default = "us-east1-a-a" | ||
} | ||
|
||
# create VPC | ||
variable "vpc_name" { | ||
type = string | ||
default = "my-vpc" | ||
} | ||
variable "auto_create_subnetworks" { | ||
type = string | ||
default = "false" | ||
} | ||
variable "routing_mode" { | ||
type = string | ||
default = "GLOBAL" | ||
} | ||
variable "mtu" { | ||
type = number | ||
default = 1460 | ||
} | ||
|
||
# create public subnet | ||
variable "public_subnet_name" { | ||
type = string | ||
default = "my-public-subnet" | ||
} | ||
variable "public_ip_cidr_range" { | ||
type = string | ||
default = "10.0.1.0/24" | ||
} | ||
|
||
# create private subnet | ||
variable "private_subnet_name" { | ||
type = string | ||
default = "my-private-subnet" | ||
} | ||
variable "private_ip_cidr_range" { | ||
type = string | ||
default = "10.0.2.0/24" | ||
} | ||
variable "private_ip_google_access" { | ||
type = string | ||
default = "true" | ||
} | ||
|
||
# create cloud NAT | ||
variable "router_name" { | ||
type = string | ||
default = "my-router" | ||
} | ||
variable "asn" { | ||
type = number | ||
default = 64514 | ||
} | ||
variable "cloud_nat_name" { | ||
type = string | ||
default = "my-cloud-nat" | ||
} | ||
variable "nat_ip_allocate_option" { | ||
type = string | ||
default = "AUTO_ONLY" | ||
} | ||
variable "enable_endpoint_independent_mapping" { | ||
type = string | ||
default = "false" | ||
} | ||
variable "enable_dynamic_port_allocation" { | ||
type = string | ||
default = "true" | ||
} | ||
variable "min_ports_per_vm" { | ||
type = number | ||
default = 2048 | ||
} | ||
variable "source_subnetwork_ip_ranges_to_nat" { | ||
type = string | ||
default = "LIST_OF_SUBNETWORKS" | ||
} | ||
variable "source_ip_ranges_to_nat" { | ||
type = string | ||
default = "ALL_IP_RANGES" | ||
} | ||
|
||
# create firewall policy | ||
variable "firewall_policy_name" { | ||
type = string | ||
default = "my-firewall-policy" | ||
} | ||
variable "priority" { | ||
type = string | ||
default = "600" | ||
} | ||
variable "direction" { | ||
type = string | ||
default = "EGRESS" | ||
} | ||
variable "action" { | ||
type = string | ||
default = "deny" | ||
} | ||
variable "rule_name" { | ||
type = string | ||
default = "deny-egress-domains" | ||
} | ||
variable "dest_fqdns" { | ||
type = list(string) | ||
default = ["quay.io", "cdn01.quay.io"] | ||
} | ||
variable "ip_protocol" { | ||
type = string | ||
default = "all" | ||
} |