Skip to content

Commit

Permalink
Add Terraform script for GCP Testing (#264)
Browse files Browse the repository at this point in the history
* 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
eth1030 authored Aug 21, 2024
1 parent a08f94c commit ec18609
Show file tree
Hide file tree
Showing 4 changed files with 337 additions and 0 deletions.
89 changes: 89 additions & 0 deletions examples/gcp/terraform/vpc-firewall/README.md
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.




98 changes: 98 additions & 0 deletions examples/gcp/terraform/vpc-firewall/main.tf
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 examples/gcp/terraform/vpc-firewall/terraform.tfvars.example
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"
122 changes: 122 additions & 0 deletions examples/gcp/terraform/vpc-firewall/variables.tf
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"
}

0 comments on commit ec18609

Please sign in to comment.