├── .gitattributes ├── .gitignore ├── .gitlab-ci.yml ├── .pre-commit-config.yaml ├── .talismanrc ├── .terraform.lock.hcl ├── .tflint.hcl ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── TERMS_OF_USE.txt ├── TROUBLE.md ├── analytics ├── analytics.tf └── variables.tf ├── azure.tf ├── cleanup.sh ├── cloud-libs-notes.sh ├── demo.sh ├── demo_app ├── app.tf └── variables.tf ├── dockerfile ├── firewall.tf ├── gitleaks.sh ├── hashicorp.asc ├── jumpboxes ├── DisableInternetExplorer-ESC.ps1 ├── linux.tf ├── variables.tf └── windows.tf ├── main.tf ├── makefile ├── network.tf ├── one_tier └── firewall │ ├── bigip.tf │ ├── ilb.tf │ ├── outputs.tf │ └── variables.tf ├── outputs.tf ├── prepare ├── setupAzureGovVars_local.sh ├── setupAzureGovVars_vault.sh └── setupAzureVars.sh ├── providers.tf ├── requirements.txt ├── templates ├── ips-cloud-init.yaml ├── onboard.tpl ├── telemetry_dashboard.omsview └── ts.json ├── three_tier ├── firewall │ ├── bigip.tf │ ├── outputs.tf │ └── variables.tf ├── ips │ ├── ips.tf │ └── variables.tf └── waf │ ├── bigip.tf │ ├── outputs.tf │ └── variables.tf └── variables.tf /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # custom 2 | admin.auto.tfvars 3 | .envVarsHelper.sh 4 | vm_as3_data.json 5 | vm01_do_data.json 6 | vm02_do_data.json 7 | onboard.sh 8 | # Local .terraform directories 9 | **/.terraform/* 10 | 11 | # .tfstate files 12 | *.tfstate 13 | *.tfstate.* 14 | .terraform.lock.hcl 15 | 16 | # Crash log files 17 | crash.log 18 | 19 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 20 | # .tfvars files are managed as part of configuration and so should be included in 21 | # version control. 22 | # 23 | # example.tfvars 24 | 25 | # Ignore override files as they are usually used to override resources locally and so 26 | # are not checked in 27 | override.tf 28 | override.tf.json 29 | *_override.tf 30 | *_override.tf.json 31 | 32 | # Include override files you do wish to add to version control using negated pattern 33 | # 34 | # !example_override.tf 35 | 36 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 37 | # example: *tfplan* 38 | 39 | *_data.json 40 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | default: 2 | image: 3 | name: hashicorp/terraform 4 | entrypoint: [""] 5 | 6 | before_script: 7 | - rm -rf .terraform 8 | - terraform --version 9 | - terraform init 10 | 11 | stages: 12 | - validate 13 | - plan 14 | - apply 15 | - destroy 16 | 17 | validate: 18 | stage: validate 19 | script: 20 | - terraform validate 21 | 22 | plan: 23 | stage: plan 24 | script: 25 | - terraform plan --out plan 26 | artifacts: 27 | paths: 28 | - plan 29 | 30 | apply: 31 | stage: apply 32 | environment: 33 | name: production 34 | script: 35 | - terraform apply --auto-approve plan 36 | - terraform state list 37 | when: manual 38 | allow_failure: false 39 | artifacts: 40 | paths: 41 | - terraform.tfstate 42 | 43 | destroy: 44 | stage: destroy 45 | environment: 46 | name: production 47 | script: 48 | - terraform destroy --auto-approve 49 | when: manual 50 | only: 51 | - main 52 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | default_language_version: 3 | python: python3.8 4 | repos: 5 | - repo: https://github.com/antonbabenko/pre-commit-terraform 6 | rev: v1.48.0 7 | hooks: 8 | - id: terraform_fmt 9 | #- id: terraform_validate 10 | - id: terraform_tflint 11 | - id: terraform_docs 12 | args: ['--args=--required=false', '--args=--sort=false'] 13 | #- id: terraform_tfsec 14 | - repo: https://github.com/pre-commit/pre-commit-hooks 15 | rev: v3.4.0 16 | hooks: 17 | - id: check-executables-have-shebangs 18 | - id: check-case-conflict 19 | - id: check-merge-conflict 20 | - id: detect-private-key 21 | - id: detect-aws-credentials 22 | - id: end-of-file-fixer 23 | #- id: sort-simple-yaml 24 | - id: check-yaml 25 | args: ['./templates/ips-cloud-init.yaml'] 26 | #- id: check-json 27 | - id: trailing-whitespace 28 | - repo: https://github.com/frnmst/md-toc 29 | rev: 7.1.0 30 | hooks: 31 | - id: md-toc 32 | - repo: https://github.com/thoughtworks/talisman 33 | rev: v1.11.0 34 | hooks: 35 | - id: talisman-commit 36 | -------------------------------------------------------------------------------- /.talismanrc: -------------------------------------------------------------------------------- 1 | fileignoreconfig: 2 | - filename: releases/v1.0.0/gen_env.py 3 | checksum: bb4864de7bde210cfc0c8f878d955f15f60954f48aa04cc40a2221432d0249c8 4 | - filename: terraform.tfstate.backup 5 | checksum: ea58aa4892e5b512a283694edbb63576f903239db49db93a43381b607e1371ae 6 | - filename: releases/v2.6.1/scripts/verifyHash 7 | checksum: 0e0ae811decd15b4c5449e7b953d178fb1893b768bad740b5c30891623fab9f9 8 | - filename: releases/v1.0.0/roles/f5-azure-scca/files/azuredeploy.json 9 | checksum: 72fdbe241c91b57ef9603ed356a6378b2acc8e9a1f9e9e1094d61766057997d0 10 | - filename: releases/v1.0.0/roles/f5-azure-scca-internal-setup/files/basic-asm-apache.xml 11 | checksum: 2efc1f44d9f95df614842982407362b1f5c35060e2108026275ca1d167641218 12 | - filename: releases/v1.0.0/roles/f5-azure-scca-internal/files/azuredeploy.json 13 | checksum: 429c57d621e3d9bae9101a820921c62ecbe484aca7e655b8422f6e366f1aeb8e 14 | - filename: releases/v1.0.0/roles/f5-azure-scca-external/files/azuredeploy.json 15 | checksum: 1da439240cad8af2ad7935ddcd11b511a0abbd5303e9c96a3737227d68f912d6 16 | - filename: releases/v2.6.1/scripts/mcinstallCloudLibs.b64 17 | checksum: 8eb83bfea54ec39959060b2fe91aae5ef3db52ff3d893cc0e4e574a90fcaa0a0 18 | - filename: releases/v2.6.1/3NIC_3Tier_HA/bigiq/azureDeploy.json 19 | checksum: f96b4e7c9ad049a5a923476eb02e9e765c2f8d73f27ca8558462720dd227035c 20 | - filename: releases/v2.6.1/3NIC_1Tier_HA/payg/azureDeploy.json 21 | checksum: 7849ca1630ca9e2a375c9a01cf7385d830f3f0449fe14921038b7306392030a4 22 | - filename: releases/v2.6.1/3NIC_1Tier_HA/bigiq/azureDeploy.json 23 | checksum: a87686116cf62d2c55bcdbec5239689977783605a249672a0a940a70e2c2fb1e 24 | - filename: releases/v2.6.1/3NIC_3Tier_HA/byol/azureDeploy.json 25 | checksum: 493412d7d13713beedf81493d70c2387e49caeea6887cd11b6d8bbfcd8177d94 26 | - filename: releases/v2.6.1/3NIC_1Tier_HA/byol/azureDeploy.json 27 | checksum: bacc9e0c8b843199838328d6020abd5a8cdbcadddea433598ede8bd581888a65 28 | - filename: releases/v2.6.1/3NIC_3Tier_HA/payg/azureDeploy.json 29 | checksum: 17746802719e00c792c2812330ffd8fd4ce21e9f3bcd5a642fdb1857bcdf22f4 30 | - filename: releases/v1.0.0/roles/f5-azure-scca-internal-setup/vars/main.yml 31 | checksum: 2738b86693fe4e631c2db2257337655fbb88180be6b329c8de4f469f7b3b23ab 32 | - filename: releases/v2.6.1/scripts/Disable-ieESC.ps1 33 | checksum: 5720913d54c69ce773fefdfaef62392b8b2419c4a29a4ba0d7b28ec9b9673ad0 34 | - filename: releases/v1.0.0/roles/f5-azure-scca/vars/main.yml 35 | checksum: 49418879206e6dc724f4555a53e5458f349dc45f72da70935d7c19fa49697569 36 | - filename: releases/v1.0.0/roles/f5-azure-scca-internal-setup/tasks/main.yml 37 | checksum: babe890bc3bf90ea733fb3f5f14e8ab52056a2f9722a0c8213e0c536197717f7 38 | - filename: releases/v2.6.1/scripts/atc_install.sh 39 | checksum: 9917a97b7cac13276756f2680e5c5d3315cd3ccf5d5fe2ff0c51f9d648afb0a1 40 | - filename: releases/v2.6.1/scripts/deploy_app.sh 41 | checksum: 1412c87a6310d5f7a82bf50c6eaa23543410c3d6b5d4c7b39a875cd7ae576498 42 | - filename: releases/v1.0.0/roles/f5-azure-scca-internal-setup/files/f5.policy_creator.tmpl 43 | checksum: bca3d52bc89a82a29002cfd73701e9666676ee00ec8d3bc81d412a82e044c6bf 44 | - filename: releases/v1.0.0/doall.sh 45 | checksum: a110ddd9051d5a0e7817f77a87b97f2d3b4a77034b7373d5913c374d0fd86e7f 46 | - filename: releases/v1.0.0/run.sh 47 | checksum: 3c01c2703678ed97abe45b61ccbfca7828e3a689fd51086106e1bf636b52ad6f 48 | - filename: releases/v1.0.0/savevars.sh 49 | checksum: b1f33b1bee1b59f5595621020b5ecdecd4f91d36deaac0e113d5e568da87cc32 50 | - filename: releases/v1.0.0/roles/f5-azure-scca-external-setup/files/f5.cloud_logger.v1.0.0.tmpl 51 | checksum: 8155890106dcff99874b1e9865e5b935678c5770740cf7d03e2779d0526a48f4 52 | - filename: releases/v1.0.0/roles/f5-azure-scca-internal/vars/main.yml 53 | checksum: 279c2689e717279d2df90cdcc93faa3150804866e255d5fb14ab533fd942a6c2 54 | - filename: releases/v1.0.0/roles/f5-azure-scca-external/vars/main.yml 55 | checksum: 47cb4a6ec594ec42c3135d248a216bbd4bd4e2b59f1f990f7d804a3f1939cfb2 56 | - filename: releases/v1.0.0/roles/f5-azure-scca-internal-setup/files/f5.cloud_logger.v1.0.0.tmpl 57 | checksum: 660bd1a6dea6a421cacbdd3f0bd6169dc2be079a8c886ac2f1ba6216895b3da3 58 | - filename: releases/v1.0.0/library/bigip_static_route.py 59 | checksum: 1eb0b75837856b529dc296ae56507abf28a17dc04837ca2ddd05409ddc3cbf4e 60 | - filename: releases/v1.0.0/roles/f5-azure-scca-external-setup/tasks/main.yml 61 | checksum: 5d5c60b42694e2dddcf80d72539fbd2f4769b893fa7cd8365d8a6de5df2ac0be 62 | - filename: releases/v1.0.0/update-vip-udr.yaml 63 | checksum: 58870a90727e5a4bf251b94f6cb419de7a964d2fe3707652a724eccbd7be836e 64 | - filename: releases/v1.0.0/azure_rm.py 65 | checksum: d6a8344eaf8e17ddc9401301c10108e63a71fb90149f58e4aa74a02ac0bf972c 66 | - filename: releases/v1.0.0/roles/f5-azure-scca-external-setup/vars/main.yml 67 | checksum: f837aa0b170948147dfe03a21133677019943807b418fbac51cbf5898897a531 68 | - filename: releases/v1.0.0/revoke-license.yaml 69 | checksum: dc51a97be04532fde8a22a0b87f8ee62a324560b31247ffc2e21b2ca1b1f8396 70 | - filename: releases/v1.0.0/grab_vars.py 71 | checksum: ea9da279f79b6082f77c00819a8781233cc91d450a440f44a5c00fad48c78fa3 72 | - filename: releases/v1.0.0/roles/f5-azure-scca-internal-setup/files/f5.http.v1.2.0rc7.tmpl 73 | checksum: f7a9b764605c4280db5fa1daa4271ec4c64a9d250a61fe866aeacc8349deac2b 74 | -------------------------------------------------------------------------------- /.terraform.lock.hcl: -------------------------------------------------------------------------------- 1 | # This file is maintained automatically by "terraform init". 2 | # Manual edits may be lost in future updates. 3 | 4 | provider "registry.terraform.io/hashicorp/azurerm" { 5 | version = "3.46.0" 6 | constraints = "3.46.0" 7 | hashes = [ 8 | "h1:hCCSjeSMrt6/hS6byqecfDVHBgiwD3BCUy1YtJJl4So=", 9 | "zh:02327ad31c998d9d55bafd280a4b1bd3702b496e49f53fad30823712cc85368a", 10 | "zh:05882df6b5b59d23e2aa0c454caea84fcc35e435eb925e18293415260b4850c8", 11 | "zh:0c0d6309abcfa24f0775df9bff81cb8f63029fead66956316d7cfa837c231873", 12 | "zh:3607e8f5da720e053f7bada6b7c21b018ba25ccff8dade66bb64c2544214b400", 13 | "zh:5662a2910bda19242b7be6bd7582a514082309691c97ee97aa9cf45bbbf45af4", 14 | "zh:58d6de82cf26e2764f3d57d0e032b06cc97c90756044486b206d83cea53d3f7a", 15 | "zh:5ee2f224ac1185e44fc4a2d60deb5c4a162d0fda07516e0939520cb8dcbedaca", 16 | "zh:bbb6f9fd9cb6e8a79c9e1e3ce74647f743f60f3ea2c325b9aececf4a55ec0343", 17 | "zh:c9d923b415f411eb68dfd43fab1753087b4701caeceb94550df562ca417c6007", 18 | "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", 19 | "zh:f6157b462ed33c27f101113b46463130d00de7f2731e05a371c922e5730a4b5e", 20 | "zh:f96be10c899c0e30870056ec9c2c5002ec2e4f07fe2a64e1b3135ec232ef6f1e", 21 | ] 22 | } 23 | 24 | provider "registry.terraform.io/hashicorp/http" { 25 | version = "2.1.0" 26 | constraints = "2.1.0" 27 | hashes = [ 28 | "h1:HmUcHqc59VeHReHD2SEhnLVQPUKHKTipJ8Jxq67GiDU=", 29 | "zh:03d82dc0887d755b8406697b1d27506bc9f86f93b3e9b4d26e0679d96b802826", 30 | "zh:0704d02926393ddc0cfad0b87c3d51eafeeae5f9e27cc71e193c141079244a22", 31 | "zh:095ea350ea94973e043dad2394f10bca4a4bf41be775ba59d19961d39141d150", 32 | "zh:0b71ac44e87d6964ace82979fc3cbb09eb876ed8f954449481bcaa969ba29cb7", 33 | "zh:0e255a170db598bd1142c396cefc59712ad6d4e1b0e08a840356a371e7b73bc4", 34 | "zh:67c8091cfad226218c472c04881edf236db8f2dc149dc5ada878a1cd3c1de171", 35 | "zh:75df05e25d14b5101d4bc6624ac4a01bb17af0263c9e8a740e739f8938b86ee3", 36 | "zh:b4e36b2c4f33fdc44bf55fa1c9bb6864b5b77822f444bd56f0be7e9476674d0e", 37 | "zh:b9b36b01d2ec4771838743517bc5f24ea27976634987c6d5529ac4223e44365d", 38 | "zh:ca264a916e42e221fddb98d640148b12e42116046454b39ede99a77fc52f59f4", 39 | "zh:fe373b2fb2cc94777a91ecd7ac5372e699748c455f44f6ea27e494de9e5e6f92", 40 | ] 41 | } 42 | 43 | provider "registry.terraform.io/hashicorp/local" { 44 | version = "2.3.0" 45 | hashes = [ 46 | "h1:+l9ZTDGmGdwnuYI5ftUjwP8UgoLw4f4V9xoCzal4LW0=", 47 | "zh:1f1920b3f78c31c6b69cdfe1e016a959667c0e2d01934e1a084b94d5a02cd9d2", 48 | "zh:550a3cdae0ddb350942624e7b2e8b31d28bc15c20511553432413b1f38f4b214", 49 | "zh:68d1d9ccbfce2ce56b28a23b22833a5369d4c719d6d75d50e101a8a8dbe33b9b", 50 | "zh:6ae3ad6d865a906920c313ec2f413d080efe32c230aca711fd106b4cb9022ced", 51 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", 52 | "zh:a0f413d50f54124057ae3dcd9353a797b84e91dc34bcf85c34a06f8aef1f9b12", 53 | "zh:a2ac6d4088ceddcd73d88505e18b8226a6e008bff967b9e2d04254ef71b4ac6b", 54 | "zh:a851010672e5218bdd4c4ea1822706c9025ef813a03da716d647dd6f8e2cffb0", 55 | "zh:aa797561755041ef2fad99ee9ffc12b5e724e246bb019b21d7409afc2ece3232", 56 | "zh:c6afa960a20d776f54bb1fc260cd13ead17280ebd87f05b9abcaa841ed29d289", 57 | "zh:df0975e86b30bb89717b8c8d6d4690b21db66de06e79e6d6cfda769f3304afe6", 58 | "zh:f0d3cc3da72135efdbe8f4cfbfb0f2f7174827887990a5545e6db1981f0d3a7c", 59 | ] 60 | } 61 | 62 | provider "registry.terraform.io/hashicorp/random" { 63 | version = "3.4.3" 64 | hashes = [ 65 | "h1:xZGZf18JjMS06pFa4NErzANI98qi59SEcBsOcS2P2yQ=", 66 | "zh:41c53ba47085d8261590990f8633c8906696fa0a3c4b384ff6a7ecbf84339752", 67 | "zh:59d98081c4475f2ad77d881c4412c5129c56214892f490adf11c7e7a5a47de9b", 68 | "zh:686ad1ee40b812b9e016317e7f34c0d63ef837e084dea4a1f578f64a6314ad53", 69 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", 70 | "zh:84103eae7251384c0d995f5a257c72b0096605048f757b749b7b62107a5dccb3", 71 | "zh:8ee974b110adb78c7cd18aae82b2729e5124d8f115d484215fd5199451053de5", 72 | "zh:9dd4561e3c847e45de603f17fa0c01ae14cae8c4b7b4e6423c9ef3904b308dda", 73 | "zh:bb07bb3c2c0296beba0beec629ebc6474c70732387477a65966483b5efabdbc6", 74 | "zh:e891339e96c9e5a888727b45b2e1bb3fcbdfe0fd7c5b4396e4695459b38c8cb1", 75 | "zh:ea4739860c24dfeaac6c100b2a2e357106a89d18751f7693f3c31ecf6a996f8d", 76 | "zh:f0c76ac303fd0ab59146c39bc121c5d7d86f878e9a69294e29444d4c653786f8", 77 | "zh:f143a9a5af42b38fed328a161279906759ff39ac428ebcfe55606e05e1518b93", 78 | ] 79 | } 80 | 81 | provider "registry.terraform.io/hashicorp/template" { 82 | version = "2.2.0" 83 | hashes = [ 84 | "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=", 85 | "zh:01702196f0a0492ec07917db7aaa595843d8f171dc195f4c988d2ffca2a06386", 86 | "zh:09aae3da826ba3d7df69efeb25d146a1de0d03e951d35019a0f80e4f58c89b53", 87 | "zh:09ba83c0625b6fe0a954da6fbd0c355ac0b7f07f86c91a2a97849140fea49603", 88 | "zh:0e3a6c8e16f17f19010accd0844187d524580d9fdb0731f675ffcf4afba03d16", 89 | "zh:45f2c594b6f2f34ea663704cc72048b212fe7d16fb4cfd959365fa997228a776", 90 | "zh:77ea3e5a0446784d77114b5e851c970a3dde1e08fa6de38210b8385d7605d451", 91 | "zh:8a154388f3708e3df5a69122a23bdfaf760a523788a5081976b3d5616f7d30ae", 92 | "zh:992843002f2db5a11e626b3fc23dc0c87ad3729b3b3cff08e32ffb3df97edbde", 93 | "zh:ad906f4cebd3ec5e43d5cd6dc8f4c5c9cc3b33d2243c89c5fc18f97f7277b51d", 94 | "zh:c979425ddb256511137ecd093e23283234da0154b7fa8b21c2687182d9aea8b2", 95 | ] 96 | } 97 | -------------------------------------------------------------------------------- /.tflint.hcl: -------------------------------------------------------------------------------- 1 | plugin "azurerm" { 2 | enabled = true 3 | } 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ## 3.0.0 6 | 7 | - converted everything to terraform, added all outstanding features. 8 | 9 | ## [2.6.1] - 2020-03-10 10 | 11 | ### Changed 12 | 13 | - 3 Tier: Changed DeclarationURL to Tier 1 and Tier 3 Declaration URLs to allow seperate AS3 declarations for each tier. 14 | - Adjusted outputs to proper PIP FQDN output 15 | - Extensive Changes to Microsoft.Compute/virtualMachines/extensions commandToExecute to help optimize time and clean up order of operations. 16 | - Updated BYOL template AS3 release, and moved everything to b64 scripts 17 | - removed SACAv1 Deploy button 18 | - added deploy buttons for payg and bigiq 19 | 20 | ### Added 21 | 22 | - PAYG template options 23 | - Tier 1 & 3 Module Parameters 24 | 25 | ## [2.5] - 2020-03-02 26 | 27 | ### Fixed 28 | 29 | - Resolved issue with Accelerated Networking Logic 30 | 31 | ### Changed 32 | 33 | - Rewrote and updated templates closer to F5 *supported* 7.0 templates. 34 | - Restricted templates to 14.1.2 and 15.0.1 35 | 36 | ### Added 37 | 38 | - Created several AS3 options; PAYG, BYOL, and Baseline. 39 | - Added parameter to select module provisioning 40 | 41 | ## [2.2] - 2019-08-06 42 | 43 | ### Changed 44 | 45 | - Made STIG a bool option in Parameters 46 | - Changed image to 14.1.00300 47 | 48 | ## [2.1] - 2019-07-10 49 | 50 | ### Added 51 | 52 | - AV Sets added to all VMs. 53 | - Managed Disks on all VMs. 54 | - Enabled HA Ports on ILB. 55 | - Added UDR for Default Route from VDMS Subnet. 56 | 57 | ### Updated 58 | 59 | - Updated Public IP(s) to Standard SKU. 60 | - Updated ALB to Standard SKU. 61 | - Updated ILB to Standard SKU. 62 | - Updated verifyHash 63 | - Updated 64 | 65 | ### Removed 66 | 67 | - PUA Option removed due to SKU. 68 | 69 | ## [2.0.2] - 2019-03-13 70 | 71 | ### Added 72 | 73 | - Preloaded DOD Root CA Bundle v5.5. 74 | - Added PUA Option. 75 | 76 | ## [2.0.1] - 2019-03-13 77 | 78 | ### Added 79 | 80 | - CHANGELOG created. 81 | 82 | ### Removed 83 | 84 | - Unused variables. 85 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2015, F5 Networks, Inc. 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 5 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # F5 & Azure Secure Cloud Computing Architecture 2 | 3 | 4 | 5 | - [F5 & Azure Secure Cloud Computing Architecture](#f5--azure-secure-cloud-computing-architecture) 6 | - [Introduction](#introduction) 7 | - [Prerequisites](#prerequisites) 8 | - [Important configuration notes](#important-configuration-notes) 9 | - [PAYG versus BYOL Settings](#payg-versus-byol-settings) 10 | - [Variables](#variables) 11 | - [Requirements](#requirements) 12 | - [Providers](#providers) 13 | - [Inputs](#inputs) 14 | - [Outputs](#outputs) 15 | - [Deployment](#deployment) 16 | - [Docker](#docker) 17 | - [Destruction](#destruction) 18 | - [Docker](#docker-1) 19 | - [Development](#development) 20 | 21 | 22 | 23 | ## Introduction 24 | 25 | Moving to the Cloud can be tough. The Department of Defense (DoD) has requirements to protect the Defense Information System Networks (DISN) and DoD Information Networks (DoDIN), even for workloads residing in a Cloud Service Provider (CSP). Per the SCCA Functional Requirements Document, the purpose of SCCA is to provide a barrier of protection between the DISN and commercial cloud services used by the DoD. 26 | 27 | “It specifically addresses attacks originating from mission applications that reside within the Cloud Service Environment (CSE) upon both the DISN infrastructure and neighboring tenants in a multi-tenant environment. It provides a consistent CSP independent level of security that enables the use of commercially available Cloud Service Offerings (CSO) for hosting DoD mission applications operating at all DoD Information System Impact Levels (i.e. 2, 4, 5, & 6).” * [https://dl.dod.cyber.mil/wp-content/uploads/cloud/pdf/SCCA_FRD_v2-9.pdf](https://dl.dod.cyber.mil/wp-content/uploads/cloud/pdf/SCCA_FRD_v2-9.pdf) 28 | 29 | This solution uses Terraform to launch a Single Tiered or Three Tier deployment of three NIC cloud-focused BIG-IP VE cluster(s) (Active/Standby) in Microsoft Azure. This is the standard cloud design where the BIG-IP VE instance is running with three interfaces, where both management and data plane traffic is segregated. 30 | 31 | The BIG-IP VEs have the following features / modules enabled: 32 | 33 | - [Local / Global Availability](https://f5.com/products/big-ip/local-traffic-manager-ltm) 34 | 35 | - [Firewall](https://www.f5.com/products/security/advanced-firewall-manager) 36 | - Firewall with Intrusion Protection and IP Intelligence only available with BYOL deployments today. 37 | 38 | - [Web Application Firewall](https://www.f5.com/products/security/advanced-waf) 39 | 40 | ## Prerequisites 41 | 42 | - **Important**: When you configure the admin password for the BIG-IP VE in the template, you cannot use the character **#**. Additionally, there are a number of other special characters that you should avoid using for F5 product user accounts. See [K2873](https://support.f5.com/csp/article/K2873) for details. 43 | - This template requires a service principal, one will be created in the provided script at ./prepare/setupAzureGovVars_local.sh. 44 | - **Important** For gov cloud deployments its important to run this script to prepare your environment, whether local or Azure Cloud CLI based. There are extra env variables that ned to be passed by TF to Gov Cloud Regions. 45 | - This deployment will be using the Terraform Azurerm provider to build out all the neccessary Azure objects. Therefore, Azure CLI is required. for installation, please follow this [Microsoft link](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-apt?view=azure-cli-latest) 46 | - If this is the first time to deploy the F5 image, the subscription used in this deployment needs to be enabled to programatically deploy. For more information, please refer to [Configure Programatic Deployment](https://azure.microsoft.com/en-us/blog/working-with-marketplace-images-on-azure-resource-manager/) 47 | - You need to set your region and log in to azure ahead of time, the scripts will map your authenitcation credentials and create a service principle, so you will not need to hardcode any credentials in the files. 48 | 49 | ## Important configuration notes 50 | 51 | - All variables are configured in variables.tf 52 | - **MOST** STIG / SRG configurations settings have been addressed in the Declarative Onboarding and Application Services templates used in this example. 53 | - An Example application is optionally deployed with this template. The example appliation includes several apps running in docker on the host: 54 | - Juiceshop on port 3000 55 | - F5 Demo app by Eric Chen on ports 80 and 443 56 | - rsyslogd with PimpMyLogs on port 808 57 | - **Note** Juiceshop and PimpMyLogs URLS are part of the terraform output when deployed. 58 | - All Configuration should happen at the root level; auto.tfvars or variables.tf. 59 | 60 | ## PAYG versus BYOL Settings 61 | 62 | - For PAYG deployments the variables image_name and product need to be configured accordingly, default values are set for PAYG. 63 | - Example: image_name = f5-bigip-virtual-edition-1g-best-hourly and product = f5-big-ip-best 64 | 65 | - For BYOL deployments the variables image_name, product, and licenses need to be configured accordingly. 66 | - Example: image_name = f5-big-all-2slot-byol, product = f5-big-ip-byol, and licenses = appropriate licenses. 67 | ## Variables 68 | 69 | 70 | ## Requirements 71 | 72 | | Name | Version | 73 | |------|---------| 74 | | terraform | ~> 0.13 | 75 | 76 | ## Providers 77 | 78 | | Name | Version | 79 | |------|---------| 80 | | azurerm | n/a | 81 | 82 | ## Inputs 83 | 84 | | Name | Description | Type | Default | 85 | |------|-------------|------|---------| 86 | | projectPrefix | REQUIRED: Prefix to prepend to all objects created, minus Windows Jumpbox | `string` | `"ccbad9e7"` | 87 | | adminUserName | REQUIRED: Admin Username for All systems | `string` | `"xadmin"` | 88 | | adminPassword | REQUIRED: Admin Password for all systems | `string` | `"pleaseUseVault123!!"` | 89 | | location | REQUIRED: Azure Region: usgovvirginia, usgovarizona, etc. For a list of available locations for your subscription use `az account list-locations -o table` | `string` | `"usgovvirginia"` | 90 | | region | Azure Region: US Gov Virginia, US Gov Arizona, etc | `string` | `"US Gov Virginia"` | 91 | | deploymentType | REQUIRED: This determines the type of deployment; one tier versus three tier: one\_tier, three\_tier | `string` | `"three_tier"` | 92 | | deployDemoApp | OPTIONAL: Deploy Demo Application with Stack. Recommended to show functionality. Options: deploy, anything else. | `string` | `"deploy"` | 93 | | sshPublicKey | OPTIONAL: ssh public key for instances | `string` | `""` | 94 | | sshPublicKeyPath | OPTIONAL: ssh public key path for instances | `string` | `"/mykey.pub"` | 95 | | cidr | REQUIRED: VNET Network CIDR | `string` | `"10.90.0.0/16"` | 96 | | subnets | REQUIRED: Subnet CIDRs | `map(string)` |
{
"application": "10.90.10.0/24",
"external": "10.90.1.0/24",
"inspect_ext": "10.90.4.0/24",
"inspect_int": "10.90.5.0/24",
"internal": "10.90.2.0/24",
"management": "10.90.0.0/24",
"vdms": "10.90.3.0/24",
"waf_ext": "10.90.6.0/24",
"waf_int": "10.90.7.0/24"
}
| 97 | | f5\_mgmt | F5 BIG-IP Management IPs. These must be in the management subnet. | `map(string)` |
{
"f5vm01mgmt": "10.90.0.4",
"f5vm02mgmt": "10.90.0.5",
"f5vm03mgmt": "10.90.0.6",
"f5vm04mgmt": "10.90.0.7"
}
| 98 | | f5\_t1\_ext | Tier 1 BIG-IP External IPs. These must be in the external subnet. | `map(string)` |
{
"f5vm01ext": "10.90.1.4",
"f5vm01ext_sec": "10.90.1.11",
"f5vm02ext": "10.90.1.5",
"f5vm02ext_sec": "10.90.1.12"
}
| 99 | | f5\_t1\_int | Tier 1 BIG-IP Internal IPs. These must be in the internal subnet. | `map(string)` |
{
"f5vm01int": "10.90.2.4",
"f5vm01int_sec": "10.90.2.11",
"f5vm02int": "10.90.2.5",
"f5vm02int_sec": "10.90.2.12"
}
| 100 | | f5\_t3\_ext | Tier 3 BIG-IP External IPs. These must be in the waf external subnet. | `map(string)` |
{
"f5vm03ext": "10.90.6.4",
"f5vm03ext_sec": "10.90.6.11",
"f5vm04ext": "10.90.6.5",
"f5vm04ext_sec": "10.90.6.12"
}
| 101 | | f5\_t3\_int | Tier 3 BIG-IP Internal IPs. These must be in the waf internal subnet. | `map(string)` |
{
"f5vm03int": "10.90.7.4",
"f5vm03int_sec": "10.90.7.11",
"f5vm04int": "10.90.7.5",
"f5vm04int_sec": "10.90.7.12"
}
| 102 | | internalILBIPs | REQUIRED: Used by One and Three Tier. Azure internal load balancer ips, these are used for ingress and egress. | `map(string)` | `{}` | 103 | | ilb01ip | REQUIRED: Used by One and Three Tier. Azure internal load balancer ip, this is used as egress, must be in internal subnet. | `string` | `"10.90.2.10"` | 104 | | ilb02ip | REQUIRED: Used by Three Tier only. Azure waf external load balancer ip, this is used as egress, must be in waf\_ext subnet. | `string` | `"10.90.6.10"` | 105 | | ilb03ip | REQUIRED: Used by Three Tier only. Azure waf external load balancer ip, this is used as ingress, must be in waf\_ext subnet. | `string` | `"10.90.6.13"` | 106 | | ilb04ip | REQUIRED: Used by Three Tier only. Azure waf external load balancer ip, this is used as ingress, must be in inspect\_external subnet. | `string` | `"10.90.4.13"` | 107 | | app01ip | OPTIONAL: Example Application used by all use-cases to demonstrate functionality of deploymeny, must reside in the application subnet. | `string` | `"10.90.10.101"` | 108 | | ips01ext | Example IPS private ips | `string` | `"10.90.4.4"` | 109 | | ips01int | n/a | `string` | `"10.90.5.4"` | 110 | | ips01mgmt | n/a | `string` | `"10.90.0.8"` | 111 | | winjumpip | REQUIRED: Used by all use-cases for RDP/Windows Jumpbox, must reside in VDMS subnet. | `string` | `"10.90.3.98"` | 112 | | linuxjumpip | REQUIRED: Used by all use-cases for SSH/Linux Jumpbox, must reside in VDMS subnet. | `string` | `"10.90.3.99"` | 113 | | instanceType | BIGIP Instance Type, DS5\_v2 is a solid baseline for BEST | `string` | `"Standard_DS5_v2"` | 114 | | jumpinstanceType | Be careful which instance type selected, jump boxes currently use Premium\_LRS managed disks | `string` | `"Standard_B2s"` | 115 | | appInstanceType | Demo Application Instance Size | `string` | `"Standard_DS3_v2"` | 116 | | image\_name | REQUIRED: BIG-IP Image Name. 'az vm image list --output table --publisher f5-networks --location [region] --offer f5-big-ip --all' Default f5-bigip-virtual-edition-1g-best-hourly is PAYG Image. For BYOL use f5-big-all-2slot-byol | `string` | `"f5-bigip-virtual-edition-1g-best-hourly"` | 117 | | product | REQUIRED: BYOL = f5-big-ip-byol, PAYG = f5-big-ip-best | `string` | `"f5-big-ip-best"` | 118 | | bigip\_version | REQUIRED: BIG-IP Version. Note: verify available versions before using as images can change. | `string` | `"14.1.400000"` | 119 | | licenses | BIGIP Setup Licenses are only needed when using BYOL images | `map(string)` |
{
"license1": "",
"license2": "",
"license3": "",
"license4": ""
}
| 120 | | hosts | n/a | `map(string)` |
{
"host1": "f5vm01",
"host2": "f5vm02",
"host3": "f5vm03",
"host4": "f5vm04"
}
| 121 | | dns\_server | REQUIRED: Default is set to Azure DNS. | `string` | `"168.63.129.16"` | 122 | | asm\_policy | REQUIRED: ASM Policy. Examples: https://github.com/f5devcentral/f5-asm-policy-templates. Default: OWASP Ready Autotuning | `string` | `"https://raw.githubusercontent.com/f5devcentral/f5-asm-policy-templates/master/owasp_ready_template/owasp-auto-tune-v1.1.xml"` | 123 | | ntp\_server | n/a | `string` | `"time.nist.gov"` | 124 | | timezone | n/a | `string` | `"UTC"` | 125 | | onboard\_log | n/a | `string` | `"/var/log/startup-script.log"` | 126 | | tags | Environment tags for objects | `map(string)` |
{
"application": "f5app",
"costcenter": "f5costcenter",
"environment": "f5env",
"group": "f5group",
"owner": "f5owner",
"purpose": "public"
}
| 127 | 128 | ## Outputs 129 | 130 | | Name | Description | 131 | |------|-------------| 132 | | DemoApplication\_443 | Public IP for applications. Https for example app, RDP for Windows Jumpbox, SSH for Linux Jumpbox | 133 | | rSyslogdHttp\_8080 | Public IP for applications. Https for example app, RDP for Windows Jumpbox, SSH for Linux Jumpbox | 134 | | tier\_one | One Tier Outputs: VM IDs, VM Mgmt IPs, VM External Private IPs | 135 | | tier\_three | Three Tier Outputs: VM IDs, VM Mgmt IPs, VM External Private IPs | 136 | 137 | 138 | 139 | ## Deployment 140 | 141 | For deployment you can do the traditional terraform commands or use the provided scripts. 142 | 143 | ```bash 144 | terraform init 145 | terraform plan 146 | terraform apply 147 | ``` 148 | 149 | OR 150 | 151 | ```bash 152 | ./demo.sh 153 | ``` 154 | 155 | ### Docker 156 | There is also a dockerfile provided, use make [options] to build as needed. 157 | 158 | ```bash 159 | make build 160 | make shell || make azure || make gov 161 | ``` 162 | 163 | ## Destruction 164 | 165 | For destruction / tear down you can do the trafitional terraform commands or use the provided scripts. 166 | 167 | ```bash 168 | terraform destroy 169 | ``` 170 | 171 | OR 172 | 173 | ```bash 174 | ./cleanup.sh 175 | ``` 176 | 177 | ### Docker 178 | 179 | ```bash 180 | make destroy || make revolution 181 | ``` 182 | 183 | ## Development 184 | 185 | Outline any requirements to setup a development environment if someone would like to contribute. You may also link to another file for this information. 186 | 187 | ```bash 188 | # test pre commit manually 189 | pre-commit run -a -v 190 | ``` 191 | -------------------------------------------------------------------------------- /TERMS_OF_USE.txt: -------------------------------------------------------------------------------- 1 | THIS LICENSE AGREEMENT IS ENTERED INTO BETWEEN THE SUBMITTING PARTY AND F5 NETWORKS, INC. AND THE SUBMITTING PARTY AGREES TO BE BOUND BY THE TERMS OF THIS AGREEMENT BY SUBMITTING, POSTING, DOWNLOADING, COPYING, MODIFYING, INPUTTING, INSTALLATION, UPLOAD OR OTHER USE OF F5 MATERIALS AND THE SUBMISSIONS. IF YOU DO NOT AGREE TO THE FOREGOING, DO NOT POST THE SUBISSIONS OR USE THE F5 MATERIALS. 2 | (1) F5 does not claim ownership of the materials you provide to F5 (including feedback and suggestions) or post, upload, input or submit to any F5 GitHub repository (collectively "Submissions"). However, by posting, uploading, inputting, providing or submitting your Submission you grant F5, its affiliated companies and necessary sub-licensees a full, complete, irrevocable copyright license to use your Submission including, without limitation, the rights to: copy, distribute, transmit, publicly display, publicly perform, reproduce, edit, translate and reformat your Submission; and to publish your name in connection with your Submission. In addition, you agree that your submission will be subject to the terms of the MIT License (https://github.com/f5devcentral/f5-postman-collections/LICENSE.txt). 3 | (2) By posting, uploading, inputting, providing or submitting your Submission you warrant and represent that you own, are approved by your employer, or otherwise control all of the rights to your Submission as described including, without limitation, all the rights necessary for you to provide, post, upload, input or submit the Submissions. 4 | (3) Infringement Indemnification. Submitting party will defend and indemnify F5 against a claim that any information, design, specification, instruction, software, data, or material furnished by the submitting party under this license infringes a trademark, copyright, or patent. F5 will notify the submitting party promptly of such claim and will give sole control of defense and all related settlement negotiations to submitting party. F5 will provide reasonable assistance, information, and authority necessary to perform these obligations. Reasonable out-of-pocket expenses incurred by F5 for providing such assistance will be reimbursed by the submitting party. 5 | (4) THE MATERIALS AND SERVICES MADE AVAILABLE AT AND THROUGH THIS SITE ARE PROVIDED BY F5 ON AN "AS IS" BASIS. F5 MAKES NO REPRESENTATIONS, WARRANTIES OR GUARANTIES OF ANY KIND, EXPRESS OR IMPLIED, AS TO THE OPERATION OF THIS SITE, ITS CONTENT, OR ANY PRODUCTS OR SERVICES DESCRIBED OR OFFERED BY THIS SITE. TO THE FULL EXTENT PERMISSIBLE BY APPLICABLE LAW, F5 DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, INCLUDING MERCHANTABILITY OF COMPUTER PROGRAMS AND INFORMATIONAL CONTENT, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, TITLE, OR THAT THE SITE CONTENT IS RELIABLE, ACCURATE, OR TIMELY. F5 WILL NOT BE LIABLE FOR ANY DAMAGES OF ANY KIND ARISING FROM THE USE OF THIS SITE, INCLUDING, BUT NOT LIMITED TO DIRECT, INDIRECT, INCIDENTAL, PUNITIVE, SPECIAL, CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF USE, DATA OR PROFITS, ARISING OUT OF OR IN ANY WAY CONNECTED WITH THE USE OR PERFORMANCE OF THE WEB SITE, WITH THE DELAY OR INABILITY TO USE THE WEB SITE OR RELATED SERVICES, THE PROVISION OF OR FAILURE TO PROVIDE SERVICES, OR FOR ANY INFORMATION, SOFTWARE, PRODUCTS, SERVICES AND RELATED GRAPHICS OBTAINED THROUGH THE WEB SITE, OR OTHERWISE ARISING OUT OF THE USE OF THE WEB SITE, WHETHER BASED ON CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY OR OTHERWISE, EVEN IF F5 OR ANY OF ITS SUPPLIERS HAS BEEN ADVISED OF THE POSSIBILITY OF DAMAGES. BECAUSE SOME STATES/JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO YOU. WHILE THIS SITE MAY PROVIDE LINKS TO THIRD PARTY SITES, F5 DOES NOT CONTROL OR ENDORSE ANY THIRD PARTY SITE AND DISCLAIMS ANY RESPONSIBILITY FOR ITS FUNCTIONALITY OR CONTENT. THESE DISCLAIMERS AND LIMITATIONS ARE MADE IN ADDITION TO THOSE MADE IN AND APPLICABLE TO VARIOUS PAGES OR SECTIONS OF THIS SITE. 6 | -------------------------------------------------------------------------------- /TROUBLE.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/f5-azure-saca/ebb56b4d72a641592d785600f6e5ac64eae06c75/TROUBLE.md -------------------------------------------------------------------------------- /analytics/analytics.tf: -------------------------------------------------------------------------------- 1 | # Create Log Analytic Workspace 2 | resource "azurerm_log_analytics_workspace" "law" { 3 | name = "${var.prefix}-law" 4 | sku = "PerNode" 5 | retention_in_days = 300 6 | resource_group_name = var.resourceGroup.name 7 | location = var.location 8 | } 9 | 10 | data "template_file" "ts_json" { 11 | template = file("./templates/ts.json") 12 | 13 | vars = { 14 | region = var.location 15 | law_id = azurerm_log_analytics_workspace.law.workspace_id 16 | law_primkey = azurerm_log_analytics_workspace.law.primary_shared_key 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /analytics/variables.tf: -------------------------------------------------------------------------------- 1 | 2 | variable prefix {} 3 | variable resourceGroup {} 4 | variable location {} 5 | variable region {} 6 | variable securityGroup { 7 | default = "none" 8 | } 9 | 10 | variable subnet { 11 | default = "none" 12 | } 13 | 14 | variable adminUserName {} 15 | variable adminPassword {} 16 | 17 | # TAGS 18 | variable tags {} 19 | -------------------------------------------------------------------------------- /azure.tf: -------------------------------------------------------------------------------- 1 | # Create a Resource Group for the new Virtual Machines 2 | resource "azurerm_resource_group" "main" { 3 | name = "${var.projectPrefix}_rg" 4 | location = var.location 5 | } 6 | 7 | 8 | # Create Availability Set 9 | resource "azurerm_availability_set" "avset" { 10 | name = "${var.projectPrefix}-avset" 11 | location = azurerm_resource_group.main.location 12 | resource_group_name = azurerm_resource_group.main.name 13 | platform_fault_domain_count = 2 14 | platform_update_domain_count = 2 15 | managed = true 16 | } 17 | 18 | # Create Availability Set 2 only for 3 tier tho 19 | resource "azurerm_availability_set" "avset2" { 20 | count = var.deploymentType == "three_tier" ? 1 : 0 21 | name = "${var.projectPrefix}-avset-2" 22 | location = azurerm_resource_group.main.location 23 | resource_group_name = azurerm_resource_group.main.name 24 | platform_fault_domain_count = 2 25 | platform_update_domain_count = 2 26 | managed = true 27 | } 28 | 29 | # Create Azure LB 30 | resource "azurerm_lb" "lb" { 31 | name = "${var.projectPrefix}-alb" 32 | location = azurerm_resource_group.main.location 33 | resource_group_name = azurerm_resource_group.main.name 34 | sku = "Standard" 35 | 36 | frontend_ip_configuration { 37 | name = "Public-LoadBalancerFrontEnd" 38 | public_ip_address_id = azurerm_public_ip.lbpip.id 39 | } 40 | } 41 | 42 | resource "azurerm_lb_backend_address_pool" "backend_pool" { 43 | name = "IngressBackendPool" 44 | #resource_group_name = azurerm_resource_group.main.name 45 | loadbalancer_id = azurerm_lb.lb.id 46 | } 47 | 48 | resource "azurerm_lb_backend_address_pool" "management_pool" { 49 | name = "EgressManagementPool" 50 | #resource_group_name = azurerm_resource_group.main.name 51 | loadbalancer_id = azurerm_lb.lb.id 52 | } 53 | 54 | resource "azurerm_lb_backend_address_pool" "primary_pool" { 55 | name = "EgressPrimaryPool" 56 | #resource_group_name = azurerm_resource_group.main.name 57 | loadbalancer_id = azurerm_lb.lb.id 58 | } 59 | 60 | resource "azurerm_lb_probe" "https_probe" { 61 | #resource_group_name = azurerm_resource_group.main.name 62 | loadbalancer_id = azurerm_lb.lb.id 63 | name = "443Probe" 64 | protocol = "Tcp" 65 | port = 443 66 | interval_in_seconds = 5 67 | number_of_probes = 2 68 | } 69 | 70 | resource "azurerm_lb_probe" "http_probe" { 71 | #resource_group_name = azurerm_resource_group.main.name 72 | loadbalancer_id = azurerm_lb.lb.id 73 | name = "8080Probe" 74 | protocol = "Tcp" 75 | port = 8080 76 | interval_in_seconds = 5 77 | number_of_probes = 2 78 | } 79 | 80 | resource "azurerm_lb_probe" "ssh_probe" { 81 | #resource_group_name = azurerm_resource_group.main.name 82 | loadbalancer_id = azurerm_lb.lb.id 83 | name = "sshProbe" 84 | protocol = "Tcp" 85 | port = 22 86 | interval_in_seconds = 5 87 | number_of_probes = 2 88 | } 89 | 90 | resource "azurerm_lb_probe" "rdp_probe" { 91 | #resource_group_name = azurerm_resource_group.main.name 92 | loadbalancer_id = azurerm_lb.lb.id 93 | name = "rdpProbe" 94 | protocol = "Tcp" 95 | port = 3389 96 | interval_in_seconds = 5 97 | number_of_probes = 2 98 | } 99 | 100 | resource "azurerm_lb_rule" "https_rule" { 101 | name = "HTTPS_Rule" 102 | #resource_group_name = azurerm_resource_group.main.name 103 | loadbalancer_id = azurerm_lb.lb.id 104 | protocol = "Tcp" 105 | frontend_port = 443 106 | backend_port = 443 107 | frontend_ip_configuration_name = "Public-LoadBalancerFrontEnd" 108 | enable_floating_ip = false 109 | disable_outbound_snat = true 110 | backend_address_pool_ids = [azurerm_lb_backend_address_pool.backend_pool.id] 111 | #backend_address_pool_id = azurerm_lb_backend_address_pool.backend_pool.id 112 | idle_timeout_in_minutes = 5 113 | probe_id = azurerm_lb_probe.https_probe.id 114 | depends_on = [azurerm_lb_probe.https_probe] 115 | } 116 | 117 | resource "azurerm_lb_rule" "http_rule" { 118 | name = "HTTPRule" 119 | #resource_group_name = azurerm_resource_group.main.name 120 | loadbalancer_id = azurerm_lb.lb.id 121 | protocol = "Tcp" 122 | frontend_port = 8080 123 | backend_port = 8080 124 | frontend_ip_configuration_name = "Public-LoadBalancerFrontEnd" 125 | enable_floating_ip = false 126 | disable_outbound_snat = true 127 | backend_address_pool_ids = [azurerm_lb_backend_address_pool.backend_pool.id] 128 | #backend_address_pool_id = azurerm_lb_backend_address_pool.backend_pool.id 129 | idle_timeout_in_minutes = 5 130 | probe_id = azurerm_lb_probe.http_probe.id 131 | depends_on = [azurerm_lb_probe.http_probe] 132 | } 133 | 134 | resource "azurerm_lb_rule" "ssh_rule" { 135 | name = "SSH_Rule" 136 | #resource_group_name = azurerm_resource_group.main.name 137 | loadbalancer_id = azurerm_lb.lb.id 138 | protocol = "Tcp" 139 | frontend_port = 22 140 | backend_port = 22 141 | frontend_ip_configuration_name = "Public-LoadBalancerFrontEnd" 142 | enable_floating_ip = false 143 | disable_outbound_snat = true 144 | backend_address_pool_ids = [azurerm_lb_backend_address_pool.backend_pool.id] 145 | #backend_address_pool_id = azurerm_lb_backend_address_pool.backend_pool.id 146 | idle_timeout_in_minutes = 5 147 | probe_id = azurerm_lb_probe.ssh_probe.id 148 | depends_on = [azurerm_lb_probe.ssh_probe] 149 | } 150 | resource "azurerm_lb_rule" "rdp_rule" { 151 | name = "RDP_Rule" 152 | #resource_group_name = azurerm_resource_group.main.name 153 | loadbalancer_id = azurerm_lb.lb.id 154 | protocol = "Tcp" 155 | frontend_port = 3389 156 | backend_port = 3389 157 | frontend_ip_configuration_name = "Public-LoadBalancerFrontEnd" 158 | enable_floating_ip = false 159 | disable_outbound_snat = true 160 | backend_address_pool_ids = [azurerm_lb_backend_address_pool.backend_pool.id] 161 | #backend_address_pool_id = azurerm_lb_backend_address_pool.backend_pool.id 162 | idle_timeout_in_minutes = 5 163 | probe_id = azurerm_lb_probe.rdp_probe.id 164 | depends_on = [azurerm_lb_probe.rdp_probe] 165 | } 166 | 167 | resource "azurerm_lb_outbound_rule" "egress_rule" { 168 | name = "egress_rule" 169 | #resource_group_name = azurerm_resource_group.main.name 170 | loadbalancer_id = azurerm_lb.lb.id 171 | protocol = "All" 172 | backend_address_pool_id = azurerm_lb_backend_address_pool.primary_pool.id 173 | allocated_outbound_ports = "9136" 174 | enable_tcp_reset = true 175 | frontend_ip_configuration { 176 | name = "Public-LoadBalancerFrontEnd" 177 | } 178 | } 179 | 180 | # Create the ILB for South LB and Egress 181 | resource "azurerm_lb" "internalLoadBalancer" { 182 | count = var.deploymentType == "three_tier" ? 1 : 0 183 | name = "${var.projectPrefix}-internal-loadbalancer" 184 | location = var.location 185 | resource_group_name = azurerm_resource_group.main.name 186 | sku = "Standard" 187 | 188 | frontend_ip_configuration { 189 | name = "Internal_LoadBalancerFrontEnd" 190 | subnet_id = azurerm_subnet.internal.id 191 | private_ip_address = var.ilb01ip 192 | private_ip_address_allocation = "Static" 193 | private_ip_address_version = "IPv4" 194 | } 195 | 196 | frontend_ip_configuration { 197 | name = "IDS_LoadBalancerFrontEnd" 198 | subnet_id = azurerm_subnet.inspect_external[0].id 199 | private_ip_address = var.ilb04ip 200 | private_ip_address_allocation = "Static" 201 | private_ip_address_version = "IPv4" 202 | } 203 | 204 | frontend_ip_configuration { 205 | name = "waf_ext_LoadBalancerFrontEnd_Egress" 206 | subnet_id = azurerm_subnet.waf_external[0].id 207 | private_ip_address = var.ilb02ip 208 | private_ip_address_allocation = "Static" 209 | private_ip_address_version = "IPv4" 210 | } 211 | 212 | frontend_ip_configuration { 213 | name = "waf_ext_LoadBalancerFrontEnd_Ingress" 214 | subnet_id = azurerm_subnet.waf_external[0].id 215 | private_ip_address = var.ilb03ip 216 | private_ip_address_allocation = "Static" 217 | private_ip_address_version = "IPv4" 218 | } 219 | } 220 | 221 | # Create the LB Pool for Internal Egress 222 | resource "azurerm_lb_backend_address_pool" "internal_backend_pool" { 223 | count = var.deploymentType == "three_tier" ? 1 : 0 224 | name = "internal_egress_pool" 225 | #resource_group_name = azurerm_resource_group.main.name 226 | loadbalancer_id = azurerm_lb.internalLoadBalancer[0].id 227 | } 228 | 229 | # Create the LB Pool for Inspect Ingress 230 | resource "azurerm_lb_backend_address_pool" "ips_backend_pool" { 231 | count = var.deploymentType == "three_tier" ? 1 : 0 232 | name = "ips_ingress_pool" 233 | #resource_group_name = azurerm_resource_group.main.name 234 | loadbalancer_id = azurerm_lb.internalLoadBalancer[0].id 235 | } 236 | 237 | # Create the LB Pool for WAF Ingress 238 | resource "azurerm_lb_backend_address_pool" "waf_ingress_pool" { 239 | count = var.deploymentType == "three_tier" ? 1 : 0 240 | name = "waf_ingress_pool" 241 | #resource_group_name = azurerm_resource_group.main.name 242 | loadbalancer_id = azurerm_lb.internalLoadBalancer[0].id 243 | } 244 | # Create the LB Pool for WAF Egress 245 | resource "azurerm_lb_backend_address_pool" "waf_egress_pool" { 246 | count = var.deploymentType == "three_tier" ? 1 : 0 247 | name = "waf_egress_pool" 248 | #resource_group_name = azurerm_resource_group.main.name 249 | loadbalancer_id = azurerm_lb.internalLoadBalancer[0].id 250 | } 251 | 252 | resource "azurerm_lb_probe" "internal_Tcp_probe" { 253 | count = var.deploymentType == "three_tier" ? 1 : 0 254 | #resource_group_name = azurerm_resource_group.main.name 255 | loadbalancer_id = azurerm_lb.internalLoadBalancer[0].id 256 | name = "${var.projectPrefix}-internal-Tcp-probe" 257 | protocol = "Tcp" 258 | port = 34568 259 | interval_in_seconds = 5 260 | number_of_probes = 2 261 | } 262 | 263 | resource "azurerm_lb_probe" "waf_probe" { 264 | count = var.deploymentType == "three_tier" ? 1 : 0 265 | #resource_group_name = azurerm_resource_group.main.name 266 | loadbalancer_id = azurerm_lb.internalLoadBalancer[0].id 267 | name = "${var.projectPrefix}-waf-Tcp-probe" 268 | protocol = "Tcp" 269 | port = 8080 270 | interval_in_seconds = 5 271 | number_of_probes = 2 272 | } 273 | 274 | resource "azurerm_lb_rule" "internal_all_rule" { 275 | count = var.deploymentType == "three_tier" ? 1 : 0 276 | name = "internal-all-protocol-ilb-egress" 277 | #resource_group_name = azurerm_resource_group.main.name 278 | loadbalancer_id = azurerm_lb.internalLoadBalancer[0].id 279 | protocol = "All" 280 | frontend_port = 0 281 | backend_port = 0 282 | load_distribution = "SourceIPProtocol" 283 | frontend_ip_configuration_name = "Internal_LoadBalancerFrontEnd" 284 | enable_floating_ip = true 285 | backend_address_pool_ids = [azurerm_lb_backend_address_pool.internal_backend_pool[0].id] 286 | #backend_address_pool_id = azurerm_lb_backend_address_pool.internal_backend_pool[0].id 287 | idle_timeout_in_minutes = 5 288 | probe_id = azurerm_lb_probe.internal_Tcp_probe[0].id 289 | depends_on = [azurerm_lb_probe.internal_Tcp_probe[0]] 290 | } 291 | 292 | resource "azurerm_lb_rule" "waf_ext_all_rule" { 293 | count = var.deploymentType == "three_tier" ? 1 : 0 294 | name = "waf-ext-all-protocol-ilb-egress" 295 | #resource_group_name = azurerm_resource_group.main.name 296 | loadbalancer_id = azurerm_lb.internalLoadBalancer[0].id 297 | protocol = "All" 298 | frontend_port = 0 299 | backend_port = 0 300 | load_distribution = "SourceIPProtocol" 301 | frontend_ip_configuration_name = "waf_ext_LoadBalancerFrontEnd_Egress" 302 | enable_floating_ip = true 303 | backend_address_pool_ids = [azurerm_lb_backend_address_pool.waf_egress_pool[0].id] 304 | #backend_address_pool_id = azurerm_lb_backend_address_pool.waf_egress_pool[0].id 305 | idle_timeout_in_minutes = 5 306 | probe_id = azurerm_lb_probe.internal_Tcp_probe[0].id 307 | depends_on = [azurerm_lb_probe.internal_Tcp_probe[0]] 308 | } 309 | 310 | resource "azurerm_lb_rule" "waf_ext_ingress_rule" { 311 | count = var.deploymentType == "three_tier" ? 1 : 0 312 | name = "waf-ext-all-protocol-ilb-ingress" 313 | #resource_group_name = azurerm_resource_group.main.name 314 | loadbalancer_id = azurerm_lb.internalLoadBalancer[0].id 315 | protocol = "All" 316 | frontend_port = 0 317 | backend_port = 0 318 | load_distribution = "SourceIPProtocol" 319 | frontend_ip_configuration_name = "waf_ext_LoadBalancerFrontEnd_Ingress" 320 | enable_floating_ip = true 321 | backend_address_pool_ids = [azurerm_lb_backend_address_pool.waf_ingress_pool[0].id] 322 | #backend_address_pool_id = azurerm_lb_backend_address_pool.waf_ingress_pool[0].id 323 | idle_timeout_in_minutes = 5 324 | probe_id = azurerm_lb_probe.waf_probe[0].id 325 | depends_on = [azurerm_lb_probe.waf_probe[0]] 326 | } 327 | -------------------------------------------------------------------------------- /cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "destroying demo" 3 | read -r -p "Are you sure? [y/N] " response 4 | if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]] 5 | then 6 | terraform destroy --auto-approve 7 | while [ $? -ne 0 ]; do 8 | terraform destroy --auto-approve 9 | done 10 | else 11 | echo "canceling" 12 | fi 13 | -------------------------------------------------------------------------------- /demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | start=$SECONDS 4 | terraform init 5 | terraform fmt 6 | terraform validate 7 | terraform plan 8 | # apply 9 | read -p "Press enter to continue" 10 | terraform apply --auto-approve 11 | duration=$(( SECONDS - start )) 12 | echo "Operation took $duration seconds" 13 | -------------------------------------------------------------------------------- /demo_app/app.tf: -------------------------------------------------------------------------------- 1 | # network interface for app vm 2 | resource azurerm_network_interface app01-nic { 3 | name = "${var.prefix}-app01-nic" 4 | location = var.resourceGroup.location 5 | resource_group_name = var.resourceGroup.name 6 | 7 | ip_configuration { 8 | name = "primary" 9 | subnet_id = var.subnet.id 10 | private_ip_address_allocation = "Static" 11 | private_ip_address = var.app01ip 12 | primary = true 13 | } 14 | 15 | tags = var.tags 16 | } 17 | 18 | resource azurerm_network_interface_security_group_association app-nsg { 19 | network_interface_id = azurerm_network_interface.app01-nic.id 20 | network_security_group_id = var.securityGroup.id 21 | } 22 | 23 | # app01-VM 24 | resource azurerm_virtual_machine app01-vm { 25 | count = 1 26 | name = "${var.prefix}-app01-vm" 27 | location = var.resourceGroup.location 28 | resource_group_name = var.resourceGroup.name 29 | 30 | network_interface_ids = [azurerm_network_interface.app01-nic.id] 31 | vm_size = var.instanceType 32 | 33 | storage_os_disk { 34 | name = "${var.prefix}-appOsDisk" 35 | caching = "ReadWrite" 36 | create_option = "FromImage" 37 | managed_disk_type = "Premium_LRS" 38 | } 39 | 40 | storage_image_reference { 41 | publisher = "Canonical" 42 | offer = "UbuntuServer" 43 | sku = "16.04.0-LTS" 44 | version = "latest" 45 | } 46 | 47 | os_profile { 48 | computer_name = "app01" 49 | admin_username = var.adminUserName 50 | admin_password = var.adminPassword 51 | custom_data = <<-EOF 52 | #!/bin/bash 53 | apt-get update -y; 54 | apt-get install -y docker.io; 55 | # demo app 56 | docker run -d -p 443:443 -p 80:80 --restart unless-stopped -e F5DEMO_APP=website -e F5DEMO_NODENAME='F5 Azure' -e F5DEMO_COLOR=ffd734 -e F5DEMO_NODENAME_SSL='F5 Azure (SSL)' -e F5DEMO_COLOR_SSL=a0bf37 chen23/f5-demo-app:ssl; 57 | # juice shop 58 | docker run -d --restart always -p 3000:3000 bkimminich/juice-shop 59 | # rsyslogd with PimpMyLogs 60 | docker run -d -e SYSLOG_USERNAME=${var.adminUserName} -e SYSLOG_PASSWORD=${var.adminPassword} -p 8080:80 -p 514:514/udp pbertera/syslogserver 61 | EOF 62 | } 63 | 64 | os_profile_linux_config { 65 | disable_password_authentication = false 66 | } 67 | 68 | tags = var.tags 69 | } 70 | -------------------------------------------------------------------------------- /demo_app/variables.tf: -------------------------------------------------------------------------------- 1 | 2 | variable prefix {} 3 | variable resourceGroup {} 4 | variable location {} 5 | variable region {} 6 | variable securityGroup { 7 | default = "none" 8 | } 9 | 10 | variable subnet {} 11 | 12 | variable app01ip {} 13 | variable adminUserName {} 14 | variable adminPassword {} 15 | 16 | variable instanceType {} 17 | 18 | # TAGS 19 | variable tags {} 20 | 21 | variable timezone {} 22 | -------------------------------------------------------------------------------- /dockerfile: -------------------------------------------------------------------------------- 1 | # Setup build arguments with default versions 2 | ARG TERRAFORM_VERSION=0.14.5 3 | ARG AZURE_CLI_VERSION=latest 4 | 5 | # Download Terraform binary 6 | FROM debian:stretch-20190506-slim as terraform 7 | ENV DEBIAN_FRONTEND="noninteractive" 8 | ARG TERRAFORM_VERSION 9 | RUN apt-get update 10 | RUN apt-get install -y apt-utils 11 | RUN apt-get install -y curl 12 | RUN apt-get install -y unzip 13 | RUN apt-get install -y gnupg 14 | RUN curl -Os https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS 15 | RUN curl -Os https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip 16 | RUN curl -Os https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_SHA256SUMS.sig 17 | COPY hashicorp.asc hashicorp.asc 18 | RUN gpg --import hashicorp.asc 19 | RUN gpg --verify terraform_${TERRAFORM_VERSION}_SHA256SUMS.sig terraform_${TERRAFORM_VERSION}_SHA256SUMS 20 | RUN grep terraform_${TERRAFORM_VERSION}_linux_amd64.zip terraform_${TERRAFORM_VERSION}_SHA256SUMS | sha256sum -c - 21 | RUN unzip -j terraform_${TERRAFORM_VERSION}_linux_amd64.zip 22 | 23 | # Build final image 24 | FROM debian:stretch-20190506-slim 25 | RUN apt-get update \ 26 | && apt-get install -y --no-install-recommends \ 27 | ca-certificates \ 28 | python3=3.5.3-1 \ 29 | curl \ 30 | jq \ 31 | && apt-get clean \ 32 | && rm -rf /var/lib/apt/lists/* \ 33 | && ln -s /usr/bin/python3 /usr/bin/python \ 34 | && curl -sL https://aka.ms/InstallAzureCLIDeb | bash 35 | COPY --from=terraform /terraform /usr/local/bin/terraform 36 | WORKDIR /workspace 37 | CMD ["bash"] 38 | -------------------------------------------------------------------------------- /firewall.tf: -------------------------------------------------------------------------------- 1 | # Create a Network Security Group with some rules 2 | resource azurerm_network_security_group main { 3 | name = "${var.projectPrefix}-nsg" 4 | location = azurerm_resource_group.main.location 5 | resource_group_name = azurerm_resource_group.main.name 6 | 7 | security_rule { 8 | name = "allow_SSH" 9 | description = "Allow SSH access" 10 | priority = 100 11 | direction = "Inbound" 12 | access = "Allow" 13 | protocol = "Tcp" 14 | source_port_range = "*" 15 | destination_port_range = "22" 16 | source_address_prefix = "*" 17 | destination_address_prefix = "*" 18 | } 19 | 20 | security_rule { 21 | name = "allow_HTTP" 22 | description = "Allow HTTP access" 23 | priority = 110 24 | direction = "Inbound" 25 | access = "Allow" 26 | protocol = "Tcp" 27 | source_port_range = "*" 28 | destination_port_range = "8080" 29 | source_address_prefix = "*" 30 | destination_address_prefix = "*" 31 | } 32 | 33 | security_rule { 34 | name = "allow_HTTPS" 35 | description = "Allow HTTPS access" 36 | priority = 120 37 | direction = "Inbound" 38 | access = "Allow" 39 | protocol = "Tcp" 40 | source_port_range = "*" 41 | destination_port_range = "443" 42 | source_address_prefix = "*" 43 | destination_address_prefix = "*" 44 | } 45 | 46 | security_rule { 47 | name = "allow_RDP" 48 | description = "Allow RDP access" 49 | priority = 130 50 | direction = "Inbound" 51 | access = "Allow" 52 | protocol = "Tcp" 53 | source_port_range = "*" 54 | destination_port_range = "3389" 55 | source_address_prefix = "*" 56 | destination_address_prefix = "*" 57 | } 58 | 59 | security_rule { 60 | name = "allow_APP_HTTPS" 61 | description = "Allow HTTPS access" 62 | priority = 140 63 | direction = "Inbound" 64 | access = "Allow" 65 | protocol = "Tcp" 66 | source_port_range = "*" 67 | destination_port_range = "8443" 68 | source_address_prefix = "*" 69 | destination_address_prefix = "*" 70 | } 71 | 72 | tags = var.tags 73 | } 74 | -------------------------------------------------------------------------------- /gitleaks.sh: -------------------------------------------------------------------------------- 1 | docker run --rm --name=gitleaks -v $(pwd):/code/ zricethezav/gitleaks -v --repo-path=/code/ 2 | -------------------------------------------------------------------------------- /hashicorp.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG v1 3 | 4 | mQENBFMORM0BCADBRyKO1MhCirazOSVwcfTr1xUxjPvfxD3hjUwHtjsOy/bT6p9f 5 | W2mRPfwnq2JB5As+paL3UGDsSRDnK9KAxQb0NNF4+eVhr/EJ18s3wwXXDMjpIifq 6 | fIm2WyH3G+aRLTLPIpscUNKDyxFOUbsmgXAmJ46Re1fn8uKxKRHbfa39aeuEYWFA 7 | 3drdL1WoUngvED7f+RnKBK2G6ZEpO+LDovQk19xGjiMTtPJrjMjZJ3QXqPvx5wca 8 | KSZLr4lMTuoTI/ZXyZy5bD4tShiZz6KcyX27cD70q2iRcEZ0poLKHyEIDAi3TM5k 9 | SwbbWBFd5RNPOR0qzrb/0p9ksKK48IIfH2FvABEBAAG0K0hhc2hpQ29ycCBTZWN1 10 | cml0eSA8c2VjdXJpdHlAaGFzaGljb3JwLmNvbT6JATgEEwECACIFAlMORM0CGwMG 11 | CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEFGFLYc0j/xMyWIIAIPhcVqiQ59n 12 | Jc07gjUX0SWBJAxEG1lKxfzS4Xp+57h2xxTpdotGQ1fZwsihaIqow337YHQI3q0i 13 | SqV534Ms+j/tU7X8sq11xFJIeEVG8PASRCwmryUwghFKPlHETQ8jJ+Y8+1asRydi 14 | psP3B/5Mjhqv/uOK+Vy3zAyIpyDOMtIpOVfjSpCplVRdtSTFWBu9Em7j5I2HMn1w 15 | sJZnJgXKpybpibGiiTtmnFLOwibmprSu04rsnP4ncdC2XRD4wIjoyA+4PKgX3sCO 16 | klEzKryWYBmLkJOMDdo52LttP3279s7XrkLEE7ia0fXa2c12EQ0f0DQ1tGUvyVEW 17 | WmJVccm5bq25AQ0EUw5EzQEIANaPUY04/g7AmYkOMjaCZ6iTp9hB5Rsj/4ee/ln9 18 | wArzRO9+3eejLWh53FoN1rO+su7tiXJA5YAzVy6tuolrqjM8DBztPxdLBbEi4V+j 19 | 2tK0dATdBQBHEh3OJApO2UBtcjaZBT31zrG9K55D+CrcgIVEHAKY8Cb4kLBkb5wM 20 | skn+DrASKU0BNIV1qRsxfiUdQHZfSqtp004nrql1lbFMLFEuiY8FZrkkQ9qduixo 21 | mTT6f34/oiY+Jam3zCK7RDN/OjuWheIPGj/Qbx9JuNiwgX6yRj7OE1tjUx6d8g9y 22 | 0H1fmLJbb3WZZbuuGFnK6qrE3bGeY8+AWaJAZ37wpWh1p0cAEQEAAYkBHwQYAQIA 23 | CQUCUw5EzQIbDAAKCRBRhS2HNI/8TJntCAClU7TOO/X053eKF1jqNW4A1qpxctVc 24 | z8eTcY8Om5O4f6a/rfxfNFKn9Qyja/OG1xWNobETy7MiMXYjaa8uUx5iFy6kMVaP 25 | 0BXJ59NLZjMARGw6lVTYDTIvzqqqwLxgliSDfSnqUhubGwvykANPO+93BBx89MRG 26 | unNoYGXtPlhNFrAsB1VR8+EyKLv2HQtGCPSFBhrjuzH3gxGibNDDdFQLxxuJWepJ 27 | EK1UbTS4ms0NgZ2Uknqn1WRU1Ki7rE4sTy68iZtWpKQXZEJa0IGnuI2sSINGcXCJ 28 | oEIgXTMyCILo34Fa/C6VCm2WBgz9zZO8/rHIiQm1J5zqz0DrDwKBUM9C 29 | =LYpS 30 | -----END PGP PUBLIC KEY BLOCK----- 31 | -------------------------------------------------------------------------------- /jumpboxes/DisableInternetExplorer-ESC.ps1: -------------------------------------------------------------------------------- 1 | function Disable-InternetExplorerESC { 2 | $AdminKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}" 3 | $UserKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}" 4 | Set-ItemProperty -Path $AdminKey -Name "IsInstalled" -Value 0 5 | Set-ItemProperty -Path $UserKey -Name "IsInstalled" -Value 0 6 | Stop-Process -Name Explorer 7 | } 8 | Disable-InternetExplorerESC 9 | -------------------------------------------------------------------------------- /jumpboxes/linux.tf: -------------------------------------------------------------------------------- 1 | # linuxJump 2 | resource azurerm_network_interface linuxJump-ext-nic { 3 | name = "${var.prefix}-linuxJump-ext-nic" 4 | location = var.resourceGroup.location 5 | resource_group_name = var.resourceGroup.name 6 | #network_security_group_id = var.securityGroup.id 7 | 8 | ip_configuration { 9 | name = "primary" 10 | subnet_id = var.subnet.id 11 | private_ip_address_allocation = "Static" 12 | private_ip_address = var.linuxjumpip 13 | primary = true 14 | } 15 | 16 | tags = var.tags 17 | } 18 | 19 | resource "azurerm_network_interface_security_group_association" "linuxJump-ext-nsg" { 20 | network_interface_id = azurerm_network_interface.linuxJump-ext-nic.id 21 | network_security_group_id = var.securityGroup.id 22 | } 23 | 24 | resource azurerm_virtual_machine linuxJump { 25 | name = "${var.prefix}-linuxJump" 26 | location = var.resourceGroup.location 27 | resource_group_name = var.resourceGroup.name 28 | 29 | network_interface_ids = [azurerm_network_interface.linuxJump-ext-nic.id] 30 | vm_size = var.instanceType 31 | 32 | storage_os_disk { 33 | name = "${var.prefix}-linuxJumpOsDisk" 34 | caching = "ReadWrite" 35 | create_option = "FromImage" 36 | managed_disk_type = "Premium_LRS" 37 | } 38 | 39 | storage_image_reference { 40 | publisher = "Canonical" 41 | offer = "UbuntuServer" 42 | sku = "16.04.0-LTS" 43 | version = "latest" 44 | } 45 | 46 | os_profile { 47 | computer_name = "linuxJump" 48 | admin_username = var.adminUserName 49 | admin_password = var.adminPassword 50 | custom_data = <<-EOF 51 | #!/bin/bash 52 | apt-get update -y; 53 | apt-get install -y docker.io; 54 | # demo app 55 | docker run -d -p 80:80 --net=host --restart unless-stopped -e F5DEMO_APP=website -e F5DEMO_NODENAME='F5 Azure' -e F5DEMO_COLOR=ffd734 -e F5DEMO_NODENAME_SSL='F5 Azure (SSL)' -e F5DEMO_COLOR_SSL=a0bf37 chen23/f5-demo-app:ssl; 56 | # juice shop 57 | docker run -d --restart always -p 3000:3000 bkimminich/juice-shop 58 | EOF 59 | } 60 | 61 | os_profile_linux_config { 62 | disable_password_authentication = false 63 | } 64 | 65 | tags = var.tags 66 | } 67 | -------------------------------------------------------------------------------- /jumpboxes/variables.tf: -------------------------------------------------------------------------------- 1 | # Instance Type 2 | 3 | variable instanceType {} 4 | 5 | # winjump 6 | variable winjumpip {} 7 | 8 | # linuxjump 9 | variable linuxjumpip {} 10 | 11 | variable timezone { default = "UTC" } 12 | 13 | # cloud 14 | variable location {} 15 | variable region {} 16 | variable prefix {} 17 | variable resourceGroup {} 18 | variable securityGroup { default = "none" } 19 | 20 | # network 21 | variable subnet {} 22 | 23 | # creds 24 | variable adminUserName {} 25 | variable adminPassword {} 26 | variable sshPublicKey {} 27 | 28 | # TAGS 29 | variable tags {} 30 | -------------------------------------------------------------------------------- /jumpboxes/windows.tf: -------------------------------------------------------------------------------- 1 | resource azurerm_network_interface winjump-ext-nic { 2 | name = "${var.prefix}-winjump-ext-nic" 3 | location = var.resourceGroup.location 4 | resource_group_name = var.resourceGroup.name 5 | 6 | ip_configuration { 7 | name = "primary" 8 | subnet_id = var.subnet.id 9 | private_ip_address_allocation = "Static" 10 | private_ip_address = var.winjumpip 11 | primary = true 12 | } 13 | 14 | tags = var.tags 15 | } 16 | 17 | resource "azurerm_network_interface_security_group_association" "winjump-ext-nsg" { 18 | network_interface_id = azurerm_network_interface.winjump-ext-nic.id 19 | network_security_group_id = var.securityGroup.id 20 | } 21 | 22 | resource azurerm_virtual_machine winJump { 23 | name = "${var.prefix}-winJump" 24 | resource_group_name = var.resourceGroup.name 25 | location = var.resourceGroup.location 26 | vm_size = var.instanceType 27 | network_interface_ids = [azurerm_network_interface.winjump-ext-nic.id] #Front-End Network 28 | 29 | os_profile_windows_config { 30 | provision_vm_agent = true 31 | timezone = var.timezone 32 | } 33 | 34 | storage_image_reference { 35 | publisher = "MicrosoftWindowsServer" 36 | offer = "WindowsServer" 37 | sku = "2016-Datacenter" 38 | version = "latest" 39 | } 40 | 41 | storage_os_disk { 42 | name = "${var.prefix}-winJump-os" 43 | caching = "ReadWrite" 44 | create_option = "FromImage" 45 | os_type = "Windows" 46 | } 47 | 48 | os_profile { 49 | computer_name = "winJump" 50 | admin_username = var.adminUserName 51 | admin_password = var.adminPassword 52 | custom_data = filebase64("./jumpboxes/DisableInternetExplorer-ESC.ps1") 53 | } 54 | 55 | tags = var.tags 56 | } 57 | 58 | resource azurerm_virtual_machine_extension winJump-run-startup-cmd { 59 | name = "${var.prefix}-winJump-run-startup-cmd" 60 | depends_on = [azurerm_virtual_machine.winJump] 61 | virtual_machine_id = azurerm_virtual_machine.winJump.id 62 | publisher = "Microsoft.Compute" 63 | type = "CustomScriptExtension" 64 | type_handler_version = "1.9" 65 | auto_upgrade_minor_version = true 66 | 67 | protected_settings = <> ./startup.b64 && cat ./startup.b64 | base64 -d >> ./startup-temp.sh && sed -e 's/\r$//' ./startup-temp.sh > ./startup-script.sh && chmod +x ./startup-script.sh && rm ./startup.b64 && bash ./startup-script.sh 1" 469 | } 470 | SETTINGS 471 | 472 | tags = var.tags 473 | } 474 | 475 | resource "azurerm_virtual_machine_extension" "f5vm02-run-startup-cmd" { 476 | name = "${var.prefix}-f5vm02-run-startup-cmd" 477 | depends_on = [azurerm_virtual_machine.f5vm01, azurerm_virtual_machine.f5vm02, azurerm_network_interface_backend_address_pool_association.mpool_assc_vm01, azurerm_network_interface_backend_address_pool_association.mpool_assc_vm02] 478 | virtual_machine_id = azurerm_virtual_machine.f5vm02.id 479 | publisher = "Microsoft.Azure.Extensions" 480 | type = "CustomScript" 481 | type_handler_version = "2.0" 482 | auto_upgrade_minor_version = true 483 | 484 | settings = <> ./startup.b64 && cat ./startup.b64 | base64 -d >> ./startup-temp.sh && sed -e 's/\r$//g' ./startup-temp.sh > ./startup-script.sh && chmod +x ./startup-script.sh && rm ./startup.b64 && bash ./startup-script.sh 2" 488 | } 489 | SETTINGS 490 | 491 | tags = var.tags 492 | } 493 | 494 | 495 | # Debug Template Outputs 496 | resource "local_file" "vm01_do_file" { 497 | content = data.template_file.vm01_do_json.rendered 498 | filename = "${path.module}/vm01_do_data.json" 499 | } 500 | 501 | resource "local_file" "vm02_do_file" { 502 | content = data.template_file.vm02_do_json.rendered 503 | filename = "${path.module}/vm02_do_data.json" 504 | } 505 | 506 | resource "local_file" "vm_as3_file" { 507 | content = data.template_file.as3_json.rendered 508 | filename = "${path.module}/vm_as3_data.json" 509 | } 510 | 511 | resource "local_file" "onboard_file" { 512 | content = data.template_file.vm_onboard.rendered 513 | filename = "${path.module}/onboard.sh" 514 | } 515 | -------------------------------------------------------------------------------- /one_tier/firewall/ilb.tf: -------------------------------------------------------------------------------- 1 | # Create the ILB for South LB and Egress 2 | resource "azurerm_lb" "internalLoadBalancer" { 3 | name = "${var.prefix}-internalloadbalancer" 4 | location = var.location 5 | resource_group_name = var.resourceGroup.name 6 | sku = "Standard" 7 | 8 | frontend_ip_configuration { 9 | name = "internalLoadBalancerFrontEnd" 10 | subnet_id = var.subnetInternal.id 11 | private_ip_address = var.ilb01ip 12 | private_ip_address_allocation = "Static" 13 | private_ip_address_version = "IPv4" 14 | } 15 | } 16 | 17 | # Create the LB Pool for ILB 18 | resource "azurerm_lb_backend_address_pool" "internal_backend_pool" { 19 | name = "InternalBackendPool1" 20 | #resource_group_name = var.resourceGroup.name 21 | loadbalancer_id = azurerm_lb.internalLoadBalancer.id 22 | } 23 | 24 | # attach interfaces to backend pool 25 | resource "azurerm_network_interface_backend_address_pool_association" "int_bpool_assc_vm01" { 26 | network_interface_id = azurerm_network_interface.vm01-int-nic.id 27 | ip_configuration_name = "secondary" 28 | backend_address_pool_id = azurerm_lb_backend_address_pool.internal_backend_pool.id 29 | } 30 | 31 | resource "azurerm_network_interface_backend_address_pool_association" "int_bpool_assc_vm02" { 32 | network_interface_id = azurerm_network_interface.vm02-int-nic.id 33 | ip_configuration_name = "secondary" 34 | backend_address_pool_id = azurerm_lb_backend_address_pool.internal_backend_pool.id 35 | } 36 | 37 | resource "azurerm_lb_probe" "internal_tcp_probe" { 38 | #resource_group_name = var.resourceGroup.name 39 | loadbalancer_id = azurerm_lb.internalLoadBalancer.id 40 | name = "${var.prefix}-internal-tcp-probe" 41 | protocol = "Tcp" 42 | port = 34568 43 | interval_in_seconds = 5 44 | number_of_probes = 2 45 | } 46 | 47 | resource "azurerm_lb_rule" "internal_all_rule" { 48 | name = "all-protocol-ilb" 49 | #resource_group_name = var.resourceGroup.name 50 | loadbalancer_id = azurerm_lb.internalLoadBalancer.id 51 | protocol = "All" 52 | frontend_port = 0 53 | backend_port = 0 54 | load_distribution = "SourceIPProtocol" 55 | frontend_ip_configuration_name = "internalLoadBalancerFrontEnd" 56 | enable_floating_ip = true 57 | backend_address_pool_ids = [azurerm_lb_backend_address_pool.internal_backend_pool.id] 58 | #backend_address_pool_id = azurerm_lb_backend_address_pool.internal_backend_pool.id 59 | idle_timeout_in_minutes = 5 60 | probe_id = azurerm_lb_probe.internal_tcp_probe.id 61 | depends_on = [azurerm_lb_probe.internal_tcp_probe] 62 | } 63 | -------------------------------------------------------------------------------- /one_tier/firewall/outputs.tf: -------------------------------------------------------------------------------- 1 | # data azurerm_public_ip f5vmpip01 { 2 | # name = azurerm_public_ip.f5vmpip01.name 3 | # resource_group_name = var.resourceGroup.name 4 | # depends_on = [azurerm_public_ip.f5vmpip01, azurerm_virtual_machine.f5vm01] 5 | # } 6 | # data azurerm_public_ip f5vmpip02 { 7 | # name = azurerm_public_ip.f5vmpip02.name 8 | # resource_group_name = var.resourceGroup.name 9 | # depends_on = [azurerm_public_ip.f5vmpip02, azurerm_virtual_machine.f5vm02] 10 | # } 11 | 12 | 13 | output f5vm01_id { value = azurerm_virtual_machine.f5vm01.id } 14 | output f5vm01_mgmt_private_ip { value = azurerm_network_interface.vm01-mgmt-nic.private_ip_address } 15 | #output f5vm01_mgmt_public_ip { value = data.azurerm_public_ip.f5vmpip01.ip_address } 16 | output f5vm01_ext_private_ip { value = azurerm_network_interface.vm01-ext-nic.private_ip_address } 17 | 18 | output f5vm02_id { value = azurerm_virtual_machine.f5vm02.id } 19 | output f5vm02_mgmt_private_ip { value = azurerm_network_interface.vm02-mgmt-nic.private_ip_address } 20 | #output f5vm02_mgmt_public_ip { value = data.azurerm_public_ip.f5vmpip02.ip_address } 21 | output f5vm02_ext_private_ip { value = azurerm_network_interface.vm02-ext-nic.private_ip_address } 22 | -------------------------------------------------------------------------------- /one_tier/firewall/variables.tf: -------------------------------------------------------------------------------- 1 | variable resourceGroup {} 2 | # admin credentials 3 | variable adminUserName {} 4 | variable adminPassword {} 5 | variable sshPublicKey {} 6 | # cloud info 7 | variable location {} 8 | variable region {} 9 | variable securityGroup { 10 | default = "none" 11 | } 12 | variable availabilitySet {} 13 | variable availabilitySet2 {} 14 | 15 | variable subnets {} 16 | 17 | variable prefix {} 18 | # bigip network 19 | variable subnetMgmt {} 20 | variable subnetExternal {} 21 | variable subnetInternal {} 22 | variable backendPool {} 23 | variable managementPool {} 24 | variable primaryPool {} 25 | 26 | variable app01ip {} 27 | 28 | variable ilb01ip {} 29 | 30 | variable f5_mgmt {} 31 | variable f5_t1_ext {} 32 | variable f5_t1_int {} 33 | 34 | # winjump 35 | variable winjumpip {} 36 | 37 | # linuxjump 38 | variable linuxjumpip {} 39 | 40 | # device 41 | variable instanceType {} 42 | 43 | 44 | # BIGIP Image 45 | variable image_name {} 46 | variable product {} 47 | variable bigip_version {} 48 | 49 | variable cidr {} 50 | 51 | # BIGIP Setup 52 | variable licenses { 53 | type = map(string) 54 | default = { 55 | "license1" = "" 56 | "license2" = "" 57 | "license3" = "" 58 | "license4" = "" 59 | } 60 | } 61 | variable hosts {} 62 | variable dns_server {} 63 | variable ntp_server {} 64 | variable timezone {} 65 | variable onboard_log { default = "/var/log/startup-script.log" } 66 | variable asm_policy {} 67 | 68 | # TAGS 69 | variable tags {} 70 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | ## OUTPUTS ### 2 | 3 | # output sg_id { 4 | # value = azurerm_network_security_group.main.id 5 | # description = "Network Security Group ID" 6 | # } 7 | # output sg_name { 8 | # value = azurerm_network_security_group.main.name 9 | # description = "Network Security Group Name" 10 | # } 11 | 12 | output DemoApplication_443 { 13 | value = "https://${azurerm_public_ip.lbpip.ip_address}" 14 | description = "Public IP for applications. Https for example app, RDP for Windows Jumpbox, SSH for Linux Jumpbox" 15 | } 16 | output rSyslogdHttp_8080 { 17 | value = "http://${azurerm_public_ip.lbpip.ip_address}:8080" 18 | description = "Public IP for applications. Https for example app, RDP for Windows Jumpbox, SSH for Linux Jumpbox" 19 | } 20 | 21 | locals { 22 | one_tier = var.deploymentType == "one_tier" ? try({ 23 | #f5vm01_id = try(module.firewall_one[0].f5vm01_id, "none") 24 | f5vm01_mgmt_private_ip = try(module.firewall_one[0].f5vm01_mgmt_private_ip, "none") 25 | f5vm01_mgmt_public_ip = "https://${try(module.firewall_one[0].f5vm01_mgmt_public_ip, "none")}" 26 | f5vm01_ext_private_ip = try(module.firewall_one[0].f5vm01_ext_private_ip, "none") 27 | # 28 | #f5vm02_id = try(module.firewall_one[0].f5vm02_id, "none") 29 | f5vm02_mgmt_private_ip = try(module.firewall_one[0].f5vm02_mgmt_private_ip, "none") 30 | f5vm02_mgmt_public_ip = "https://${try(module.firewall_one[0].f5vm02_mgmt_public_ip, "none")}" 31 | f5vm02_ext_private_ip = try(module.firewall_one[0].f5vm02_ext_private_ip, "none") 32 | }) : { none = "none" } 33 | three_tier = var.deploymentType == "three_tier" ? try( 34 | { 35 | #f5vm01_id = try(module.firewall_three[0].f5vm01_id, "none") 36 | f5vm01_mgmt_private_ip = try(module.firewall_three[0].f5vm01_mgmt_private_ip, "none") 37 | f5vm01_mgmt_public_ip = "https://${try(module.firewall_three[0].f5vm01_mgmt_public_ip, "none")}" 38 | f5vm01_ext_private_ip = try(module.waf_three[0].f5vm01_ext_private_ip, "none") 39 | # 40 | #f5vm02_id = try(module.firewall_three[0].f5vm02_id, "none") 41 | f5vm02_mgmt_private_ip = try(module.firewall_three[0].f5vm02_mgmt_private_ip, "none") 42 | f5vm02_mgmt_public_ip = "https://${try(module.firewall_three[0].f5vm02_mgmt_public_ip, "none")}" 43 | f5vm02_ext_private_ip = try(module.waf_three[0].f5vm02_ext_private_ip, "none") 44 | # 45 | #f5vm03_id = try(module.waf_three[0].f5vm03_id, "none") 46 | f5vm03_mgmt_private_ip = try(module.waf_three[0].f5vm03_mgmt_private_ip, "none") 47 | f5vm03_mgmt_public_ip = "https://${try(module.waf_three[0].f5vm03_mgmt_public_ip, "none")}" 48 | f5vm03_ext_private_ip = try(module.waf_three[0].f5vm03_ext_private_ip, "none") 49 | # 50 | #f5vm04_id = try(module.waf_three[0].f5vm04_id, "none") 51 | f5vm04_mgmt_private_ip = try(module.waf_three[0].f5vm04_mgmt_private_ip, "none") 52 | f5vm04_mgmt_public_ip = "https://${try(module.waf_three[0].f5vm04_mgmt_public_ip, "none")}" 53 | f5vm04_ext_private_ip = try(module.waf_three[0].f5vm04_ext_private_ip, "none") 54 | 55 | #"${try(odule.waf_three[0].f5vm04_mgmt_public_ip , "none")}" 56 | }) : { none = "none" } 57 | } 58 | 59 | # single tier 60 | output tier_one { 61 | value = local.one_tier 62 | description = "One Tier Outputs: VM IDs, VM Mgmt IPs, VM External Private IPs" 63 | } 64 | # three tier 65 | output tier_three { 66 | value = local.three_tier 67 | description = "Three Tier Outputs: VM IDs, VM Mgmt IPs, VM External Private IPs" 68 | } 69 | -------------------------------------------------------------------------------- /prepare/setupAzureGovVars_local.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #Need to check OS / Platform 4 | osName=`uname -s` 5 | case $osName in 6 | Linux*) export machine="Linux" ;; 7 | Darwin*) export machine="Mac" ;; 8 | *) export machine="UNKNOWN:$osName" ;; 9 | esac 10 | 11 | echo $machine 12 | 13 | if [[ "$machine" == "Mac" ]]; then 14 | echo "OSX Detected, need to Install / Update Brew and jq..." 15 | #Need to update brew and make sure jq is installed to process json 16 | echo "updating & upgrading brew..." 17 | brew update || brew update 18 | brew upgrade 19 | 20 | if brew ls --versions jq > /dev/null; then 21 | # The package is installed 22 | echo "jq installed proceeding..." 23 | else 24 | echo "installing jq..." 25 | brew install jq 26 | fi 27 | elif [[ "$machine" == "Linux" ]]; then 28 | if [ -f /etc/redhat-release ]; then 29 | yum -y update 30 | yum -y install jq 31 | fi 32 | if [ -f /etc/lsb-release ]; then 33 | apt-get --assume-yes update 34 | apt-get --assume-yes install jq 35 | fi 36 | fi 37 | 38 | #Map Subscription 39 | export ARM_SUBSCRIPTION_ID=`az account show | jq -r '.id'` 40 | 41 | #Create ServicePrincipal for ClientID and Secret 42 | spn=`az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/$ARM_SUBSCRIPTION_ID" --name http://sccaServicePrincipalName` 43 | 44 | echo "Setting environment variables for Terraform" 45 | export ARM_CLIENT_ID=`echo $spn | jq -r '.appId'` 46 | echo $spn | jq -r '.appId' 47 | export ARM_CLIENT_SECRET=`echo $spn | jq -r '.password'` 48 | echo $spn | jq -r '.password' 49 | export ARM_TENANT_ID=`az account show | jq -r '.tenantId'` 50 | az account show | jq -r '.tenantId' 51 | 52 | # Not needed for public, required for usgovernment, german, china 53 | #export ARM_ENVIRONMENT=`az account show | jq -r '.environmentName'` 54 | export ARM_ENVIRONMENT="usgovernment" 55 | 56 | # Accept terms for programatic deployment of images 57 | az vm image terms accept --offer f5-big-ip-byol --publisher f5-networks --plan f5-big-ip-byol 58 | az vm image terms accept --offer f5-big-ip-best --publisher f5-networks --plan f5-big-ip-best 59 | -------------------------------------------------------------------------------- /prepare/setupAzureGovVars_vault.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Change these variables according to your needs 4 | RESOURCE_GROUP_NAME=tfstate 5 | STORAGE_ACCOUNT_NAME=tfstate$RANDOM 6 | CONTAINER_NAME=tfstate 7 | VAULT_NAME=sccaKeyVault$RANDOM 8 | SECRET_NAME=sccaSecret 9 | 10 | #Map Subscription 11 | export ARM_SUBSCRIPTION_ID=`az account show | jq -r '.id'` 12 | 13 | #Create ServicePrincipal for ClientID and Secret 14 | spn=`az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/$ARM_SUBSCRIPTION_ID" --name http://sccaServicePrincipalName` 15 | 16 | # Create resource group 17 | az group create --name $RESOURCE_GROUP_NAME --location usgovvirginia 18 | 19 | # Create storage account 20 | az storage account create --resource-group $RESOURCE_GROUP_NAME --name $STORAGE_ACCOUNT_NAME --sku Standard_LRS --encryption-services blob 21 | 22 | # Get storage account key 23 | ACCOUNT_KEY=$(az storage account keys list --resource-group $RESOURCE_GROUP_NAME --account-name $STORAGE_ACCOUNT_NAME --query [0].value -o tsv) 24 | 25 | # Create blob container 26 | az storage container create --name $CONTAINER_NAME --account-name $STORAGE_ACCOUNT_NAME --account-key $ACCOUNT_KEY 27 | 28 | # Create Azure KeyVault 29 | az keyvault create -g $RESOURCE_GROUP_NAME --name $VAULT_NAME 30 | 31 | # Set Azure KeyVault Secret value to storage account key 32 | az keyvault secret set --vault-name $VAULT_NAME --name $SECRET_NAME --value $ACCOUNT_KEY 33 | 34 | echo "Setting environment variables for Terraform" 35 | export ARM_SUBSCRIPTION_ID=$ARM_SUBSCRIPTION_ID 36 | export ARM_CLIENT_ID=`echo $spn | jq -r '.appId'` 37 | export ARM_CLIENT_SECRET=`echo $spn | jq -r '.password'` 38 | export ARM_TENANT_ID=`az account show | jq -r '.tenantId'` 39 | export ARM_ACCESS_KEY=$(az keyvault secret show --name $SECRET_NAME --vault-name $VAULT_NAME --query value -o tsv) 40 | 41 | # Not needed for public, required for usgovernment, german, china 42 | #export ARM_ENVIRONMENT=`az account show | jq -r '.environmentName'` 43 | export ARM_ENVIRONMENT="usgovernment" 44 | -------------------------------------------------------------------------------- /prepare/setupAzureVars.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #Need to check OS / Platform 4 | osName=`uname -s` 5 | case $osName in 6 | Linux*) export machine=Linux;; 7 | Darwin*) export machine=Mac;; 8 | *) export machine="UNKNOWN:$osName" 9 | esac 10 | 11 | if [ $machine == "Mac" ]; then 12 | echo "OSX Detected, need to Install / Update Brew and jq..." 13 | #Need to update brew and make sure jq is installed to process json 14 | echo "updating & upgrading brew..." 15 | brew update || brew update 16 | brew upgrade 17 | 18 | if brew ls --versions jq > /dev/null; then 19 | # The package is installed 20 | echo "jq installed proceeding..." 21 | else 22 | echo "installing jq..." 23 | brew install jq 24 | fi 25 | elif [ $machine == "Linux" ]; then 26 | if [ -f /etc/redhat-release ]; then 27 | yum -y update 28 | yum -y install jq 29 | fi 30 | if [ -f /etc/lsb-release ]; then 31 | apt-get --assume-yes update 32 | apt-get --assume-yes install jq 33 | fi 34 | fi 35 | 36 | az cloud set --name AzureUSGovernment 37 | 38 | az login --use-device-code 39 | 40 | #Create ServicePrincipal for ClientID and Secret 41 | spn=`az ad sp create-for-rbac --name scaServicePrincipalName` 42 | 43 | echo "Setting environment variables for Terraform" 44 | export ARM_SUBSCRIPTION_ID=`az account show | jq -r '.id'` 45 | export ARM_CLIENT_ID=`echo $spn | jq -r '.appId'` 46 | export ARM_CLIENT_SECRET=`echo $spn | jq -r '.password'` 47 | export ARM_TENANT_ID=`az account show | jq -r '.tenantId'` 48 | 49 | # Not needed for public, required for usgovernment, german, china 50 | export ARM_ENVIRONMENT=`az account show | jq -r '.environmentName'` 51 | -------------------------------------------------------------------------------- /providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | version = "3.46.0" 6 | } 7 | http = { 8 | source = "hashicorp/http" 9 | version = "2.1.0" 10 | } 11 | } 12 | } 13 | 14 | provider "azurerm" { 15 | # Configuration options 16 | features { 17 | resource_group { 18 | prevent_deletion_if_contains_resources = false 19 | } 20 | } 21 | } 22 | 23 | 24 | provider "http" {} 25 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Sphinx<2.0 2 | git+git://github.com/f5devcentral/f5-sphinx-theme@master#egg=f5_sphinx_theme 3 | recommonmark 4 | sphinxcontrib-googleanalytics 5 | sphinxcontrib-addmetahtml 6 | sphinxcontrib-nwdiag 7 | sphinxcontrib-blockdiag 8 | -------------------------------------------------------------------------------- /templates/ips-cloud-init.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | 3 | write_files: 4 | - path: /etc/rsyslog.d/10-rsyslog.conf 5 | content: | 6 | *.* @${log_destination}:514 7 | - path: /etc/networkd-dispatcher/routable.d/10-ifup-hooks 8 | content: | 9 | #!/bin/sh 10 | # ifconfig $IFACE 0.0.0.0 up 11 | # ip link set $IFACE promisc on 12 | sudo iptables -I FORWARD -i eth1 -o eth2 -j NFQUEUE --queue-num=4 13 | sudo iptables -I FORWARD -i eth2 -o eth1 -j NFQUEUE --queue-num=4 14 | exit 0 15 | - path: /etc/networkd-dispatcher/routable.d/50-postup-hooks 16 | content: | 17 | #!/bin/sh 18 | if [ $IFACE != "eth0"] 19 | ethtool -K $IFACE gro off lro off 20 | fi 21 | exit 0 22 | - path: /etc/networkd-dispatcher/dormant.d/promisc_bridge 23 | content: | 24 | #!/bin/sh 25 | set -e 26 | if [ $IFACE != "eth0"] 27 | ip link set eth1 up promisc on 28 | ip link set eth2 up promisc on 29 | fi 30 | exit 0 31 | - path: /etc/networkd-dispatcher/off.d/50-ifdown-hooks 32 | content: | 33 | #!/bin/sh 34 | ip link set $IFACE promisc off 35 | ifconfig $IFACE down 36 | exit 0 37 | - path: /lib/systemd/system/snort.service 38 | content: | 39 | [Unit] 40 | Description=Snort NIDS Daemon 41 | After=syslog.target network.target 42 | [Service] 43 | Type=simple 44 | ExecStart=/usr/sbin/snort -D -c /etc/snort/snort.conf -Q 45 | [Install] 46 | WantedBy=multi-user.target 47 | 48 | apt: 49 | primary: 50 | - arches: [default] 51 | search_dns: True 52 | package_upgrade: true 53 | packages: 54 | - build-essential 55 | - bridge-utils 56 | - libpcap-dev 57 | - libpcre3-dev 58 | - libdumbnet-dev 59 | - bison 60 | - flex 61 | - zlib1g-dev 62 | - liblzma-dev 63 | - openssl 64 | - libssl-dev 65 | - ethtool 66 | - autoconf 67 | - libtool 68 | - libtool-bin 69 | - pkg-config 70 | - gcc 71 | - zlib1g-dev 72 | - libluajit-5.1-dev 73 | - libnghttp2-dev 74 | - libdnet 75 | - git 76 | - libcrypt-ssleay-perl 77 | - liblwp-useragent-determined-perl 78 | - libnetfilter-queue-dev 79 | 80 | runcmd: 81 | - sudo chmod +x /etc/networkd-dispatcher/routable.d/10-ifup-hooks 82 | - sudo chmod +x /etc/networkd-dispatcher/routable.d/50-postup-hooks 83 | - sudo chmod +x /etc/networkd-dispatcher/dormant.d/promisc_bridge 84 | - sudo chmod +x /etc/networkd-dispatcher/off.d/50-ifdown-hooks 85 | - sudo echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf 86 | - sudo apt autoremove -y 87 | - sudo mkdir -p /etc/snort/rules 88 | - sudo chmod -R 5775 /etc/snort 89 | - sudo mkdir /var/log/snort 90 | - sudo chmod -R 5775 /var/log/snort 91 | - sudo mkdir -p /home/root/snort_src 92 | - cd /home/root/snort_src 93 | - [wget, "https://www.snort.org/downloads/snort/daq-2.0.7.tar.gz"] 94 | - [wget, "https://www.snort.org/downloads/archive/snort/snort-2.9.16.1.tar.gz"] 95 | - [wget, "https://www.snort.org/downloads/community/community-rules.tar.gz"] 96 | - git clone https://github.com/John-Lin/docker-snort.git 97 | - tar -xvzf daq-2.0.7.tar.gz 98 | - tar -xvzf snort-2.9.16.1.tar.gz 99 | - tar -xvzf community-rules.tar.gz 100 | - cd /home/root/snort_src/daq-2.0.7 101 | - autoreconf -f -i 102 | - ./configure 103 | - make 104 | - sudo make install 105 | - cd /home/root/snort_src/snort-2.9.16.1 106 | - autoreconf -f -i 107 | - ./configure --enable-sourcefire 108 | - make 109 | - sudo make install 110 | - sudo ldconfig 111 | - sudo ln -s /usr/local/bin/snort /usr/sbin/snort 112 | - sudo mkdir -p /usr/local/lib/snort_dynamicrules 113 | - sudo cp /home/root/snort_src/snort-2.9.16.1/etc/* /etc/snort/ 114 | - sudo touch /etc/snort/rules/white_list.rules /etc/snort/rules/black_list.rules 115 | - sudo cp /home/root/snort_src/docker-snort/snortrules-snapshot-2972/rules/* /etc/snort/rules 116 | - sudo echo "config policy_mode:inline" >> /etc/snort/snort.conf 117 | - sudo sed -i 's/..\/rules/\/etc\/snort\/rules/g' /etc/snort/snort.conf 118 | - "sudo sed -i 's/# config daq: /config daq: nfq/g' /etc/snort/snort.conf" 119 | - "sudo sed -i 's/# config daq_mode: /config daq_mode: inline/g' /etc/snort/snort.conf" 120 | - "sudo sed -i 's/# config daq_var: /config daq_var: queue=4/g' /etc/snort/snort.conf" 121 | - sudo echo 'alert icmp any any -> $HOME_NET any (msg:"ICMP test detected"; GID:1; sid:10000001; rev:001; classtype:icmp-event;)' >> /home/root/local.rules 122 | - sudo rm -rf /etc/snort/rules/local.rules 123 | - sudo cp /home/root/local.rules /etc/snort/rules/local.rules 124 | - sudo sysctl -p 125 | - sudo route add -net ${wafSubnetPrefix} netmask ${internalMask} gw ${wafGateway} 126 | - sudo route add -net ${internalSubnetPrefix} netmask ${wafMask} gw ${internalGateway} 127 | - sudo iptables -I FORWARD -i eth1 -o eth2 -j NFQUEUE --queue-num=4 128 | - sudo iptables -I FORWARD -i eth2 -o eth1 -j NFQUEUE --queue-num=4 129 | - sudo systemctl enable snort 130 | - sudo systemctl start snort 131 | #- sudo snort -D -c /etc/snort/snort.conf -Q 132 | 133 | final_message: "The system is finally up, after $UPTIME seconds" 134 | -------------------------------------------------------------------------------- /templates/onboard.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # vars 4 | # 5 | # get device id for do 6 | deviceId=$1 7 | # 8 | admin_username='${uname}' 9 | admin_password='${upassword}' 10 | CREDS="$admin_username:$admin_password" 11 | LOG_FILE=${onboard_log} 12 | # constants 13 | mgmt_port=`tmsh list sys httpd ssl-port | grep ssl-port | sed 's/ssl-port //;s/ //g'` 14 | authUrl="/mgmt/shared/authn/login" 15 | rpmInstallUrl="/mgmt/shared/iapp/package-management-tasks" 16 | rpmFilePath="/var/config/rest/downloads" 17 | local_host="http://localhost:8100" 18 | # do 19 | doUrl="/mgmt/shared/declarative-onboarding" 20 | doCheckUrl="/mgmt/shared/declarative-onboarding/info" 21 | doTaskUrl="/mgmt/shared/declarative-onboarding/task" 22 | # as3 23 | as3Url="/mgmt/shared/appsvcs/declare" 24 | as3CheckUrl="/mgmt/shared/appsvcs/info" 25 | as3TaskUrl="/mgmt/shared/appsvcs/task/" 26 | # ts 27 | tsUrl="/mgmt/shared/telemetry/declare" 28 | tsCheckUrl="/mgmt/shared/telemetry/info" 29 | # cloud failover ext 30 | cfUrl="/mgmt/shared/cloud-failover/declare" 31 | cfCheckUrl="/mgmt/shared/cloud-failover/info" 32 | # fast 33 | fastCheckUrl="/mgmt/shared/fast/info" 34 | # declaration content 35 | cat > /config/do1.json < /config/do2.json < /config/as3.json <>$LOG_FILE 56 | else 57 | #if file exists, exit as only want to run once 58 | exit 59 | fi 60 | 61 | exec 1>$LOG_FILE 2>&1 62 | 63 | startTime=$(date +%s) 64 | echo "start device ID:$deviceId date: $(date)" 65 | function timer () { 66 | echo "Time Elapsed: $(( ${1} / 3600 ))h $(( (${1} / 60) % 60 ))m $(( ${1} % 60 ))s" 67 | } 68 | waitMcpd () { 69 | checks=0 70 | while [[ "$checks" -lt 120 ]]; do 71 | tmsh -a show sys mcp-state field-fmt | grep -q running 72 | if [ $? == 0 ]; then 73 | echo "[INFO: mcpd ready]" 74 | break 75 | fi 76 | echo "[WARN: mcpd not ready yet]" 77 | let checks=checks+1 78 | sleep 10 79 | done 80 | } 81 | waitActive () { 82 | checks=0 83 | while [[ "$checks" -lt 30 ]]; do 84 | tmsh -a show sys ready | grep -q no 85 | if [ $? == 1 ]; then 86 | echo "[INFO: system ready]" 87 | break 88 | fi 89 | echo "[WARN: system not ready yet count: $checks]" 90 | tmsh -a show sys ready | grep no 91 | let checks=checks+1 92 | sleep 10 93 | done 94 | } 95 | # CHECK TO SEE NETWORK IS READY 96 | count=0 97 | while true 98 | do 99 | STATUS=$(curl -s -k -I example.com | grep HTTP) 100 | if [[ $STATUS == *"200"* ]]; then 101 | echo "[INFO: internet access check passed]" 102 | break 103 | elif [ $count -le 6 ]; then 104 | echo "Status code: $STATUS Not done yet..." 105 | count=$[$count+1] 106 | else 107 | echo "[WARN: GIVE UP...]" 108 | break 109 | fi 110 | sleep 10 111 | done 112 | # download latest atc tools 113 | toolsList=$(cat -</dev/null 2>&1 <<<"$code"; then 413 | echo "Parsed JSON successfully and got something other than false/null count: $taskCount" 414 | status=$(curl -s -u $CREDS $local_host$doTaskUrl/$task | jq -r .result.status) 415 | sleep 1 416 | echo "status: $status code: $code" 417 | # 200,202,422,400,404,500,422 418 | echo "DO: $task response:$code status:$status" 419 | sleep 1 420 | #FINISHED,STARTED,RUNNING,ROLLING_BACK,FAILED,ERROR,NULL 421 | case $status in 422 | FINISHED) 423 | # finished 424 | echo " $task status: $status " 425 | # bigstart start dhclient 426 | break 2 427 | ;; 428 | STARTED) 429 | # started 430 | echo " $filename status: $status " 431 | sleep 30 432 | ;; 433 | RUNNING) 434 | # running 435 | echo "DO Status: $status task: $task Not done yet...count:$taskCount" 436 | # wait for active-online-state 437 | waitMcpd 438 | if [[ "$taskCount" -le 5 ]]; then 439 | sleep 60 440 | fi 441 | waitActive 442 | #sleep 120 443 | taskCount=$[$taskCount+1] 444 | ;; 445 | FAILED) 446 | # failed 447 | error=$(curl -s -u $CREDS $local_host$doTaskUrl/$task | jq -r .result.status) 448 | echo "failed $task, $error" 449 | #count=$[$count+1] 450 | break 451 | ;; 452 | ERROR) 453 | # error 454 | error=$(curl -s -u $CREDS $local_host$doTaskUrl/$task | jq -r .result.status) 455 | echo "Error $task, $error" 456 | #count=$[$count+1] 457 | break 458 | ;; 459 | ROLLING_BACK) 460 | # Rolling back 461 | echo "Rolling back failed status: $status task: $task" 462 | break 463 | ;; 464 | OK) 465 | # complete no change 466 | echo "Complete no change status: $status task: $task" 467 | break 2 468 | ;; 469 | *) 470 | # other 471 | echo "other: $status" 472 | echo "other task: $task count: $taskCount" 473 | debug=$(curl -s -u $CREDS $local_host$doTaskUrl/$task) 474 | echo "other debug: $debug" 475 | case $debug in 476 | *not*registered*) 477 | # restnoded response DO api is unresponsive 478 | echo "DO endpoint not avaliable waiting..." 479 | sleep 30 480 | ;; 481 | *resterrorresponse*) 482 | # restnoded response DO api is unresponsive 483 | echo "DO endpoint not avaliable waiting..." 484 | sleep 30 485 | ;; 486 | *start-limit*) 487 | # dhclient issue hit 488 | echo " do dhclient starting issue hit start another task" 489 | break 490 | ;; 491 | esac 492 | sleep 30 493 | taskCount=$[$taskCount+1] 494 | ;; 495 | esac 496 | else 497 | echo "Failed to parse JSON, or got false/null" 498 | echo "DO status code: $code" 499 | debug=$(curl -s -u $CREDS $local_host$doTaskUrl/$task) 500 | echo "debug DO code: $debug" 501 | count=$[$count+1] 502 | fi 503 | done 504 | done 505 | } 506 | # mgmt 507 | echo "set management" 508 | echo -e "create cli transaction; 509 | modify sys global-settings mgmt-dhcp disabled; 510 | submit cli transaction" | tmsh -q 511 | tmsh save /sys config 512 | # get as3 values 513 | externalVip=$(curl -sf --retry 20 -H Metadata:true "http://169.254.169.254/metadata/instance/network/interface?api-version=2017-08-01" | jq -r '.[1].ipv4.ipAddress[1].privateIpAddress') 514 | 515 | # end get values 516 | 517 | # run DO 518 | echo "----run do----" 519 | count=0 520 | while [ $count -le 4 ] 521 | do 522 | doStatus=$(checkDO) 523 | echo "DO check status: $doStatus" 524 | if [ $deviceId == 1 ] && [[ "$doStatus" = *"online"* ]]; then 525 | echo "running do for id:$deviceId" 526 | bigstart stop dhclient 527 | runDO do1.json 528 | if [ "$?" == 0 ]; then 529 | echo "done with do" 530 | bigstart start dhclient 531 | results=$(restcurl -u $CREDS -X GET $doTaskUrl | jq '.[] | .id, .result') 532 | echo "do results: $results" 533 | break 534 | fi 535 | elif [ $deviceId == 2 ] && [[ "$doStatus" = *"online"* ]]; then 536 | echo "running do for id:$deviceId" 537 | bigstart stop dhclient 538 | runDO do2.json 539 | if [ "$?" == 0 ]; then 540 | echo "done with do" 541 | bigstart start dhclient 542 | results=$(restcurl -u $CREDS -X GET $doTaskUrl | jq '.[] | .id, .result') 543 | echo "do results: $results" 544 | break 545 | fi 546 | elif [ $count -le 2 ]; then 547 | echo "DeviceID: $deviceId Status code: $doStatus DO not ready yet..." 548 | count=$[$count+1] 549 | sleep 30 550 | else 551 | echo "DO not online status: $doStatus" 552 | break 553 | fi 554 | done 555 | function runAS3 () { 556 | count=0 557 | while [ $count -le 4 ] 558 | do 559 | # wait for do to finish 560 | waitActive 561 | # make task 562 | task=$(curl -s -u $CREDS -H "Content-Type: Application/json" -H 'Expect:' -X POST $local_host$as3Url?async=true -d @/config/as3.json | jq -r .id) 563 | echo "===== starting as3 task: $task =====" 564 | sleep 1 565 | count=$[$count+1] 566 | # check task code 567 | taskCount=0 568 | while [ $taskCount -le 3 ] 569 | do 570 | as3CodeType=$(curl -s -u $CREDS -X GET $local_host$as3TaskUrl/$task | jq -r type ) 571 | if [[ "$as3CodeType" == "object" ]]; then 572 | code=$(curl -s -u $CREDS -X GET $local_host$as3TaskUrl/$task | jq -r .) 573 | tenants=$(curl -s -u $CREDS -X GET $local_host$as3TaskUrl/$task | jq -r .results[].tenant) 574 | echo "object: $code" 575 | elif [ "$as3CodeType" == "array" ]; then 576 | echo "array $code check task, breaking" 577 | break 578 | else 579 | echo "unknown type:$as3CodeType" 580 | fi 581 | sleep 1 582 | if jq -e . >/dev/null 2>&1 <<<"$code"; then 583 | echo "Parsed JSON successfully and got something other than false/null" 584 | status=$(curl -s -u $CREDS $local_host$as3TaskUrl/$task | jq -r .items[].results[].message) 585 | case $status in 586 | *progress) 587 | # in progress 588 | echo -e "Running: $task status: $status tenants: $tenants count: $taskCount " 589 | sleep 120 590 | taskCount=$[$taskCount+1] 591 | ;; 592 | *Error*) 593 | # error 594 | echo -e "Error Task: $task status: $status tenants: $tenants " 595 | if [[ "$status" = *"progress"* ]]; then 596 | sleep 180 597 | break 598 | else 599 | break 600 | fi 601 | ;; 602 | *failed*) 603 | # failed 604 | echo -e "failed: $task status: $status tenants: $tenants " 605 | break 606 | ;; 607 | *success*) 608 | # successful! 609 | echo -e "success: $task status: $status tenants: $tenants " 610 | break 3 611 | ;; 612 | no*change) 613 | # finished 614 | echo -e "no change: $task status: $status tenants: $tenants " 615 | break 4 616 | ;; 617 | *) 618 | # other 619 | echo "status: $status" 620 | debug=$(curl -s -u $CREDS $local_host$as3TaskUrl/$task) 621 | echo "debug: $debug" 622 | error=$(curl -s -u $CREDS $local_host$as3TaskUrl/$task | jq -r '.results[].message') 623 | echo "Other: $task, $error" 624 | break 625 | ;; 626 | esac 627 | else 628 | echo "Failed to parse JSON, or got false/null" 629 | echo "AS3 status code: $code" 630 | debug=$(curl -s -u $CREDS $local_host$doTaskUrl/$task) 631 | echo "debug AS3 code: $debug" 632 | count=$[$count+1] 633 | fi 634 | done 635 | done 636 | } 637 | 638 | # modify as3 639 | #sdToken=$(echo "$token" | base64) 640 | sed -i "s/-external-virtual-address-/$externalVip/g" /config/as3.json 641 | #sed -i "s/-sd-sa-token-b64-/$token/g" /config/as3.json 642 | # end modify as3 643 | 644 | # metadata route 645 | echo -e 'create cli transaction; 646 | modify sys db config.allow.rfc3927 value enable; 647 | create sys management-route metadata-route network 169.254.169.254/32 gateway ${mgmtGateway}; 648 | submit cli transaction' | tmsh -q 649 | tmsh save /sys config 650 | # add management route with metric 0 for the win 651 | route add -net default gw ${mgmtGateway} netmask 0.0.0.0 dev mgmt metric 0 652 | # run as3 653 | count=0 654 | while [ $count -le 4 ] 655 | do 656 | as3Status=$(checkAS3) 657 | echo "AS3 check status: $as3Status" 658 | if [[ "$as3Status" == *"online"* ]]; then 659 | if [ $deviceId == 1 ]; then 660 | echo "running as3" 661 | runAS3 662 | echo "done with as3" 663 | results=$(restcurl -u $CREDS $as3TaskUrl | jq '.items[] | .id, .results') 664 | echo "as3 results: $results" 665 | break 666 | else 667 | echo "Not posting as3 device $deviceid not primary" 668 | break 669 | fi 670 | elif [ $count -le 2 ]; then 671 | echo "Status code: $as3Status As3 not ready yet..." 672 | count=$[$count+1] 673 | else 674 | echo "As3 API Status $as3Status" 675 | break 676 | fi 677 | done 678 | # 679 | # 680 | # cleanup 681 | ## remove declarations 682 | # rm -f /config/do1.json 683 | # rm -f /config/do2.json 684 | # rm -f /config/as3.json 685 | ## disable/replace default admin account 686 | # echo -e "create cli transaction; 687 | # modify /sys db systemauth.primaryadminuser value $admin_username; 688 | # submit cli transaction" | tmsh -q 689 | tmsh save sys config 690 | echo "timestamp end: $(date)" 691 | echo "setup complete $(timer "$(($(date +%s) - $startTime))")" 692 | exit 693 | -------------------------------------------------------------------------------- /templates/telemetry_dashboard.omsview: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "location": { 6 | "type": "string", 7 | "defaultValue": "" 8 | }, 9 | "resourcegroup": { 10 | "type": "string", 11 | "defaultValue": "" 12 | }, 13 | "subscriptionId": { 14 | "type": "string", 15 | "defaultValue": "" 16 | }, 17 | "workspace": { 18 | "type": "string", 19 | "defaultValue": "" 20 | }, 21 | "workspaceapiversion": { 22 | "type": "string", 23 | "defaultValue": "" 24 | } 25 | }, 26 | "resources": [ 27 | { 28 | "apiVersion": "[parameters('workspaceapiversion')]", 29 | "name": "[parameters('workspace')]", 30 | "type": "Microsoft.OperationalInsights/workspaces", 31 | "location": "[parameters('location')]", 32 | "id": "[Concat('/subscriptions/', parameters('subscriptionId'), '/resourceGroups/', parameters('resourcegroup'), '/providers/Microsoft.OperationalInsights/workspaces/', parameters('workspace'))]", 33 | "resources": [ 34 | { 35 | "apiVersion": "2015-11-01-preview", 36 | "name": "Devices", 37 | "type": "views", 38 | "location": "[parameters('location')]", 39 | "id": "[Concat('/subscriptions/', parameters('subscriptionId'), '/resourceGroups/', parameters('resourcegroup'), '/providers/Microsoft.OperationalInsights/workspaces/', parameters('workspace'),'/views/Devices')]", 40 | "dependson": [ 41 | "[Concat('/subscriptions/', parameters('subscriptionId'), '/resourceGroups/', parameters('resourcegroup'), '/providers/Microsoft.OperationalInsights/workspaces/', parameters('workspace'))]" 42 | ], 43 | "properties": { 44 | "Id": "Devices", 45 | "Name": "Devices", 46 | "Author": null, 47 | "Source": "Local", 48 | "Version": 2, 49 | "Dashboard": [ 50 | { 51 | "Id": "LineChartCalloutStackedBuilderBlade", 52 | "Type": "Blade", 53 | "Version": 0, 54 | "Configuration": { 55 | "General": { 56 | "title": "Violations", 57 | "newGroup": false 58 | }, 59 | "charts": [ 60 | { 61 | "Header": { 62 | "Title": "ASM Violations over time", 63 | "Subtitle": "" 64 | }, 65 | "LineChart": { 66 | "Query": "F5Telemetry_ASM_CL | where isnotempty(attack_type_s)", 67 | "yAxis": { 68 | "isLogarithmic": false, 69 | "units": { 70 | "baseUnitType": "", 71 | "baseUnit": "", 72 | "displayUnit": "" 73 | }, 74 | "customLabel": "" 75 | }, 76 | "NavigationSelect": {} 77 | } 78 | }, 79 | { 80 | "Header": { 81 | "Title": "Requests over time", 82 | "Subtitle": "" 83 | }, 84 | "LineChart": { 85 | "Query": "F5Telemetry_LTM_CL | where event_source_s == \"request_logging\"", 86 | "yAxis": { 87 | "isLogarithmic": false, 88 | "units": { 89 | "baseUnitType": "", 90 | "baseUnit": "", 91 | "displayUnit": "" 92 | }, 93 | "customLabel": "" 94 | }, 95 | "NavigationSelect": {} 96 | } 97 | }, 98 | { 99 | "Header": { 100 | "Title": "Empty", 101 | "Subtitle": "" 102 | }, 103 | "LineChart": { 104 | "Query": "", 105 | "yAxis": { 106 | "isLogarithmic": false, 107 | "units": { 108 | "baseUnitType": "", 109 | "baseUnit": "", 110 | "displayUnit": "" 111 | }, 112 | "customLabel": "" 113 | }, 114 | "NavigationSelect": {} 115 | } 116 | } 117 | ] 118 | } 119 | }, 120 | { 121 | "Id": "NumberTileListBuilderBlade", 122 | "Type": "Blade", 123 | "Version": 0, 124 | "Configuration": { 125 | "General": { 126 | "title": "Source IP's triggering violations", 127 | "newGroup": false, 128 | "icon": "", 129 | "useIcon": false 130 | }, 131 | "Tile": { 132 | "Query": "F5Telemetry_ASM_CL | where isnotempty(attack_type_s) | summarize AggregatedValue = count() by ip_client_s | count", 133 | "Legend": "Count of Unique Source IP's", 134 | "NavigationSelect": {} 135 | }, 136 | "List": { 137 | "Query": "F5Telemetry_ASM_CL | where isnotempty(attack_type_s) | summarize AggregatedValue = count() by ip_client_s | sort by AggregatedValue desc", 138 | "HideGraph": false, 139 | "enableSparklines": false, 140 | "operation": "Summary", 141 | "ColumnsTitle": { 142 | "Name": "IP", 143 | "Value": "Count" 144 | }, 145 | "Color": "#0072c6", 146 | "thresholds": { 147 | "isEnabled": false, 148 | "values": [ 149 | { 150 | "name": "Normal", 151 | "threshold": "Default", 152 | "color": "#009e49", 153 | "isDefault": true 154 | }, 155 | { 156 | "name": "Warning", 157 | "threshold": "60", 158 | "color": "#fcd116", 159 | "isDefault": false 160 | }, 161 | { 162 | "name": "Error", 163 | "threshold": "90", 164 | "color": "#ba141a", 165 | "isDefault": false 166 | } 167 | ] 168 | }, 169 | "NameDSVSeparator": "", 170 | "NavigationQuery": "search {selected item} | sort by TimeGenerated desc", 171 | "NavigationSelect": { 172 | "NavigationQuery": "search {selected item} | sort by TimeGenerated desc" 173 | } 174 | } 175 | } 176 | }, 177 | { 178 | "Id": "NumberTileListBuilderBlade", 179 | "Type": "Blade", 180 | "Version": 0, 181 | "Configuration": { 182 | "General": { 183 | "title": "Attack Types", 184 | "newGroup": false, 185 | "icon": "", 186 | "useIcon": false 187 | }, 188 | "Tile": { 189 | "Query": "F5Telemetry_ASM_CL | where isnotempty(attack_type_s) | summarize AggregatedValue = count() by attack_type_s | count", 190 | "Legend": "Count of attack types", 191 | "NavigationSelect": {} 192 | }, 193 | "List": { 194 | "Query": "F5Telemetry_ASM_CL | where isnotempty(attack_type_s) | summarize AggregatedValue = count() by attack_type_s | sort by AggregatedValue desc", 195 | "HideGraph": false, 196 | "enableSparklines": false, 197 | "operation": "Summary", 198 | "ColumnsTitle": { 199 | "Name": "Computer", 200 | "Value": "Count" 201 | }, 202 | "Color": "#0072c6", 203 | "thresholds": { 204 | "isEnabled": false, 205 | "values": [ 206 | { 207 | "name": "Normal", 208 | "threshold": "Default", 209 | "color": "#009e49", 210 | "isDefault": true 211 | }, 212 | { 213 | "name": "Warning", 214 | "threshold": "60", 215 | "color": "#fcd116", 216 | "isDefault": false 217 | }, 218 | { 219 | "name": "Error", 220 | "threshold": "90", 221 | "color": "#ba141a", 222 | "isDefault": false 223 | } 224 | ] 225 | }, 226 | "NameDSVSeparator": "", 227 | "NavigationQuery": "search {selected item} | sort by TimeGenerated desc", 228 | "NavigationSelect": { 229 | "NavigationQuery": "search {selected item} | sort by TimeGenerated desc" 230 | } 231 | } 232 | } 233 | }, 234 | { 235 | "Id": "LineChartCalloutStackedBuilderBlade", 236 | "Type": "Blade", 237 | "Version": 0, 238 | "Configuration": { 239 | "General": { 240 | "title": "Device Info", 241 | "newGroup": false 242 | }, 243 | "charts": [ 244 | { 245 | "Header": { 246 | "Title": "CPU", 247 | "Subtitle": "" 248 | }, 249 | "LineChart": { 250 | "Query": "F5Telemetry_system_CL | summarize AggregatedValue = avg(cpu_d) by hostname_s | sort by AggregatedValue desc", 251 | "yAxis": { 252 | "isLogarithmic": false, 253 | "units": { 254 | "baseUnitType": "", 255 | "baseUnit": "", 256 | "displayUnit": "" 257 | }, 258 | "customLabel": "" 259 | }, 260 | "NavigationSelect": {} 261 | } 262 | }, 263 | { 264 | "Header": { 265 | "Title": "Memory", 266 | "Subtitle": "" 267 | }, 268 | "LineChart": { 269 | "Query": "F5Telemetry_system_CL | summarize AggregatedValue = avg(memory_d) by hostname_s | sort by AggregatedValue desc", 270 | "yAxis": { 271 | "isLogarithmic": false, 272 | "units": { 273 | "baseUnitType": "", 274 | "baseUnit": "", 275 | "displayUnit": "" 276 | }, 277 | "customLabel": "" 278 | }, 279 | "NavigationSelect": {} 280 | } 281 | }, 282 | { 283 | "Header": { 284 | "Title": "TMM Memory", 285 | "Subtitle": "" 286 | }, 287 | "LineChart": { 288 | "Query": "F5Telemetry_system_CL | summarize AggregatedValue = avg(tmmMemory_d) by hostname_s | sort by AggregatedValue desc", 289 | "yAxis": { 290 | "isLogarithmic": false, 291 | "units": { 292 | "baseUnitType": "", 293 | "baseUnit": "", 294 | "displayUnit": "" 295 | }, 296 | "customLabel": "" 297 | }, 298 | "NavigationSelect": {} 299 | } 300 | } 301 | ] 302 | } 303 | } 304 | ], 305 | "Filters": [], 306 | "OverviewTile": { 307 | "Id": "SingleNumberBuilderTile", 308 | "Type": "OverviewTile", 309 | "Version": 2, 310 | "Configuration": { 311 | "Tile": { 312 | "Legend": "Count", 313 | "Query": "F5Telemetry_system_CL | summarize dcount(hostname_s) " 314 | }, 315 | "Advanced": { 316 | "DataFlowVerification": { 317 | "Enabled": false, 318 | "Query": "search * | limit 1 | project TimeGenerated", 319 | "Message": "" 320 | } 321 | } 322 | } 323 | } 324 | } 325 | } 326 | ] 327 | } 328 | ] 329 | } 330 | -------------------------------------------------------------------------------- /templates/ts.json: -------------------------------------------------------------------------------- 1 | { 2 | "class": "Telemetry", 3 | "My_System": { 4 | "class": "Telemetry_System", 5 | "systemPoller": { 6 | "interval": 60 7 | } 8 | }, 9 | "My_Listener": { 10 | "class": "Telemetry_Listener", 11 | "port": 6514 12 | }, 13 | "My_Consumer": { 14 | "class": "Telemetry_Consumer", 15 | "type": "Azure_Log_Analytics", 16 | "workspaceId": "${law_id}", 17 | "passphrase": { 18 | "cipherText": "${law_primkey}" 19 | }, 20 | "useManagedIdentity": false, 21 | "region": "${region}" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /three_tier/firewall/bigip.tf: -------------------------------------------------------------------------------- 1 | # # Create a Public IP for the Virtual Machines 2 | # resource azurerm_public_ip f5vmpip01 { 3 | # name = "${var.prefix}-vm01-mgmt-pip01-delete-me" 4 | # location = var.resourceGroup.location 5 | # resource_group_name = var.resourceGroup.name 6 | # allocation_method = "Static" 7 | # sku = "Standard" 8 | 9 | # tags = { 10 | # Name = "${var.prefix}-f5vm-public-ip" 11 | # } 12 | # } 13 | # resource azurerm_public_ip f5vmpip02 { 14 | # name = "${var.prefix}-vm02-mgmt-pip02-delete-me" 15 | # location = var.resourceGroup.location 16 | # resource_group_name = var.resourceGroup.name 17 | # allocation_method = "Static" 18 | # sku = "Standard" 19 | 20 | # tags = { 21 | # Name = "${var.prefix}-f5vm-public-ip" 22 | # } 23 | # } 24 | 25 | # Obtain Gateway IP for each Subnet 26 | locals { 27 | depends_on = [var.subnetMgmt.id, var.subnetExternal.id] 28 | mgmt_gw = cidrhost(var.subnets["management"], 1) 29 | ext_gw = cidrhost(var.subnets["external"], 1) 30 | int_gw = cidrhost(var.subnets["internal"], 1) 31 | } 32 | 33 | # Create the first network interface card for Management 34 | resource "azurerm_network_interface" "vm01-mgmt-nic" { 35 | name = "${var.prefix}-vm01-mgmt-nic" 36 | location = var.resourceGroup.location 37 | resource_group_name = var.resourceGroup.name 38 | 39 | ip_configuration { 40 | name = "primary" 41 | subnet_id = var.subnetMgmt.id 42 | private_ip_address_allocation = "Static" 43 | private_ip_address = var.f5_mgmt["f5vm01mgmt"] 44 | #public_ip_address_id = azurerm_public_ip.f5vmpip01.id 45 | } 46 | 47 | tags = var.tags 48 | } 49 | 50 | # Associate the Network Interface to the ManagementPool 51 | resource "azurerm_network_interface_backend_address_pool_association" "mpool_assc_vm01" { 52 | network_interface_id = azurerm_network_interface.vm01-mgmt-nic.id 53 | ip_configuration_name = "primary" 54 | #backend_address_pool_id = var.managementPool.id 55 | backend_address_pool_id = var.primaryPool.id 56 | } 57 | # Associate the Network Interface to the ManagementPool 58 | resource "azurerm_network_interface_backend_address_pool_association" "mpool_assc_vm02" { 59 | network_interface_id = azurerm_network_interface.vm02-mgmt-nic.id 60 | ip_configuration_name = "primary" 61 | #backend_address_pool_id = var.managementPool.id 62 | backend_address_pool_id = var.primaryPool.id 63 | } 64 | 65 | resource "azurerm_network_interface_security_group_association" "bigip01-mgmt-nsg" { 66 | network_interface_id = azurerm_network_interface.vm01-mgmt-nic.id 67 | network_security_group_id = var.securityGroup.id 68 | } 69 | 70 | resource "azurerm_network_interface" "vm02-mgmt-nic" { 71 | name = "${var.prefix}-vm02-mgmt-nic" 72 | location = var.resourceGroup.location 73 | resource_group_name = var.resourceGroup.name 74 | 75 | ip_configuration { 76 | name = "primary" 77 | subnet_id = var.subnetMgmt.id 78 | private_ip_address_allocation = "Static" 79 | private_ip_address = var.f5_mgmt["f5vm02mgmt"] 80 | #public_ip_address_id = azurerm_public_ip.f5vmpip02.id 81 | } 82 | 83 | tags = var.tags 84 | } 85 | 86 | resource "azurerm_network_interface_security_group_association" "bigip02-mgmt-nsg" { 87 | network_interface_id = azurerm_network_interface.vm02-mgmt-nic.id 88 | network_security_group_id = var.securityGroup.id 89 | } 90 | 91 | # Create the second network interface card for External 92 | resource "azurerm_network_interface" "vm01-ext-nic" { 93 | name = "${var.prefix}-vm01-ext-nic" 94 | location = var.resourceGroup.location 95 | resource_group_name = var.resourceGroup.name 96 | enable_ip_forwarding = true 97 | enable_accelerated_networking = var.bigip_version == "latest" ? true : false 98 | 99 | ip_configuration { 100 | name = "primary" 101 | subnet_id = var.subnetExternal.id 102 | private_ip_address_allocation = "Static" 103 | private_ip_address = var.f5_t1_ext["f5vm01ext"] 104 | primary = true 105 | } 106 | 107 | ip_configuration { 108 | name = "secondary" 109 | subnet_id = var.subnetExternal.id 110 | private_ip_address_allocation = "Static" 111 | private_ip_address = var.f5_t1_ext["f5vm01ext_sec"] 112 | } 113 | 114 | tags = { 115 | Name = "${var.prefix}-vm01-ext-int" 116 | environment = var.tags["environment"] 117 | owner = var.tags["owner"] 118 | group = var.tags["group"] 119 | costcenter = var.tags["costcenter"] 120 | application = var.tags["application"] 121 | f5_cloud_failover_label = "saca" 122 | f5_cloud_failover_nic_map = "external" 123 | } 124 | } 125 | 126 | resource "azurerm_network_interface_security_group_association" "bigip01-ext-nsg" { 127 | network_interface_id = azurerm_network_interface.vm01-ext-nic.id 128 | network_security_group_id = var.securityGroup.id 129 | } 130 | 131 | resource "azurerm_network_interface" "vm02-ext-nic" { 132 | name = "${var.prefix}-vm02-ext-nic" 133 | location = var.resourceGroup.location 134 | resource_group_name = var.resourceGroup.name 135 | enable_ip_forwarding = true 136 | enable_accelerated_networking = var.bigip_version == "latest" ? true : false 137 | 138 | ip_configuration { 139 | name = "primary" 140 | subnet_id = var.subnetExternal.id 141 | private_ip_address_allocation = "Static" 142 | private_ip_address = var.f5_t1_ext["f5vm02ext"] 143 | primary = true 144 | } 145 | 146 | ip_configuration { 147 | name = "secondary" 148 | subnet_id = var.subnetExternal.id 149 | private_ip_address_allocation = "Static" 150 | private_ip_address = var.f5_t1_ext["f5vm02ext_sec"] 151 | } 152 | 153 | tags = { 154 | Name = "${var.prefix}-vm01-ext-int" 155 | environment = var.tags["environment"] 156 | owner = var.tags["owner"] 157 | group = var.tags["group"] 158 | costcenter = var.tags["costcenter"] 159 | application = var.tags["application"] 160 | f5_cloud_failover_label = "saca" 161 | f5_cloud_failover_nic_map = "external" 162 | } 163 | } 164 | 165 | resource "azurerm_network_interface_security_group_association" "bigip02-ext-nsg" { 166 | network_interface_id = azurerm_network_interface.vm02-ext-nic.id 167 | network_security_group_id = var.securityGroup.id 168 | } 169 | 170 | # Create the third network interface card for Internal 171 | resource "azurerm_network_interface" "vm01-int-nic" { 172 | name = "${var.prefix}-vm01-int-nic" 173 | location = var.resourceGroup.location 174 | resource_group_name = var.resourceGroup.name 175 | enable_ip_forwarding = true 176 | enable_accelerated_networking = var.bigip_version == "latest" ? true : false 177 | 178 | ip_configuration { 179 | name = "primary" 180 | subnet_id = var.subnetInternal.id 181 | private_ip_address_allocation = "Static" 182 | private_ip_address = var.f5_t1_int["f5vm01int"] 183 | primary = true 184 | } 185 | 186 | ip_configuration { 187 | name = "secondary" 188 | subnet_id = var.subnetInternal.id 189 | private_ip_address_allocation = "Static" 190 | private_ip_address = var.f5_t1_int["f5vm01int_sec"] 191 | } 192 | 193 | tags = var.tags 194 | } 195 | 196 | resource "azurerm_network_interface_security_group_association" "bigip01-int-nsg" { 197 | network_interface_id = azurerm_network_interface.vm01-int-nic.id 198 | network_security_group_id = var.securityGroup.id 199 | } 200 | 201 | resource "azurerm_network_interface" "vm02-int-nic" { 202 | name = "${var.prefix}-vm02-int-nic" 203 | location = var.resourceGroup.location 204 | resource_group_name = var.resourceGroup.name 205 | enable_ip_forwarding = true 206 | enable_accelerated_networking = var.bigip_version == "latest" ? true : false 207 | 208 | ip_configuration { 209 | name = "primary" 210 | subnet_id = var.subnetInternal.id 211 | private_ip_address_allocation = "Static" 212 | private_ip_address = var.f5_t1_int["f5vm02int"] 213 | primary = true 214 | } 215 | 216 | ip_configuration { 217 | name = "secondary" 218 | subnet_id = var.subnetInternal.id 219 | private_ip_address_allocation = "Static" 220 | private_ip_address = var.f5_t1_int["f5vm02int_sec"] 221 | } 222 | 223 | tags = var.tags 224 | } 225 | 226 | resource "azurerm_network_interface_security_group_association" "bigip02-int-nsg" { 227 | network_interface_id = azurerm_network_interface.vm02-int-nic.id 228 | network_security_group_id = var.securityGroup.id 229 | } 230 | 231 | # Associate the External Network Interface to the BackendPool 232 | resource "azurerm_network_interface_backend_address_pool_association" "bpool_assc_vm01" { 233 | network_interface_id = azurerm_network_interface.vm01-ext-nic.id 234 | ip_configuration_name = "secondary" 235 | backend_address_pool_id = var.backendPool.id 236 | } 237 | 238 | resource "azurerm_network_interface_backend_address_pool_association" "bpool_assc_vm02" { 239 | network_interface_id = azurerm_network_interface.vm02-ext-nic.id 240 | ip_configuration_name = "secondary" 241 | backend_address_pool_id = var.backendPool.id 242 | } 243 | 244 | resource "azurerm_network_interface_backend_address_pool_association" "primary_pool_assc_vm01" { 245 | network_interface_id = azurerm_network_interface.vm01-ext-nic.id 246 | ip_configuration_name = "primary" 247 | backend_address_pool_id = var.primaryPool.id 248 | } 249 | 250 | resource "azurerm_network_interface_backend_address_pool_association" "primary_pool_assc_vm02" { 251 | network_interface_id = azurerm_network_interface.vm02-ext-nic.id 252 | ip_configuration_name = "primary" 253 | backend_address_pool_id = var.primaryPool.id 254 | } 255 | 256 | # attach interfaces to backend pool 257 | resource "azurerm_network_interface_backend_address_pool_association" "int_bpool_assc_vm01" { 258 | network_interface_id = azurerm_network_interface.vm01-int-nic.id 259 | ip_configuration_name = "secondary" 260 | backend_address_pool_id = var.internalBackPool.id 261 | } 262 | 263 | resource "azurerm_network_interface_backend_address_pool_association" "int_bpool_assc_vm02" { 264 | network_interface_id = azurerm_network_interface.vm02-int-nic.id 265 | ip_configuration_name = "secondary" 266 | backend_address_pool_id = var.internalBackPool.id 267 | } 268 | 269 | # Create F5 BIGIP VMs 270 | resource "azurerm_virtual_machine" "f5vm01" { 271 | name = "${var.prefix}-f5vm01" 272 | location = var.resourceGroup.location 273 | resource_group_name = var.resourceGroup.name 274 | primary_network_interface_id = azurerm_network_interface.vm01-mgmt-nic.id 275 | network_interface_ids = [azurerm_network_interface.vm01-mgmt-nic.id, azurerm_network_interface.vm01-ext-nic.id, azurerm_network_interface.vm01-int-nic.id] 276 | vm_size = var.instanceType 277 | availability_set_id = var.availabilitySet.id 278 | 279 | delete_os_disk_on_termination = true 280 | delete_data_disks_on_termination = true 281 | 282 | storage_image_reference { 283 | publisher = "f5-networks" 284 | offer = var.product 285 | sku = var.image_name 286 | version = var.bigip_version 287 | } 288 | 289 | storage_os_disk { 290 | name = "${var.prefix}-vm01-osdisk" 291 | caching = "ReadWrite" 292 | create_option = "FromImage" 293 | managed_disk_type = "Standard_LRS" 294 | } 295 | 296 | os_profile { 297 | computer_name = "${var.prefix}vm01" 298 | admin_username = var.adminUserName 299 | admin_password = var.adminPassword 300 | } 301 | 302 | os_profile_linux_config { 303 | disable_password_authentication = false 304 | } 305 | 306 | plan { 307 | name = var.image_name 308 | publisher = "f5-networks" 309 | product = var.product 310 | } 311 | 312 | tags = var.tags 313 | } 314 | 315 | resource "azurerm_virtual_machine" "f5vm02" { 316 | name = "${var.prefix}-f5vm02" 317 | location = var.resourceGroup.location 318 | resource_group_name = var.resourceGroup.name 319 | primary_network_interface_id = azurerm_network_interface.vm02-mgmt-nic.id 320 | network_interface_ids = [azurerm_network_interface.vm02-mgmt-nic.id, azurerm_network_interface.vm02-ext-nic.id, azurerm_network_interface.vm02-int-nic.id] 321 | vm_size = var.instanceType 322 | availability_set_id = var.availabilitySet.id 323 | 324 | delete_os_disk_on_termination = true 325 | delete_data_disks_on_termination = true 326 | 327 | storage_image_reference { 328 | publisher = "f5-networks" 329 | offer = var.product 330 | sku = var.image_name 331 | version = var.bigip_version 332 | } 333 | 334 | storage_os_disk { 335 | name = "${var.prefix}-vm02-osdisk" 336 | caching = "ReadWrite" 337 | create_option = "FromImage" 338 | managed_disk_type = "Standard_LRS" 339 | } 340 | 341 | os_profile { 342 | computer_name = "${var.prefix}vm02" 343 | admin_username = var.adminUserName 344 | admin_password = var.adminPassword 345 | } 346 | 347 | os_profile_linux_config { 348 | disable_password_authentication = false 349 | } 350 | 351 | plan { 352 | name = var.image_name 353 | publisher = "f5-networks" 354 | product = var.product 355 | } 356 | 357 | tags = var.tags 358 | } 359 | 360 | # Setup Onboarding scripts 361 | data "template_file" "vm_onboard" { 362 | template = file("./templates/onboard.tpl") 363 | vars = { 364 | uname = var.adminUserName 365 | upassword = var.adminPassword 366 | doVersion = "latest" 367 | as3Version = "latest" 368 | tsVersion = "latest" 369 | cfVersion = "latest" 370 | fastVersion = "1.0.0" 371 | doExternalDeclarationUrl = "https://example.domain.com/do.json" 372 | as3ExternalDeclarationUrl = "https://example.domain.com/as3.json" 373 | tsExternalDeclarationUrl = "https://example.domain.com/ts.json" 374 | cfExternalDeclarationUrl = "https://example.domain.com/cf.json" 375 | onboard_log = var.onboard_log 376 | mgmtGateway = local.mgmt_gw 377 | DO1_Document = data.template_file.vm01_do_json.rendered 378 | DO2_Document = data.template_file.vm02_do_json.rendered 379 | AS3_Document = data.template_file.as3_json.rendered 380 | } 381 | } 382 | 383 | # as3 uuid generation 384 | resource "random_uuid" "as3_uuid" {} 385 | 386 | data "http" "onboard" { 387 | url = "https://raw.githubusercontent.com/Mikej81/f5-bigip-hardening-DO/master/dist/terraform/latest/${var.licenses["license1"] != "" ? "byol" : "payg"}_cluster.json" 388 | } 389 | 390 | data "template_file" "vm01_do_json" { 391 | template = data.http.onboard.body 392 | vars = { 393 | host1 = var.hosts["host1"] 394 | host2 = var.hosts["host2"] 395 | local_host = var.hosts["host1"] 396 | external_selfip = "${var.f5_t1_ext["f5vm01ext"]}/${element(split("/", var.subnets["external"]), 1)}" 397 | internal_selfip = "${var.f5_t1_int["f5vm01int"]}/${element(split("/", var.subnets["internal"]), 1)}" 398 | log_localip = var.f5_t1_ext["f5vm01ext"] 399 | log_destination = var.app01ip 400 | vdmsSubnet = var.subnets["vdms"] 401 | appSubnet = var.subnets["application"] 402 | vnetSubnet = var.cidr 403 | remote_host = var.hosts["host2"] 404 | remote_selfip = var.f5_t1_ext["f5vm02ext"] 405 | externalGateway = local.ext_gw 406 | internalGateway = local.int_gw 407 | mgmtGateway = local.mgmt_gw 408 | dns_server = var.dns_server 409 | ntp_server = var.ntp_server 410 | timezone = var.timezone 411 | admin_user = var.adminUserName 412 | admin_password = var.adminPassword 413 | license = var.licenses["license1"] != "" ? var.licenses["license1"] : "" 414 | } 415 | } 416 | 417 | data "template_file" "vm02_do_json" { 418 | template = data.http.onboard.body 419 | vars = { 420 | host1 = var.hosts["host1"] 421 | host2 = var.hosts["host2"] 422 | local_host = var.hosts["host2"] 423 | external_selfip = "${var.f5_t1_ext["f5vm02ext"]}/${element(split("/", var.subnets["external"]), 1)}" 424 | internal_selfip = "${var.f5_t1_int["f5vm02int"]}/${element(split("/", var.subnets["internal"]), 1)}" 425 | log_localip = var.f5_t1_ext["f5vm02ext"] 426 | log_destination = var.app01ip 427 | vdmsSubnet = var.subnets["vdms"] 428 | appSubnet = var.subnets["application"] 429 | vnetSubnet = var.cidr 430 | remote_host = var.hosts["host1"] 431 | remote_selfip = var.f5_t1_ext["f5vm01ext"] 432 | externalGateway = local.ext_gw 433 | internalGateway = local.int_gw 434 | mgmtGateway = local.mgmt_gw 435 | dns_server = var.dns_server 436 | ntp_server = var.ntp_server 437 | timezone = var.timezone 438 | admin_user = var.adminUserName 439 | admin_password = var.adminPassword 440 | license = var.licenses["license2"] != "" ? var.licenses["license2"] : "" 441 | } 442 | } 443 | 444 | data "http" "appservice" { 445 | url = "https://raw.githubusercontent.com/Mikej81/f5-bigip-hardening-AS3/master/dist/terraform/latest/sccaSingleTier.json" 446 | } 447 | 448 | data "template_file" "as3_json" { 449 | template = data.http.appservice.body 450 | vars = { 451 | uuid = random_uuid.as3_uuid.result 452 | baseline_waf_policy = var.asm_policy 453 | exampleVipAddress = var.f5_t1_ext["f5vm01ext"] 454 | exampleVipSubnet = var.subnets["external"] 455 | ips_pool_addresses = var.ilb03ip 456 | rdp_pool_addresses = var.ilb03ip 457 | ssh_pool_addresses = var.ilb03ip 458 | app_pool_addresses = var.ilb03ip 459 | log_destination = var.ilb03ip 460 | example_vs_address = var.subnets["external"] 461 | mgmtVipAddress = var.f5_t1_ext["f5vm01ext_sec"] 462 | mgmtVipAddress2 = var.f5_t1_ext["f5vm02ext_sec"] 463 | transitVipAddress = var.f5_t1_int["f5vm01int_sec"] 464 | transitVipAddress2 = var.f5_t1_int["f5vm02int_sec"] 465 | } 466 | } 467 | 468 | # Run Startup Script 469 | resource "azurerm_virtual_machine_extension" "f5vm01-run-startup-cmd" { 470 | name = "${var.prefix}-f5vm01-run-startup-cmd" 471 | depends_on = [azurerm_virtual_machine.f5vm01, azurerm_network_interface_backend_address_pool_association.mpool_assc_vm01, azurerm_network_interface_backend_address_pool_association.mpool_assc_vm02] 472 | virtual_machine_id = azurerm_virtual_machine.f5vm01.id 473 | publisher = "Microsoft.Azure.Extensions" 474 | type = "CustomScript" 475 | type_handler_version = "2.0" 476 | 477 | settings = <> ./startup.b64 && cat ./startup.b64 | base64 -d >> ./startup-temp.sh && sed -e 's/\r$//' ./startup-temp.sh > ./startup-script.sh && chmod +x ./startup-script.sh && rm ./startup.b64 && bash ./startup-script.sh 1" 480 | } 481 | SETTINGS 482 | 483 | tags = var.tags 484 | } 485 | 486 | resource "azurerm_virtual_machine_extension" "f5vm02-run-startup-cmd" { 487 | name = "${var.prefix}-f5vm02-run-startup-cmd" 488 | depends_on = [azurerm_virtual_machine.f5vm01, azurerm_virtual_machine.f5vm02, azurerm_network_interface_backend_address_pool_association.mpool_assc_vm01, azurerm_network_interface_backend_address_pool_association.mpool_assc_vm02] 489 | virtual_machine_id = azurerm_virtual_machine.f5vm02.id 490 | publisher = "Microsoft.Azure.Extensions" 491 | type = "CustomScript" 492 | type_handler_version = "2.0" 493 | 494 | settings = <> ./startup.b64 && cat ./startup.b64 | base64 -d >> ./startup-temp.sh && sed -e 's/\r$//g' ./startup-temp.sh > ./startup-script.sh && chmod +x ./startup-script.sh && rm ./startup.b64 && bash ./startup-script.sh 2" 497 | } 498 | SETTINGS 499 | 500 | tags = var.tags 501 | } 502 | 503 | 504 | # Debug Template Outputs 505 | resource "local_file" "vm01_do_file" { 506 | content = data.template_file.vm01_do_json.rendered 507 | filename = "${path.module}/vm01_do_data.json" 508 | } 509 | 510 | resource "local_file" "vm02_do_file" { 511 | content = data.template_file.vm02_do_json.rendered 512 | filename = "${path.module}/vm02_do_data.json" 513 | } 514 | 515 | resource "local_file" "vm_as3_file" { 516 | content = data.template_file.as3_json.rendered 517 | filename = "${path.module}/vm_as3_data.json" 518 | } 519 | 520 | resource "local_file" "onboard_file" { 521 | content = data.template_file.vm_onboard.rendered 522 | filename = "${path.module}/onboard.sh" 523 | } 524 | -------------------------------------------------------------------------------- /three_tier/firewall/outputs.tf: -------------------------------------------------------------------------------- 1 | # data azurerm_public_ip f5vmpip01 { 2 | # name = azurerm_public_ip.f5vmpip01.name 3 | # resource_group_name = var.resourceGroup.name 4 | # depends_on = [azurerm_public_ip.f5vmpip01, azurerm_virtual_machine.f5vm01] 5 | # } 6 | # data azurerm_public_ip f5vmpip02 { 7 | # name = azurerm_public_ip.f5vmpip02.name 8 | # resource_group_name = var.resourceGroup.name 9 | # depends_on = [azurerm_public_ip.f5vmpip02, azurerm_virtual_machine.f5vm02] 10 | # } 11 | 12 | 13 | output f5vm01_id { value = azurerm_virtual_machine.f5vm01.id } 14 | output f5vm01_mgmt_private_ip { value = azurerm_network_interface.vm01-mgmt-nic.private_ip_address } 15 | #output f5vm01_mgmt_public_ip { value = data.azurerm_public_ip.f5vmpip01.ip_address } 16 | output f5vm01_ext_private_ip { value = azurerm_network_interface.vm01-ext-nic.private_ip_address } 17 | 18 | output f5vm02_id { value = azurerm_virtual_machine.f5vm02.id } 19 | output f5vm02_mgmt_private_ip { value = azurerm_network_interface.vm02-mgmt-nic.private_ip_address } 20 | #output f5vm02_mgmt_public_ip { value = data.azurerm_public_ip.f5vmpip02.ip_address } 21 | output f5vm02_ext_private_ip { value = azurerm_network_interface.vm02-ext-nic.private_ip_address } 22 | -------------------------------------------------------------------------------- /three_tier/firewall/variables.tf: -------------------------------------------------------------------------------- 1 | variable resourceGroup {} 2 | # admin credentials 3 | variable adminUserName {} 4 | variable adminPassword {} 5 | variable sshPublicKey {} 6 | # cloud info 7 | variable location {} 8 | variable region {} 9 | variable securityGroup { 10 | default = "none" 11 | } 12 | variable availabilitySet {} 13 | variable availabilitySet2 {} 14 | 15 | variable prefix {} 16 | # bigip network 17 | variable subnets {} 18 | variable subnetMgmt {} 19 | variable subnetExternal {} 20 | variable subnetInternal {} 21 | variable subnetWafExt {} 22 | variable subnetWafInt {} 23 | variable app01ip {} 24 | 25 | variable backendPool {} 26 | variable managementPool {} 27 | variable primaryPool {} 28 | variable internalBackPool {} 29 | 30 | variable f5_mgmt {} 31 | variable f5_t1_ext {} 32 | variable f5_t1_int {} 33 | variable f5_t3_ext {} 34 | variable f5_t3_int {} 35 | 36 | # winjump 37 | variable winjumpip {} 38 | 39 | # linuxjump 40 | variable linuxjumpip {} 41 | 42 | # device 43 | variable instanceType {} 44 | 45 | 46 | # BIGIP Image 47 | variable image_name {} 48 | variable product {} 49 | variable bigip_version {} 50 | 51 | variable cidr {} 52 | 53 | variable ilb01ip {} 54 | variable ilb02ip {} 55 | variable ilb03ip {} 56 | 57 | # BIGIP Setup 58 | variable licenses { 59 | type = map(string) 60 | default = { 61 | "license1" = "" 62 | "license2" = "" 63 | "license3" = "" 64 | "license4" = "" 65 | } 66 | } 67 | 68 | variable hosts {} 69 | variable dns_server {} 70 | variable ntp_server {} 71 | variable timezone {} 72 | variable onboard_log { default = "/var/log/startup-script.log" } 73 | variable asm_policy {} 74 | 75 | # TAGS 76 | variable tags {} 77 | -------------------------------------------------------------------------------- /three_tier/ips/ips.tf: -------------------------------------------------------------------------------- 1 | resource "random_id" "randomId" { 2 | keepers = { 3 | # Generate a new ID only when a new resource group is defined 4 | resource_group = var.resourceGroup.name 5 | } 6 | byte_length = 8 7 | } 8 | 9 | # # Create a Public IP for the Virtual Machines 10 | # resource azurerm_public_ip ipspip01 { 11 | # name = "${var.prefix}-ips-mgmt-pip01-delete-me" 12 | # location = var.resourceGroup.location 13 | # resource_group_name = var.resourceGroup.name 14 | # allocation_method = "Static" 15 | # sku = "Standard" 16 | 17 | # tags = { 18 | # Name = "${var.prefix}-ips-public-ip" 19 | # } 20 | # } 21 | 22 | resource "azurerm_storage_account" "ips_storageaccount" { 23 | name = "diag${random_id.randomId.hex}" 24 | resource_group_name = var.resourceGroup.name 25 | location = var.resourceGroup.location 26 | account_replication_type = "LRS" 27 | account_tier = "Standard" 28 | 29 | tags = var.tags 30 | } 31 | 32 | resource "azurerm_network_interface" "ips01-mgmt-nic" { 33 | name = "${var.prefix}-ips01-mgmt-nic" 34 | location = var.resourceGroup.location 35 | resource_group_name = var.resourceGroup.name 36 | 37 | enable_accelerated_networking = true 38 | enable_ip_forwarding = true 39 | 40 | ip_configuration { 41 | name = "primary" 42 | subnet_id = var.subnetMgmt.id 43 | private_ip_address_allocation = "Static" 44 | private_ip_address = var.ips01mgmt 45 | primary = true 46 | #public_ip_address_id = azurerm_public_ip.ipspip01.id 47 | } 48 | 49 | tags = var.tags 50 | } 51 | 52 | resource "azurerm_network_interface_backend_address_pool_association" "mpool_assc_ips01" { 53 | network_interface_id = azurerm_network_interface.ips01-mgmt-nic.id 54 | ip_configuration_name = "primary" 55 | backend_address_pool_id = var.primaryPool.id 56 | } 57 | 58 | resource "azurerm_network_interface" "ips01-ext-nic" { 59 | name = "${var.prefix}-ips01-ext-nic" 60 | location = var.resourceGroup.location 61 | resource_group_name = var.resourceGroup.name 62 | 63 | enable_accelerated_networking = true 64 | enable_ip_forwarding = true 65 | 66 | ip_configuration { 67 | name = "primary" 68 | subnet_id = var.subnetInspectExt.id 69 | private_ip_address_allocation = "Static" 70 | private_ip_address = var.ips01ext 71 | primary = true 72 | } 73 | 74 | tags = var.tags 75 | } 76 | 77 | # internal network interface for ips vm 78 | resource "azurerm_network_interface" "ips01-int-nic" { 79 | name = "${var.prefix}-ips01-int-nic" 80 | location = var.resourceGroup.location 81 | resource_group_name = var.resourceGroup.name 82 | 83 | enable_accelerated_networking = true 84 | enable_ip_forwarding = true 85 | 86 | ip_configuration { 87 | name = "primary" 88 | subnet_id = var.subnetInspectInt.id 89 | private_ip_address_allocation = "Static" 90 | private_ip_address = var.ips01int 91 | primary = true 92 | } 93 | 94 | tags = var.tags 95 | } 96 | 97 | # Associate the External Network Interface to the BackendPool 98 | resource "azurerm_network_interface_backend_address_pool_association" "ips_pool_assc_ingress" { 99 | network_interface_id = azurerm_network_interface.ips01-ext-nic.id 100 | ip_configuration_name = "primary" 101 | backend_address_pool_id = var.ipsIngressPool.id 102 | } 103 | 104 | resource "azurerm_network_interface_backend_address_pool_association" "ips_pool_assc_egress" { 105 | network_interface_id = azurerm_network_interface.ips01-int-nic.id 106 | ip_configuration_name = "primary" 107 | backend_address_pool_id = var.ipsEgressPool.id 108 | } 109 | 110 | # network interface for ips vm 111 | resource "azurerm_network_interface_security_group_association" "ips-ext-nsg" { 112 | network_interface_id = azurerm_network_interface.ips01-ext-nic.id 113 | network_security_group_id = var.securityGroup.id 114 | } 115 | # network interface for ips vm 116 | resource "azurerm_network_interface_security_group_association" "ips-int-nsg" { 117 | network_interface_id = azurerm_network_interface.ips01-int-nic.id 118 | network_security_group_id = var.securityGroup.id 119 | } 120 | # network interface for ips vm 121 | resource "azurerm_network_interface_security_group_association" "ips-mgmt-nsg" { 122 | network_interface_id = azurerm_network_interface.ips01-mgmt-nic.id 123 | network_security_group_id = var.securityGroup.id 124 | } 125 | 126 | # set up proxy config 127 | 128 | # Obtain Gateway IP for each Subnet 129 | locals { 130 | depends_on = [var.subnetMgmt, var.internalSubnet, var.wafSubnet] 131 | mgmt_gw = cidrhost(var.subnets["management"], 1) 132 | int_gw = cidrhost(var.subnets["internal"], 1) 133 | int_mask = cidrnetmask(var.subnets["internal"]) 134 | extInspectGw = cidrhost(var.subnets["inspect_ext"], 1) 135 | intInspectGw = cidrhost(var.subnets["inspect_int"], 1) 136 | waf_ext_gw = cidrhost(var.subnets["waf_ext"], 1) 137 | waf_ext_mask = cidrnetmask(var.subnets["waf_ext"]) 138 | } 139 | 140 | data "template_file" "vm_onboard" { 141 | template = file("./templates/ips-cloud-init.yaml") 142 | vars = { 143 | #gateway = gateway 144 | internalSubnetPrefix = cidrhost(var.subnets["internal"], 0) 145 | internalMask = local.int_mask 146 | internalGateway = local.extInspectGw 147 | wafSubnetPrefix = cidrhost(var.subnets["waf_ext"], 0) 148 | wafMask = local.waf_ext_mask 149 | wafGateway = local.intInspectGw 150 | log_destination = var.app01ip 151 | } 152 | } 153 | 154 | data "template_cloudinit_config" "config" { 155 | gzip = true 156 | base64_encode = true 157 | 158 | # Main cloud-config configuration file. 159 | part { 160 | filename = "init.cfg" 161 | content_type = "text/cloud-config" 162 | content = data.template_file.vm_onboard.rendered 163 | } 164 | } 165 | 166 | # ips01-VM 167 | resource "azurerm_linux_virtual_machine" "ips01-vm" { 168 | name = "${var.prefix}-ips01-vm" 169 | location = var.resourceGroup.location 170 | resource_group_name = var.resourceGroup.name 171 | depends_on = [azurerm_network_interface_backend_address_pool_association.mpool_assc_ips01] 172 | 173 | network_interface_ids = [azurerm_network_interface.ips01-mgmt-nic.id, azurerm_network_interface.ips01-ext-nic.id, azurerm_network_interface.ips01-int-nic.id] 174 | size = var.instanceType 175 | 176 | admin_username = var.adminUserName 177 | admin_password = var.adminPassword 178 | disable_password_authentication = false 179 | computer_name = "${var.prefix}-ips01-vm" 180 | 181 | os_disk { 182 | caching = "ReadWrite" 183 | storage_account_type = "Premium_LRS" 184 | } 185 | 186 | source_image_reference { 187 | publisher = "Canonical" 188 | offer = "UbuntuServer" 189 | sku = "18.04-LTS" 190 | version = "latest" 191 | } 192 | 193 | custom_data = data.template_cloudinit_config.config.rendered 194 | 195 | boot_diagnostics { 196 | storage_account_uri = azurerm_storage_account.ips_storageaccount.primary_blob_endpoint 197 | } 198 | 199 | tags = var.tags 200 | } 201 | 202 | resource "local_file" "cloud_init_file" { 203 | content = data.template_file.vm_onboard.rendered 204 | filename = "${path.module}/cloud-init.yml" 205 | } 206 | -------------------------------------------------------------------------------- /three_tier/ips/variables.tf: -------------------------------------------------------------------------------- 1 | # templates directory 2 | variable templates { 3 | default = "/workspace/templates" 4 | } 5 | variable location {} 6 | variable region {} 7 | variable prefix {} 8 | variable resourceGroup {} 9 | variable securityGroup { 10 | default = "none" 11 | } 12 | 13 | variable subnets {} 14 | variable subnetMgmt {} 15 | variable subnetInspectExt {} 16 | variable subnetInspectInt {} 17 | variable internalSubnet {} 18 | variable wafSubnet {} 19 | variable virtual_network_name {} 20 | 21 | variable ips01ext {} 22 | variable ips01int {} 23 | variable ips01mgmt {} 24 | variable app01ip {} 25 | variable adminUserName {} 26 | variable adminPassword {} 27 | 28 | variable ipsIngressPool {} 29 | variable ipsEgressPool {} 30 | variable primaryPool {} 31 | 32 | # device 33 | variable instanceType {} 34 | 35 | # TAGS 36 | variable tags {} 37 | 38 | variable timezone {} 39 | -------------------------------------------------------------------------------- /three_tier/waf/bigip.tf: -------------------------------------------------------------------------------- 1 | # # Create a Public IP for the Virtual Machines 2 | # resource azurerm_public_ip f5vmpip03 { 3 | # name = "${var.prefix}-vm03-mgmt-pip03-delete-me" 4 | # location = var.resourceGroup.location 5 | # resource_group_name = var.resourceGroup.name 6 | # allocation_method = "Static" 7 | # sku = "Standard" 8 | 9 | # tags = { 10 | # Name = "${var.prefix}-f5vm-public-ip" 11 | # } 12 | # } 13 | # resource azurerm_public_ip f5vmpip04 { 14 | # name = "${var.prefix}-vm04-mgmt-pip04-delete-me" 15 | # location = var.resourceGroup.location 16 | # resource_group_name = var.resourceGroup.name 17 | # allocation_method = "Static" 18 | # sku = "Standard" 19 | 20 | # tags = { 21 | # Name = "${var.prefix}-f5vm-public-ip" 22 | # } 23 | # } 24 | 25 | # Obtain Gateway IP for each Subnet 26 | locals { 27 | depends_on = [var.subnetMgmt, var.subnetWafExt, var.subnetWafInt] 28 | mgmt_gw = cidrhost(var.subnets["management"], 1) 29 | waf_ext_gw = cidrhost(var.subnets["waf_ext"], 1) 30 | waf_int_gw = cidrhost(var.subnets["waf_int"], 1) 31 | } 32 | 33 | # Create the first network interface card for Management 34 | resource "azurerm_network_interface" "vm03-mgmt-nic" { 35 | name = "${var.prefix}-vm03-mgmt-nic" 36 | location = var.resourceGroup.location 37 | resource_group_name = var.resourceGroup.name 38 | 39 | ip_configuration { 40 | name = "primary" 41 | subnet_id = var.subnetMgmt.id 42 | private_ip_address_allocation = "Static" 43 | private_ip_address = var.f5_mgmt["f5vm03mgmt"] 44 | #public_ip_address_id = azurerm_public_ip.f5vmpip03.id 45 | } 46 | 47 | tags = var.tags 48 | } 49 | 50 | resource "azurerm_network_interface" "vm04-mgmt-nic" { 51 | name = "${var.prefix}-vm04-mgmt-nic" 52 | location = var.resourceGroup.location 53 | resource_group_name = var.resourceGroup.name 54 | 55 | ip_configuration { 56 | name = "primary" 57 | subnet_id = var.subnetMgmt.id 58 | private_ip_address_allocation = "Static" 59 | private_ip_address = var.f5_mgmt["f5vm04mgmt"] 60 | #public_ip_address_id = azurerm_public_ip.f5vmpip04.id 61 | } 62 | 63 | tags = var.tags 64 | } 65 | 66 | resource "azurerm_network_interface_security_group_association" "bigip03-mgmt-nsg" { 67 | network_interface_id = azurerm_network_interface.vm03-mgmt-nic.id 68 | network_security_group_id = var.securityGroup.id 69 | } 70 | 71 | resource "azurerm_network_interface_security_group_association" "bigip04-mgmt-nsg" { 72 | network_interface_id = azurerm_network_interface.vm04-mgmt-nic.id 73 | network_security_group_id = var.securityGroup.id 74 | } 75 | 76 | # Associate the Network Interface to the ManagementPool 77 | resource "azurerm_network_interface_backend_address_pool_association" "mpool_assc_vm01" { 78 | network_interface_id = azurerm_network_interface.vm03-mgmt-nic.id 79 | ip_configuration_name = "primary" 80 | #backend_address_pool_id = var.managementPool.id 81 | backend_address_pool_id = var.primaryPool.id 82 | } 83 | # Associate the Network Interface to the ManagementPool 84 | resource "azurerm_network_interface_backend_address_pool_association" "mpool_assc_vm02" { 85 | network_interface_id = azurerm_network_interface.vm04-mgmt-nic.id 86 | ip_configuration_name = "primary" 87 | #backend_address_pool_id = var.managementPool.id 88 | backend_address_pool_id = var.primaryPool.id 89 | } 90 | 91 | # Create the second network interface card for External 92 | resource "azurerm_network_interface" "vm03-ext-nic" { 93 | name = "${var.prefix}-vm03-ext-nic" 94 | location = var.resourceGroup.location 95 | resource_group_name = var.resourceGroup.name 96 | enable_ip_forwarding = true 97 | enable_accelerated_networking = var.bigip_version == "latest" ? true : false 98 | 99 | ip_configuration { 100 | name = "primary" 101 | subnet_id = var.subnetWafExt[0].id 102 | private_ip_address_allocation = "Static" 103 | private_ip_address = var.f5_t3_ext["f5vm03ext"] 104 | primary = true 105 | } 106 | 107 | ip_configuration { 108 | name = "secondary" 109 | subnet_id = var.subnetWafExt[0].id 110 | private_ip_address_allocation = "Static" 111 | private_ip_address = var.f5_t3_ext["f5vm03ext_sec"] 112 | } 113 | 114 | tags = { 115 | Name = "${var.prefix}-vm03-ext-int" 116 | environment = var.tags["environment"] 117 | owner = var.tags["owner"] 118 | group = var.tags["group"] 119 | costcenter = var.tags["costcenter"] 120 | application = var.tags["application"] 121 | f5_cloud_failover_label = "saca" 122 | f5_cloud_failover_nic_map = "external" 123 | } 124 | } 125 | 126 | resource "azurerm_network_interface_security_group_association" "bigip03-ext-nsg" { 127 | network_interface_id = azurerm_network_interface.vm03-ext-nic.id 128 | network_security_group_id = var.securityGroup.id 129 | } 130 | 131 | resource "azurerm_network_interface" "vm04-ext-nic" { 132 | name = "${var.prefix}-vm04-ext-nic" 133 | location = var.resourceGroup.location 134 | resource_group_name = var.resourceGroup.name 135 | enable_ip_forwarding = true 136 | enable_accelerated_networking = var.bigip_version == "latest" ? true : false 137 | 138 | ip_configuration { 139 | name = "primary" 140 | subnet_id = var.subnetWafExt[0].id 141 | private_ip_address_allocation = "Static" 142 | private_ip_address = var.f5_t3_ext["f5vm04ext"] 143 | primary = true 144 | } 145 | 146 | ip_configuration { 147 | name = "secondary" 148 | subnet_id = var.subnetWafExt[0].id 149 | private_ip_address_allocation = "Static" 150 | private_ip_address = var.f5_t3_ext["f5vm04ext_sec"] 151 | } 152 | 153 | tags = { 154 | Name = "${var.prefix}-vm03-ext-int" 155 | environment = var.tags["environment"] 156 | owner = var.tags["owner"] 157 | group = var.tags["group"] 158 | costcenter = var.tags["costcenter"] 159 | application = var.tags["application"] 160 | f5_cloud_failover_label = "saca" 161 | f5_cloud_failover_nic_map = "external" 162 | } 163 | } 164 | 165 | resource "azurerm_network_interface_security_group_association" "bigip04-ext-nsg" { 166 | network_interface_id = azurerm_network_interface.vm04-ext-nic.id 167 | network_security_group_id = var.securityGroup.id 168 | } 169 | 170 | # Associate the External Network Interfaces to the Waf Backend Pools 171 | resource "azurerm_network_interface_backend_address_pool_association" "bpool_assc_vm01" { 172 | network_interface_id = azurerm_network_interface.vm03-ext-nic.id 173 | ip_configuration_name = "secondary" 174 | backend_address_pool_id = var.wafIngressPool.id 175 | } 176 | 177 | resource "azurerm_network_interface_backend_address_pool_association" "bpool_assc_vm02" { 178 | network_interface_id = azurerm_network_interface.vm04-ext-nic.id 179 | ip_configuration_name = "secondary" 180 | backend_address_pool_id = var.wafIngressPool.id 181 | } 182 | 183 | # Create the third network interface card for Internal 184 | resource "azurerm_network_interface" "vm03-int-nic" { 185 | name = "${var.prefix}-vm03-int-nic" 186 | location = var.resourceGroup.location 187 | resource_group_name = var.resourceGroup.name 188 | enable_ip_forwarding = true 189 | enable_accelerated_networking = var.bigip_version == "latest" ? true : false 190 | 191 | ip_configuration { 192 | name = "primary" 193 | subnet_id = var.subnetWafInt[0].id 194 | private_ip_address_allocation = "Static" 195 | private_ip_address = var.f5_t3_int["f5vm03int"] 196 | primary = true 197 | } 198 | tags = var.tags 199 | } 200 | 201 | resource "azurerm_network_interface_security_group_association" "bigip03-int-nsg" { 202 | network_interface_id = azurerm_network_interface.vm03-int-nic.id 203 | network_security_group_id = var.securityGroup.id 204 | } 205 | 206 | resource "azurerm_network_interface" "vm04-int-nic" { 207 | name = "${var.prefix}-vm04-int-nic" 208 | location = var.resourceGroup.location 209 | resource_group_name = var.resourceGroup.name 210 | enable_ip_forwarding = true 211 | enable_accelerated_networking = var.bigip_version == "latest" ? true : false 212 | 213 | ip_configuration { 214 | name = "primary" 215 | subnet_id = var.subnetWafInt[0].id 216 | private_ip_address_allocation = "Static" 217 | private_ip_address = var.f5_t3_int["f5vm04int"] 218 | primary = true 219 | } 220 | 221 | tags = var.tags 222 | } 223 | 224 | resource "azurerm_network_interface_security_group_association" "bigip04-int-nsg" { 225 | network_interface_id = azurerm_network_interface.vm04-int-nic.id 226 | network_security_group_id = var.securityGroup.id 227 | } 228 | 229 | # Create F5 BIGIP VMs 230 | resource "azurerm_virtual_machine" "f5vm03" { 231 | name = "${var.prefix}-f5vm03" 232 | location = var.resourceGroup.location 233 | resource_group_name = var.resourceGroup.name 234 | primary_network_interface_id = azurerm_network_interface.vm03-mgmt-nic.id 235 | network_interface_ids = [azurerm_network_interface.vm03-mgmt-nic.id, azurerm_network_interface.vm03-ext-nic.id, azurerm_network_interface.vm03-int-nic.id] 236 | vm_size = var.instanceType 237 | availability_set_id = var.availabilitySet.id 238 | 239 | delete_os_disk_on_termination = true 240 | delete_data_disks_on_termination = true 241 | 242 | storage_image_reference { 243 | publisher = "f5-networks" 244 | offer = var.product 245 | sku = var.image_name 246 | version = var.bigip_version 247 | } 248 | 249 | storage_os_disk { 250 | name = "${var.prefix}-vm03-osdisk" 251 | caching = "ReadWrite" 252 | create_option = "FromImage" 253 | managed_disk_type = "Standard_LRS" 254 | } 255 | 256 | os_profile { 257 | computer_name = "${var.prefix}vm03" 258 | admin_username = var.adminUserName 259 | admin_password = var.adminPassword 260 | } 261 | 262 | os_profile_linux_config { 263 | disable_password_authentication = false 264 | } 265 | 266 | plan { 267 | name = var.image_name 268 | publisher = "f5-networks" 269 | product = var.product 270 | } 271 | 272 | tags = var.tags 273 | } 274 | 275 | resource "azurerm_virtual_machine" "f5vm04" { 276 | name = "${var.prefix}-f5vm04" 277 | location = var.resourceGroup.location 278 | resource_group_name = var.resourceGroup.name 279 | primary_network_interface_id = azurerm_network_interface.vm04-mgmt-nic.id 280 | network_interface_ids = [azurerm_network_interface.vm04-mgmt-nic.id, azurerm_network_interface.vm04-ext-nic.id, azurerm_network_interface.vm04-int-nic.id] 281 | vm_size = var.instanceType 282 | availability_set_id = var.availabilitySet.id 283 | 284 | delete_os_disk_on_termination = true 285 | delete_data_disks_on_termination = true 286 | 287 | storage_image_reference { 288 | publisher = "f5-networks" 289 | offer = var.product 290 | sku = var.image_name 291 | version = var.bigip_version 292 | } 293 | 294 | storage_os_disk { 295 | name = "${var.prefix}-vm04-osdisk" 296 | caching = "ReadWrite" 297 | create_option = "FromImage" 298 | managed_disk_type = "Standard_LRS" 299 | } 300 | 301 | os_profile { 302 | computer_name = "${var.prefix}vm04" 303 | admin_username = var.adminUserName 304 | admin_password = var.adminPassword 305 | } 306 | 307 | os_profile_linux_config { 308 | disable_password_authentication = false 309 | } 310 | 311 | plan { 312 | name = var.image_name 313 | publisher = "f5-networks" 314 | product = var.product 315 | } 316 | 317 | tags = var.tags 318 | } 319 | 320 | # Setup Onboarding scripts 321 | 322 | data "template_file" "vm_onboard" { 323 | template = file("./templates/onboard.tpl") 324 | vars = { 325 | uname = var.adminUserName 326 | upassword = var.adminPassword 327 | doVersion = "latest" 328 | as3Version = "latest" 329 | tsVersion = "latest" 330 | cfVersion = "latest" 331 | fastVersion = "1.0.0" 332 | doExternalDeclarationUrl = "https://example.domain.com/do.json" 333 | as3ExternalDeclarationUrl = "https://example.domain.com/as3.json" 334 | tsExternalDeclarationUrl = "https://example.domain.com/ts.json" 335 | cfExternalDeclarationUrl = "https://example.domain.com/cf.json" 336 | onboard_log = var.onboard_log 337 | mgmtGateway = local.mgmt_gw 338 | DO1_Document = data.template_file.vm03_do_json.rendered 339 | DO2_Document = data.template_file.vm04_do_json.rendered 340 | AS3_Document = data.template_file.as3_json.rendered 341 | } 342 | } 343 | 344 | # as3 uuid generation 345 | resource "random_uuid" "as3_uuid" {} 346 | 347 | data "http" "onboard" { 348 | url = "https://raw.githubusercontent.com/Mikej81/f5-bigip-hardening-DO/master/dist/terraform/latest/${var.licenses["license3"] != "" ? "byol" : "payg"}_cluster_waf_tier.json" 349 | } 350 | 351 | data "template_file" "vm03_do_json" { 352 | template = data.http.onboard.body 353 | vars = { 354 | host1 = var.hosts["host3"] 355 | host2 = var.hosts["host4"] 356 | local_host = var.hosts["host3"] 357 | external_selfip = "${var.f5_t3_ext["f5vm03ext"]}/${element(split("/", var.subnets["waf_ext"]), 1)}" 358 | internal_selfip = "${var.f5_t3_int["f5vm03int"]}/${element(split("/", var.subnets["waf_int"]), 1)}" 359 | log_localip = var.f5_t3_ext["f5vm03ext"] 360 | log_destination = var.app01ip 361 | vdmsSubnet = var.subnets["vdms"] 362 | appSubnet = var.subnets["application"] 363 | vnetSubnet = var.cidr 364 | remote_host = var.hosts["host4"] 365 | remote_selfip = var.f5_t3_ext["f5vm04ext"] 366 | externalGateway = local.waf_ext_gw 367 | internalGateway = local.waf_int_gw 368 | mgmtGateway = local.mgmt_gw 369 | dns_server = var.dns_server 370 | ntp_server = var.ntp_server 371 | timezone = var.timezone 372 | admin_user = var.adminUserName 373 | admin_password = var.adminPassword 374 | license = var.licenses["license3"] != "" ? var.licenses["license3"] : "" 375 | } 376 | } 377 | 378 | data "template_file" "vm04_do_json" { 379 | template = data.http.onboard.body 380 | vars = { 381 | host1 = var.hosts["host3"] 382 | host2 = var.hosts["host4"] 383 | local_host = var.hosts["host4"] 384 | external_selfip = "${var.f5_t3_ext["f5vm04ext"]}/${element(split("/", var.subnets["waf_ext"]), 1)}" 385 | internal_selfip = "${var.f5_t3_int["f5vm04int"]}/${element(split("/", var.subnets["waf_int"]), 1)}" 386 | log_localip = var.f5_t3_ext["f5vm04ext"] 387 | log_destination = var.app01ip 388 | vdmsSubnet = var.subnets["vdms"] 389 | appSubnet = var.subnets["application"] 390 | vnetSubnet = var.cidr 391 | remote_host = var.hosts["host3"] 392 | remote_selfip = var.f5_t3_ext["f5vm03ext"] 393 | externalGateway = local.waf_ext_gw 394 | internalGateway = local.waf_int_gw 395 | mgmtGateway = local.mgmt_gw 396 | dns_server = var.dns_server 397 | ntp_server = var.ntp_server 398 | timezone = var.timezone 399 | admin_user = var.adminUserName 400 | admin_password = var.adminPassword 401 | license = var.licenses["license4"] != "" ? var.licenses["license4"] : "" 402 | } 403 | } 404 | 405 | data "http" "appservice" { 406 | url = "https://raw.githubusercontent.com/Mikej81/f5-bigip-hardening-AS3/master/dist/terraform/latest/sccaWAFTier.json" 407 | } 408 | 409 | data "template_file" "as3_json" { 410 | template = data.http.appservice.body 411 | vars = { 412 | uuid = random_uuid.as3_uuid.result 413 | baseline_waf_policy = var.asm_policy 414 | exampleVipAddress = var.f5_t3_ext["f5vm03ext"] 415 | exampleVipSubnet = var.subnets["waf_ext"] 416 | ips_pool_addresses = var.app01ip 417 | rdp_pool_addresses = var.winjumpip 418 | ssh_pool_addresses = var.linuxjumpip 419 | app_pool_addresses = var.app01ip 420 | log_destination = var.app01ip 421 | mgmtVipAddress = var.f5_t3_ext["f5vm03ext_sec"] 422 | mgmtVipAddress2 = var.f5_t3_ext["f5vm04ext_sec"] 423 | transitVipAddress = var.f5_t3_int["f5vm03int_sec"] 424 | transitVipAddress2 = var.f5_t3_int["f5vm04int_sec"] 425 | } 426 | } 427 | 428 | # Run Startup Script 429 | resource "azurerm_virtual_machine_extension" "f5vm03-run-startup-cmd" { 430 | name = "${var.prefix}-f5vm03-run-startup-cmd" 431 | depends_on = [azurerm_virtual_machine.f5vm03, azurerm_network_interface_backend_address_pool_association.mpool_assc_vm01, azurerm_network_interface_backend_address_pool_association.mpool_assc_vm02] 432 | virtual_machine_id = azurerm_virtual_machine.f5vm03.id 433 | publisher = "Microsoft.Azure.Extensions" 434 | type = "CustomScript" 435 | type_handler_version = "2.0" 436 | 437 | settings = <> ./startup.b64 && cat ./startup.b64 | base64 -d >> ./startup-temp.sh && sed -e 's/\r$//' ./startup-temp.sh > ./startup-script.sh && chmod +x ./startup-script.sh && rm ./startup.b64 && bash ./startup-script.sh 1" 440 | } 441 | SETTINGS 442 | 443 | tags = var.tags 444 | } 445 | 446 | resource "azurerm_virtual_machine_extension" "f5vm04-run-startup-cmd" { 447 | name = "${var.prefix}-f5vm04-run-startup-cmd" 448 | depends_on = [azurerm_virtual_machine.f5vm03, azurerm_virtual_machine.f5vm04, azurerm_network_interface_backend_address_pool_association.mpool_assc_vm01, azurerm_network_interface_backend_address_pool_association.mpool_assc_vm02] 449 | virtual_machine_id = azurerm_virtual_machine.f5vm04.id 450 | publisher = "Microsoft.Azure.Extensions" 451 | type = "CustomScript" 452 | type_handler_version = "2.0" 453 | 454 | settings = <> ./startup.b64 && cat ./startup.b64 | base64 -d >> ./startup-temp.sh && sed -e 's/\r$//g' ./startup-temp.sh > ./startup-script.sh && chmod +x ./startup-script.sh && rm ./startup.b64 && bash ./startup-script.sh 2" 457 | } 458 | SETTINGS 459 | 460 | tags = var.tags 461 | } 462 | 463 | 464 | # Debug Template Outputs 465 | resource "local_file" "vm03_do_file" { 466 | content = data.template_file.vm03_do_json.rendered 467 | filename = "${path.module}/vm03_do_data.json" 468 | } 469 | 470 | resource "local_file" "vm04_do_file" { 471 | content = data.template_file.vm04_do_json.rendered 472 | filename = "${path.module}/vm04_do_data.json" 473 | } 474 | 475 | resource "local_file" "vm_as3_file" { 476 | content = data.template_file.as3_json.rendered 477 | filename = "${path.module}/vm_as3_data.json" 478 | } 479 | 480 | resource "local_file" "onboard_file" { 481 | content = data.template_file.vm_onboard.rendered 482 | filename = "${path.module}/onboard.sh" 483 | } 484 | -------------------------------------------------------------------------------- /three_tier/waf/outputs.tf: -------------------------------------------------------------------------------- 1 | # data azurerm_public_ip f5vmpip03 { 2 | # name = azurerm_public_ip.f5vmpip03.name 3 | # resource_group_name = var.resourceGroup.name 4 | # depends_on = [azurerm_public_ip.f5vmpip03, azurerm_virtual_machine.f5vm03] 5 | # } 6 | # data azurerm_public_ip f5vmpip04 { 7 | # name = azurerm_public_ip.f5vmpip04.name 8 | # resource_group_name = var.resourceGroup.name 9 | # depends_on = [azurerm_public_ip.f5vmpip04, azurerm_virtual_machine.f5vm04] 10 | # } 11 | 12 | 13 | output f5vm03_id { value = azurerm_virtual_machine.f5vm03.id } 14 | output f5vm03_mgmt_private_ip { value = azurerm_network_interface.vm03-mgmt-nic.private_ip_address } 15 | #output f5vm03_mgmt_public_ip { value = data.azurerm_public_ip.f5vmpip03.ip_address } 16 | output f5vm03_ext_private_ip { value = azurerm_network_interface.vm03-ext-nic.private_ip_address } 17 | 18 | output f5vm04_id { value = azurerm_virtual_machine.f5vm04.id } 19 | output f5vm04_mgmt_private_ip { value = azurerm_network_interface.vm04-mgmt-nic.private_ip_address } 20 | #output f5vm04_mgmt_public_ip { value = data.azurerm_public_ip.f5vmpip04.ip_address } 21 | output f5vm04_ext_private_ip { value = azurerm_network_interface.vm04-ext-nic.private_ip_address } 22 | -------------------------------------------------------------------------------- /three_tier/waf/variables.tf: -------------------------------------------------------------------------------- 1 | variable resourceGroup { 2 | default = "" 3 | } 4 | # admin credentials 5 | variable adminUserName { default = "" } 6 | variable adminPassword { default = "" } 7 | variable sshPublicKey { default = "" } 8 | # cloud info 9 | variable location {} 10 | variable region {} 11 | variable securityGroup {} 12 | variable availabilitySet {} 13 | variable availabilitySet2 {} 14 | 15 | variable prefix {} 16 | # bigip network 17 | variable subnets {} 18 | variable subnetMgmt {} 19 | variable subnetExternal {} 20 | variable subnetInternal {} 21 | variable subnetWafExt {} 22 | variable subnetWafInt {} 23 | variable app01ip {} 24 | variable backendPool { 25 | description = "azureLB resource pool" 26 | } 27 | variable primaryPool {} 28 | variable managementPool {} 29 | variable wafEgressPool {} 30 | variable wafIngressPool {} 31 | 32 | variable ilb02ip {} 33 | 34 | # bigip networks 35 | variable f5_mgmt {} 36 | variable f5_t1_ext {} 37 | variable f5_t1_int {} 38 | variable f5_t3_ext {} 39 | variable f5_t3_int {} 40 | 41 | # winjump 42 | variable winjumpip {} 43 | 44 | # linuxjump 45 | variable linuxjumpip {} 46 | 47 | # device 48 | variable instanceType {} 49 | 50 | 51 | # BIGIP Image 52 | variable image_name {} 53 | variable product {} 54 | variable bigip_version {} 55 | 56 | variable vnet {} 57 | 58 | # BIGIP Setup 59 | variable hosts {} 60 | variable cidr {} 61 | variable licenses { 62 | type = map(string) 63 | default = { 64 | "license1" = "" 65 | "license2" = "" 66 | "license3" = "" 67 | "license4" = "" 68 | } 69 | } 70 | 71 | variable dns_server {} 72 | variable ntp_server {} 73 | variable timezone { default = "UTC" } 74 | variable onboard_log { default = "/var/log/startup-script.log" } 75 | ## ASM Policy 76 | ## -Examples: https://github.com/f5devcentral/f5-asm-policy-templates 77 | ## -Default is using OWASP Ready Autotuning 78 | variable asm_policy {} 79 | 80 | # TAGS 81 | variable tags {} 82 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | # Azure Environment 2 | variable projectPrefix { 3 | type = string 4 | description = "REQUIRED: Prefix to prepend to all objects created, minus Windows Jumpbox" 5 | default = "ccbad9e7" 6 | } 7 | variable adminUserName { 8 | type = string 9 | description = "REQUIRED: Admin Username for All systems" 10 | default = "xadmin" 11 | } 12 | variable adminPassword { 13 | type = string 14 | description = "REQUIRED: Admin Password for all systems" 15 | default = "pleaseUseVault123!!" 16 | } 17 | variable location { 18 | type = string 19 | description = "REQUIRED: Azure Region: usgovvirginia, usgovarizona, etc. For a list of available locations for your subscription use `az account list-locations -o table`" 20 | default = "usgovvirginia" 21 | } 22 | variable region { 23 | type = string 24 | description = "Azure Region: US Gov Virginia, US Gov Arizona, etc" 25 | default = "US Gov Virginia" 26 | } 27 | variable deploymentType { 28 | type = string 29 | description = "REQUIRED: This determines the type of deployment; one tier versus three tier: one_tier, three_tier" 30 | default = "three_tier" 31 | } 32 | variable deployDemoApp { 33 | type = string 34 | description = "OPTIONAL: Deploy Demo Application with Stack. Recommended to show functionality. Options: deploy, anything else." 35 | default = "deploy" 36 | } 37 | variable sshPublicKey { 38 | type = string 39 | description = "OPTIONAL: ssh public key for instances" 40 | default = "" 41 | } 42 | variable sshPublicKeyPath { 43 | type = string 44 | description = "OPTIONAL: ssh public key path for instances" 45 | default = "/mykey.pub" 46 | } 47 | 48 | # NETWORK 49 | variable cidr { 50 | description = "REQUIRED: VNET Network CIDR" 51 | default = "10.90.0.0/16" 52 | } 53 | 54 | variable subnets { 55 | type = map(string) 56 | description = "REQUIRED: Subnet CIDRs" 57 | default = { 58 | "management" = "10.90.0.0/24" 59 | "external" = "10.90.1.0/24" 60 | "internal" = "10.90.2.0/24" 61 | "vdms" = "10.90.3.0/24" 62 | "inspect_ext" = "10.90.4.0/24" 63 | "inspect_int" = "10.90.5.0/24" 64 | "waf_ext" = "10.90.6.0/24" 65 | "waf_int" = "10.90.7.0/24" 66 | "application" = "10.90.10.0/24" 67 | } 68 | } 69 | 70 | variable f5_mgmt { 71 | description = "F5 BIG-IP Management IPs. These must be in the management subnet." 72 | type = map(string) 73 | default = { 74 | f5vm01mgmt = "10.90.0.4" 75 | f5vm02mgmt = "10.90.0.5" 76 | f5vm03mgmt = "10.90.0.6" 77 | f5vm04mgmt = "10.90.0.7" 78 | } 79 | } 80 | 81 | # bigip external private ips, these must be in external subnet 82 | variable f5_t1_ext { 83 | description = "Tier 1 BIG-IP External IPs. These must be in the external subnet." 84 | type = map(string) 85 | default = { 86 | f5vm01ext = "10.90.1.4" 87 | f5vm01ext_sec = "10.90.1.11" 88 | f5vm02ext = "10.90.1.5" 89 | f5vm02ext_sec = "10.90.1.12" 90 | } 91 | } 92 | 93 | variable f5_t1_int { 94 | description = "Tier 1 BIG-IP Internal IPs. These must be in the internal subnet." 95 | type = map(string) 96 | default = { 97 | f5vm01int = "10.90.2.4" 98 | f5vm01int_sec = "10.90.2.11" 99 | f5vm02int = "10.90.2.5" 100 | f5vm02int_sec = "10.90.2.12" 101 | } 102 | } 103 | 104 | variable f5_t3_ext { 105 | description = "Tier 3 BIG-IP External IPs. These must be in the waf external subnet." 106 | type = map(string) 107 | default = { 108 | f5vm03ext = "10.90.6.4" 109 | f5vm03ext_sec = "10.90.6.11" 110 | f5vm04ext = "10.90.6.5" 111 | f5vm04ext_sec = "10.90.6.12" 112 | } 113 | } 114 | 115 | variable f5_t3_int { 116 | description = "Tier 3 BIG-IP Internal IPs. These must be in the waf internal subnet." 117 | type = map(string) 118 | default = { 119 | f5vm03int = "10.90.7.4" 120 | f5vm03int_sec = "10.90.7.11" 121 | f5vm04int = "10.90.7.5" 122 | f5vm04int_sec = "10.90.7.12" 123 | } 124 | } 125 | 126 | variable internalILBIPs { 127 | description = "REQUIRED: Used by One and Three Tier. Azure internal load balancer ips, these are used for ingress and egress." 128 | type = map(string) 129 | default = {} 130 | } 131 | 132 | variable ilb01ip { 133 | type = string 134 | description = "REQUIRED: Used by One and Three Tier. Azure internal load balancer ip, this is used as egress, must be in internal subnet." 135 | default = "10.90.2.10" 136 | } 137 | 138 | variable ilb02ip { 139 | type = string 140 | description = "REQUIRED: Used by Three Tier only. Azure waf external load balancer ip, this is used as egress, must be in waf_ext subnet." 141 | default = "10.90.6.10" 142 | } 143 | 144 | variable ilb03ip { 145 | type = string 146 | description = "REQUIRED: Used by Three Tier only. Azure waf external load balancer ip, this is used as ingress, must be in waf_ext subnet." 147 | default = "10.90.6.13" 148 | } 149 | 150 | variable ilb04ip { 151 | type = string 152 | description = "REQUIRED: Used by Three Tier only. Azure waf external load balancer ip, this is used as ingress, must be in inspect_external subnet." 153 | default = "10.90.4.13" 154 | } 155 | 156 | variable app01ip { 157 | type = string 158 | description = "OPTIONAL: Example Application used by all use-cases to demonstrate functionality of deploymeny, must reside in the application subnet." 159 | default = "10.90.10.101" 160 | } 161 | 162 | # Example IPS private ips 163 | variable ips01ext { default = "10.90.4.4" } 164 | variable ips01int { default = "10.90.5.4" } 165 | variable ips01mgmt { default = "10.90.0.8" } 166 | 167 | variable winjumpip { 168 | type = string 169 | description = "REQUIRED: Used by all use-cases for RDP/Windows Jumpbox, must reside in VDMS subnet." 170 | default = "10.90.3.98" 171 | } 172 | 173 | variable linuxjumpip { 174 | type = string 175 | description = "REQUIRED: Used by all use-cases for SSH/Linux Jumpbox, must reside in VDMS subnet." 176 | default = "10.90.3.99" 177 | } 178 | 179 | # BIGIP Instance Type, DS5_v2 is a solid baseline for BEST 180 | variable instanceType { default = "Standard_DS5_v2" } 181 | 182 | # Be careful which instance type selected, jump boxes currently use Premium_LRS managed disks 183 | variable jumpinstanceType { default = "Standard_B2s" } 184 | 185 | # Demo Application Instance Size 186 | variable appInstanceType { default = "Standard_DS3_v2" } 187 | 188 | # BIGIP Image 189 | variable image_name { 190 | type = string 191 | description = "REQUIRED: BIG-IP Image Name. 'az vm image list --output table --publisher f5-networks --location [region] --offer f5-big-ip --all' Default f5-bigip-virtual-edition-1g-best-hourly is PAYG Image. For BYOL use f5-big-all-2slot-byol" 192 | default = "f5-bigip-virtual-edition-1g-best-hourly" 193 | } 194 | variable product { 195 | type = string 196 | description = "REQUIRED: BYOL = f5-big-ip-byol, PAYG = f5-big-ip-best" 197 | default = "f5-big-ip-best" 198 | } 199 | variable bigip_version { 200 | type = string 201 | description = "REQUIRED: BIG-IP Version. Note: verify available versions before using as images can change." 202 | default = "14.1.400000" 203 | } 204 | 205 | # BIGIP Setup 206 | # Licenses are only needed when using BYOL images 207 | variable licenses { 208 | type = map(string) 209 | default = { 210 | "license1" = "" 211 | "license2" = "" 212 | "license3" = "" 213 | "license4" = "" 214 | } 215 | } 216 | 217 | variable hosts { 218 | type = map(string) 219 | default = { 220 | "host1" = "f5vm01" 221 | "host2" = "f5vm02" 222 | "host3" = "f5vm03" 223 | "host4" = "f5vm04" 224 | } 225 | } 226 | 227 | variable dns_server { 228 | type = string 229 | description = "REQUIRED: Default is set to Azure DNS." 230 | default = "168.63.129.16" 231 | } 232 | 233 | ## ASM Policy 234 | variable asm_policy { 235 | type = string 236 | description = "REQUIRED: ASM Policy. Examples: https://github.com/f5devcentral/f5-asm-policy-templates. Default: OWASP Ready Autotuning" 237 | default = "https://raw.githubusercontent.com/f5devcentral/f5-asm-policy-templates/master/owasp_ready_template/owasp-auto-tune-v1.1.xml" 238 | } 239 | 240 | variable ntp_server { default = "time.nist.gov" } 241 | variable timezone { default = "UTC" } 242 | variable onboard_log { default = "/var/log/startup-script.log" } 243 | 244 | # TAGS 245 | variable tags { 246 | description = "Environment tags for objects" 247 | type = map(string) 248 | default = { 249 | "purpose" = "public" 250 | "environment" = "f5env" 251 | "owner" = "f5owner" 252 | "group" = "f5group" 253 | "costcenter" = "f5costcenter" 254 | "application" = "f5app" 255 | } 256 | } 257 | --------------------------------------------------------------------------------