{"id":19925681,"url":"https://github.com/paloaltonetworks/google-cloud-hub-spoke-tutorial","last_synced_at":"2025-05-03T08:31:14.169Z","repository":{"id":71203717,"uuid":"561478691","full_name":"PaloAltoNetworks/google-cloud-hub-spoke-tutorial","owner":"PaloAltoNetworks","description":"Build \u0026 secure a Google Cloud  hub-and-spoke architecture with VM-Series. ","archived":false,"fork":false,"pushed_at":"2025-03-03T19:20:26.000Z","size":108811,"stargazers_count":10,"open_issues_count":1,"forks_count":8,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-07T13:38:01.954Z","etag":null,"topics":["autoscaling","gcp","google-cloud","google-cloud-platform","highavailability","hub","pan-os","terraform","vm-series","vmseries"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PaloAltoNetworks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-03T19:28:51.000Z","updated_at":"2025-03-03T19:20:30.000Z","dependencies_parsed_at":"2023-03-07T09:15:52.806Z","dependency_job_id":"9829afba-a1a2-439a-9e04-2c846b723e98","html_url":"https://github.com/PaloAltoNetworks/google-cloud-hub-spoke-tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaloAltoNetworks%2Fgoogle-cloud-hub-spoke-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaloAltoNetworks%2Fgoogle-cloud-hub-spoke-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaloAltoNetworks%2Fgoogle-cloud-hub-spoke-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaloAltoNetworks%2Fgoogle-cloud-hub-spoke-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PaloAltoNetworks","download_url":"https://codeload.github.com/PaloAltoNetworks/google-cloud-hub-spoke-tutorial/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252162521,"owners_count":21704266,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autoscaling","gcp","google-cloud","google-cloud-platform","highavailability","hub","pan-os","terraform","vm-series","vmseries"],"created_at":"2024-11-12T22:23:42.830Z","updated_at":"2025-05-03T08:31:14.162Z","avatar_url":"https://github.com/PaloAltoNetworks.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Secure Google Cloud Hub-and-Spoke with VM-Series\n\nThis tutorial shows how to deploy and scale Palo Alto Networks VM-Series Next Generation Firewall with Terraform to secure a hub and spoke architecture in Google Cloud.  The VM-Series enables enterprises to secure their applications, users, and data deployed across Google Cloud and other virtualization environments.  \n\nThis tutorial is intended for network administrators, solution architects, and security professionals who are familiar with [Compute Engine](https://cloud.google.com/compute) and [Virtual Private Cloud (VPC) networking](https://cloud.google.com/vpc).\n\n\n## Architecture\n\nBelow is a diagram of the tutorial.  VM-Series firewalls are deployed with a regional managed instance group to secure north/south and east/west traffic for two spoke VPC networks.  \n\n\u003cimg src=\"images/diagram.png\"\u003e\n\n\n| Traffic Pattern        | Description                                                                                                                                                                                                                                                                                                       |\n| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Internet inbound       | Traffic from the internet to apps hosted in the spoke VPCs is distributed by the External Load Balancer to the VM-Series untrust interfaces (`NIC0`). The VM-Series translates the traffic through its trust interface (`NIC2`) to the spoke network. |\n| Internet outbound      | Traffic from the spoke VPCs to the internet is routed to the internal load balancer balancer in the trust VPC. The VM-Series translates the traffic through its untrust interface (`NIC0`) to the internet destination.                                                                | \n| East-west (Intra \u0026 Inter VPC) | Traffic between networks (**inter-VPC**) and traffic within a network (**intra-VPC**) is routed to the internal load balancer in the trust VPC via [Policy-Based routes](https://cloud.google.com/vpc/docs/policy-based-routes). The VM-Series inspects and hairpins the traffic through the trust interface (`NIC2`) and to the destination. |\n\n## Requirements\n\nThe following is required for this tutorial:\n\n1. A Google Cloud project. \n2. A machine with Terraform version:`\"~\u003e 1.7\"`\n\n\u003e [!NOTE]\n\u003e This tutorial assumes you are using Google Cloud Shell. \n\n\n## Prepare for Deployment\n\n1. Enable the required APIs, generate an SSH key, and clone the repository. \n\n    ```\n    gcloud services enable compute.googleapis.com\n    ssh-keygen -f ~/.ssh/vmseries-tutorial -t rsa\n    git clone https://github.com/PaloAltoNetworks/google-cloud-hub-spoke-tutorial\n    cd google-cloud-hub-spoke-tutorial\n    ```\n\n2. Create a `terraform.tfvars` file.\n\n    ```\n    cp terraform.tfvars.example terraform.tfvars\n    ```\n\n3. Edit the `terraform.tfvars` file and set values for the following variables:\n\n    | Key                         | Value                                                                                | Default                        |\n    | --------------------------- | ------------------------------------------------------------------------------------ | ------------------------------ |\n    | `project_id`                | The Project ID within Google Cloud.                                                  | `null`                         |\n    | `public_key_path`           | The local path of the public key you previously created                              | `~/.ssh/vmseries-tutorial.pub` |\n    | `mgmt_allow_ips`            | A list of IPv4 addresses which have access to the VM-Series management interface.    | `[\"0.0.0.0/0\"]`                |\n    | `create_spoke_networks`     | Set to `false` if you do not want to create the spoke networks.                      | `true`                         |\n    | `vmseries_image_name`       | Set to the VM-Series image you want to deploy.                                       | `vmseries-flex-bundle2-1022h2` |\n    | `enable_session_resiliency` | Set to `true` to enable [Session Resiliency](https://docs.paloaltonetworks.com/vm-series/11-1/vm-series-deployment/set-up-the-vm-series-firewall-on-google-cloud-platform/deploy-vm-series-on-gcp/enable-session-resiliency-on-vm-series-for-gcp) using [Memorystore for Redis](https://cloud.google.com/memorystore/docs/redis/memorystore-for-redis-overview).              | `false`                        |\n\n\u003e [!TIP]\n\u003e For `vmseries_image_name`, a full list of public images can be found with this command:\n\u003e ```\n\u003e gcloud compute images list --project paloaltonetworksgcp-public --filter='name ~ .*vmseries-flex.*'\n\u003e ```\n\n\u003e [!NOTE]\n\u003e If you are using BYOL image (i.e. `vmseries-flex-byol-*`), the license can be applied during or after deployment.  To license during deployment, add your VM-Series Authcodes to `bootstrap_files/authcodes`.  See [VM-Series Bootstrap Methods](https://docs.paloaltonetworks.com/vm-series/11-1/vm-series-deployment/bootstrap-the-vm-series-firewall) for more information.  \n\n\n4. Save your `terraform.tfvars` file.\n\n\n### (Optional) Bootstrap to Panorama\nIn production environments, it is highly recommended to use [Panorama](https://docs.paloaltonetworks.com/panorama/10-2/panorama-admin/manage-firewalls) to manage the VM-Series.  Panorama enables you to scale the VM-Series for performance while managing the them as a single entity. \n\nFor more information, see the [Panorama Staging](docs/panorama_staging.md) community guide.\n\n#### Modify Terraform to Bootstrap to Panorama\n1. In your `terraform.tfvars` set values for your Panorama IP, device group, template stack, and VM Auth Key. \n\n    \u003cpre\u003e\n    panorama_ip       = \u003cb\u003e\"1.1.1.1\"\u003c/b\u003e\n    panorama_dg       = \u003cb\u003e\"your-device-group\"\u003c/b\u003e\n    panorama_ts       = \u003cb\u003e\"your-template-stack\"\u003c/b\u003e\n    panorama_auth_key = \u003cb\u003e\"your-auth-key\"\u003c/b\u003e\n    \u003c/pre\u003e\n\n2. Save your `terraform.tfvars`.\n\n\u003e[!NOTE]\n\u003e In this Terraform plan, setting a value for `panorama_ip` removes the GCS Storage Bucket from the VM-Series metadata configuration.\n\n\n\n### Deploy\n\nWhen no further changes are necessary in the configuration, deploy the resources:\n\n1. Initialize and apply the Terraform plan.  \n\n    ```\n    terraform init\n    terraform apply\n    ```\n\n2. After all the resources are created, Terraform displays the following message:\n\n    ```\n    Apply complete!\n\n    Outputs:\n\n    EXTERNAL_LB_IP = \"35.68.75.133\"\n    ```\n\n\u003e [!NOTE]\n\u003e The `EXTERNAL_LB_IP` output displays the IP address of the external load balancer’s forwarding rule.\n\n## Access the VM-Series firewall\n\nTo access the VM-Series user interface, a password must be set for the `admin` user.\n\n1. Retrieve the `EXTERNAL_IP` attached to the VM-Series MGT interface (`NIC1`).\n\n    ```\n    gcloud compute instances list \\\n        --filter='tags.items=(vmseries-tutorial)' \\\n        --format='value(EXTERNAL_IP)'\n    ```\n\n2. SSH to the VM-Series using the `EXTERNAL_IP` with your private SSH key. \n\n    ```\n    ssh admin@\u003cEXTERNAL_IP\u003e -i ~/.ssh/vmseries-tutorial\n    ```\n\n3. On the VM-Series, set a password for the `admin` username. \n\n    ```\n    configure\n    set mgt-config users admin password\n    ```\n\n4. Commit the changes.\n    ```\n    commit\n    ```\n\n5. Enter `exit` twice to terminate the session.\n\n6. Access the VM-Series web interface using a web browser.  Login with the `admin` user and password.\n\n    ```\n    https://\u003cEXTERNAL_IP\u003e\n    ```\n\n## Internet inbound traffic\n\nInternet traffic is distributed by the external load balancer to the VM-Series untrust interfaces. The VM-Series inspects and translates the traffic to `spoke1-vm1` in the `spoke 1` network.\n\n\u003cimg src=\"images/diagram_ingress.png\"\u003e\n\n\u003e [!IMPORTANT]\n\u003e The spoke VMs in this tutorial are configured with Jenkins and a generic web service.\n\n1. Open a HTTP connection to the web service on `spoke1-vm1` by copying the `EXTERNAL_LB_IP` output value into a web browser.\n\n    ```\n    http://\u003cEXTERNAL_LB_IP\u003e\n    ```\n\n    \u003cimg src=\"images/ss01.png\" width=\"50%\"\u003e\n\n\n2. Open a session to the Jenkins service on `spoke1-vm1` by appending port `8080` to the URL.\n\n    ```\n    http://\u003cEXTERNAL_LB_IP\u003e:8080\n    ```\n\n    \u003cimg src=\"images/ss02.png\" width=\"50%\"\u003e\n\n\u003e [!TIP]\n\u003e Your request to Jenkins should fail.  This is because its App-ID™ has not been enabled on the VM-Series, yet.\n\n\n### Safely enabling applications with App-ID™ \n\nPalo Alto Networks [App-ID™](https://www.paloaltonetworks.com/technologies/app-id) enables you to see applications on your network and learn their behavioral characteristics with their relative risk.  You can use App-ID™ to enable Jenkins traffic through the VM-Series security policies.\n\n1. On the VM-Series, go to **Policies → Security** and open the `inbound-web` security policy.\n    \n2. In the **Application** tab, add the `jenkins` App-ID.  Click **OK**.\n\n    \u003cimg src=\"images/ss03.png\"\u003e\n\n3. Click **Commit → Commit** to apply the changes to the VM-Series configuration.\n\n4. Attempt to access the `jenkins` service again.  The page should now resolve.\n\n    \u003cimg src=\"images/ss04.png\" width=\"50%\"\u003e\n\n5. On the VM-Series, go to **Monitor → Traffic** and enter the filter below to search for `jenkins` traffic.\n\n    ```\n    ( app eq jenkins )\n    ```\n\n    \u003cimg src=\"images/ss05.png\"\u003e\n\n\u003e [!TIP]\n\u003e You should see the jenkins traffic was denied before its App-ID was added to the security policy.\n\n\n### Internet outbound \u0026 east/west traffic \n\n[Policy based routes](https://cloud.google.com/vpc/docs/policy-based-routes) \u0026 [custom static routes](https://cloud.google.com/vpc/docs/routes) defined within the spoke's route table steer traffic to the VM-Series internal load balancer. This enables the VM-Series to secure egress traffic from the spoke networks, including: outbound internet, inter-VPC, and intra-VPC traffic. \n\n\u003cimg src=\"images/diagram_egress.png\"\u003e\n\n\n1. Open an SSH session with `spoke2-vm1`.  \n\n    ```\n    ssh paloalto@\u003cEXTERNAL_LB_IP\u003e -i ~/.ssh/vmseries-tutorial\n    ```\n    \u003e The external load balancer distributes the request to the VM-Series.  The VM-Series inspects and translates the traffic to `spoke2-vm1`. \n\n\n\n2. Test **outbound internet** inspection by generating pseudo malicious traffic to the internet.\n\n    ```\n    curl -s -o /dev/null -w \"%{http_code}\\n\" http://www.eicar.org/cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh --data \"echo Content-Type: text/plain; echo; uname -a\" --max-time 2\n    curl -s -o /dev/null -w \"%{http_code}\\n\" http://www.eicar.org/cgi-bin/user.sh -H \"FakeHeader:() { :; }; echo Content-Type: text/html; echo ; /bin/uname -a\" --max-time 2\n    ```\n\n\n3. Test **inter-vpc** inspection by generating pseudo malicious traffic between `spoke2-vm1` and `spoke1-vm1`.\n\n    ```\n    curl http://10.1.0.10/cgi-bin/../../../..//bin/cat%20/etc/passwd\n    ```\n\n4. Test **intra-vpc** inspection by generating pseudo malicious traffic between `spoke2-vm1` and `spoke2-vm2`.\n\n    ```\n    curl -H 'User-Agent: () { :; }; 123.123.123.123:9999' http://10.2.0.11/cgi-bin/test-critical\n    ```\n\n4. On the VM-Series, go to **Monitor → Threat** to view the threat logs.  \n\n    \u003cimg src=\"images/ss06.png\"\u003e \n\n\u003e [!TIP]\n\u003e The security policies enable you to allow or block traffic based on the user, application, and device.  When traffic matches an allow rule, the security profiles that are attached to the rule provide further content inspection. See [Cloud-Delivered Security Services](https://www.paloaltonetworks.com/network-security/security-subscriptions) for more information.\n\n\n\n\n## Autoscaling the VM-Series\n\nRegional managed instance groups enable you to scale VM-Series across zones within a region.  This allows you to scale the security protecting cloud workloads. \n\nThe VM-Series publishes PAN-OS metrics to Google Cloud Monitoring.   \n\n\n### View custom metrics in Cloud Monitoring\n\nThe Terraform plan creates a custom Cloud Monitoring dashboard that displays the VM-Series performance metrics.  To view the dashboard, perform the following: \n\n1. In the Google Cloud console, select **Monitoring → Dashboards**.\n2. Select the dashboard named **VM-Series Metrics**.\n\n    \u003cimg src=\"images/ss07.png\" width=\"500\"\u003e\n\n\u003e [!TIP]\n\u003e Each metric can be set as an scaling parameter for the instance group.  See [Publishing Custom PAN-OS Metrics](https://docs.paloaltonetworks.com/vm-series/10-2/vm-series-deployment/about-the-vm-series-firewall/custom-pan-os-metrics-published-for-monitoring) for more information.\n\n\n### Scaling the VM-Series\nThe Terraform plan sets the min/max firewall count to `1`.  To simulate a scaling event, modify the instance group min/max thresholds.\n\n1. Go to **Compute Engine → Instance Groups**.\n2. Open the `vmseries` instance group and click **EDIT**. \n3. Under **Group size \u0026 autoscaling**, set the minimum to `2` and the maximum number of instances to `3`.\n\n    \u003cimg src=\"images/ss08.png\" width=\"50%\"\u003e \n\n4. Click **Save**. \n5. Go to **Compute Engine → VM instances** to view the new VM-Series firewall.\n6. Once the VM-Series finishes bootstrapping, follow the [Access the VM-Series firewall](#access-the-vm-series-firewall) instructions to gain access to the firewall’s web interface.  \n    \n\u003e [!IMPORTANT]\n\u003e This step is not required if you are bootstrapping the VM-Series to Panorama.  This is because Panorama pushes the entire configuration to the scaled firewalls.\n\n7. On the scaled VM-Series, navigate to **Monitor → Traffic**.  The traffic logs should be populated demonstrating the scaled VM-Series is now processing traffic. \n\n\u003e [!TIP]\n\u003e You can also perform this in Terraform by adding the following values to your `terraform.tfvars`.\u003c/br\u003e\n\u003e `vmseries_replica_minimum = 2`\u003c/br\u003e\n\u003e `vmseries_replica_maximum = 3`\n\n\n\n## (Optional) Using Session Resiliency\nIf session resiliency is enabled prior to deployment (`enable_session_resiliency = true`), sessions are stored in a Google Cloud Memorystore Redis Cache. This enables you to maintain layer-4 sessions by transferring sessions to healthy firewalls within the instance group.\n\n### Configure IPerf between spoke VMs\n\nUse [iPerf](https://iperf.fr/iperf-doc.php) to create parallel TCP connections between `spoke2-vm1` (client) and `spoke1-vm1` (server).  \n\n1. In cloud shell, SSH to `spoke1-vm1`.\n\n    ```\n    gcloud compute ssh paloalto@spoke1-vm1 --zone=us-central1-a\n    ```\n\n2. Install `iperf` on `spoke1-vm1`.\n\n    ```\n    sudo apt-get update\n    sudo apt-get install iperf\n    ```\n\n3. Make `spoke1-vm1` a server listening on `TCP:5001`.\n\n    ```\n    iperf -s -f M -p 5001 -t 3600\n    ```\n    \n4. In a *separate cloud shell tab*, SSH into `spoke2-vm1`.\n\n    ```\n    gcloud compute ssh paloalto@spoke2-vm1 --zone=us-central1-a\n    ```\n\n5. Install `iperf` on `spoke2-vm1`\n\n    ```\n    sudo apt-get update\n    sudo apt-get install iperf\n    ```\n\n6. Create `50` parallel connections from `spoke2-vm1` to `spoke1-vm1` using port `TCP:5001`. \n\n    ```\n    iperf -c 10.1.0.10 -f M -p 5001 -P 50 -t 3600\n    ```\n\n     \n\n7. On each firewall, go to **Monitor → Traffic** and enter the filter to search for the `iperf` connections.\n\n    ```\n    ( port.dst eq '5001' )\n    ```\n    \u003cimg src=\"images/ss09.png\"\u003e\n\n\u003e [!NOTE]\n\u003e On both firewalls you should see active connections on `TCP:5001`.\n\n\n### Trigger a failure event\nSimulate a failure event by randomly descaling one of the firewalls.  After the descale completes, verify all of the `iperf` connections are still transfering data.\n\n1. Go to **Compute Engine → Instance Groups**.\n2. Open the `vmseries` instance group and click **EDIT**. \n3. Under **Group size \u0026 autoscaling**, set the minimum to `1` and the maximum number of instances to `1`.\n\n    \u003cimg src=\"images/ss10.png\" width=\"50%\"\u003e \n\n4. Wait for one of the VM-Series firewalls to descale.\n\n4. On `spoke2-vm1`, kill the `iperf` connection by entering `ctrl + c`.\n\n\u003e [!TIP]\n\u003e You should see the connection transfers are still running, indicating the sessions have successfully failed over. \n\n\n\n\n\n## Clean up\n\nDelete all the resources when you no longer need them.\n\n1. Run the following command\n    \n    ```\n    terraform destroy\n    ```\n\n2. At the prompt to perform the actions, enter `yes`. \n   \n   After all the resources are deleted, Terraform displays the following message:\n\n    ```\n    Destroy complete!\n    ```\n\n## Additional information\n\n* Learn about the[ VM-Series on Google Cloud](https://docs.paloaltonetworks.com/vm-series/10-2/vm-series-deployment/set-up-the-vm-series-firewall-on-google-cloud-platform/about-the-vm-series-firewall-on-google-cloud-platform).\n* Getting started with [Palo Alto Networks PAN-OS](https://docs.paloaltonetworks.com/pan-os). \n* Read about [securing Google Cloud Networks with the VM-Series](https://cloud.google.com/architecture/partners/palo-alto-networks-ngfw).\n* Learn about [VM-Series licensing on all platforms](https://docs.paloaltonetworks.com/vm-series/10-2/vm-series-deployment/license-the-vm-series-firewall/vm-series-firewall-licensing.html#id8fea514c-0d85-457f-b53c-d6d6193df07c).\n* Use the [VM-Series Terraform modules for Google Cloud](https://registry.terraform.io/modules/PaloAltoNetworks/vmseries-modules/google/latest). \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaloaltonetworks%2Fgoogle-cloud-hub-spoke-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaloaltonetworks%2Fgoogle-cloud-hub-spoke-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaloaltonetworks%2Fgoogle-cloud-hub-spoke-tutorial/lists"}