diff --git a/.github/actions/plan_apply/action.yml b/.github/actions/plan_apply/action.yml
new file mode 100644
index 00000000..0a7d6c13
--- /dev/null
+++ b/.github/actions/plan_apply/action.yml
@@ -0,0 +1,63 @@
+name: 'TF plan/apply'
+description: 'Runs Terraform plan and/or apply for a specified path.'
+inputs:
+ tf_version:
+ description: 'TF version used.'
+ required: true
+ path:
+ description: 'Path to Terraform module.'
+ required: true
+ do_apply:
+ description: When set to true runs also apply
+ type: boolean
+ default: false
+ idempotence:
+ description: When set to true runs plan to on already applied configuration
+ type: boolean
+ default: true
+
+runs:
+ using: "composite"
+ steps:
+
+ - name: setup Terraform
+ uses: hashicorp/setup-terraform@v2
+ with:
+ terraform_version: ${{ inputs.tf_version }}
+ # below settings is required for Terratest (details are in https://github.com/gruntwork-io/terratest/issues/706)
+ terraform_wrapper: false
+
+ - name: configure AWS credentials
+ uses: aws-actions/configure-aws-credentials@v2
+ with:
+ role-to-assume: ${{ env.ASSUME_ROLE }}
+ role-session-name: gh-action-role-session
+ aws-region: ${{ env.AWS_REGION }}
+ # TODO: it's temporary solution until in repository settings -> secrets and variables -> variables
+ # there will be defined new repository variable AWS_REGION
+ env:
+ AWS_REGION : "us-east-1"
+
+ - name: test infrastructure
+ id: test
+ env:
+ TPATH: ${{ inputs.path }}
+ DO_APPLY: ${{ inputs.do_apply }}
+ shell: bash
+ run: |
+ echo "::group::TERRATEST"
+ cd "$GITHUB_WORKSPACE/$TPATH"
+ DO_APPLY=$DO_APPLY make test
+ echo "::endgroup::"
+
+ - name: destroy
+ id: destroy
+ if: always() && inputs.do_apply == 'true'
+ env:
+ TPATH: ${{ inputs.path }}
+ shell: bash
+ run: |
+ cd "$GITHUB_WORKSPACE/$TPATH"
+ echo "::group::TERRAFORM DESTROY"
+ make destroy
+ echo "::endgroup::"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index d1c85d40..00000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,108 +0,0 @@
-
----
-name: CI/CD
-on:
- push:
- branches:
- - main
- - develop
- pull_request:
- schedule:
- - cron: '0 0 1 * *'
-
-jobs:
- pre-commit:
- name: Verify the pre-commit framework was used properly by developers
- runs-on: ubuntu-latest
-
- steps:
- - name: Check out source
- uses: actions/checkout@v2
-
- - name: Set up Python
- uses: actions/setup-python@v2
- with:
- # Semantic version range syntax (like 3.x) or the exact Python version
- python-version: '3.11.0'
-
- - name: Run pre-commit framework as the developer should run it
- run: sudo ./scripts/install.sh && sudo ./scripts/run.sh
-
- - name: The `git diff` showing whether the pre-commit mandated extra changes to the repository files
- if: failure()
- run: git diff
-
- validate:
- name: Validate
- runs-on: ubuntu-latest
-
- steps:
- - name: Check out source
- uses: actions/checkout@v2
-
- - name: Set up Terraform
- uses: hashicorp/setup-terraform@v1
- with:
- terraform_version: 1.0.0
-
- - name: terraform validate
- env:
- AWS_DEFAULT_REGION: us-west-2
- run: |
- cd "$GITHUB_WORKSPACE"
- for dir in $(find modules examples -type d -not \( -name ".?*" \) -maxdepth 1 -mindepth 1);
- do
- if [[ "$dir" == "modules/transit_gateway_peering" ]];
- then
- echo "Skipping directory: $dir"
- echo "Terraform does not support validating a module which uses an aliased provider (module-specific; validating an entire configuration works fine)."
- continue
- fi
-
- echo "Processing directory: $dir"
- cd "$GITHUB_WORKSPACE/$dir"
- terraform init -backend=false
- terraform validate
- done
-
- checkov:
- name: Scan Terraform code with Checkov
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v2
- - name: Set up Python 3.8
- uses: actions/setup-python@v1
- with:
- python-version: 3.8
- - name: Test with Checkov
- id: checkov
- uses: bridgecrewio/checkov-action@master
- with:
- output_format: cli
- directory: .
- framework: terraform
- compact: true
- soft_fail: true
- quiet: true # display only failed checks
-
- # release:
- # name: release
- # if: github.event_name == 'push' && github.ref == 'refs/heads/main'
- # needs: [validate]
- # runs-on: ubuntu-latest
-
- # steps:
- # - name: Checkout
- # uses: actions/checkout@v2
-
- # - name: Create release and publish
- # id: release
- # uses: cycjimmy/semantic-release-action@v2
- # with:
- # semantic_version: 17.4.2
- # extra_plugins: |
- # conventional-changelog-conventionalcommits@^4.5.0
- # @semantic-release/git@^9.0.0
- # env:
- # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/oidc.yml b/.github/workflows/oidc.yml
deleted file mode 100644
index 0d410f6a..00000000
--- a/.github/workflows/oidc.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-# Sample workflow to perform terratest against a test AWS account
-name: AWS Terratest workflow
-on: workflow_dispatch
-
-env:
- AWS_REGION : "eu-west-2"
-
-permissions:
- id-token: write # This is required for requesting the JWT
- contents: read # This is required for actions/checkout
-jobs:
- TerraTest:
- runs-on: ubuntu-latest
- steps:
- - name: Git clone the repository
- uses: actions/checkout@v3
-
- - name: configure aws credentials
- uses: aws-actions/configure-aws-credentials@v1
- with:
- role-to-assume: ${{ secrets.ASSUME_ROLE }}
- role-session-name: gh-action-role-session
- aws-region: ${{ env.AWS_REGION }}
-
- - name: Setup Dependencies
- working-directory: tests/vpc/deployment
- run: go get -v -t -d && go mod tidy
-
- - name: Test
- working-directory: tests/vpc/deployment
- run: go test -v
\ No newline at end of file
diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml
new file mode 100644
index 00000000..bbe81057
--- /dev/null
+++ b/.github/workflows/pr_ci.yml
@@ -0,0 +1,29 @@
+name: PR CI
+run-name: "CI pipeline for PR - (#${{ github.event.number }}) ${{ github.event.pull_request.title }}"
+
+permissions:
+ contents: read
+ actions: read
+ id-token: write
+
+on:
+ pull_request:
+ types:
+ - opened
+ - reopened
+ - synchronize
+ - ready_for_review
+ branches: ['main']
+
+jobs:
+ pr_ci_wrkflw:
+ name: Run CI
+ uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/pr_ci.yml@v1.2.0
+ if: github.actor != 'dependabot[bot]'
+ secrets: inherit
+ with:
+ cloud: aws
+ tf_version: 1.2 1.3 1.4 1.5
+ do_apply: false
+ fail_fast: false
+ apply_timeout: 120
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 627a399a..00000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-name: Release
-on: workflow_dispatch
-
-jobs:
- release:
- name: release
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout
- uses: actions/checkout@v2
-
- - name: Create release and publish
- id: release
- uses: cycjimmy/semantic-release-action@v2
- with:
- semantic_version: 17.4.2
- extra_plugins: |
- conventional-changelog-conventionalcommits@^4.5.0
- @semantic-release/git@^9.0.0
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/release_ci.yml b/.github/workflows/release_ci.yml
new file mode 100644
index 00000000..4a1ebae5
--- /dev/null
+++ b/.github/workflows/release_ci.yml
@@ -0,0 +1,25 @@
+name: Release CI
+run-name: "Continous Release"
+
+permissions:
+ contents: write
+ issues: read
+ id-token: write
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: '0 1 * * 4' # this means every Thursday @1am UTC
+
+jobs:
+ release_wrkflw:
+ name: Do release
+ uses: PaloAltoNetworks/terraform-modules-vmseries-ci-workflows/.github/workflows/release_ci.yml@v1.2.0
+ if: github.actor != 'dependabot[bot]'
+ secrets: inherit
+ with:
+ cloud: aws
+ max_parallel: 10
+ do_apply: true
+ fail_fast: false
+ apply_timeout: 120
diff --git a/examples/centralized_design/Makefile b/examples/centralized_design/Makefile
new file mode 100644
index 00000000..7258f45c
--- /dev/null
+++ b/examples/centralized_design/Makefile
@@ -0,0 +1,11 @@
+init:
+ @../../makefile.sh init
+
+validate:
+ @../../makefile.sh validate
+
+test:
+ @../../makefile.sh test
+
+destroy:
+ @../../makefile.sh destroy
diff --git a/examples/centralized_design/main_test.go b/examples/centralized_design/main_test.go
new file mode 100644
index 00000000..6bc58612
--- /dev/null
+++ b/examples/centralized_design/main_test.go
@@ -0,0 +1,47 @@
+package centralized_design
+
+import (
+ "fmt"
+ "math/rand"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
+ "github.com/gruntwork-io/terratest/modules/logger"
+ "github.com/gruntwork-io/terratest/modules/terraform"
+)
+
+func TestExampleCentralizedDesign(t *testing.T) {
+ // prepare random prefix
+ source := rand.NewSource(time.Now().UnixNano())
+ random := rand.New(source)
+ number := random.Intn(1000)
+ namePrefix := fmt.Sprintf("terra%d-", number)
+
+ // define options for Terraform
+ terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
+ TerraformDir: ".",
+ VarFiles: []string{"example.tfvars"},
+ Vars: map[string]interface{}{
+ "name_prefix": namePrefix,
+ "ssh_key_name": "test-ssh-key",
+ },
+ Logger: logger.Default,
+ Lock: true,
+ Upgrade: true,
+ SetVarsAfterVarFiles: true,
+ })
+
+ // prepare list of items to check
+ assertList := []testskeleton.AssertExpression{}
+
+ // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan
+ if os.Getenv("DO_APPLY") == "true" {
+ // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment
+ testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList)
+ } else {
+ // plan test infrastructure and verify outputs
+ testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected")
+ }
+}
diff --git a/examples/combined_design/Makefile b/examples/combined_design/Makefile
new file mode 100644
index 00000000..7258f45c
--- /dev/null
+++ b/examples/combined_design/Makefile
@@ -0,0 +1,11 @@
+init:
+ @../../makefile.sh init
+
+validate:
+ @../../makefile.sh validate
+
+test:
+ @../../makefile.sh test
+
+destroy:
+ @../../makefile.sh destroy
diff --git a/examples/combined_design/main_test.go b/examples/combined_design/main_test.go
new file mode 100644
index 00000000..e0c7a3e6
--- /dev/null
+++ b/examples/combined_design/main_test.go
@@ -0,0 +1,47 @@
+package centralized_design
+
+import (
+ "fmt"
+ "math/rand"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
+ "github.com/gruntwork-io/terratest/modules/logger"
+ "github.com/gruntwork-io/terratest/modules/terraform"
+)
+
+func TestExampleCombinedDesign(t *testing.T) {
+ // prepare random prefix
+ source := rand.NewSource(time.Now().UnixNano())
+ random := rand.New(source)
+ number := random.Intn(1000)
+ namePrefix := fmt.Sprintf("terra%d-", number)
+
+ // define options for Terraform
+ terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
+ TerraformDir: ".",
+ VarFiles: []string{"example.tfvars"},
+ Vars: map[string]interface{}{
+ "name_prefix": namePrefix,
+ "ssh_key_name": "test-ssh-key",
+ },
+ Logger: logger.Default,
+ Lock: true,
+ Upgrade: true,
+ SetVarsAfterVarFiles: true,
+ })
+
+ // prepare list of items to check
+ assertList := []testskeleton.AssertExpression{}
+
+ // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan
+ if os.Getenv("DO_APPLY") == "true" {
+ // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment
+ testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList)
+ } else {
+ // plan test infrastructure and verify outputs
+ testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected")
+ }
+}
diff --git a/examples/combined_design_autoscale/Makefile b/examples/combined_design_autoscale/Makefile
new file mode 100644
index 00000000..7258f45c
--- /dev/null
+++ b/examples/combined_design_autoscale/Makefile
@@ -0,0 +1,11 @@
+init:
+ @../../makefile.sh init
+
+validate:
+ @../../makefile.sh validate
+
+test:
+ @../../makefile.sh test
+
+destroy:
+ @../../makefile.sh destroy
diff --git a/examples/combined_design_autoscale/example.tfvars b/examples/combined_design_autoscale/example.tfvars
new file mode 100644
index 00000000..62bfe4d5
--- /dev/null
+++ b/examples/combined_design_autoscale/example.tfvars
@@ -0,0 +1,592 @@
+### GENERAL
+region = "eu-central-1" # TODO: update here
+name_prefix = "example-" # TODO: update here
+
+global_tags = {
+ ManagedBy = "terraform"
+ Application = "Palo Alto Networks VM-Series NGFW"
+ Owner = "PS Team"
+}
+
+ssh_key_name = "example-frankfurt" # TODO: update here
+
+### VPC
+vpcs = {
+ # Do not use `-` in key for VPC as this character is used in concatation of VPC and subnet for module `subnet_set` in `main.tf`
+ security_vpc = {
+ name = "security-vpc"
+ cidr = "10.100.0.0/16"
+ nacls = {
+ trusted_path_monitoring = {
+ name = "trusted-path-monitoring"
+ rules = {
+ block_outbound_icmp_1 = {
+ rule_number = 110
+ egress = true
+ protocol = "icmp"
+ rule_action = "deny"
+ cidr_block = "10.100.1.0/24"
+ from_port = null
+ to_port = null
+ }
+ block_outbound_icmp_2 = {
+ rule_number = 120
+ egress = true
+ protocol = "icmp"
+ rule_action = "deny"
+ cidr_block = "10.100.65.0/24"
+ from_port = null
+ to_port = null
+ }
+ allow_other_outbound = {
+ rule_number = 200
+ egress = true
+ protocol = "-1"
+ rule_action = "allow"
+ cidr_block = "0.0.0.0/0"
+ from_port = null
+ to_port = null
+ }
+ allow_inbound = {
+ rule_number = 300
+ egress = false
+ protocol = "-1"
+ rule_action = "allow"
+ cidr_block = "0.0.0.0/0"
+ from_port = null
+ to_port = null
+ }
+ }
+ }
+ }
+ security_groups = {
+ vmseries_private = {
+ name = "vmseries_private"
+ rules = {
+ all_outbound = {
+ description = "Permit All traffic outbound"
+ type = "egress", from_port = "0", to_port = "0", protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+ geneve = {
+ description = "Permit GENEVE to GWLB subnets"
+ type = "ingress", from_port = "6081", to_port = "6081", protocol = "udp"
+ cidr_blocks = [
+ "10.100.5.0/24", "10.100.69.0/24"
+ ]
+ }
+ health_probe = {
+ description = "Permit Port 80 Health Probe to GWLB subnets"
+ type = "ingress", from_port = "80", to_port = "80", protocol = "tcp"
+ cidr_blocks = [
+ "10.100.5.0/24", "10.100.69.0/24"
+ ]
+ }
+ }
+ }
+ vmseries_mgmt = {
+ name = "vmseries_mgmt"
+ rules = {
+ all_outbound = {
+ description = "Permit All traffic outbound"
+ type = "egress", from_port = "0", to_port = "0", protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+ https = {
+ description = "Permit HTTPS"
+ type = "ingress", from_port = "443", to_port = "443", protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"] # TODO: update here (replace 0.0.0.0/0 by your IP range)
+ }
+ ssh = {
+ description = "Permit SSH"
+ type = "ingress", from_port = "22", to_port = "22", protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"] # TODO: update here (replace 0.0.0.0/0 by your IP range)
+ }
+ panorama_ssh = {
+ description = "Permit Panorama SSH (Optional)"
+ type = "ingress", from_port = "22", to_port = "22", protocol = "tcp"
+ cidr_blocks = ["10.0.0.0/8"]
+ }
+ panorama_mgmt = {
+ description = "Permit Panorama Management"
+ type = "ingress", from_port = "3978", to_port = "3978", protocol = "tcp"
+ cidr_blocks = ["10.0.0.0/8"]
+ }
+ panorama_log = {
+ description = "Permit Panorama Logging"
+ type = "ingress", from_port = "28443", to_port = "28443", protocol = "tcp"
+ cidr_blocks = ["10.0.0.0/8"]
+ }
+ }
+ }
+ vmseries_public = {
+ name = "vmseries_public"
+ rules = {
+ all_outbound = {
+ description = "Permit All traffic outbound"
+ type = "egress", from_port = "0", to_port = "0", protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+ ssh = {
+ description = "Permit SSH"
+ type = "ingress", from_port = "22", to_port = "22", protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"] # TODO: update here (replace 0.0.0.0/0 by your IP range)
+ }
+ https = {
+ description = "Permit HTTPS"
+ type = "ingress", from_port = "443", to_port = "443", protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"] # TODO: update here (replace 0.0.0.0/0 by your IP range)
+ }
+ http = {
+ description = "Permit HTTP"
+ type = "ingress", from_port = "80", to_port = "80", protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"] # TODO: update here (replace 0.0.0.0/0 by your IP range)
+ }
+ }
+ }
+ }
+ subnets = {
+ # Do not modify value of `set=`, it is an internal identifier referenced by main.tf
+ # Value of `nacl` must match key of objects stored in `nacls`
+ "10.100.0.0/24" = { az = "eu-central-1a", set = "mgmt", nacl = null }
+ "10.100.64.0/24" = { az = "eu-central-1b", set = "mgmt", nacl = null }
+ "10.100.1.0/24" = { az = "eu-central-1a", set = "private", nacl = "trusted_path_monitoring" }
+ "10.100.65.0/24" = { az = "eu-central-1b", set = "private", nacl = "trusted_path_monitoring" }
+ "10.100.2.0/24" = { az = "eu-central-1a", set = "public", nacl = null }
+ "10.100.66.0/24" = { az = "eu-central-1b", set = "public", nacl = null }
+ "10.100.3.0/24" = { az = "eu-central-1a", set = "tgw_attach", nacl = null }
+ "10.100.67.0/24" = { az = "eu-central-1b", set = "tgw_attach", nacl = null }
+ "10.100.4.0/24" = { az = "eu-central-1a", set = "gwlbe_outbound", nacl = null }
+ "10.100.68.0/24" = { az = "eu-central-1b", set = "gwlbe_outbound", nacl = null }
+ "10.100.5.0/24" = { az = "eu-central-1a", set = "gwlb", nacl = null }
+ "10.100.69.0/24" = { az = "eu-central-1b", set = "gwlb", nacl = null }
+ "10.100.10.0/24" = { az = "eu-central-1a", set = "gwlbe_eastwest", nacl = null }
+ "10.100.74.0/24" = { az = "eu-central-1b", set = "gwlbe_eastwest", nacl = null }
+ }
+ routes = {
+ # Value of `vpc_subnet` is built from key of VPCs concatenate with `-` and key of subnet in format: `VPCKEY-SUBNETKEY`
+ # Value of `next_hop_key` must match keys use to create TGW attachment, IGW, GWLB endpoint or other resources
+ # Value of `next_hop_type` is internet_gateway, nat_gateway, transit_gateway_attachment or gwlbe_endpoint
+ mgmt_default = {
+ vpc_subnet = "security_vpc-mgmt"
+ to_cidr = "0.0.0.0/0"
+ next_hop_key = "security_vpc"
+ next_hop_type = "internet_gateway"
+ }
+ mgmt_panorama = {
+ vpc_subnet = "security_vpc-mgmt"
+ to_cidr = "10.255.0.0/16"
+ next_hop_key = "security"
+ next_hop_type = "transit_gateway_attachment"
+ }
+ mgmt_rfc1918 = {
+ vpc_subnet = "security_vpc-mgmt"
+ to_cidr = "10.0.0.0/8"
+ next_hop_key = "security"
+ next_hop_type = "transit_gateway_attachment"
+ }
+ tgw_rfc1918 = {
+ vpc_subnet = "security_vpc-tgw_attach"
+ to_cidr = "10.0.0.0/8"
+ next_hop_key = "security_gwlb_eastwest"
+ next_hop_type = "gwlbe_endpoint"
+ }
+ tgw_default = {
+ vpc_subnet = "security_vpc-tgw_attach"
+ to_cidr = "0.0.0.0/0"
+ next_hop_key = "security_gwlb_outbound"
+ next_hop_type = "gwlbe_endpoint"
+ }
+ public_default = {
+ vpc_subnet = "security_vpc-public"
+ to_cidr = "0.0.0.0/0"
+ next_hop_key = "security_vpc"
+ next_hop_type = "internet_gateway"
+ }
+ gwlbe_outbound_rfc1918 = {
+ vpc_subnet = "security_vpc-gwlbe_outbound"
+ to_cidr = "10.0.0.0/8"
+ next_hop_key = "security"
+ next_hop_type = "transit_gateway_attachment"
+ }
+ gwlbe_eastwest_rfc1918 = {
+ vpc_subnet = "security_vpc-gwlbe_eastwest"
+ to_cidr = "10.0.0.0/8"
+ next_hop_key = "security"
+ next_hop_type = "transit_gateway_attachment"
+ }
+ }
+ }
+ app1_vpc = {
+ name = "app1-spoke-vpc"
+ cidr = "10.104.0.0/16"
+ nacls = {}
+ security_groups = {
+ app1_vm = {
+ name = "app1_vm"
+ rules = {
+ all_outbound = {
+ description = "Permit All traffic outbound"
+ type = "egress", from_port = "0", to_port = "0", protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+ ssh = {
+ description = "Permit SSH"
+ type = "ingress", from_port = "22", to_port = "22", protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"] # TODO: update here (replace 0.0.0.0/0 by your IP range)
+ }
+ https = {
+ description = "Permit HTTPS"
+ type = "ingress", from_port = "443", to_port = "443", protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"] # TODO: update here (replace 0.0.0.0/0 by your IP range)
+ }
+ http = {
+ description = "Permit HTTP"
+ type = "ingress", from_port = "80", to_port = "80", protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"] # TODO: update here (replace 0.0.0.0/0 by your IP range)
+ }
+ }
+ }
+ }
+ subnets = {
+ # Do not modify value of `set=`, it is an internal identifier referenced by main.tf.
+ "10.104.0.0/24" = { az = "eu-central-1a", set = "app1_vm", nacl = null }
+ "10.104.128.0/24" = { az = "eu-central-1b", set = "app1_vm", nacl = null }
+ "10.104.2.0/24" = { az = "eu-central-1a", set = "app1_lb", nacl = null }
+ "10.104.130.0/24" = { az = "eu-central-1b", set = "app1_lb", nacl = null }
+ "10.104.3.0/24" = { az = "eu-central-1a", set = "app1_gwlbe", nacl = null }
+ "10.104.131.0/24" = { az = "eu-central-1b", set = "app1_gwlbe", nacl = null }
+ }
+ routes = {
+ # Value of `vpc_subnet` is built from key of VPCs concatenate with `-` and key of subnet in format: `VPCKEY-SUBNETKEY`
+ # Value of `next_hop_key` must match keys use to create TGW attachment, IGW, GWLB endpoint or other resources
+ # Value of `next_hop_type` is internet_gateway, nat_gateway, transit_gateway_attachment or gwlbe_endpoint
+ vm_default = {
+ vpc_subnet = "app1_vpc-app1_vm"
+ to_cidr = "0.0.0.0/0"
+ next_hop_key = "app1"
+ next_hop_type = "transit_gateway_attachment"
+ }
+ gwlbe_default = {
+ vpc_subnet = "app1_vpc-app1_gwlbe"
+ to_cidr = "0.0.0.0/0"
+ next_hop_key = "app1_vpc"
+ next_hop_type = "internet_gateway"
+ }
+ lb_default = {
+ vpc_subnet = "app1_vpc-app1_lb"
+ to_cidr = "0.0.0.0/0"
+ next_hop_key = "app1_inbound"
+ next_hop_type = "gwlbe_endpoint"
+ }
+ }
+ }
+ app2_vpc = {
+ name = "app2-spoke-vpc"
+ cidr = "10.105.0.0/16"
+ nacls = {}
+ security_groups = {
+ app2_vm = {
+ name = "app2_vm"
+ rules = {
+ all_outbound = {
+ description = "Permit All traffic outbound"
+ type = "egress", from_port = "0", to_port = "0", protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+ ssh = {
+ description = "Permit SSH"
+ type = "ingress", from_port = "22", to_port = "22", protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"] # TODO: update here (replace 0.0.0.0/0 by your IP range)
+ }
+ https = {
+ description = "Permit HTTPS"
+ type = "ingress", from_port = "443", to_port = "443", protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"] # TODO: update here (replace 0.0.0.0/0 by your IP range)
+ }
+ http = {
+ description = "Permit HTTP"
+ type = "ingress", from_port = "80", to_port = "80", protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"] # TODO: update here (replace 0.0.0.0/0 by your IP range)
+ }
+ }
+ }
+ }
+ subnets = {
+ # Do not modify value of `set=`, it is an internal identifier referenced by main.tf.
+ "10.105.0.0/24" = { az = "eu-central-1a", set = "app2_vm", nacl = null }
+ "10.105.128.0/24" = { az = "eu-central-1b", set = "app2_vm", nacl = null }
+ "10.105.2.0/24" = { az = "eu-central-1a", set = "app2_lb", nacl = null }
+ "10.105.130.0/24" = { az = "eu-central-1b", set = "app2_lb", nacl = null }
+ "10.105.3.0/24" = { az = "eu-central-1a", set = "app2_gwlbe", nacl = null }
+ "10.105.131.0/24" = { az = "eu-central-1b", set = "app2_gwlbe", nacl = null }
+ }
+ routes = {
+ # Value of `vpc_subnet` is built from key of VPCs concatenate with `-` and key of subnet in format: `VPCKEY-SUBNETKEY`
+ # Value of `next_hop_key` must match keys use to create TGW attachment, IGW, GWLB endpoint or other resources
+ # Value of `next_hop_type` is internet_gateway, nat_gateway, transit_gateway_attachment or gwlbe_endpoint
+ vm_default = {
+ vpc_subnet = "app2_vpc-app2_vm"
+ to_cidr = "0.0.0.0/0"
+ next_hop_key = "app2"
+ next_hop_type = "transit_gateway_attachment"
+ }
+ gwlbe_default = {
+ vpc_subnet = "app2_vpc-app2_gwlbe"
+ to_cidr = "0.0.0.0/0"
+ next_hop_key = "app2_vpc"
+ next_hop_type = "internet_gateway"
+ }
+ lb_default = {
+ vpc_subnet = "app2_vpc-app2_lb"
+ to_cidr = "0.0.0.0/0"
+ next_hop_key = "app2_inbound"
+ next_hop_type = "gwlbe_endpoint"
+ }
+ }
+ }
+}
+
+### TRANSIT GATEWAY
+tgw = {
+ create = true
+ id = null
+ name = "tgw"
+ asn = "64512"
+ route_tables = {
+ # Do not change keys `from_security_vpc` and `from_spoke_vpc` as they are used in `main.tf` and attachments
+ "from_security_vpc" = {
+ create = true
+ name = "from_security"
+ }
+ "from_spoke_vpc" = {
+ create = true
+ name = "from_spokes"
+ }
+ }
+ attachments = {
+ # Value of `vpc_subnet` is built from key of VPCs concatenate with `-` and key of subnet in format: `VPCKEY-SUBNETKEY`
+ # Value of `route_table` and `propagate_routes_to` must match `route_tables` stores under `tgw`
+ security = {
+ name = "vmseries"
+ vpc_subnet = "security_vpc-tgw_attach"
+ route_table = "from_security_vpc"
+ propagate_routes_to = "from_spoke_vpc"
+ }
+ app1 = {
+ name = "app1-spoke-vpc"
+ vpc_subnet = "app1_vpc-app1_vm"
+ route_table = "from_spoke_vpc"
+ propagate_routes_to = "from_security_vpc"
+ }
+ app2 = {
+ name = "app2-spoke-vpc"
+ vpc_subnet = "app2_vpc-app2_vm"
+ route_table = "from_spoke_vpc"
+ propagate_routes_to = "from_security_vpc"
+ }
+ }
+}
+
+### NAT GATEWAY
+natgws = {}
+
+### GATEWAY LOADBALANCER
+gwlbs = {
+ # Value of `vpc_subnet` is built from key of VPCs concatenate with `-` and key of subnet in format: `VPCKEY-SUBNETKEY`
+ security_gwlb = {
+ name = "security-gwlb"
+ vpc_subnet = "security_vpc-gwlb"
+ }
+}
+gwlb_endpoints = {
+ # Value of `gwlb` must match key of objects stored in `gwlbs`
+ # Value of `vpc` must match key of objects stored in `vpcs`
+ # Value of `vpc_subnet` is built from key of VPCs concatenate with `-` and key of subnet in format: `VPCKEY-SUBNETKEY`
+ security_gwlb_eastwest = {
+ name = "eastwest-gwlb-endpoint"
+ gwlb = "security_gwlb"
+ vpc = "security_vpc"
+ vpc_subnet = "security_vpc-gwlbe_eastwest"
+ act_as_next_hop = false
+ to_vpc_subnets = null
+ }
+ security_gwlb_outbound = {
+ name = "outbound-gwlb-endpoint"
+ gwlb = "security_gwlb"
+ vpc = "security_vpc"
+ vpc_subnet = "security_vpc-gwlbe_outbound"
+ act_as_next_hop = false
+ to_vpc_subnets = null
+ }
+ app1_inbound = {
+ name = "app1-gwlb-endpoint"
+ gwlb = "security_gwlb"
+ vpc = "app1_vpc"
+ vpc_subnet = "app1_vpc-app1_gwlbe"
+ act_as_next_hop = true
+ to_vpc_subnets = "app1_vpc-app1_lb"
+ }
+ app2_inbound = {
+ name = "app2-gwlb-endpoint"
+ gwlb = "security_gwlb"
+ vpc = "app2_vpc"
+ vpc_subnet = "app2_vpc-app2_gwlbe"
+ act_as_next_hop = true
+ to_vpc_subnets = "app2_vpc-app2_lb"
+ }
+}
+
+### VM-SERIES
+vmseries_asgs = {
+ main_asg = {
+ # Value of `panorama-server`, `auth-key`, `dgname`, `tplname` can be taken from plugin `sw_fw_license`
+ bootstrap_options = {
+ mgmt-interface-swap = "enable"
+ plugin-op-commands = "panorama-licensing-mode-on,aws-gwlb-inspect:enable,aws-gwlb-overlay-routing:enable" # TODO: update here
+ panorama-server = "" # TODO: update here
+ auth-key = "" # TODO: update here
+ dgname = "" # TODO: update here
+ tplname = "" # TODO: update here
+ dhcp-send-hostname = "yes" # TODO: update here
+ dhcp-send-client-id = "yes" # TODO: update here
+ dhcp-accept-server-hostname = "yes" # TODO: update here
+ dhcp-accept-server-domain = "yes" # TODO: update here
+ }
+
+ panos_version = "10.2.3" # TODO: update here
+ ebs_kms_id = "alias/aws/ebs" # TODO: update here
+
+ # Value of `vpc` must match key of objects stored in `vpcs`
+ vpc = "security_vpc"
+
+ # Value of `gwlb` must match key of objects stored in `gwlbs`
+ gwlb = "security_gwlb"
+
+ interfaces = {
+ private = {
+ device_index = 0
+ security_group = "vmseries_private"
+ subnet = {
+ "privatea" = "eu-central-1a",
+ "privateb" = "eu-central-1b"
+ }
+ create_public_ip = false
+ source_dest_check = false
+ }
+ mgmt = {
+ device_index = 1
+ security_group = "vmseries_mgmt"
+ subnet = {
+ "mgmta" = "eu-central-1a",
+ "mgmtb" = "eu-central-1b"
+ }
+ create_public_ip = true
+ source_dest_check = true
+ }
+ public = {
+ device_index = 2
+ security_group = "vmseries_public"
+ subnet = {
+ "publica" = "eu-central-1a",
+ "publicb" = "eu-central-1b"
+ }
+ create_public_ip = true
+ source_dest_check = false
+ }
+ }
+
+ # Value of `gwlb_endpoint` must match key of objects stored in `gwlb_endpoints`
+ subinterfaces = {
+ inbound = {
+ app1 = {
+ gwlb_endpoint = "app1_inbound"
+ subinterface = "ethernet1/1.11"
+ }
+ app2 = {
+ gwlb_endpoint = "app2_inbound"
+ subinterface = "ethernet1/1.12"
+ }
+ }
+ outbound = {
+ only_1_outbound = {
+ gwlb_endpoint = "security_gwlb_outbound"
+ subinterface = "ethernet1/1.20"
+ }
+ }
+ eastwest = {
+ only_1_eastwest = {
+ gwlb_endpoint = "security_gwlb_eastwest"
+ subinterface = "ethernet1/1.30"
+ }
+ }
+ }
+
+ asg = {
+ desired_cap = 0
+ min_size = 0
+ max_size = 4
+ }
+
+ scaling_plan = {
+ enabled = true # TODO: update here
+ metric_name = "panSessionActive" # TODO: update here
+ target_value = 75 # TODO: update here
+ statistic = "Average" # TODO: update here
+ cloudwatch_namespace = "example-vmseries" # TODO: update here
+ tags = {
+ ManagedBy = "terraform"
+ }
+ }
+ }
+}
+
+### PANORAMA
+panorama_attachment = {
+ transit_gateway_attachment_id = null # TODO: update here
+ vpc_cidr = "10.255.0.0/24" # TODO: update here
+}
+
+### SPOKE VMS
+spoke_vms = {
+ "app1_vm01" = {
+ az = "eu-central-1a"
+ vpc = "app1_vpc"
+ vpc_subnet = "app1_vpc-app1_vm"
+ security_group = "app1_vm"
+ type = "t2.micro"
+ }
+ "app1_vm02" = {
+ az = "eu-central-1b"
+ vpc = "app1_vpc"
+ vpc_subnet = "app1_vpc-app1_vm"
+ security_group = "app1_vm"
+ type = "t2.micro"
+ }
+ "app2_vm01" = {
+ az = "eu-central-1a"
+ vpc = "app2_vpc"
+ vpc_subnet = "app2_vpc-app2_vm"
+ security_group = "app2_vm"
+ type = "t2.micro"
+ }
+ "app2_vm02" = {
+ az = "eu-central-1b"
+ vpc = "app2_vpc"
+ vpc_subnet = "app2_vpc-app2_vm"
+ security_group = "app2_vm"
+ type = "t2.micro"
+ }
+}
+
+### SPOKE LOADBALANCERS
+spoke_lbs = {
+ "app1-nlb" = {
+ vpc_subnet = "app1_vpc-app1_lb"
+ vms = ["app1_vm01", "app1_vm02"]
+ }
+ "app2-nlb" = {
+ vpc_subnet = "app2_vpc-app2_lb"
+ vms = ["app2_vm01", "app2_vm02"]
+ }
+}
\ No newline at end of file
diff --git a/examples/combined_design_autoscale/main.tf b/examples/combined_design_autoscale/main.tf
index 2d15e69d..b47547a9 100644
--- a/examples/combined_design_autoscale/main.tf
+++ b/examples/combined_design_autoscale/main.tf
@@ -336,5 +336,5 @@ module "vm_series_asg" {
scaling_target_value = each.value.scaling_plan.target_value
scaling_statistic = each.value.scaling_plan.statistic
scaling_cloudwatch_namespace = each.value.scaling_plan.cloudwatch_namespace
- scaling_tags = each.value.scaling_plan.tags
+ scaling_tags = merge(each.value.scaling_plan.tags, { prefix : var.name_prefix })
}
diff --git a/examples/combined_design_autoscale/main_test.go b/examples/combined_design_autoscale/main_test.go
new file mode 100644
index 00000000..bcea9e06
--- /dev/null
+++ b/examples/combined_design_autoscale/main_test.go
@@ -0,0 +1,47 @@
+package centralized_design
+
+import (
+ "fmt"
+ "math/rand"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
+ "github.com/gruntwork-io/terratest/modules/logger"
+ "github.com/gruntwork-io/terratest/modules/terraform"
+)
+
+func TestExampleCombinedAutoscaleDesign(t *testing.T) {
+ // prepare random prefix
+ source := rand.NewSource(time.Now().UnixNano())
+ random := rand.New(source)
+ number := random.Intn(1000)
+ namePrefix := fmt.Sprintf("terra%d-", number)
+
+ // define options for Terraform
+ terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
+ TerraformDir: ".",
+ VarFiles: []string{"example.tfvars"},
+ Vars: map[string]interface{}{
+ "name_prefix": namePrefix,
+ "ssh_key_name": "test-ssh-key",
+ },
+ Logger: logger.Default,
+ Lock: true,
+ Upgrade: true,
+ SetVarsAfterVarFiles: true,
+ })
+
+ // prepare list of items to check
+ assertList := []testskeleton.AssertExpression{}
+
+ // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan
+ if os.Getenv("DO_APPLY") == "true" {
+ // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment
+ testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList)
+ } else {
+ // plan test infrastructure and verify outputs
+ testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected")
+ }
+}
diff --git a/examples/isolated_design/Makefile b/examples/isolated_design/Makefile
new file mode 100644
index 00000000..7258f45c
--- /dev/null
+++ b/examples/isolated_design/Makefile
@@ -0,0 +1,11 @@
+init:
+ @../../makefile.sh init
+
+validate:
+ @../../makefile.sh validate
+
+test:
+ @../../makefile.sh test
+
+destroy:
+ @../../makefile.sh destroy
diff --git a/examples/isolated_design/example.tfvars b/examples/isolated_design/example.tfvars
index ca8d85e5..7924166b 100644
--- a/examples/isolated_design/example.tfvars
+++ b/examples/isolated_design/example.tfvars
@@ -167,12 +167,12 @@ vpcs = {
next_hop_key = "security_vpc"
next_hop_type = "internet_gateway"
}
- mgmt_panorama = {
- vpc_subnet = "security_vpc-mgmt"
- to_cidr = "10.255.0.0/24"
- next_hop_key = "security_vpc_panorama"
- next_hop_type = "vpc_peer"
- }
+ # mgmt_panorama = {
+ # vpc_subnet = "security_vpc-mgmt"
+ # to_cidr = "10.255.0.0/24"
+ # next_hop_key = "security_vpc_panorama"
+ # next_hop_type = "vpc_peer"
+ # }
public_default = {
vpc_subnet = "security_vpc-public"
to_cidr = "0.0.0.0/0"
@@ -473,7 +473,7 @@ vmseries = {
### PANORAMA
panorama_connection = {
security_vpc = "security_vpc"
- peering_vpc_id = "vpc-123456789" # TODO: update here
+ peering_vpc_id = null # TODO: update here
vpc_cidr = "10.255.0.0/24" # TODO: update here
}
diff --git a/examples/isolated_design/main.tf b/examples/isolated_design/main.tf
index b944445c..9369fde6 100644
--- a/examples/isolated_design/main.tf
+++ b/examples/isolated_design/main.tf
@@ -49,6 +49,7 @@ module "subnet_sets" {
### VPC PEERINGS ###
resource "aws_vpc_peering_connection" "this" {
+ count = var.panorama_connection.peering_vpc_id != null ? 1 : 0
peer_vpc_id = var.panorama_connection.peering_vpc_id
vpc_id = module.vpc[var.panorama_connection.security_vpc].id
auto_accept = true
@@ -116,9 +117,9 @@ locals {
next_hop_set = (
rv.next_hop_type == "internet_gateway" ? module.vpc[rv.next_hop_key].igw_as_next_hop_set : (
rv.next_hop_type == "gwlbe_endpoint" ? module.gwlbe_endpoint[rv.next_hop_key].next_hop_set : (
- rv.next_hop_type == "vpc_peer" ? {
+ rv.next_hop_type == "vpc_peer" && var.panorama_connection.peering_vpc_id != null ? {
type = "vpc_peer"
- id = aws_vpc_peering_connection.this.id
+ id = aws_vpc_peering_connection.this[0].id
ids = {}
} : null
)
diff --git a/examples/isolated_design/main_test.go b/examples/isolated_design/main_test.go
new file mode 100644
index 00000000..234e95cd
--- /dev/null
+++ b/examples/isolated_design/main_test.go
@@ -0,0 +1,47 @@
+package centralized_design
+
+import (
+ "fmt"
+ "math/rand"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
+ "github.com/gruntwork-io/terratest/modules/logger"
+ "github.com/gruntwork-io/terratest/modules/terraform"
+)
+
+func TestExampleIsolatedDesign(t *testing.T) {
+ // prepare random prefix
+ source := rand.NewSource(time.Now().UnixNano())
+ random := rand.New(source)
+ number := random.Intn(1000)
+ namePrefix := fmt.Sprintf("terra%d-", number)
+
+ // define options for Terraform
+ terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
+ TerraformDir: ".",
+ VarFiles: []string{"example.tfvars"},
+ Vars: map[string]interface{}{
+ "name_prefix": namePrefix,
+ "ssh_key_name": "test-ssh-key",
+ },
+ Logger: logger.Default,
+ Lock: true,
+ Upgrade: true,
+ SetVarsAfterVarFiles: true,
+ })
+
+ // prepare list of items to check
+ assertList := []testskeleton.AssertExpression{}
+
+ // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan
+ if os.Getenv("DO_APPLY") == "true" {
+ // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment
+ testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList)
+ } else {
+ // plan test infrastructure and verify outputs
+ testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected")
+ }
+}
diff --git a/examples/panorama_standalone/Makefile b/examples/panorama_standalone/Makefile
new file mode 100644
index 00000000..7258f45c
--- /dev/null
+++ b/examples/panorama_standalone/Makefile
@@ -0,0 +1,11 @@
+init:
+ @../../makefile.sh init
+
+validate:
+ @../../makefile.sh validate
+
+test:
+ @../../makefile.sh test
+
+destroy:
+ @../../makefile.sh destroy
diff --git a/examples/panorama_standalone/main_test.go b/examples/panorama_standalone/main_test.go
new file mode 100644
index 00000000..335355d9
--- /dev/null
+++ b/examples/panorama_standalone/main_test.go
@@ -0,0 +1,47 @@
+package centralized_design
+
+import (
+ "fmt"
+ "math/rand"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
+ "github.com/gruntwork-io/terratest/modules/logger"
+ "github.com/gruntwork-io/terratest/modules/terraform"
+)
+
+func TestExampleStandalonePanorama(t *testing.T) {
+ // prepare random prefix
+ source := rand.NewSource(time.Now().UnixNano())
+ random := rand.New(source)
+ number := random.Intn(1000)
+ namePrefix := fmt.Sprintf("terra%d-", number)
+
+ // define options for Terraform
+ terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
+ TerraformDir: ".",
+ VarFiles: []string{"example.tfvars"},
+ Vars: map[string]interface{}{
+ "name_prefix": namePrefix,
+ "ssh_key_name": "test-ssh-key",
+ },
+ Logger: logger.Default,
+ Lock: true,
+ Upgrade: true,
+ SetVarsAfterVarFiles: true,
+ })
+
+ // prepare list of items to check
+ assertList := []testskeleton.AssertExpression{}
+
+ // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan
+ if os.Getenv("DO_APPLY") == "true" {
+ // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment
+ testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList)
+ } else {
+ // plan test infrastructure and verify outputs
+ testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected")
+ }
+}
diff --git a/examples/standalone_vmseries_with_userdata_bootstrap/Makefile b/examples/standalone_vmseries_with_userdata_bootstrap/Makefile
new file mode 100644
index 00000000..7258f45c
--- /dev/null
+++ b/examples/standalone_vmseries_with_userdata_bootstrap/Makefile
@@ -0,0 +1,11 @@
+init:
+ @../../makefile.sh init
+
+validate:
+ @../../makefile.sh validate
+
+test:
+ @../../makefile.sh test
+
+destroy:
+ @../../makefile.sh destroy
diff --git a/examples/standalone_vmseries_with_userdata_bootstrap/README.md b/examples/standalone_vmseries_with_userdata_bootstrap/README.md
index f7397a1a..6b288e5f 100644
--- a/examples/standalone_vmseries_with_userdata_bootstrap/README.md
+++ b/examples/standalone_vmseries_with_userdata_bootstrap/README.md
@@ -71,7 +71,7 @@ No resources.
| [bootstrap\_options](#input\_bootstrap\_options) | n/a | `any` | n/a | yes |
| [ebs\_kms\_key\_alias](#input\_ebs\_kms\_key\_alias) | n/a | `any` | n/a | yes |
| [global\_tags](#input\_global\_tags) | n/a | `any` | n/a | yes |
-| [name](#input\_name) | n/a | `any` | n/a | yes |
+| [name\_prefix](#input\_name\_prefix) | n/a | `any` | n/a | yes |
| [region](#input\_region) | n/a | `any` | n/a | yes |
| [security\_vpc\_cidr](#input\_security\_vpc\_cidr) | n/a | `any` | n/a | yes |
| [security\_vpc\_name](#input\_security\_vpc\_name) | n/a | `any` | n/a | yes |
diff --git a/examples/standalone_vmseries_with_userdata_bootstrap/example.tfvars b/examples/standalone_vmseries_with_userdata_bootstrap/example.tfvars
index 576930cb..9022f494 100644
--- a/examples/standalone_vmseries_with_userdata_bootstrap/example.tfvars
+++ b/examples/standalone_vmseries_with_userdata_bootstrap/example.tfvars
@@ -1,6 +1,6 @@
# General
-region = "us-east-1"
-name = "vmseries-example"
+region = "eu-central-1"
+name_prefix = "vmseries-example"
global_tags = {
ManagedBy = "Terraform"
Application = "Palo Alto Networks VM-Series NGFW"
@@ -13,7 +13,7 @@ security_vpc_cidr = "10.100.0.0/16"
# Subnets
security_vpc_subnets = {
# Do not modify value of `set=`, it is an internal identifier referenced by main.tf.
- "10.100.0.0/24" = { az = "us-east-1a", set = "mgmt" }
+ "10.100.0.0/24" = { az = "eu-central-1a", set = "mgmt", nacl = null }
}
# Security Groups
@@ -45,7 +45,7 @@ ssh_key_name = "example-ssh-key"
vmseries_version = "10.2.2"
vmseries = {
vmseries01 = {
- az = "us-east-1a"
+ az = "eu-central-1a"
interfaces = {
mgmt = {
device_index = 0
@@ -60,7 +60,7 @@ vmseries = {
bootstrap_options = "plugin-op-commands=aws-gwlb-inspect:enable,aws-gwlb-overlay-routing:enable;type=dhcp-client;hostname=vms01"
-ebs_kms_key_alias = "alias/example-key-alias"
+ebs_kms_key_alias = "alias/aws/ebs"
# Routes
security_vpc_routes_outbound_destin_cidrs = ["0.0.0.0/0"]
diff --git a/examples/standalone_vmseries_with_userdata_bootstrap/main.tf b/examples/standalone_vmseries_with_userdata_bootstrap/main.tf
index 1335c89b..af185ddf 100644
--- a/examples/standalone_vmseries_with_userdata_bootstrap/main.tf
+++ b/examples/standalone_vmseries_with_userdata_bootstrap/main.tf
@@ -1,7 +1,7 @@
module "security_vpc" {
source = "../../modules/vpc"
- name = var.security_vpc_name
+ name = "${var.name_prefix}${var.security_vpc_name}"
cidr_block = var.security_vpc_cidr
security_groups = var.security_vpc_security_groups
create_internet_gateway = true
@@ -18,14 +18,25 @@ module "security_subnet_sets" {
name = each.key
vpc_id = module.security_vpc.id
has_secondary_cidrs = module.security_vpc.has_secondary_cidrs
- cidrs = { for k, v in var.security_vpc_subnets : k => v if v.set == each.key }
+ nacl_associations = {
+ for i in flatten([
+ for k, v in var.security_vpc_subnets :
+ {
+ az : v.az,
+ nacl_id : lookup(module.security_vpc.nacl_ids, v.nacl, null)
+ } if v.nacl != null && v.set == each.key
+ ]) : i.az => i.nacl_id
+ }
+ cidrs = {
+ for k, v in var.security_vpc_subnets : k => v if v.set == each.key
+ }
}
module "vmseries" {
for_each = var.vmseries
source = "../../modules/vmseries"
- name = var.name
+ name = "${var.name_prefix}vmseries"
ssh_key_name = var.ssh_key_name
bootstrap_options = var.bootstrap_options
ebs_kms_key_alias = var.ebs_kms_key_alias
diff --git a/examples/standalone_vmseries_with_userdata_bootstrap/main_test.go b/examples/standalone_vmseries_with_userdata_bootstrap/main_test.go
new file mode 100644
index 00000000..321b2656
--- /dev/null
+++ b/examples/standalone_vmseries_with_userdata_bootstrap/main_test.go
@@ -0,0 +1,47 @@
+package centralized_design
+
+import (
+ "fmt"
+ "math/rand"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
+ "github.com/gruntwork-io/terratest/modules/logger"
+ "github.com/gruntwork-io/terratest/modules/terraform"
+)
+
+func TestExampleStandaloneVmseries(t *testing.T) {
+ // prepare random prefix
+ source := rand.NewSource(time.Now().UnixNano())
+ random := rand.New(source)
+ number := random.Intn(1000)
+ namePrefix := fmt.Sprintf("terra%d-", number)
+
+ // define options for Terraform
+ terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
+ TerraformDir: ".",
+ VarFiles: []string{"example.tfvars"},
+ Vars: map[string]interface{}{
+ "name_prefix": namePrefix,
+ "ssh_key_name": "test-ssh-key",
+ },
+ Logger: logger.Default,
+ Lock: true,
+ Upgrade: true,
+ SetVarsAfterVarFiles: true,
+ })
+
+ // prepare list of items to check
+ assertList := []testskeleton.AssertExpression{}
+
+ // if DO_APPLY is not empty and equal true, then Terraform apply is used, in other case only Terraform plan
+ if os.Getenv("DO_APPLY") == "true" {
+ // deploy test infrastructure and verify outputs and check if there are no planned changes after deployment
+ testskeleton.DeployInfraCheckOutputsVerifyChanges(t, terraformOptions, assertList)
+ } else {
+ // plan test infrastructure and verify outputs
+ testskeleton.PlanInfraCheckErrors(t, terraformOptions, assertList, "No errors are expected")
+ }
+}
diff --git a/examples/standalone_vmseries_with_userdata_bootstrap/variables.tf b/examples/standalone_vmseries_with_userdata_bootstrap/variables.tf
index 8e5b5479..f05af290 100644
--- a/examples/standalone_vmseries_with_userdata_bootstrap/variables.tf
+++ b/examples/standalone_vmseries_with_userdata_bootstrap/variables.tf
@@ -1,5 +1,5 @@
variable "region" {}
-variable "name" {}
+variable "name_prefix" {}
variable "global_tags" {}
variable "security_vpc_name" {}
variable "security_vpc_cidr" {}
diff --git a/tests/internal/helpers/helpers.go b/go/helpers/helpers.go
similarity index 100%
rename from tests/internal/helpers/helpers.go
rename to go/helpers/helpers.go
diff --git a/tests/internal/testskeleton/testskeleton.go b/go/testskeleton/testskeleton.go
similarity index 98%
rename from tests/internal/testskeleton/testskeleton.go
rename to go/testskeleton/testskeleton.go
index ffe90ec7..05f5b625 100644
--- a/tests/internal/testskeleton/testskeleton.go
+++ b/go/testskeleton/testskeleton.go
@@ -275,9 +275,13 @@ func PlanInfraCheckErrors(t *testing.T, terraformOptions *terraform.Options,
// Terraform initalization and plan
if _, err := terraform.InitAndPlanE(t, terraformOptions); err != nil {
- // Verify errors and compare to expected results
- assert.Error(t, err)
- AssertErrors(t, err, assertList)
+ if len(assertList) > 0 {
+ // Verify errors and compare to expected results
+ assert.Error(t, err)
+ AssertErrors(t, err, assertList)
+ } else {
+ t.Error(noErrorsMessage)
+ }
} else {
// Fail test, if errors were expected
if len(assertList) > 0 {
diff --git a/makefile.sh b/makefile.sh
new file mode 100755
index 00000000..a1cff972
--- /dev/null
+++ b/makefile.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+set -o pipefail
+set -e
+
+COMMAND=$1
+
+case $1 in
+ init)
+ echo ":: INITIALIZING TERRAFORM ::"
+ terraform init
+ echo
+ ;;
+
+ validate)
+ echo ":: INITIALIZING TERRAFORM ::"
+ terraform init -backend=false
+ echo
+ echo ":: VALIDATING CODE ::"
+ terraform validate
+ echo
+ ;;
+
+ test)
+ echo ":: DOWNLOADING GO DEPENDENCIES ::"
+ go get -v -t -d && go mod tidy
+ echo
+ echo ":: EXECUTING TERRATEST ::"
+ go test -v -timeout 120m -count=1
+ echo
+ ;;
+
+ destroy)
+ echo ":: DESTROYING INFRASTRUCTURE ::"
+ for i in {1..3}; do terraform destroy -auto-approve -var-file=example.tfvars && break || sleep 3; done
+ ;;
+
+ *)
+ echo "ERROR: wrong param passed:: [$1]"
+ exit 1
+
+esac
diff --git a/modules/alb/Makefile b/modules/alb/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/alb/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/asg/Makefile b/modules/asg/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/asg/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/bootstrap/Makefile b/modules/bootstrap/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/bootstrap/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/crosszone_failover/Makefile b/modules/crosszone_failover/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/crosszone_failover/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/gwlb/Makefile b/modules/gwlb/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/gwlb/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/gwlb_endpoint_set/Makefile b/modules/gwlb_endpoint_set/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/gwlb_endpoint_set/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/nat_gateway_set/Makefile b/modules/nat_gateway_set/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/nat_gateway_set/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/nlb/Makefile b/modules/nlb/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/nlb/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/panorama/Makefile b/modules/panorama/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/panorama/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/subnet_set/Makefile b/modules/subnet_set/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/subnet_set/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/transit_gateway/Makefile b/modules/transit_gateway/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/transit_gateway/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/transit_gateway_attachment/Makefile b/modules/transit_gateway_attachment/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/transit_gateway_attachment/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/transit_gateway_peering/Makefile b/modules/transit_gateway_peering/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/transit_gateway_peering/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/transit_gateway_peering/versions.tf b/modules/transit_gateway_peering/versions.tf
index 238718cf..9ff8478e 100644
--- a/modules/transit_gateway_peering/versions.tf
+++ b/modules/transit_gateway_peering/versions.tf
@@ -8,3 +8,7 @@ terraform {
}
}
}
+
+provider "aws" {
+ alias = "remote"
+}
diff --git a/modules/vmseries/Makefile b/modules/vmseries/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/vmseries/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/vpc/Makefile b/modules/vpc/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/vpc/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/vpc_endpoint/Makefile b/modules/vpc_endpoint/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/vpc_endpoint/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/modules/vpc_route/Makefile b/modules/vpc_route/Makefile
new file mode 100644
index 00000000..f9cee6eb
--- /dev/null
+++ b/modules/vpc_route/Makefile
@@ -0,0 +1,2 @@
+validate:
+ @../../makefile.sh validate
\ No newline at end of file
diff --git a/tests/alb/main_test.go b/tests/alb/main_test.go
index b457f583..1a12bb86 100644
--- a/tests/alb/main_test.go
+++ b/tests/alb/main_test.go
@@ -4,8 +4,8 @@ import (
"log"
"testing"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/helpers"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/helpers"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
)
diff --git a/tests/bootstrap/main_test.go b/tests/bootstrap/main_test.go
index 93338a59..87ae09eb 100644
--- a/tests/bootstrap/main_test.go
+++ b/tests/bootstrap/main_test.go
@@ -7,7 +7,7 @@ import (
"testing"
"time"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
)
diff --git a/tests/panorama/main_test.go b/tests/panorama/main_test.go
index 211ed453..9db64d85 100644
--- a/tests/panorama/main_test.go
+++ b/tests/panorama/main_test.go
@@ -3,8 +3,8 @@ package panorama
import (
"testing"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/helpers"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/helpers"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
)
diff --git a/tests/subnet_set/main_test.go b/tests/subnet_set/main_test.go
index 7c8e6fb4..48e8573f 100644
--- a/tests/subnet_set/main_test.go
+++ b/tests/subnet_set/main_test.go
@@ -3,7 +3,7 @@ package subnet_set
import (
"testing"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
"github.com/gruntwork-io/terratest/modules/terraform"
)
diff --git a/tests/transit_gateway/main_test.go b/tests/transit_gateway/main_test.go
index a7e60cad..ffc7ec81 100644
--- a/tests/transit_gateway/main_test.go
+++ b/tests/transit_gateway/main_test.go
@@ -3,7 +3,7 @@ package transit_gateway
import (
"testing"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
)
diff --git a/tests/transit_gateway_attachment/main_test.go b/tests/transit_gateway_attachment/main_test.go
index c0c21aac..0b320c64 100644
--- a/tests/transit_gateway_attachment/main_test.go
+++ b/tests/transit_gateway_attachment/main_test.go
@@ -3,7 +3,7 @@ package transit_gateway_attachment
import (
"testing"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
)
diff --git a/tests/transit_gateway_peering/main_test.go b/tests/transit_gateway_peering/main_test.go
index 3b25ce00..82e6b646 100644
--- a/tests/transit_gateway_peering/main_test.go
+++ b/tests/transit_gateway_peering/main_test.go
@@ -3,7 +3,7 @@ package transit_gateway_peering
import (
"testing"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
)
diff --git a/tests/vmseries/main_test.go b/tests/vmseries/main_test.go
index aa7943dd..b4e227c1 100644
--- a/tests/vmseries/main_test.go
+++ b/tests/vmseries/main_test.go
@@ -3,8 +3,8 @@ package vmseries
import (
"testing"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/helpers"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/helpers"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
tfjson "github.com/hashicorp/terraform-json"
diff --git a/tests/vpc/deployment/main_test.go b/tests/vpc/deployment/main_test.go
index 9794dc70..02d5d736 100644
--- a/tests/vpc/deployment/main_test.go
+++ b/tests/vpc/deployment/main_test.go
@@ -3,7 +3,7 @@ package vpc_deployment
import (
"testing"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
)
diff --git a/tests/vpc/plan/main_test.go b/tests/vpc/plan/main_test.go
index b806c279..10d36343 100644
--- a/tests/vpc/plan/main_test.go
+++ b/tests/vpc/plan/main_test.go
@@ -3,7 +3,7 @@ package vpc_plan
import (
"testing"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
)
diff --git a/tests/vpc_route/main_test.go b/tests/vpc_route/main_test.go
index a1ea812d..19c89365 100644
--- a/tests/vpc_route/main_test.go
+++ b/tests/vpc_route/main_test.go
@@ -3,7 +3,7 @@ package vpc_route
import (
"testing"
- "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
+ "github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/go/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
)