To use this new release you need to perform a full deployment. You cannot automatically upgrade from the previous launchpad.

Moving forward this version adds the foundations to support future upgrade without destroying the launchpad.
This commit is contained in:
Arnaud Lheureux 2020-11-06 12:45:13 +08:00 коммит произвёл GitHub
Родитель 3dd8436e2a
Коммит c1829121f1
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
318 изменённых файлов: 11832 добавлений и 8581 удалений

Просмотреть файл

@ -4,13 +4,13 @@
// Update the 'dockerComposeFile' list if you have more compose files or use different names. // Update the 'dockerComposeFile' list if you have more compose files or use different names.
"dockerComposeFile": "docker-compose.yml", "dockerComposeFile": "docker-compose.yml",
// Container user to use in VSCode Online and GitHub Codespaces
"containerUser" : "vscode",
// The 'service' property is the name of the service for the container that VS Code should // The 'service' property is the name of the service for the container that VS Code should
// use. Update this value and .devcontainer/docker-compose.yml to the real service name. // use. Update this value and .devcontainer/docker-compose.yml to the real service name.
"service": "rover", "service": "rover",
// Container user to use in VSCode Online and GitHub Codespaces
"containerUser" : "vscode",
// The optional 'workspaceFolder' property is the path VS Code should open by default when // The optional 'workspaceFolder' property is the path VS Code should open by default when
// connected. This is typically a volume mount in .devcontainer/docker-compose.yml // connected. This is typically a volume mount in .devcontainer/docker-compose.yml
"workspaceFolder": "/tf/caf", "workspaceFolder": "/tf/caf",
@ -31,7 +31,7 @@
// "shutdownAction": "none", // "shutdownAction": "none",
// Uncomment the next line to run commands after the container is created. // Uncomment the next line to run commands after the container is created.
"postCreateCommand": "cp -R /tmp/.ssh-localhost/* ~/.ssh && chmod 700 ~/.ssh && chmod 600 ~/.ssh/*", "postCreateCommand": "cp -R /tmp/.ssh-localhost/* ~/.ssh && sudo chmod 600 ~/.ssh/* && sudo chown -R $(whoami) /tf/caf && git config --global core.editor vi && pre-commit install && pre-commit update",
// Add the IDs of extensions you want installed when the container is created in the array below. // Add the IDs of extensions you want installed when the container is created in the array below.
"extensions": [ "extensions": [

Просмотреть файл

@ -6,7 +6,8 @@
version: '3.7' version: '3.7'
services: services:
rover: rover:
image: aztfmod/rover:2009.0210 image: aztfmod/rover:2010.2808
user: vscode
labels: labels:
- "caf=Azure CAF" - "caf=Azure CAF"

272
.github/workflows/landingzones.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,272 @@
#
# Copyright (c) Microsoft Corporation
# Licensed under the MIT License.
#
name: landingzones
on:
pull_request:
paths-ignore:
- 'documentation/**'
- '_pictures/**'
- 'README.md'
- 'CHANGELOG.md'
push:
paths-ignore:
- 'documentation/**'
- '_pictures/**'
- 'README.md'
- 'CHANGELOG.md'
schedule:
- cron: '0 4 * * *'
env:
TF_CLI_ARGS: '-no-color'
TF_CLI_ARGS_destroy: '-auto-approve -refresh=false'
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
jobs:
foundations100:
name: foundations-100
runs-on: ubuntu-latest
strategy:
fail-fast: true
max-parallel: 1
matrix:
random_length: ['5']
container:
image: aztfmod/rover:2010.2808
options: --user 0
steps:
- uses: actions/checkout@v2
- name: Login azure
run: |
az login --service-principal -u '${{ env.ARM_CLIENT_ID }}' -p '${{ env.ARM_CLIENT_SECRET }}' --tenant '${{ env.ARM_TENANT_ID }}'
az account set -s ${{ env.ARM_SUBSCRIPTION_ID }}
echo "local user: $(whoami)"
- name: launchpad
run: |
/tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a apply \
-var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/100 \
-level level0 \
-launchpad \
-parallelism=30 \
--environment ${{ github.run_id }} \
'-var random_length=${{ matrix.random_length }}' \
'-var prefix=g${{ github.run_id }}' \
'-var tags={testing_job_id="${{ github.run_id }}"}'
- name: foundations
run: |
/tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a apply \
-level level1 \
-parallelism=30 \
--environment ${{ github.run_id }}
networking100:
name: networking-100
runs-on: ubuntu-latest
needs: foundations100
strategy:
fail-fast: false
matrix:
config_files: [
"caf_networking/scenario/100-single-region-hub",
"caf_networking/scenario/101-multi-region-hub",
"caf_networking/scenario/105-hub-and-spoke",
"caf_networking/scenario/106-hub-virtual-wan-firewall"
]
container:
image: aztfmod/rover:2010.2808
options: --user 0
steps:
- uses: actions/checkout@v2
- name: Login azure
run: |
az login --service-principal -u '${{ env.ARM_CLIENT_ID }}' -p '${{ env.ARM_CLIENT_SECRET }}' --tenant '${{ env.ARM_TENANT_ID }}'
az account set -s ${{ env.ARM_SUBSCRIPTION_ID }}
- name: deploy example
run: |
/tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a apply \
-tfstate $(basename ${{ matrix.config_files }}).tfstate \
-level level2 \
-parallelism=30 \
-var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \
--environment ${{ github.run_id }}
- name: destroy example
run: |
/tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a destroy \
-tfstate $(basename ${{ matrix.config_files }}).tfstate \
-level level2 \
-parallelism=30 \
-var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \
--environment ${{ github.run_id }} \
-refresh=false \
-auto-approve
foundations200:
name: foundations-200
runs-on: ubuntu-latest
needs: networking100
if: always()
strategy:
fail-fast: true
max-parallel: 1
matrix:
random_length: ['5']
container:
image: aztfmod/rover:2010.2808
options: --user 0
steps:
- uses: actions/checkout@v2
- name: Login azure
run: |
az login --service-principal -u '${{ env.ARM_CLIENT_ID }}' -p '${{ env.ARM_CLIENT_SECRET }}' --tenant '${{ env.ARM_TENANT_ID }}'
az account set -s ${{ env.ARM_SUBSCRIPTION_ID }}
echo "local user: $(whoami)"
- name: launchpad-200-upgrade
run: |
/tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a apply \
-var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/200 \
-level level0 \
-launchpad \
-parallelism=30 \
--environment ${{ github.run_id }} \
'-var random_length=${{ matrix.random_length }}' \
'-var prefix=g${{ github.run_id }}' \
'-var tags={testing_job_id="${{ github.run_id }}"}'
- name: foundations-200-upgrade
run: |
/tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a apply \
-level level1 \
--environment ${{ github.run_id }}
networking200:
name: networking-200
runs-on: ubuntu-latest
needs: foundations200
strategy:
fail-fast: false
matrix:
config_files: [
"caf_networking/scenario/200-single-region-hub",
"caf_networking/scenario/201-multi-region-hub",
"caf_networking/scenario/210-aks-private"
]
container:
image: aztfmod/rover:2010.2808
options: --user 0
steps:
- uses: actions/checkout@v2
- name: Login azure
run: |
az login --service-principal -u '${{ env.ARM_CLIENT_ID }}' -p '${{ env.ARM_CLIENT_SECRET }}' --tenant '${{ env.ARM_TENANT_ID }}'
az account set -s ${{ env.ARM_SUBSCRIPTION_ID }}
- name: deploy example
run: |
/tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a apply \
-tfstate $(basename ${{ matrix.config_files }}).tfstate \
-level level2 \
-parallelism=30 \
-var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \
--environment ${{ github.run_id }}
- name: destroy example
run: |
/tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a destroy \
-tfstate $(basename ${{ matrix.config_files }}).tfstate \
-level level2 \
-parallelism=30 \
-var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \
--environment ${{ github.run_id }} \
-refresh=false \
-auto-approve
foundations_destroy:
name: foundations_destroy
runs-on: ubuntu-latest
if: always()
needs: networking200
strategy:
fail-fast: false
matrix:
random_length: ['5']
container:
image: aztfmod/rover:2010.2808
options: --user 0
steps:
- uses: actions/checkout@v2
- name: Login azure
run: |
az login --service-principal -u '${{ env.ARM_CLIENT_ID }}' -p '${{ env.ARM_CLIENT_SECRET }}' --tenant '${{ env.ARM_TENANT_ID }}'
az account set -s ${{ env.ARM_SUBSCRIPTION_ID }}
echo "local user: $(whoami)"
- name: foundations
run: |
/tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a destroy \
-level level1 \
-parallelism=30 \
--environment ${{ github.run_id }} \
-auto-approve
- name: Remove launchpad
run: |
/tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a destroy \
-var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/200 \
-level level0 \
-launchpad \
-parallelism=30 \
--environment ${{ github.run_id }} \
'-var random_length=${{ matrix.random_length }}' \
'-var prefix=g${{ github.run_id }}' \
'-var tags={testing_job_id="${{ github.run_id }}"}' \
-auto-approve
- name: Complete purge
if: ${{ always() }}
run: |
for i in `az monitor diagnostic-settings subscription list -o tsv --query "value[?contains(name, '${{ github.run_id }}' )].name"`; do echo "purging subscription diagnostic-settings: $i" && $(az monitor diagnostic-settings subscription delete --name $i --yes); done
for i in `az monitor log-profiles list -o tsv --query '[].name'`; do az monitor log-profiles delete --name $i; done
for i in `az ad group list --query "[?contains(displayName, '${{ github.run_id }}')].objectId" -o tsv`; do echo "purging Azure AD group: $i" && $(az ad group delete --verbose --group $i || true); done
for i in `az ad app list --query "[?contains(displayName, '${{ github.run_id }}')].appId" -o tsv`; do echo "purging Azure AD app: $i" && $(az ad app delete --verbose --id $i || true); done
for i in `az keyvault list-deleted --query "[?tags.environment=='${{ github.run_id }}'].name" -o tsv`; do az keyvault purge --name $i; done
for i in `az group list --query "[?tags.environment=='${{ github.run_id }}'].name" -o tsv`; do echo "purging resource group: $i" && $(az group delete -n $i -y --no-wait || true); done
for i in `az role assignment list --query "[?contains(roleDefinitionName, '${{ github.run_id }}')].roleDefinitionName" -o tsv`; do echo "purging role assignment: $i" && $(az role assignment delete --role $i || true); done
for i in `az role definition list --query "[?contains(roleName, '${{ github.run_id }}')].roleName" -o tsv`; do echo "purging custom role definition: $i" && $(az role definition delete --name $i || true); done

278
.github/workflows/master.yml поставляемый
Просмотреть файл

@ -1,278 +0,0 @@
#
# Copyright (c) Microsoft Corporation
# Licensed under the MIT License.
#
name: landingzones
on:
pull_request:
branches:
- master
push:
branches:
- master
paths-ignore:
- 'documentation/**'
- '_pictures/**'
- 'README.md'
- 'CHANGELOG.md'
schedule:
- cron: '0 0 * * *'
env:
TF_CLI_ARGS: '-no-color'
TF_CLI_ARGS_destroy: '-auto-approve -refresh=false'
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
TFVARS_PATH: '/tf/caf/caf-terraform-landingzones'
jobs:
tfsec:
name: Run TFsec
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Terraform security scan
uses: triat/terraform-security-scan@v2.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
level0:
name: level0
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 1
matrix:
region: ["westus2"]
convention: ["random"]
container:
image: aztfmod/rover:2009.0210
options: --user 0
steps:
- uses: actions/checkout@v2
- name: Login azure
run: |
az login --service-principal -u '${{ env.ARM_CLIENT_ID }}' -p '${{ env.ARM_CLIENT_SECRET }}' --tenant '${{ env.ARM_TENANT_ID }}'
az account set -s ${{ env.ARM_SUBSCRIPTION_ID }}
echo "local user: $(whoami)"
- name: Locate launchpad
run: |
ln -s ${GITHUB_WORKSPACE} /tf/caf
id=$(az storage account list --query "[?tags.tfstate=='level0' && tags.environment=='${{ github.run_id }}']" -o json | jq -r .[0].id)
if [ "${id}" == "null" ]; then
/tf/rover/rover.sh -lz /tf/caf/caf-terraform-landingzones/landingzones/launchpad -a apply \
-launchpad \
--environment ${{ github.run_id }} \
'-var prefix=g${{ github.run_id }}' \
'-var location=${{ matrix.region }}' \
'-var convention=${{ matrix.convention }}' \
'-var tags={testing_job_id="${{ github.run_id }}"}'
fi
caf_foundations:
name: caf_foundations
runs-on: ubuntu-latest
needs: level0
strategy:
fail-fast: false
matrix:
landingzone: ["landingzone_caf_foundations"]
region: ["southeastasia"]
convention: ["random"]
environment: ["integration-tests"]
container:
image: aztfmod/rover:2009.0210
options: --user 0
steps:
- uses: actions/checkout@v2
- name: setup context
id: context
run: |
ln -s ${GITHUB_WORKSPACE} /tf/caf
echo "ls /tf/caf" && ls -lsa /tf/caf
ls -lsa /tmp
# workspace='caffoundationsci'
# echo ::set-env name=TF_VAR_workspace::${workspace}
- name: Login azure
run: |
az login --service-principal -u '${{ env.ARM_CLIENT_ID }}' -p '${{ env.ARM_CLIENT_SECRET }}' --tenant '${{ env.ARM_TENANT_ID }}'
az account set -s ${{ env.ARM_SUBSCRIPTION_ID }}
echo "local user: $(whoami)"
- name: deploy caf_foundations
run: |
/tf/rover/rover.sh -lz /tf/caf/caf-terraform-landingzones/landingzones/${{ matrix.landingzone }} -a apply \
--environment ${{ github.run_id }} \
-var prefix=g${{ github.run_id}} \
'-var tags={testing_job_id="${{ github.run_id }}"}' \
'-var-file ${{ env.TFVARS_PATH }}/environments/${{ matrix.environment }}/${{ matrix.landingzone }}/${{ matrix.landingzone }}_${{ matrix.region }}_${{ matrix.convention }}.tfvars'
landingzones:
name: landingzones
runs-on: ubuntu-latest
needs: [level0, caf_foundations]
strategy:
fail-fast: false
matrix:
landingzone: ["landingzone_networking"]
examples: ["101-multiple-vnets", "102-multiple-vnets-peering", "103-hub-vnet-with-firewall", "104-hub-vnet-with-firewall-bastion", "105-hub-virtual-wan-firewall"]
convention: ["cafrandom"]
container:
image: aztfmod/rover:2009.0210
options: --user 0
steps:
- uses: actions/checkout@v2
- name: setup context
id: context
run: |
ln -s ${GITHUB_WORKSPACE} /tf/caf
echo "ls /tf/caf" && ls -lsa /tf/caf
ls -lsa /tmp
- name: Login azure
run: |
az login --service-principal -u '${{ env.ARM_CLIENT_ID }}' -p '${{ env.ARM_CLIENT_SECRET }}' --tenant '${{ env.ARM_TENANT_ID }}'
az account set -s ${{ env.ARM_SUBSCRIPTION_ID }}
echo "local user: $(whoami)"
- name: Deploy landing_zone
run: |
/tf/rover/rover.sh -lz /tf/caf/caf-terraform-landingzones/landingzones/${{ matrix.landingzone }} -a apply \
-env ${{ github.run_id }} \
'-var tags={testing_job_id="${{ github.run_id }}"}' \
-tfstate ${{ matrix.examples }}_landingzone_networking.tfstate \
'-var-file ${{ env.TFVARS_PATH }}/landingzones/${{ matrix.landingzone }}/examples/${{ matrix.examples }}/configuration.tfvars'
- name: Destroy landing_zone
if: always()
run: |
/tf/rover/rover.sh -lz /tf/caf/caf-terraform-landingzones/landingzones/${{ matrix.landingzone }} -a destroy \
--environment ${{ github.run_id }} \
'-var tags={testing_job_id="${{ github.run_id }}"}' \
-tfstate ${{ matrix.examples }}_landingzone_networking.tfstate \
'-var-file ${{ env.TFVARS_PATH }}/landingzones/${{ matrix.landingzone }}/examples/${{ matrix.examples }}/configuration.tfvars'
caf_foundations_destroy:
name: caf_foundations_destroy
runs-on: ubuntu-latest
if: always()
needs: landingzones
strategy:
fail-fast: false
matrix:
landingzone: ["landingzone_caf_foundations"]
region: ["southeastasia"]
convention: ["random"]
environment: ["integration-tests"]
container:
image: aztfmod/rover:2009.0210
options: --user 0
steps:
- uses: actions/checkout@v2
- name: setup context
id: context
run: |
ln -s ${GITHUB_WORKSPACE} /tf/caf
echo "ls /tf/caf" && ls -lsa /tf/caf
ls -lsa /tmp
# workspace='caffoundationsci'
# echo ::set-env name=TF_VAR_workspace::${workspace}
- name: Login azure
run: |
az login --service-principal -u '${{ env.ARM_CLIENT_ID }}' -p '${{ env.ARM_CLIENT_SECRET }}' --tenant '${{ env.ARM_TENANT_ID }}'
az account set -s ${{ env.ARM_SUBSCRIPTION_ID }}
echo "local user: $(whoami)"
- name: destroy caf_foundations
run: |
/tf/rover/rover.sh -lz /tf/caf/caf-terraform-landingzones/landingzones/${{ matrix.landingzone }} -a destroy \
--environment ${{ github.run_id }} \
-var prefix=g${{ github.run_id}} \
'-var tags={testing_job_id="${{ github.run_id }}"}' \
'-var-file ${{ env.TFVARS_PATH }}/environments/${{ matrix.environment }}/${{ matrix.landingzone }}/${{ matrix.landingzone }}_${{ matrix.region }}_${{ matrix.convention }}.tfvars' \
'-auto-approve'
level0_destroy:
name: level0_destroy
runs-on: ubuntu-latest
if: always()
needs: caf_foundations_destroy
strategy:
fail-fast: false
matrix:
region: ["westus2"]
convention: ["random"]
container:
image: aztfmod/rover:2009.0210
options: --user 0
steps:
- uses: actions/checkout@v2
- name: Login azure
run: |
az login --service-principal -u '${{ env.ARM_CLIENT_ID }}' -p '${{ env.ARM_CLIENT_SECRET }}' --tenant '${{ env.ARM_TENANT_ID }}'
az account set -s ${{ env.ARM_SUBSCRIPTION_ID }}
echo "local user: $(whoami)"
- name: Remove launchpad
run: |
ln -s ${GITHUB_WORKSPACE} /tf/caf
/tf/rover/rover.sh -lz /tf/caf/caf-terraform-landingzones/landingzones/launchpad -a destroy \
-launchpad \
-env ${{ github.run_id }} \
'-var prefix=g${{ github.run_id }}' \
'-var location=${{ matrix.region }}' \
'-var convention=${{ matrix.convention }}' \
'-var tags={testing_job_id="${{ github.run_id }}"}' \
-auto-approve
- name: Complete purge
if: ${{ always() }}
run: |
for i in `az monitor log-profiles list -o tsv --query '[].name'`; do az monitor log-profiles delete --name $i; done
for i in `az ad group list --query "[?contains(displayName, '${{ github.run_id }}')].objectId" -o tsv`; do echo "purging Azure AD group: $i" && $(az ad group delete --verbose --group $i || true); done
for i in `az ad app list --query "[?contains(displayName, '${{ github.run_id }}')].appId" -o tsv`; do echo "purging Azure AD app: $i" && $(az ad app delete --verbose --id $i || true); done
for i in `az group list --query "[?tags.testing_job_id=='${{ github.run_id }}'].name" -o tsv`; do echo "purging resource group: $i" && $(az group delete -n $i -y --no-wait || true); done
for i in `az role assignment list --query "[?contains(roleDefinitionName, '${{ github.run_id }}')].roleDefinitionName" -o tsv`; do echo "purging role assignment: $i" && $(az role assignment delete --role $i || true); done
for i in `az role definition list --query "[?contains(roleName, '${{ github.run_id }}')].roleName" -o tsv`; do echo "purging custom role definition: $i" && $(az role definition delete --name $i || true); done

21
.pre-commit-config.yaml Normal file
Просмотреть файл

@ -0,0 +1,21 @@
# See http://pre-commit.com for more information
# See http://pre-commit.com/hooks.html for more hooks
repos:
- repo: git://github.com/antonbabenko/pre-commit-terraform
rev: v1.43.0
hooks:
- id: terraform_fmt
# - id: terraform_docs
# - id: terraform_tflint
# - id: terraform_tfsec
- repo: git://github.com/pre-commit/pre-commit-hooks
rev: v3.3.0
hooks:
- id: check-merge-conflict
- id: trailing-whitespace
- id: check-yaml
- id: check-added-large-files
# - repo: git://github.com/markdownlint/markdownlint
# rev: v0.9.0
# hooks:
# - id: markdownlint

Просмотреть файл

@ -1,4 +1,13 @@
## v8.0.2001 (August 2020) ## v9.0.2009 (September 2020)
BREAKING CHANGES:
* Iterating on our new key-based iterative model to simplify deployment and maintenance, this is a major refactoring that will bring compatibility with enterprise-scale landing zones and extensible platform for construction sets (solutions and applications) deployed on top of core landing zones.
FEATURES:
* **added support for azurerm 2.28 :** On all sample landing zones [azurerm provider](https://github.com/terraform-providers/terraform-provider-azurerm/releases/tag/v2.28.0)
## v8.0.2008 (August 2020)
BREAKING CHANGES: BREAKING CHANGES:

Просмотреть файл

@ -2,7 +2,6 @@
[![VScodespaces](https://img.shields.io/endpoint?url=https%3A%2F%2Faka.ms%2Fvso-badge)](https://online.visualstudio.com/environments/new?name=caf%20landing%20zones&repo=azure/caf-terraform-landingzones) [![VScodespaces](https://img.shields.io/endpoint?url=https%3A%2F%2Faka.ms%2Fvso-badge)](https://online.visualstudio.com/environments/new?name=caf%20landing%20zones&repo=azure/caf-terraform-landingzones)
[![Gitter](https://badges.gitter.im/aztfmod/community.svg)](https://gitter.im/aztfmod/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Gitter](https://badges.gitter.im/aztfmod/community.svg)](https://gitter.im/aztfmod/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
# Azure Cloud Adoption Framework landing zones for Terraform # Azure Cloud Adoption Framework landing zones for Terraform
Microsoft [Cloud Adoption Framework for Azure](https://aka.ms/caf) provides you with guidance and best practices to adopt Azure. Microsoft [Cloud Adoption Framework for Azure](https://aka.ms/caf) provides you with guidance and best practices to adopt Azure.
@ -24,25 +23,64 @@ Cloud Adoption Framework for Azure Terraform landing zones is an Open Source pro
* Propose a prescriptive guidance on how to enable DevOps for infrastructure as code on Microsoft Azure. * Propose a prescriptive guidance on how to enable DevOps for infrastructure as code on Microsoft Azure.
* Foster a community of Azure *Terraformers* using a common set of practices and sharing best practices. * Foster a community of Azure *Terraformers* using a common set of practices and sharing best practices.
## What's new in this release
This release is relying extensively on Terraform 0.13 capabilities (module iterations, conditional modules, variables validation, etc.).
Those new features allow more complex and more dynamic code composition. The following concepts are used:
* **No-code environment composition**: a landing zone environment can be composed customizing variable files and code must be robust enough to accommodate combinations and composition.
* **Flexible foundations to meet customer needs**: everything is customizable at all layers.
* **Key-based configuration and customization**: all configuration objects will call each other based on the object keys.
* **Iteration-based objects deployment**: a landing zone calls all its modules, iterating on complex objects for technical resources deployment.
* **Enterprise-scale support**: added support for foundations landing zones to optionally leverage Azure Enterprise-scale module.
* **Terraform Cloud/Enterprise bootstrap**: added initial support for Hashicorp Terraform Cloud/Enterprise to support environment bootstrap.
## Getting started ## Getting started
See our [Getting Started](./documentation/getting_started/getting_started.md) on your laptop, or on the web with [Getting Started on VSCodespaces](./documentation/getting_started/getting_started_codespaces.md). See our [Getting Started](./documentation/getting_started/getting_started.md) on your laptop, or on the web with [Getting Started on VSCodespaces](./documentation/getting_started/getting_started_codespaces.md).
See our [Getting Started Video](https://www.youtube.com/watch?v=t1exCkWft60) See our [Getting Started Video](https://www.youtube.com/watch?v=t1exCkWft60)
## Sample configuration repository
When starting an enterprise deployment, we recommend you start creating a configuration repository where you start crafting you configuration environment.
You can find the [starter repository here](https://github.com/Azure/caf-terraform-landingzones-starter)
## Documentation ## Documentation
More details on how to develop, deploy and operate with landing zones can be found in the reference section [here](./documentation/README.md) More details on how to develop, deploy and operate with landing zones can be found in the reference section [here](./documentation/README.md)
## Sample landing zones ## Sample landing zones
Currently we provide you with the following sample landing zones: Currently we provide you with the following core sample landing zones:
| Name | Purpose | | Name | Purpose |
|---------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [landingzone_caf_foundations](./landingzones/landingzone_caf_foundations) | setup all the fundamentals for a subscription (logging, accounting, security.). You can find all details of the caf_foundations landing zone [Here](./landingzones/landingzone_caf_foundations/readme.md) | | [caf_foundations](./landingzones/caf_foundations) | setup all the fundamentals for a subscription (logging, accounting, security.). You can find all details of the caf_foundations landing zone [Here](./landingzones/landingzone_caf_foundations/readme.md) |
| [landingzone_networking](./landingzones/landingzone_networking) | enables creation of any Azure networking combination of Virtual Networks-based hub-and-spoke topologies or Azure Virtual WAN based topologies. | | [caf_networking](./landingzones/caf_networking) | enables creation of any Azure networking combination of Virtual Networks-based hub-and-spoke topologies or Azure Virtual WAN based topologies. |
| [launchpad](./landingzones/launchpad) | provides the state management capabilities and security features leveraging Azure storage for the backend, provides secret management and modular approach to support plugin for Azure DevOps automated pipeline creation (and others) | | [caf_shared_services](./landingzones/caf_shared_services) | provides shared services like monitoring, Azure Backup, Azure Site Recovery etc. |
| [caf_launchpad](./landingzones/caf_launchpad) | provides the state management capabilities and security features leveraging Azure storage for the backend, provides secret management and modular approach to support plugin for Azure DevOps automated pipeline creation (and others) |
For each landing zones, we provide different level of configuration examples to meet different purposes:
| level | scenario | requirements |
|-------|----------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------|
| 100 | Start with this one! basic functionalities and features, no RBAC or security hardening - for demo and simple POC | working on any subscription with Owner permissions |
| 200 | intermediate functionalities includes diagnostics features and Azure Active Directory groups | may need custom AAD permissions |
| 300 | advanced functionalities, includes RBAC features, virtual network and private link scenario and reduced portal view for hardened items | need custom AAD permissions |
| 400 | advanced functionalities, includes RBAC features and security hardening | need custom AAD permissions |
## Landing zone solutions
Once you deploy the core components, you can leverage the following additional solution landing zones (work in progress!):
| Solution | URL |
|---------------------------|-------------------------------------------------------|
| Azure Kubernetes Services | https://github.com/aztfmod/landingzone_aks |
| Data and Analytics | https://github.com/aztfmod/landingzone_data_analytics |
| SAP HANA on Azure | Coming Soon |
| Shared Image Gallery | Coming soon |
## Repositories ## Repositories

Просмотреть файл

@ -0,0 +1,155 @@
# Setting up identity bootstrap account
The purpose of the CAF Level 0 (L0) bootstrap Azure AD application is to own the creation of the launchpads. During that process a new Azure AD application is created with less permissions on the directory and also more specific Azure permissions to fulfill the Azure operations of the
level0 (subscription creation for example)
This document explains the manual process to create the L0 Azure AD app and the following information must be captured:
| Variable | Item | Value |
| -------------------- | ------------------------ | ---- |
|ARM\_CLIENT\_ID | Application (client) ID | |
|ARM\_CLIENT\_SECRET | Client secret | |
|ARM\_TENANT\_ID | Directory (tenant) ID | |
|ARM\_SUBSCRIPTION\_ID | Subscription ID | |
## Create Azure AD L0 App
Go to Azure Active Directory
![](./images/Bootstrap/image1.png)
Create a **new** Azure **Active Directory Application**
![](./images/Bootstrap/image2.png)
![](./images/Bootstrap/image3.png)
From the property pane select "**API permissions**"
![](./images/Bootstrap/image4.png)
**Remove** the default one
![](./images/Bootstrap/image5.png)
**Confirm the deletion**
![](./images/Bootstrap/image6.png)
Click on "**Add a permission**"
![](./images/Bootstrap/image7.png)
Select "**Application permissions**"
![](./images/Bootstrap/image8.png)
Select from "**Application**", "**Application.ReadWrite.OwnedBy**"
![](./images/Bootstrap/image9.png)
Then from "**Directory**" select "**Directory.ReadWrite.All**"
![](./images/Bootstrap/image10.png)
Complete the operation by pressing the blue button "**Add permissions**"
Click again on "*Add permission*"
![](./images/Bootstrap/image11.png)
Select the "**Microsoft Graph**"
![](./images/Bootstrap/image12.png)
Select "**Application permissions**"
![](./images/Bootstrap/image13.png)
From "**AppRoleAssignment**" select "**AppRoleAssignment.ReadWrite.All**"
![](./images/Bootstrap/image14.png)
From "**DelegatedPermissionGrant**" select "**DelegatedPermissionGrant.ReadWrite.All**"
![](./images/Bootstrap/image15.png)
From "**Directory**" select "**Directory.ReadWrite.All**"
![](./images/Bootstrap/MSGraph_directory.png)
Complete the operation by clicking on the blue button "**Add permissions**"
You need to be logged-in with a user who has directory role "**Global Admin**" or permission to grant consents. When ready press the button "**Grant admin consent for \[name of your tenant\]**"
![](./images/Bootstrap/Grant_Admin_Consent.png)
Confirm
![](./images/Bootstrap/image17.png)
You can see the consents have been given with the green tick button
![](./images/Bootstrap/Granted_Admin_Consent.png)
Now the Azure Active Directory Application has been created and given the right permission on the APIs, you need to set a complex password.
From the property pane select "**Certificates & secrets**"
![](./images/Bootstrap/image19.png)
Click on "**New client secret**"
![](./images/Bootstrap/image20.png)
Put a description -- *date of the creation of the secret* as an example
![](./images/Bootstrap/image21.png)
When ready click on the blue button "Add". Note the password will be displayed only after the creation. Copy the password as you will not be able to retrieve it again later. If you missed that step, delete the password and recreate a new one.
![](./images/Bootstrap/image22.png)
### Capture the tenant ID
![](./images/Bootstrap/image23.png)
Capture the client ID
![](./images/Bootstrap/image24.png)
### Capture the subscription ID
From the Azure Portal search bar, type "**Subscription**"
![](./images/Bootstrap/image25.png)
Capture the subscription ID
![](./images/Bootstrap/image26.png)
## Grant subscription owner to level0-security
![](./images/Bootstrap/image25.png)
Click on the subscription
![](./images/Bootstrap/image26.png)
Go to "**Access control (IAM)**"
![](./images/Bootstrap/image27.png)
Select "**Add**".. "**Add role assignment**"
![](./images/Bootstrap/image28.png)
Select Role as "**Owner**". Set the Azure Active Directory application name you created earlier.
![](./images/Bootstrap/image29.png)
Click on the name and then on the "**save**" button
![](./images/Bootstrap/image30.png)
If all the steps have been completed successfully, you are ready to deploy the level 0 open source launchpad.

Просмотреть файл

@ -0,0 +1,97 @@
# Enterprise Adoption Guide on Cloud Adoption Framework for Azure - Landing zones on Terraform
## Overview
In this guide, we summarize steps to get started in an enteprise environment.
# Get Started (Step By Step)
![](./images/Enterprise/Getting_Started.png)
## Azure Sandpit Environment
Successful implementations tend to focus on building first a sandpit/innovation hub environment where all stakeholders (IT operations, security, compliance, information protection, finance, and business) define their requirements.
The DevOps team focuses on building, automating, testing modules, and landing zones to create an infrastructure environment that is good enough.
We define a sandpit environment as an environment where innovation and experimentations can happen "freely".
As such is it composed of:
- One or more subscriptions that are isolated from ANY customer environment.
- A separate Azure AD tenant space.
## Azure DevOps
### Projects
Ideally multiple projects needed to fully utilize Azure landing zones capabilities:
* **Main Project** - Repository of your private Terraform code and project management for landing zones adoption in your organization
* **Configuration Projects** - For each environments (Production, Non-production, Sandpit) that you plan to leverage Azure Terraform landing zone, dedicated project in Azure Devops is needed to fully utilize the automation mechanism provided. This will reduce the risk and minimize error on mixing environments configuration files(.tfvars),pipelines and variables.
Examples Azure DevOps setup:
| Organization | Project | Purpose |
| ------------ | ------- | ------- |
| Contoso | Azure Terraform Landing Zone | Project Management of LZ and Repository for custom terraform code that specific to Contoso requirements |
| Contoso | contososandpit | Repo to Store configuration file (tfvars), Pipeline, agent pool specific to sandpit |
| Contoso | contosodev | Repo to Store configuration file (tfvars), Pipeline, agent pool specific to nonprod |
| Contoso | contosoprod | Repo to Store configuration file (tfvars), Pipeline, agent pool specific to prod |
<br><br>
#### Sandpit IaC Configuration:
![](./images/Enterprise/Sandpit_IAC.png)
<br>
#### Prod & NonProd IaC Configuration:
![](./images/Enterprise/Prod_NonPROD_IAC.png)
### Repositories
During the lifecycle of the landing zones deployment you will probably find that it is easier to work first with a mono-repository environment but we recommend using multiple repositories as follow:
* **Configuration repository**: [this template can be used](https://github.com/azure/caf-terraform-landingzones-starter) as configuration repository for CAF landing zones, containing definition of the configuration for your different environments.
* **Logic repository**: this Azure CAF landing zone repository. Documentation to come on how to fork this repository.
This approach allows you to easily:
* check-in your configuration in your specific Git repository.
* resync the code with the public codebase for updates.
* customize the code if needed and contribute back to the community.
### Full IaC Architecture (Contoso example)
![](./images/Enterprise/environment_seperation.png)
## Bootstrap process
### Bootstrap identity
In order to start consuming Azure Terraform landing zones, we need to create a privileged account to boostrap the environment.
You can opt for:
1. Using an user account with enough permission (Azure Active Directory Global Administrator)
2. Provision the identity bootstrap account with Azure AD application, you can refer to [the following documentation](./bootstrap_account_provisioning.md)
## Next steps
Once you done on those 3 important steps your organization is ready to adopt Azure Terraform Landing Zone. You can start by [following this documentation](../getting_started/getting_started.md) in order to setup your local development environment.
<br>
*if you are using Azure AD application for bootstrapping you might need to login with below command (with all the details from previous step [from following documentation](./bootstrap_account_provisioning.md)):
```bash
export ARM_CLIENT_ID=
export ARM_CLIENT_SECRET=
export ARM_TENANT_ID=
export ARM_SUBSCRIPTION_ID=
az login --service-principal -u ${ARM_CLIENT_ID} -p ${ARM_CLIENT_SECRET} --tenant ${ARM_TENANT_ID}
az account set --subscription ${ARM_SUBSCRIPTION_ID}
```
You are good to go. Start with launchpad and continue with higher level landing zones.

Двоичные данные
documentation/enterprise/images/Bootstrap/Grant_Admin_Consent.PNG Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 35 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 36 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/MSGraph_directory.PNG Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.1 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image1.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 45 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image10.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image11.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image12.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 15 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image13.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 16 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image14.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image15.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image16.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 46 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image17.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.9 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image18.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 47 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image19.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.5 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image2.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 18 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image20.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 13 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image21.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 10 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image22.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.9 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image23.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 22 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image24.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 25 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image25.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.9 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image26.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.9 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image27.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.6 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image28.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.5 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image29.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 30 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image3.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 70 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image30.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.8 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image4.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.2 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image5.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 29 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image6.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image7.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 89 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image8.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 22 KiB

Двоичные данные
documentation/enterprise/images/Bootstrap/image9.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 18 KiB

Двоичные данные
documentation/enterprise/images/Enterprise/Getting_Started.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 38 KiB

Двоичные данные
documentation/enterprise/images/Enterprise/Prod_NonPROD_IAC.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 163 KiB

Двоичные данные
documentation/enterprise/images/Enterprise/Sandpit_IAC.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 152 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 71 KiB

Просмотреть файл

@ -40,8 +40,6 @@ You will have to accept local mapping to your filesystem when Docker prompts you
After a while, your environment is ready, note on the lower left part of Visual Studio Code, that you are now in your Azure CAF rover, which is your environment to use Azure landing zones. After a while, your environment is ready, note on the lower left part of Visual Studio Code, that you are now in your Azure CAF rover, which is your environment to use Azure landing zones.
## Deploying your first landing zone
You must be authenticated first: You must be authenticated first:
For that we will rely on Azure authentication as completed by Azure Cli, via browser method: For that we will rely on Azure authentication as completed by Azure Cli, via browser method:
@ -55,35 +53,52 @@ We recommend that you verify the output of the login and make sure the subscript
az account set --subscription <subscription_GUID> az account set --subscription <subscription_GUID>
``` ```
On the first run, you need to use the launchpad to create the foundations for Terraform environment: ## Deploying the DevOps requirements
On the first run, you need to use the launchpad to create the foundations for Terraform environment. This will set storage accounts to store the state files, and key vaults to get you started with a secure environment. It can eventually be upgraded to support your DevOps environment (pipelines, etc.)
You can find more information on the launchpad settings [Here](../../landingzones/caf_launchpad)
```bash ```bash
rover -lz /tf/caf/landingzones/launchpad -a apply -launchpad rover -launchpad -lz /tf/caf/landingzones/caf_launchpad \
-var-folder /tf/caf/landingzones/caf_launchpad/scenario/100 \
-a apply
``` ```
This command will interactively prompt you for *var.location*, asking for the name of a supported Azure region **where you want to deploy the Terraform state and dependencies**. You can specify that in the argument as in the following example: ## Deploying the foundations
Next step is to deploy the foundations (this typically could include management groups, policies, etc.). We can start with it empty, and enrich it later.
You can find more information on the launchpad settings [Here](../../landingzones/caf_launchpad)
Get started with the basic foundations:
```bash ```bash
rover -lz /tf/caf/landingzones/launchpad -a apply -launchpad -var 'location=westus' rover -lz /tf/caf/landingzones/caf_foundations \
-level level1 \
-a apply
``` ```
You can then launch your first landing zone! ## Deploying a networking scenario
Please note that each landing zone come with its own deployment settings, which may deploy resources in different region than where you set the foundations. You can deploy one of the typical Azure network topologies (hub, hub and spoke, Virtual WAN).
You are ready to start: Have a look at the example scenario [Here](../../landingzones/caf_networking) and pick one you want to deploy.
You can deploy a simple hub networking using:
```bash ```bash
rover -lz /tf/caf/landingzones/landingzone_caf_foundations -a plan rover -lz /tf/caf/landingzones/caf_networking \
-level level2 \
-var-folder /tf/caf/landingzones/caf_networking/scenario/100-single-region-hub \
-a apply
``` ```
```bash ## Destroying your test
rover -lz /tf/caf/landingzones/landingzone_caf_foundations -a apply
``` Once you are done testing, just use the same commands as before, juste replace the last line ```-a apply``` by ```-a destroy```.
```bash
rover -lz /tf/caf/landingzones/landingzone_caf_foundations -a destroy
```
## Updating your development environment ## Updating your development environment

Просмотреть файл

@ -36,7 +36,7 @@ Open a Terminal using ```CTRL``` + ```J``` or ```Command``` + ```J```
You are ready to use landing zones by launching the rover as below: You are ready to use landing zones by launching the rover as below:
```bash ```bash
/tf/rover/rover.sh rover
``` ```
![Create](../../_pictures/getting_started/vs_codespaces_rover.png) ![Create](../../_pictures/getting_started/vs_codespaces_rover.png)
@ -47,7 +47,7 @@ You must be authenticated first:
For that we will rely on Azure authentication as completed by Azure Cli, via browser method: For that we will rely on Azure authentication as completed by Azure Cli, via browser method:
```bash ```bash
/tf/rover/rover.sh login rover login
``` ```
We recommend that you verify the output of the login and make sure the subscription selected by default is the one you want to work on. If not, you can use the following switch: We recommend that you verify the output of the login and make sure the subscription selected by default is the one you want to work on. If not, you can use the following switch:
@ -56,34 +56,49 @@ We recommend that you verify the output of the login and make sure the subscript
az account set --subscription <subscription_GUID> az account set --subscription <subscription_GUID>
``` ```
On the first run, you need to apply the launchpad as the first landing zone:
## Deploying the DevOps requirements
On the first run, you need to use the launchpad to create the foundations for Terraform environment. This will set storage accounts to store the state files, and key vaults to get you started with a secure environment. It can eventually be upgraded to support your DevOps environment (pipelines, etc.)
You can find more information on the launchpad settings [Here](../../landingzones/caf_launchpad)
```bash ```bash
/tf/rover/rover.sh -lz /tf/caf/landingzones/launchpad -a apply -launchpad rover -launchpad -lz /tf/caf/landingzones/caf_launchpad \
-var-folder /tf/caf/landingzones/caf_launchpad/scenario/100 \
-a apply
``` ```
You can specify a location for the launchpad using the following command: ## Deploying the foundations
Next step is to deploy the foundations (this typically could include management groups, policies, etc.). We can start with it empty, and enrich it later.
You can find more information on the launchpad settings [Here](../../landingzones/caf_launchpad)
Get started with the basic foundations:
```bash ```bash
/tf/rover/rover.sh -lz /tf/caf/landingzones/launchpad -a apply -launchpad -var location=westus rover -lz /tf/caf/landingzones/caf_foundations \
-level level1 \
-a apply
``` ```
You can then launch your first landing zone! ## Deploying a networking scenario
Please note that each landing zone come with its own deployment settings, which may deploy resources in different region than where you set the foundations. You can deploy one of the typical Azure network topologies (hub, hub and spoke, Virtual WAN).
You are ready to start: Have a look at the example scenario [Here](../../landingzones/caf_networking) and pick one you want to deploy.
You can deploy a simple hub networking using:
```bash ```bash
/tf/rover/rover.sh -lz /tf/caf/landingzones/landingzone_caf_foundations -a plan rover -lz /tf/caf/landingzones/caf_networking \
-level level2 \
-var-folder /tf/caf/landingzones/caf_networking/scenario/100-single-region-hub \
-a apply
``` ```
```bash ## Destroying your test
/tf/rover/rover.sh -lz /tf/caf/landingzones/landingzone_caf_foundations -a apply
```
```bash Once you are done testing, just use the same commands as before, juste replace the last line ```-a apply``` by ```-a destroy```.
/tf/rover/rover.sh -lz /tf/caf/landingzones/landingzone_caf_foundations -a destroy
```
Happy deployment with Azure landing zones, let us know your feedback and how you need it to evolve.

Просмотреть файл

@ -1,225 +0,0 @@
# Sample Cloud Adoption Framework foundations landing zone
## globalsettings
global_settings = {
#specifies the set of locations you are going to use in this landing zone
location_map = {
southeastasia = "southeastasia"
eastasia = "eastasia"
}
#naming convention to be used as defined in naming convention module, accepted values are cafclassic, cafrandom, random, passthrough
convention = "cafrandom"
#Set of tags for core operations
tags_hub = {
owner = "CAF"
deploymentType = "Terraform"
costCenter = "1664"
BusinessUnit = "SHARED"
DR = "NON-DR-ENABLED"
}
# Set of resource groups to land the foundations
resource_groups_hub = {
southeastasia = {
HUB-CORE-SEC = {
name = "hub-core-sec-sea"
location = "southeastasia"
}
HUB-OPERATIONS = {
name = "hub-operations-sea"
location = "southeastasia"
}
}
eastasia = {
HUB-CORE-SEC = {
name = "hub-core-sec-hk"
location = "southeastasia"
}
HUB-OPERATIONS = {
name = "hub-operations-hk"
location = "southeastasia"
}
}
}
}
## accounting settings
accounting_settings = {
# Azure diagnostics logs retention period
southeastasia = {
# Azure Subscription activity logs retention period
azure_activity_log_enabled = false
azure_activity_logs_name = "actlogs"
azure_activity_logs_event_hub = false
azure_activity_logs_retention = 365
azure_activity_audit = {
log = [
# ["Audit category name", "Audit enabled)"]
["Administrative", true],
["Security", true],
["ServiceHealth", true],
["Alert", true],
["Recommendation", true],
["Policy", true],
["Autoscale", true],
["ResourceHealth", true],
]
}
azure_diagnostics_logs_name = "diaglogs"
azure_diagnostics_logs_event_hub = false
#Logging and monitoring
analytics_workspace_name = "caflalogs-sg"
##Log analytics solutions to be deployed
solution_plan_map = {
NetworkMonitoring = {
"publisher" = "Microsoft"
"product" = "OMSGallery/NetworkMonitoring"
},
ADAssessment = {
"publisher" = "Microsoft"
"product" = "OMSGallery/ADAssessment"
},
ADReplication = {
"publisher" = "Microsoft"
"product" = "OMSGallery/ADReplication"
},
AgentHealthAssessment = {
"publisher" = "Microsoft"
"product" = "OMSGallery/AgentHealthAssessment"
},
DnsAnalytics = {
"publisher" = "Microsoft"
"product" = "OMSGallery/DnsAnalytics"
},
ContainerInsights = {
"publisher" = "Microsoft"
"product" = "OMSGallery/ContainerInsights"
},
KeyVaultAnalytics = {
"publisher" = "Microsoft"
"product" = "OMSGallery/KeyVaultAnalytics"
}
}
}
eastasia = {
# Azure Subscription activity logs retention period
azure_activity_log_enabled = false
azure_activity_logs_name = "actlogs"
azure_activity_logs_event_hub = false
azure_activity_logs_retention = 365
azure_activity_audit = {
log = [
# ["Audit category name", "Audit enabled)"]
["Administrative", true],
["Security", true],
["ServiceHealth", true],
["Alert", true],
["Recommendation", true],
["Policy", true],
["Autoscale", true],
["ResourceHealth", true],
]
}
azure_diagnostics_logs_name = "diaglogs"
azure_diagnostics_logs_event_hub = false
#Logging and monitoring
analytics_workspace_name = "caflalogs-hk"
##Log analytics solutions to be deployed
solution_plan_map = {
NetworkMonitoring = {
"publisher" = "Microsoft"
"product" = "OMSGallery/NetworkMonitoring"
},
ADAssessment = {
"publisher" = "Microsoft"
"product" = "OMSGallery/ADAssessment"
},
ADReplication = {
"publisher" = "Microsoft"
"product" = "OMSGallery/ADReplication"
},
AgentHealthAssessment = {
"publisher" = "Microsoft"
"product" = "OMSGallery/AgentHealthAssessment"
},
DnsAnalytics = {
"publisher" = "Microsoft"
"product" = "OMSGallery/DnsAnalytics"
},
ContainerInsights = {
"publisher" = "Microsoft"
"product" = "OMSGallery/ContainerInsights"
},
KeyVaultAnalytics = {
"publisher" = "Microsoft"
"product" = "OMSGallery/KeyVaultAnalytics"
}
}
}
}
## governance
governance_settings = {
southeastasia = {
#current code supports only two levels of managemenr groups and one root
deploy_mgmt_groups = false
management_groups = {
root = {
name = "caf-rootmgmtgroup"
subscriptions = []
#list your subscriptions ID in this field as ["GUID1", "GUID2"]
children = {
child1 = {
name = "tree1child1"
subscriptions = []
}
child2 = {
name = "tree1child2"
subscriptions = []
}
child3 = {
name = "tree1child3"
subscriptions = []
}
}
}
}
policy_matrix = {
#autoenroll_asc = true - to be implemented via builtin policies
autoenroll_monitor_vm = true
autoenroll_netwatcher = false
no_public_ip_spoke = false
cant_create_ip_spoke = false
managed_disks_only = true
restrict_locations = false
list_of_allowed_locs = ["southeastasia", "eastasia"]
restrict_supported_svc = false
list_of_supported_svc = ["Microsoft.Network/publicIPAddresses", "Microsoft.Compute/disks"]
msi_location = "southeastasia"
}
}
eastasia = {}
}
## security
security_settings = {
#Azure Security Center Configuration
enable_security_center = false
security_center = {
contact_email = "email@email.com"
contact_phone = "9293829328"
alerts_to_admins = true
alert_notifications = true
}
#Enables Azure Sentinel on the Log Analaytics repo
enable_sentinel = true
}

Просмотреть файл

@ -1,172 +0,0 @@
# Configuration sample for Azure Virtual WAN hub and spoke
virtual_hub_config = {
virtual_wan = {
resource_group_name = "virtualwan"
name = "ContosovWAN"
dns_name = "private.contoso.com"
hubs = {
hub1 = {
hub_name = "SEA-HUB"
region = "southeastasia"
hub_address_prefix = "10.0.3.0/24"
deploy_firewall = true
peerings = {}
firewall_name = "azfwsg"
firewall_resource_groupe_name = "azfwsg"
deploy_p2s = false
p2s_config = {
name = "caf-sea-vpn-p2s"
scale_unit = 2
connection_configuration = {
name = "client-connections"
vpn_client_address_pool = {
address_prefixes = ["192.168.0.0/24"]
}
}
server_config = {
vpn_authentication_types = ["Certificate"]
client_root_certificate = {
name = "DigiCert-Federated-ID-Root-CA"
public_cert_data = <<EOF
MIIDuzCCAqOgAwIBAgIQCHTZWCM+IlfFIRXIvyKSrjANBgkqhkiG9w0BAQsFADBn
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSYwJAYDVQQDEx1EaWdpQ2VydCBGZWRlcmF0ZWQgSUQg
Um9vdCBDQTAeFw0xMzAxMTUxMjAwMDBaFw0zMzAxMTUxMjAwMDBaMGcxCzAJBgNV
BAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdp
Y2VydC5jb20xJjAkBgNVBAMTHURpZ2lDZXJ0IEZlZGVyYXRlZCBJRCBSb290IENB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvAEB4pcCqnNNOWE6Ur5j
QPUH+1y1F9KdHTRSza6k5iDlXq1kGS1qAkuKtw9JsiNRrjltmFnzMZRBbX8Tlfl8
zAhBmb6dDduDGED01kBsTkgywYPxXVTKec0WxYEEF0oMn4wSYNl0lt2eJAKHXjNf
GTwiibdP8CUR2ghSM2sUTI8Nt1Omfc4SMHhGhYD64uJMbX98THQ/4LMGuYegou+d
GTiahfHtjn7AboSEknwAMJHCh5RlYZZ6B1O4QbKJ+34Q0eKgnI3X6Vc9u0zf6DH8
Dk+4zQDYRRTqTnVO3VT8jzqDlCRuNtq6YvryOWN74/dq8LQhUnXHvFyrsdMaE1X2
DwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNV
HQ4EFgQUGRdkFnbGt1EWjKwbUne+5OaZvRYwHwYDVR0jBBgwFoAUGRdkFnbGt1EW
jKwbUne+5OaZvRYwDQYJKoZIhvcNAQELBQADggEBAHcqsHkrjpESqfuVTRiptJfP
9JbdtWqRTmOf6uJi2c8YVqI6XlKXsD8C1dUUaaHKLUJzvKiazibVuBwMIT84AyqR
QELn3e0BtgEymEygMU569b01ZPxoFSnNXc7qDZBDef8WfqAV/sxkTi8L9BkmFYfL
uGLOhRJOFprPdoDIUBB+tmCl3oDcBy3vnUeOEioz8zAkprcb3GHwHAK+vHmmfgcn
WsfMLH4JCLa/tRYL+Rw/N3ybCkDp00s0WUZ+AoDywSl0Q/ZEnNY0MsFiw6LyIdbq
M/s/1JRtO3bDSzD9TazRVzn2oBqzSa8VgIo5C1nOnoAKJTlsClJKvIhnRlaLQqk=
EOF
}
}
}
deploy_s2s = false
s2s_config = {
name = "caf-sea-vpn-s2s"
scale_unit = 1
}
deploy_er = false
er_config = {
name = "caf-sea-er"
scale_units = 1
}
}
hub2 = {
hub_name = "HK-HUB"
region = "eastasia"
hub_address_prefix = "10.0.4.0/24"
deploy_firewall = true
firewall_name = "azfhk"
firewall_resource_groupe_name = "azfhk"
peerings = {
## this key must match with the key of the virtual network declared in the var.spokes structure
spoke1 = {
# TODO: add support for remote_virtual_network_id = <ID of the virtual network>
# optional if the virtual network has been provisionned outside.
hub_to_vitual_network_traffic_allowed = true
vitual_network_to_hub_gateways_traffic_allowed = true
internet_security_enabled = false
}
}
deploy_p2s = false
p2s_config = {}
deploy_s2s = false
s2s_config = {}
deploy_er = false
er_config = {}
}
}
}
}
spokes = {
spoke1 = {
rg = {
name = "virtualhub-spoke-test"
location = "eastasia"
}
peering_name = "spoke1-hub-hk-link"
network = {
vnet = {
name = "Core-Network"
address_space = ["10.0.10.0/24"]
}
specialsubnets = {}
subnets = {
subnet0 = {
name = "Web_tier"
cidr = ["10.0.10.0/26"]
nsg_name = "Web_tier_nsg"
nsg = [
{
name = "HTTP-In",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "HTTPS-In",
priority = "101"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "*"
},
]
}
subnet2 = {
name = "Data_tier"
cidr = ["10.0.10.128/26"]
nsg_name = "Data_tier_nsg"
nsg = [
{
name = "TDS-In",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "UDP"
source_port_range = "*"
destination_port_range = "1433"
source_address_prefix = "*"
destination_address_prefix = "*"
}
]
}
}
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["VMProtectionAlerts", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
}
}

Просмотреть файл

@ -1,435 +0,0 @@
# Configuration sample for a hub and spoke environment
# definition of variables for the virtual network
rg_network = {
CORE-NET = {
name = "network-core"
}
TRANSIT-NET = {
name = "network-transit"
}
EDGE-NET = {
name = "network-edge"
}
}
# settings for the core network blueprint
core_networking = {
shared_services_vnet = {
vnet = {
name = "Core-Network"
address_space = ["10.0.0.0/8"]
}
specialsubnets = {
AzureFirewallSubnet = {
name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet
cidr = ["10.0.4.0/24"]
}
GatewaySubnet = {
name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway
cidr = ["10.0.255.224/27"]
}
}
subnets = {
subnet0 = {
name = "Active_Directory"
cidr = ["10.0.1.0/24"]
nsg_name = "Active_Directory_nsg"
nsg = [
{
name = "W32Time",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "UDP"
source_port_range = "*"
destination_port_range = "123"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "RPC-Endpoint-Mapper",
priority = "101"
direction = "Inbound"
access = "Allow"
protocol = "UDP"
source_port_range = "*"
destination_port_range = "135"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "Kerberos-password-change",
priority = "102"
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "464"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "RPC-Dynamic-range",
priority = "103"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "49152-65535"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "LDAP",
priority = "104"
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "389"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "LDAP-SSL",
priority = "105"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "636"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "LDAP-GC",
priority = "106"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "3268"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "LDAP-GC-SSL",
priority = "107"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "3269"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "DNS",
priority = "108"
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "53"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "Kerberos",
priority = "109"
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "88"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "SMB",
priority = "110"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "445"
source_address_prefix = "*"
destination_address_prefix = "*"
}
]
}
subnet1 = {
name = "AzureBastionSubnet" #Must be called AzureBastionSubnet
cidr = ["10.0.0.128/25"]
nsg_name = "AzureBastionSubnet_nsg"
nsg = [
{
name = "bastion-in-allow",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "bastion-control-in-allow-443",
priority = "120"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "135"
source_address_prefix = "GatewayManager"
destination_address_prefix = "*"
},
{
name = "Kerberos-password-change",
priority = "121"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "4443"
source_address_prefix = "GatewayManager"
destination_address_prefix = "*"
},
{
name = "bastion-vnet-out-allow-22",
priority = "103"
direction = "Outbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "VirtualNetwork"
},
{
name = "bastion-vnet-out-allow-3389",
priority = "101"
direction = "Outbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "3389"
source_address_prefix = "*"
destination_address_prefix = "VirtualNetwork"
},
{
name = "bastion-azure-out-allow",
priority = "120"
direction = "Outbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "AzureCloud"
}
]
}
}
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["VMProtectionAlerts", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
# Settings for the public IP address to be used for Azure Firewall
# Must be standard and static for
firewall_ip_addr_config = {
ip_name = "firewall"
allocation_method = "Static"
sku = "Standard" #defaults to Basic
ip_version = "IPv4" #defaults to IP4, Only dynamic for IPv6, Supported arguments are IPv4 or IPv6, NOT Both
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the Azure Firewall settings
az_fw_config = {
name = "azfw"
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AzureFirewallApplicationRule", true, true, 30],
["AzureFirewallNetworkRule", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the UDR object
udr_web_to_az_firewall = {
nexthop_type = "VirtualAppliance"
prefix = "0.0.0.0/0"
route_name = "web_to_az_firewall"
subnet_to_udr = "Web_tier"
nexthop_ip = ""
}
udr_transit_to_az_firewall = {
nexthop_type = "VirtualAppliance"
prefix = "10.0.1.0/24"
route_name = "transit_to_az_firewall"
subnet_to_udr = "GatewaySubnet"
nexthop_ip = ""
}
## DDoS standard configuration
enable_ddos_standard = false
ddos_name = "ddos_protection_plan"
## settings for Azure bastion configuration
## not enabled, uncomment the code in the networking shared services blueprint.
enable_bastion = false
bastion_ip_addr_config = {
ip_name = "bastion"
ip_addr = {
allocation_method = "Static"
#Dynamic Public IP Addresses aren't allocated until they're assigned to a resource (such as a Virtual Machine or a Load Balancer) by design within Azure
#properties below are optional
sku = "Standard" #defaults to Basic
ip_version = "IPv4" #defaults to IP4, Only dynamic for IPv6, Supported arguments are IPv4 or IPv6, NOT Both
#dns_prefix = "arnaudmytest"
#timeout = 15 #TCP timeout for idle connections. The value can be set between 4 and 30 minutes.
#zones = [1] #1 zone number, IP address must be standard, ZoneRedundant argument is not supported in provider at time of writing
#reverse_fqdn = ""
#public_ip_prefix_id = "/subscriptions/00000000-00000-0000-0000-000000000000/resourceGroups/uqvh-hub-ingress-net/providers/Microsoft.Network/publicIPPrefixes/myprefix"
#refer to the prefix and check sku types are same in IP and prefix
}
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
bastion_config = {
name = "azurebastion"
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["BastionAuditLogs", true, true, 30],
]
metric = [
# ["AllMetrics", true, true, 30],
]
}
}
# Settings for the Virtual Network gateway to be created
provision_gateway = false
gateway_config = {
gateway_type = "VPN"
# Possible values are "VPN" or "ExpressRoute"
vpn_gateway_name = "vpngateway"
active_active = false
#An active-active gateway requires a HighPerformance or an UltraPerformance sku. If false, an active-standby gateway will be created. Defaults to false.
enable_bgp = false
#If true, BGP (Border Gateway Protocol) will be enabled for this Virtual Network Gateway. Defaults to false.
vpn_gateway_sku = "Basic"
#Valid options are Basic, Standard, HighPerformance, UltraPerformance, ErGw1AZ, ErGw2AZ, ErGw3AZ, VpnGw1, VpnGw2, VpnGw3, VpnGw1AZ, VpnGw2AZ, and VpnGw3AZ
#and depend on the gateway_type (ER or VPN) and vpn_type arguments, ie: PolicyBased gateway only supports the Basic sku.
vpn_gateway_type = "RouteBased"
#The routing type of the Virtual Network Gateway. Valid options are RouteBased or PolicyBased. Defaults to RouteBased.
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["GatewayDiagnosticLog", true, true, 30],
["TunnelDiagnosticLog", true, true, 30],
["RouteDiagnosticLog", true, true, 30],
["IKEDiagnosticLog", true, true, 30],
["P2SDiagnosticLog", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
pip = {
name = "vpn"
allocation_method = "Dynamic"
sku = "Basic"
#For basic SKU, you can pick the zone to be deployed - if you want multi zone - pick Standard IP and pick AZ aware VPN gateway SKU
#dns_prefix = "arnaudvpn"
#zones = ["1"]
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
}
#Settings for the connection to be established
#Settings for the local network connection
connection_name = "onpremconnection"
remote_network_connect = true
remote_network = {
gateway_name = "caf_local_network"
gateway_ip = "1.2.3.4"
gateway_adress_space = ["1.0.0.0/8"]
bgp_settings = {
# asn =
# bgp_peering_address =
# peer_weight =
}
}
##Settings for the Azure Key Vault
akv_config = {
name = "vpn-akv"
akv_features = {
enabled_for_disk_encryption = true
enabled_for_deployment = true
enabled_for_template_deployment = true
}
sku_name = "standard"
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AuditEvent", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
}

Просмотреть файл

@ -1,265 +0,0 @@
# Configuration sample for a hub and spoke environment
# definition of variables for the virtual network
rg_network = {
CORE-NET = {
name = "network-core"
}
TRANSIT-NET = {
name = "network-transit"
}
EDGE-NET = {
name = "network-edge"
}
}
# settings for the core network blueprint
core_networking = {
shared_services_vnet = {
vnet = {
name = "Core-Network"
address_space = ["10.0.0.0/8"]
}
specialsubnets = {
AzureFirewallSubnet = {
name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet
cidr = "10.0.4.0/24"
}
GatewaySubnet = {
name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway
cidr = "10.0.255.224/27"
}
}
subnets = {
subnet0 = {
name = "Active_Directory"
cidr = "10.0.1.0/24"
nsg_inbound = [
# {"Name", "Priority", "Direction", "Action", "Protocol", "source_port_range", "destination_port_range", "source_address_prefix", "destination_address_prefix" },
["W32Time", "100", "Inbound", "Allow", "udp", "*", "123", "*", "*"],
["RPC-Endpoint-Mapper", "101", "Inbound", "Allow", "tcp", "*", "135", "*", "*"],
["Kerberos-password-change", "102", "Inbound", "Allow", "*", "*", "464", "*", "*"],
["RPC-Dynamic-range", "103", "Inbound", "Allow", "tcp", "*", "49152-65535", "*", "*"],
["LDAP", "104", "Inbound", "Allow", "*", "*", "389", "*", "*"],
["LDAP-SSL", "105", "Inbound", "Allow", "tcp", "*", "636", "*", "*"],
["LDAP-GC", "106", "Inbound", "Allow", "tcp", "*", "3268", "*", "*"],
["LDAP-GC-SSL", "107", "Inbound", "Allow", "tcp", "*", "3269", "*", "*"],
["DNS", "108", "Inbound", "Allow", "*", "*", "53", "*", "*"],
["Kerberos", "109", "Inbound", "Allow", "*", "*", "88", "*", "*"],
["SMB", "110", "Inbound", "Allow", "tcp", "*", "445", "*", "*"],
]
}
subnet1 = {
name = "AzureBastionSubnet" #Must be called AzureBastionSubnet
cidr = "10.0.0.128/25"
nsg_inbound = [
["bastion-in-allow", "100", "Inbound", "Allow", "tcp", "*", "443", "*", "*"],
["bastion-control-in-allow-443", "120", "Inbound", "Allow", "tcp", "*", "443", "GatewayManager", "*"],
["bastion-control-in-allow-4443", "121", "Inbound", "Allow", "tcp", "*", "4443", "GatewayManager", "*"],
]
nsg_outbound = [
["bastion-vnet-out-allow-22", "100", "Outbound", "Allow", "tcp", "*", "22", "*", "VirtualNetwork"],
["bastion-vnet-out-allow-3389", "101", "Outbound", "Allow", "tcp", "*", "3389", "*", "VirtualNetwork"],
["bastion-azure-out-allow", "120", "Outbound", "Allow", "tcp", "*", "443", "*", "AzureCloud"],
]
}
}
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["VMProtectionAlerts", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
# Settings for the public IP address to be used for Azure Firewall
# Must be standard and static for
firewall_ip_addr_config = {
ip_name = "firewall"
allocation_method = "Static"
sku = "Standard" #defaults to Basic
ip_version = "IPv4" #defaults to IP4, Only dynamic for IPv6, Supported arguments are IPv4 or IPv6, NOT Both
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the Azure Firewall settings
az_fw_config = {
name = "azfw"
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AzureFirewallApplicationRule", true, true, 30],
["AzureFirewallNetworkRule", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the UDR object
udr_web_to_az_firewall = {
nexthop_type = "VirtualAppliance"
prefix = "0.0.0.0/0"
route_name = "web_to_az_firewall"
subnet_to_udr = "Web_tier"
nexthop_ip = ""
}
udr_transit_to_az_firewall = {
nexthop_type = "VirtualAppliance"
prefix = "10.0.1.0/24"
route_name = "transit_to_az_firewall"
subnet_to_udr = "GatewaySubnet"
nexthop_ip = ""
}
## DDoS standard configuration
enable_ddos_standard = false
ddos_name = "ddos_protection_plan"
## settings for Azure bastion configuration
## not enabled, uncomment the code in the networking shared services blueprint.
enable_bastion = true
bastion_ip_addr_config = {
ip_name = "bastion"
ip_addr = {
allocation_method = "Static"
#Dynamic Public IP Addresses aren't allocated until they're assigned to a resource (such as a Virtual Machine or a Load Balancer) by design within Azure
#properties below are optional
sku = "Standard" #defaults to Basic
ip_version = "IPv4" #defaults to IP4, Only dynamic for IPv6, Supported arguments are IPv4 or IPv6, NOT Both
#dns_prefix = "arnaudmytest"
#timeout = 15 #TCP timeout for idle connections. The value can be set between 4 and 30 minutes.
#zones = [1] #1 zone number, IP address must be standard, ZoneRedundant argument is not supported in provider at time of writing
#reverse_fqdn = ""
#public_ip_prefix_id = "/subscriptions/00000000-00000-0000-0000-000000000000/resourceGroups/uqvh-hub-ingress-net/providers/Microsoft.Network/publicIPPrefixes/myprefix"
#refer to the prefix and check sku types are same in IP and prefix
}
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
bastion_config = {
name = "azurebastion"
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["BastionAuditLogs", true, true, 30],
]
metric = [
# ["AllMetrics", true, true, 30],
]
}
}
# Settings for the Virtual Network gateway to be created
provision_gateway = false
gateway_config = {
gateway_type = "VPN"
# Possible values are "VPN" or "ExpressRoute"
vpn_gateway_name = "vpngateway"
active_active = false
#An active-active gateway requires a HighPerformance or an UltraPerformance sku. If false, an active-standby gateway will be created. Defaults to false.
enable_bgp = false
#If true, BGP (Border Gateway Protocol) will be enabled for this Virtual Network Gateway. Defaults to false.
vpn_gateway_sku = "Basic"
#Valid options are Basic, Standard, HighPerformance, UltraPerformance, ErGw1AZ, ErGw2AZ, ErGw3AZ, VpnGw1, VpnGw2, VpnGw3, VpnGw1AZ, VpnGw2AZ, and VpnGw3AZ
#and depend on the gateway_type (ER or VPN) and vpn_type arguments, ie: PolicyBased gateway only supports the Basic sku.
vpn_gateway_type = "RouteBased"
#The routing type of the Virtual Network Gateway. Valid options are RouteBased or PolicyBased. Defaults to RouteBased.
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["GatewayDiagnosticLog", true, true, 30],
["TunnelDiagnosticLog", true, true, 30],
["RouteDiagnosticLog", true, true, 30],
["IKEDiagnosticLog", true, true, 30],
["P2SDiagnosticLog", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
pip = {
name = "vpn"
allocation_method = "Dynamic"
sku = "Basic"
#For basic SKU, you can pick the zone to be deployed - if you want multi zone - pick Standard IP and pick AZ aware VPN gateway SKU
#dns_prefix = "arnaudvpn"
#zones = ["1"]
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
}
#Settings for the connection to be established
#Settings for the local network connection
connection_name = "onpremconnection"
remote_network_connect = true
remote_network = {
gateway_name = "caf_local_network"
gateway_ip = "1.2.3.4"
gateway_adress_space = ["1.0.0.0/8"]
bgp_settings = {
# asn =
# bgp_peering_address =
# peer_weight =
}
}
##Settings for the Azure Key Vault
akv_config = {
name = "vpn-akv"
akv_features = {
enabled_for_disk_encryption = true
enabled_for_deployment = true
enabled_for_template_deployment = true
}
sku_name = "standard"
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AuditEvent", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
}

Просмотреть файл

@ -1,265 +0,0 @@
# Configuration sample for a hub and spoke environment
# definition of variables for the virtual network
rg_network = {
CORE-NET = {
name = "network-core"
}
TRANSIT-NET = {
name = "network-transit"
}
EDGE-NET = {
name = "network-edge"
}
}
# settings for the core network blueprint
core_networking = {
shared_services_vnet = {
vnet = {
name = "Core-Network"
address_space = ["10.0.0.0/8"]
}
specialsubnets = {
AzureFirewallSubnet = {
name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet
cidr = "10.0.4.0/24"
}
GatewaySubnet = {
name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway
cidr = "10.0.255.224/27"
}
}
subnets = {
subnet0 = {
name = "Active_Directory"
cidr = "10.0.1.0/24"
nsg_inbound = [
# {"Name", "Priority", "Direction", "Action", "Protocol", "source_port_range", "destination_port_range", "source_address_prefix", "destination_address_prefix" },
["W32Time", "100", "Inbound", "Allow", "udp", "*", "123", "*", "*"],
["RPC-Endpoint-Mapper", "101", "Inbound", "Allow", "tcp", "*", "135", "*", "*"],
["Kerberos-password-change", "102", "Inbound", "Allow", "*", "*", "464", "*", "*"],
["RPC-Dynamic-range", "103", "Inbound", "Allow", "tcp", "*", "49152-65535", "*", "*"],
["LDAP", "104", "Inbound", "Allow", "*", "*", "389", "*", "*"],
["LDAP-SSL", "105", "Inbound", "Allow", "tcp", "*", "636", "*", "*"],
["LDAP-GC", "106", "Inbound", "Allow", "tcp", "*", "3268", "*", "*"],
["LDAP-GC-SSL", "107", "Inbound", "Allow", "tcp", "*", "3269", "*", "*"],
["DNS", "108", "Inbound", "Allow", "*", "*", "53", "*", "*"],
["Kerberos", "109", "Inbound", "Allow", "*", "*", "88", "*", "*"],
["SMB", "110", "Inbound", "Allow", "tcp", "*", "445", "*", "*"],
]
}
subnet1 = {
name = "AzureBastionSubnet" #Must be called AzureBastionSubnet
cidr = "10.0.0.128/25"
nsg_inbound = [
["bastion-in-allow", "100", "Inbound", "Allow", "tcp", "*", "443", "*", "*"],
["bastion-control-in-allow-443", "120", "Inbound", "Allow", "tcp", "*", "443", "GatewayManager", "*"],
["bastion-control-in-allow-4443", "121", "Inbound", "Allow", "tcp", "*", "4443", "GatewayManager", "*"],
]
nsg_outbound = [
["bastion-vnet-out-allow-22", "100", "Outbound", "Allow", "tcp", "*", "22", "*", "VirtualNetwork"],
["bastion-vnet-out-allow-3389", "101", "Outbound", "Allow", "tcp", "*", "3389", "*", "VirtualNetwork"],
["bastion-azure-out-allow", "120", "Outbound", "Allow", "tcp", "*", "443", "*", "AzureCloud"],
]
}
}
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["VMProtectionAlerts", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
# Settings for the public IP address to be used for Azure Firewall
# Must be standard and static for
firewall_ip_addr_config = {
ip_name = "firewall"
allocation_method = "Static"
sku = "Standard" #defaults to Basic
ip_version = "IPv4" #defaults to IP4, Only dynamic for IPv6, Supported arguments are IPv4 or IPv6, NOT Both
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the Azure Firewall settings
az_fw_config = {
name = "azfw"
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AzureFirewallApplicationRule", true, true, 30],
["AzureFirewallNetworkRule", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the UDR object
udr_web_to_az_firewall = {
nexthop_type = "VirtualAppliance"
prefix = "0.0.0.0/0"
route_name = "web_to_az_firewall"
subnet_to_udr = "Web_tier"
nexthop_ip = ""
}
udr_transit_to_az_firewall = {
nexthop_type = "VirtualAppliance"
prefix = "10.0.1.0/24"
route_name = "transit_to_az_firewall"
subnet_to_udr = "GatewaySubnet"
nexthop_ip = ""
}
## DDoS standard configuration
enable_ddos_standard = false
ddos_name = "ddos_protection_plan"
## settings for Azure bastion configuration
## not enabled, uncomment the code in the networking shared services blueprint.
enable_bastion = false
bastion_ip_addr_config = {
ip_name = "bastion"
ip_addr = {
allocation_method = "Static"
#Dynamic Public IP Addresses aren't allocated until they're assigned to a resource (such as a Virtual Machine or a Load Balancer) by design within Azure
#properties below are optional
sku = "Standard" #defaults to Basic
ip_version = "IPv4" #defaults to IP4, Only dynamic for IPv6, Supported arguments are IPv4 or IPv6, NOT Both
#dns_prefix = "arnaudmytest"
#timeout = 15 #TCP timeout for idle connections. The value can be set between 4 and 30 minutes.
#zones = [1] #1 zone number, IP address must be standard, ZoneRedundant argument is not supported in provider at time of writing
#reverse_fqdn = ""
#public_ip_prefix_id = "/subscriptions/00000000-00000-0000-0000-000000000000/resourceGroups/uqvh-hub-ingress-net/providers/Microsoft.Network/publicIPPrefixes/myprefix"
#refer to the prefix and check sku types are same in IP and prefix
}
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
bastion_config = {
name = "azurebastion"
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["BastionAuditLogs", true, true, 30],
]
metric = [
# ["AllMetrics", true, true, 30],
]
}
}
# Settings for the Virtual Network gateway to be created
provision_gateway = false
gateway_config = {
gateway_type = "VPN"
# Possible values are "VPN" or "ExpressRoute"
vpn_gateway_name = "vpngateway"
active_active = false
#An active-active gateway requires a HighPerformance or an UltraPerformance sku. If false, an active-standby gateway will be created. Defaults to false.
enable_bgp = false
#If true, BGP (Border Gateway Protocol) will be enabled for this Virtual Network Gateway. Defaults to false.
vpn_gateway_sku = "Basic"
#Valid options are Basic, Standard, HighPerformance, UltraPerformance, ErGw1AZ, ErGw2AZ, ErGw3AZ, VpnGw1, VpnGw2, VpnGw3, VpnGw1AZ, VpnGw2AZ, and VpnGw3AZ
#and depend on the gateway_type (ER or VPN) and vpn_type arguments, ie: PolicyBased gateway only supports the Basic sku.
vpn_gateway_type = "RouteBased"
#The routing type of the Virtual Network Gateway. Valid options are RouteBased or PolicyBased. Defaults to RouteBased.
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["GatewayDiagnosticLog", true, true, 30],
["TunnelDiagnosticLog", true, true, 30],
["RouteDiagnosticLog", true, true, 30],
["IKEDiagnosticLog", true, true, 30],
["P2SDiagnosticLog", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
pip = {
name = "vpn"
allocation_method = "Dynamic"
sku = "Basic"
#For basic SKU, you can pick the zone to be deployed - if you want multi zone - pick Standard IP and pick AZ aware VPN gateway SKU
#dns_prefix = "arnaudvpn"
#zones = ["1"]
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
}
#Settings for the connection to be established
#Settings for the local network connection
connection_name = "onpremconnection"
remote_network_connect = true
remote_network = {
gateway_name = "caf_local_network"
gateway_ip = "1.2.3.4"
gateway_adress_space = ["1.0.0.0/8"]
bgp_settings = {
# asn =
# bgp_peering_address =
# peer_weight =
}
}
##Settings for the Azure Key Vault
akv_config = {
name = "vpn-akv"
akv_features = {
enabled_for_disk_encryption = true
enabled_for_deployment = true
enabled_for_template_deployment = true
}
sku_name = "standard"
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AuditEvent", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
}

Просмотреть файл

@ -1,85 +0,0 @@
resource_groups = {
vnet_us = {
name = "vnet-hub-us"
location = "westus2"
useprefix = true
max_length = 40
}
}
vnets = {
hub_us = {
resource_group_key = "vnet_us"
location = "westus2"
vnet = {
name = "hub"
address_space = ["10.10.100.0/24"]
}
specialsubnets = {
AzureFirewallSubnet = {
name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet
cidr = ["10.10.100.192/26"]
}
}
subnets = {
}
# Override the default var.diagnostics.vnet
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["VMProtectionAlerts", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
}
firewalls = {
# Southeastasia firewall (do not change the key when created)
westus2 = {
location = "westus2"
resource_group_key = "vnet_us"
vnet_key = "hub_us"
# Settings for the public IP address to be used for Azure Firewall
# Must be standard and static for
firewall_ip_addr_config = {
ip_name = "firewall"
allocation_method = "Static"
sku = "Standard" #defaults to Basic
ip_version = "IPv4" #defaults to IP4, Only dynamic for IPv6, Supported arguments are IPv4 or IPv6, NOT Both
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the Azure Firewall settings
az_fw_config = {
name = "azfw"
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AzureFirewallApplicationRule", true, true, 30],
["AzureFirewallNetworkRule", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
}
}

Просмотреть файл

@ -1,420 +0,0 @@
# definition of variables for the virtual network
rg_network = {
CORE-NET = {
name = "-network-core"
}
TRANSIT-NET = {
name = "-network-transit"
}
EDGE-NET = {
name = "-network-edge"
}
}
# settings for the core network blueprint
core_networking = {
shared_services_vnet = {
vnet = {
name = "Core-Network"
address_space = ["10.0.0.0/8"]
}
specialsubnets = {
AzureFirewallSubnet = {
name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet
cidr = ["10.0.4.0/24"]
}
GatewaySubnet = {
name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway
cidr = ["10.0.255.224/27"]
}
}
subnets = {
subnet0 = {
name = "Web_tier"
cidr = ["10.0.1.0/24"]
nsg_name = "Web_tier_nsg"
nsg = [
{
name = "HTTP-In",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "HTTPS-In",
priority = "101"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "*"
},
]
}
subnet1 = {
name = "Business_tier"
cidr = ["10.0.2.0/24"]
nsg_name = "Business_tier_nsg"
nsg = [
{
name = "HTTP-In",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "HTTPS-In",
priority = "101"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "HTTP-Out",
priority = "100"
direction = "Outbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "HTTPS-Out",
priority = "101"
direction = "Outbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "*"
},
]
}
subnet2 = {
name = "Data_tier"
cidr = ["10.0.3.0/24"]
nsg_name = "Data_tier_nsg"
nsg = [
{
name = "TDS-In",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "UDP"
source_port_range = "*"
destination_port_range = "1433"
source_address_prefix = "*"
destination_address_prefix = "*"
}
]
}
subnet3 = {
name = "AzureBastionSubnet" #Must be called AzureBastionSubnet
cidr = ["10.0.0.128/25"]
nsg_name = "AzureBastionSubnet_nsg"
nsg = [
{
name = "bastion-in-allow",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "bastion-control-in-allow-443",
priority = "120"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "135"
source_address_prefix = "GatewayManager"
destination_address_prefix = "*"
},
{
name = "Kerberos-password-change",
priority = "121"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "4443"
source_address_prefix = "GatewayManager"
destination_address_prefix = "*"
},
{
name = "bastion-vnet-out-allow-22",
priority = "103"
direction = "Outbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "VirtualNetwork"
},
{
name = "bastion-vnet-out-allow-3389",
priority = "101"
direction = "Outbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "3389"
source_address_prefix = "*"
destination_address_prefix = "VirtualNetwork"
},
{
name = "bastion-azure-out-allow",
priority = "120"
direction = "Outbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "AzureCloud"
}
]
}
}
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["VMProtectionAlerts", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
# netwatcher = {
# create = true
# #create the network watcher for a subscription and for the location of the vnet
# name = "arnaud-nw-test"
# #name of the network watcher to be created
# flow_logs_settings = {
# enabled = true
# retention = true
# period = 7
# }
# traffic_analytics_settings = {
# enabled = true
# }
# }
}
# Settings for the public IP address to be used for Azure Firewall
# Must be standard and static for
ip_addr_config = {
ip_name = "firewall"
allocation_method = "Static"
sku = "Standard" #defaults to Basic
ip_version = "IPv4" #defaults to IP4, Only dynamic for IPv6, Supported arguments are IPv4 or IPv6, NOT Both
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the Azure Firewall settings
az_fw_config = {
name = "azfw"
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AzureFirewallApplicationRule", true, true, 30],
["AzureFirewallNetworkRule", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the UDR object
udr_web_to_az_firewall = {
nexthop_type = "VirtualAppliance"
prefix = "0.0.0.0/0"
route_name = "web_to_az_firewall"
subnet_to_udr = "Web_tier"
nexthop_ip = ""
}
udr_transit_to_az_firewall = {
nexthop_type = "VirtualAppliance"
prefix = "10.0.1.0/24"
route_name = "transit_to_az_firewall"
subnet_to_udr = "GatewaySubnet"
nexthop_ip = ""
}
## DDoS standard configuration
enable_ddos_standard = false
ddos_name = "ddos_protection_plan"
## settings for Azure bastion configuration
## not enabled, uncomment the code in the networking shared services blueprint.
enable_bastion = true
bastion_ip_addr_config = {
ip_name = "bastion"
ip_addr = {
allocation_method = "Static"
#Dynamic Public IP Addresses aren't allocated until they're assigned to a resource (such as a Virtual Machine or a Load Balancer) by design within Azure
#properties below are optional
sku = "Standard" #defaults to Basic
ip_version = "IPv4" #defaults to IP4, Only dynamic for IPv6, Supported arguments are IPv4 or IPv6, NOT Both
#dns_prefix = "arnaudmytest"
#timeout = 15 #TCP timeout for idle connections. The value can be set between 4 and 30 minutes.
#zones = [1] #1 zone number, IP address must be standard, ZoneRedundant argument is not supported in provider at time of writing
#reverse_fqdn = ""
#public_ip_prefix_id = "/subscriptions/00000000-00000-0000-0000-000000000000/resourceGroups/uqvh-hub-ingress-net/providers/Microsoft.Network/publicIPPrefixes/myprefix"
#refer to the prefix and check sku types are same in IP and prefix
}
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
bastion_config = {
name = "azurebastionalz"
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["BastionAuditLogs", true, true, 30],
]
metric = [
# ["AllMetrics", true, true, 30],
]
}
}
# Settings for the Virtual Network gateway to be created
provision_gateway = false
gateway_config = {
gateway_type = "VPN"
# Possible values are "VPN" or "ExpressRoute"
vpn_gateway_name = "vpngateway"
active_active = false
#An active-active gateway requires a HighPerformance or an UltraPerformance sku. If false, an active-standby gateway will be created. Defaults to false.
enable_bgp = false
#If true, BGP (Border Gateway Protocol) will be enabled for this Virtual Network Gateway. Defaults to false.
vpn_gateway_sku = "Basic"
#Valid options are Basic, Standard, HighPerformance, UltraPerformance, ErGw1AZ, ErGw2AZ, ErGw3AZ, VpnGw1, VpnGw2, VpnGw3, VpnGw1AZ, VpnGw2AZ, and VpnGw3AZ
#and depend on the gateway_type (ER or VPN) and vpn_type arguments, ie: PolicyBased gateway only supports the Basic sku.
vpn_gateway_type = "RouteBased"
#The routing type of the Virtual Network Gateway. Valid options are RouteBased or PolicyBased. Defaults to RouteBased.
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["GatewayDiagnosticLog", true, true, 30],
["TunnelDiagnosticLog", true, true, 30],
["RouteDiagnosticLog", true, true, 30],
["IKEDiagnosticLog", true, true, 30],
["P2SDiagnosticLog", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
pip = {
name = "vpn"
allocation_method = "Dynamic"
sku = "Basic"
#For basic SKU, you can pick the zone to be deployed - if you want multi zone - pick Standard IP and pick AZ aware VPN gateway SKU
#dns_prefix = "arnaudvpn"
#zones = ["1"]
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
}
#Settings for the connection to be established
#Settings for the local network connection
connection_name = "onpremconnection"
remote_network_connect = true
remote_network = {
gateway_name = "caf_local_network"
gateway_ip = "1.2.3.4"
gateway_adress_space = ["1.0.0.0/8"]
bgp_settings = {
# asn =
# bgp_peering_address =
# peer_weight =
}
}
##Settings for the Azure Key Vault
akv_config = {
name = "vpn-akv"
akv_features = {
enabled_for_disk_encryption = true
enabled_for_deployment = true
enabled_for_template_deployment = true
}
sku_name = "standard"
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AuditEvent", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
}

Просмотреть файл

@ -1 +0,0 @@
# nothing

Просмотреть файл

@ -1,577 +0,0 @@
# settings for the shared network blueprint
resource_groups_shared_services = {
HUB-CORE-NET = {
name = "-hub-network-shared"
location = "southeastasia"
}
}
enable_ddos_standard = false
ddos_name = "ddos_protection_plan"
shared_services_vnet = {
vnet = {
name = "Shared-Services"
address_space = ["10.101.4.0/22"]
dns = []
}
specialsubnets = {
}
subnets = {
subnet0 = {
name = "Critical_Applications"
cidr = ["10.101.4.0/25"]
nsg_name = "Critical_Applications_nsg"
service_endpoints = []
}
subnet1 = {
name = "Active_Directory"
cidr = ["10.101.4.128/27"]
service_endpoints = []
nsg_name = "Active_Directory_nsg"
nsg = [
{
name = "W32Time",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "UDP"
source_port_range = "*"
destination_port_range = "123"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "RPC-Endpoint-Mapper",
priority = "101"
direction = "Inbound"
access = "Allow"
protocol = "UDP"
source_port_range = "*"
destination_port_range = "135"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "Kerberos-password-change",
priority = "102"
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "464"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "RPC-Dynamic-range",
priority = "103"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "49152-65535"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "LDAP",
priority = "104"
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "389"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "LDAP-SSL",
priority = "105"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "636"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "LDAP-GC",
priority = "106"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "3268"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "LDAP-GC-SSL",
priority = "107"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "3269"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "DNS",
priority = "108"
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "53"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "Kerberos",
priority = "109"
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "88"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "SMB",
priority = "110"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "445"
source_address_prefix = "*"
destination_address_prefix = "*"
}
]
}
subnet2 = {
name = "SQL_Servers"
cidr = ["10.101.4.160/27"]
service_endpoints = []
nsg_name = "Data_tier_nsg"
nsg = [
{
name = "TDS-In",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "UDP"
source_port_range = "*"
destination_port_range = "1433"
source_address_prefix = "*"
destination_address_prefix = "*"
}
]
}
subnet4 = {
name = "AzureBastionSubnet"
cidr = ["10.101.4.192/27"]
nsg_name = "AzureBastionSubnet_nsg"
nsg = [
{
name = "bastion-in-allow",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "*"
},
{
name = "bastion-control-in-allow-443",
priority = "120"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "135"
source_address_prefix = "GatewayManager"
destination_address_prefix = "*"
},
{
name = "Kerberos-password-change",
priority = "121"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "4443"
source_address_prefix = "GatewayManager"
destination_address_prefix = "*"
},
{
name = "bastion-vnet-out-allow-22",
priority = "103"
direction = "Outbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "VirtualNetwork"
},
{
name = "bastion-vnet-out-allow-3389",
priority = "101"
direction = "Outbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "3389"
source_address_prefix = "*"
destination_address_prefix = "VirtualNetwork"
},
{
name = "bastion-azure-out-allow",
priority = "120"
direction = "Outbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "AzureCloud"
}
]
}
}
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["VMProtectionAlerts", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
## settings for Azure bastion configuration
## not enabled, uncomment the code in the networking shared services blueprint.
enable_bastion = true
bastion_config = {
name = "azurebastion"
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["BastionAuditLogs", true, true, 30],
]
metric = [
# ["AllMetrics", true, true, 30],
]
}
ip_name = "caf-pip-bastion"
ip_addr = {
allocation_method = "Static"
#Dynamic Public IP Addresses aren't allocated until they're assigned to a resource (such as a Virtual Machine or a Load Balancer) by design within Azure
#properties below are optional
sku = "Standard" #defaults to Basic
ip_version = "IPv4" #defaults to IP4, Only dynamic for IPv6, Supported arguments are IPv4 or IPv6, NOT Both
#dns_prefix = "arnaudmytest"
#timeout = 15 #TCP timeout for idle connections. The value can be set between 4 and 30 minutes.
#zones = [1] #1 zone number, IP address must be standard, ZoneRedundant argument is not supported in provider at time of writing
#reverse_fqdn = ""
#public_ip_prefix_id = "/subscriptions/00000000-00000-0000-0000-000000000000/resourceGroups/uqvh-hub-ingress-net/providers/Microsoft.Network/publicIPPrefixes/myprefix"
#refer to the prefix and check sku types are same in IP and prefix
}
ip_diags = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# settings for the shared egress blueprint
resource_groups_shared_egress = {
HUB-EGRESS-NET = {
name = "-hub-network-egress"
location = "southeastasia"
}
}
# Settings for the shared services egress vnet - note that Azure Firewall subnet must be at least /26
networking_egress = {
vnet = {
name = "Shared-Egress"
address_space = ["10.0.0.0/25"]
dns = ["192.168.0.16", "192.168.0.64"]
}
specialsubnets = {
AzureFirewallSubnet = {
name = "AzureFirewallSubnet"
cidr = ["10.0.0.0/26"]
service_endpoints = []
}
}
subnets = {
subnet1 = {
name = "Network_Monitoring"
cidr = ["10.0.0.64/26"]
nsg_name = "Network_Monitoring_nsg"
}
}
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["VMProtectionAlerts", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
# Settings for the public IP address to be used for egress
# Must be standard and static for Azure Firewall
ip_addr_config = {
ip_name = "caf-pip-egress"
allocation_method = "Static"
#Dynamic Public IP Addresses aren't allocated until they're assigned to a resource (such as a Virtual Machine or a Load Balancer) by design within Azure
#properties below are optional
sku = "Standard" #defaults to Basic
ip_version = "IPv4" #defaults to IP4, Only dynamic for IPv6, Supported arguments are IPv4 or IPv6, NOT Both
#dns_prefix = "arnaudmytest"
#timeout = 15 #TCP timeout for idle connections. The value can be set between 4 and 30 minutes.
#zones = [1] #1 zone number, IP address must be standard, ZoneRedundant argument is not supported in provider at time of writing
#reverse_fqdn = ""
#public_ip_prefix_id = "/subscriptions/00000000-00000-0000-0000-000000000000/resourceGroups/uqvh-hub-ingress-net/providers/Microsoft.Network/publicIPPrefixes/myprefix"
#refer to the prefix and check sku types are same in IP and prefix
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the Azure Firewall settings
az_fw_config = {
name = "az-fw-caf"
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AzureFirewallApplicationRule", true, true, 30],
["AzureFirewallNetworkRule", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the UDR object
udr_object = {
nexthop_type = "VirtualAppliance"
prefix = "0.0.0.0/0"
route_name = "myWay"
subnets_to_udr = ""
nexthop_ip = ""
}
# settings for the transit network blueprint
#resource group creation
resource_groups_shared_transit = {
HUB-NET-TRANSIT = {
name = "-hub-network-transit"
location = "southeastasia"
}
}
# Settings for the shared services egress vnet
networking_transit = {
vnet = {
name = "Shared-Transit"
address_space = ["172.16.0.0/23"]
dns = ["192.168.0.16", "192.168.0.64"]
}
specialsubnets = {
GatewaySubnet = {
name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway
cidr = ["172.16.0.0/24"]
service_endpoints = []
}
}
subnets = {
subnet1 = {
name = "NetworkMonitoring"
cidr = ["172.16.1.0/24"]
nsg_name = "NetworkMonitoring_msg"
service_endpoints = []
}
}
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["VMProtectionAlerts", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
# Settings for the public IP address to be used for egress
public_ip_addr = {
name = "caf-pip-vpn"
allocation_method = "Dynamic"
sku = "Basic"
#For basic SKU, you can pick the zone to be deployed - if you want multi zone - pick Standard IP and pick AZ aware VPN gateway SKU
#dns_prefix = "arnaudvpn"
#zones = ["1"]
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["DDoSProtectionNotifications", true, true, 30],
["DDoSMitigationFlowLogs", true, true, 30],
["DDoSMitigationReports", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
# Settings for the Virtual Network gateway to be created
provision_gateway = false
gateway_config = {
gateway_type = "VPN"
# Possible values are "VPN" or "ExpressRoute"
vpn_gateway_name = "mygateway"
active_active = false
#An active-active gateway requires a HighPerformance or an UltraPerformance sku. If false, an active-standby gateway will be created. Defaults to false.
enable_bgp = false
#If true, BGP (Border Gateway Protocol) will be enabled for this Virtual Network Gateway. Defaults to false.
vpn_gateway_sku = "Basic"
#Valid options are Basic, Standard, HighPerformance, UltraPerformance, ErGw1AZ, ErGw2AZ, ErGw3AZ, VpnGw1, VpnGw2, VpnGw3, VpnGw1AZ, VpnGw2AZ, and VpnGw3AZ
#and depend on the gateway_type (ER or VPN) and vpn_type arguments, ie: PolicyBased gateway only supports the Basic sku.
vpn_gateway_type = "RouteBased"
#The routing type of the Virtual Network Gateway. Valid options are RouteBased or PolicyBased. Defaults to RouteBased.
diagnostics = {
log = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["GatewayDiagnosticLog", true, true, 30],
["TunnelDiagnosticLog", true, true, 30],
["RouteDiagnosticLog", true, true, 30],
["IKEDiagnosticLog", true, true, 30],
["P2SDiagnosticLog", true, true, 30],
]
metric = [
["AllMetrics", true, true, 30],
]
}
}
#Settings for the connection to be established
#Settings for the local network connection
connection_name = "onpremconnection"
remote_network_connect = true
remote_network = {
gateway_name = "caf_local_network"
gateway_ip = "1.2.3.4"
gateway_adress_space = ["1.0.0.0/8"]
}
##Settings for the Azure Key Vault
akv_config = {
name = "techakv"
akv_features = {
enabled_for_disk_encryption = true
enabled_for_deployment = true
enabled_for_template_deployment = true
}
sku_name = "premium"
# network_acls = {
# bypass = "AzureServices"
# default_action = "Deny"
# }
diagnostics = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AuditEvent", true, true, 60],
]
metric = [
#["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 60],
]
}
}
# settings for the operations blueprint
# #Azure Site Recovery Configuration
asr_config = {
asr_vault_name = "asr"
asr_diags = {
log_analytics_destination_type = "Dedicated"
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AzureBackupReport", true, true, 30],
["CoreAzureBackup", true, true, 30],
["AddonAzureBackupAlerts", true, true, 30],
["AddonAzureBackupJobs", true, true, 30],
["AddonAzureBackupPolicy", true, true, 30],
["AddonAzureBackupProtectedInstance", true, true, 30],
["AddonAzureBackupStorage", true, true, 30],
["AzureSiteRecoveryJobs", true, true, 30],
["AzureSiteRecoveryEvents", true, true, 30],
["AzureSiteRecoveryReplicatedItems", true, true, 30],
["AzureSiteRecoveryReplicationStats", true, true, 30],
["AzureSiteRecoveryRecoveryPoints", true, true, 30],
["AzureSiteRecoveryReplicationDataUploadRate", true, true, 30],
["AzureSiteRecoveryProtectedDiskDataChurn", true, true, 30],
]
metric = [
#["AllMetrics", 60, True],
]
}
}
#Azure Automation account name
auto_config = {
auto_account = "azauto"
auto_diags = {
log = [
# ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["JobLogs", true, true, 30],
["JobStreams", true, true, 30],
["DscNodeStatus", true, true, 30],
]
metric = [
# ["Category name", "Metric Enabled(true/false)", "Retention Enabled(true/false)", Retention_period]
["AllMetrics", true, true, 30],
]
}
}

Просмотреть файл

@ -0,0 +1,40 @@
# Cloud Adoption Framework for Azure - Landing zones on Terraform - Foundations
The foundations landing zone allows you to manage the core components of an environment:
* Management groups
* Policies
* Auditing and Accounting, deployment or connection to existing ones.
Foundations landing zone operates at **level 1**.
For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md).
</BR>
## Components
CAF foundations landing zone leverages the enterprise-scale module in order to deploy its core components.
## Deploying CAF foundations
By default, the content of this landing zone is empty unless you specify a configuration file to enable it.
```bash
# To deploy the CAF foundations in passthrough mode
rover -lz /tf/caf/landingzones/caf_foundations \
-level level1 \
-a apply
```
## Deploying CAF foundations with enterprise-scale (experimental)
This is currently work in progress.
Use the following configuration file in order to get started with the enterprise-scale module integration:
```bash
rover -lz /tf/caf/landingzones/caf_foundations \
-var-folder /tf/caf/landingzones/caf_foundations/scenario/200 \
-level level1 \
-a apply
```

Просмотреть файл

@ -0,0 +1,25 @@
module "enterprise_scale" {
source = "Azure/caf-enterprise-scale/azurerm"
version = "0.0.6-preview"
root_parent_id = data.azurerm_client_config.current.tenant_id
# Define a custom ID to use for the root Management Group
# Also used as a prefix for all core Management Group IDs
root_id = "caf"
# Control whether to deploy the default core landing zones // default = true
deploy_core_landing_zones = false
# Control whether to deploy the demo landing zones // default = false
deploy_demo_landing_zones = false
# Set a path for the custom archetype library path
library_path = try(format("%s%s", path.root, var.enterprise_scale.library_path), "")
# Deploys the custom landing zone configuration as defined in config file
custom_landing_zones = try(var.enterprise_scale.management_groups, {})
default_location = local.global_settings.regions[local.global_settings.default_region]
}

Просмотреть файл

@ -0,0 +1,57 @@
locals {
landingzone = {
current = {
storage_account_name = var.tfstate_storage_account_name
container_name = var.tfstate_container_name
resource_group_name = var.tfstate_resource_group_name
}
lower = {
storage_account_name = var.lower_storage_account_name
container_name = var.lower_container_name
resource_group_name = var.lower_resource_group_name
}
}
}
data "terraform_remote_state" "remote" {
for_each = try(var.landingzone.tfstates, {})
backend = var.landingzone.backend_type
config = {
storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name
container_name = local.landingzone[try(each.value.level, "current")].container_name
resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name
key = each.value.tfstate
}
}
locals {
landingzone_tag = {
"landingzone" = var.landingzone.key
}
tags = merge(var.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version })
global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings
diagnostics = {
diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition)
diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations
storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts
log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics
}
remote = {
managed_identities = {
for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {}))
}
azuread_groups = {
for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {}))
}
vnets = {
for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {}))
}
}
}

Просмотреть файл

@ -0,0 +1,63 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 2.32.0"
}
azuread = {
source = "hashicorp/azuread"
version = "~> 1.0.0"
}
random = {
source = "hashicorp/random"
version = "~> 2.2.1"
}
null = {
source = "hashicorp/null"
version = "~> 2.1.0"
}
tls = {
source = "hashicorp/tls"
version = "~> 2.2.0"
}
azurecaf = {
source = "aztfmod/azurecaf"
version = "~> 1.1.0"
}
}
required_version = ">= 0.13"
}
provider "azurerm" {
features {
key_vault {
purge_soft_delete_on_destroy = true
}
}
}
data "azurerm_client_config" "current" {}
data "azurerm_subscription" "current" {}
locals {
# Update the tfstates map
tfstates = merge(
map(var.landingzone.key,
map(
"storage_account_name", var.tfstate_storage_account_name,
"container_name", var.tfstate_container_name,
"resource_group_name", var.tfstate_resource_group_name,
"key", var.tfstate_key,
"level", var.landingzone.level,
"tenant_id", var.tenant_id,
"subscription_id", data.azurerm_client_config.current.subscription_id
)
)
,
data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates
)
}

Просмотреть файл

@ -0,0 +1,27 @@
output global_settings {
value = local.global_settings
sensitive = true
}
output diagnostics {
value = local.diagnostics
sensitive = true
}
output vnets {
value = local.remote.vnets
sensitive = true
}
output managed_identities {
value = local.remote.managed_identities
sensitive = true
}
output azuread_groups {
value = local.remote.azuread_groups
sensitive = true
}
output tfstates {
value = local.tfstates
sensitive = true
}

Просмотреть файл

@ -0,0 +1,45 @@
landingzone = {
backend_type = "azurerm"
global_settings_key = "launchpad"
level = "level1"
key = "caf_foundations"
tfstates = {
launchpad = {
level = "lower"
tfstate = "caf_launchpad.tfstate"
}
}
}
enterprise_scale = {
#path to the policies definition and assignment repo
library_path = "/scenario/200/lib"
#management groups hierarchy configuration
management_groups = {
caf = {
display_name = "CAF-RootManagementGroup"
parent_management_group_id = ""
subscription_ids = []
archetype_config = {
archetype_id = "es_root"
parameters = {}
access_control = {}
}
}
child-caf = {
display_name = "CAF-ChildManagementGroup"
parent_management_group_id = "caf"
subscription_ids = []
archetype_config = {
archetype_id = "es_management"
parameters = {
ES-Deploy-ForwardDiagLog = {
logAnalytics = "central_logs_region1"
}
}
access_control = {}
}
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
{
"es_management": {
"policy_assignments": [
"ES-Deploy-ASC-Standard"
],
"policy_definitions": [
],
"policy_set_definitions": [],
"role_assignments": [],
"role_definitions": []
}
}

Просмотреть файл

@ -0,0 +1,13 @@
{
"es_root": {
"policy_assignments": [
"ES-Deploy-ASC-Standard"
],
"policy_definitions": [
"ES-Deploy-ASC-Standard"
],
"policy_set_definitions": [],
"role_assignments": [],
"role_definitions": []
}
}

Просмотреть файл

@ -0,0 +1,28 @@
{
"name": "ES-Allowed-Locations",
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"properties": {
"description": "Specifies the allowed locations (regions) where resources can be deployed",
"displayName": "ES-Allowed-Resource-Locations",
"notScopes": [],
"parameters": {
"listOfAllowedLocations": {
"value": [
"uksouth",
"ukwest"
]
}
},
"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c",
"scope": "${current_scope_resource_id}"
},
"sku": {
"name": "A0",
"tier": "Free"
},
"location": "${default_location}",
"identity": {
"type": "None"
}
}

Просмотреть файл

@ -0,0 +1,28 @@
{
"name": "ES-Allowed-RSG-Locations",
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"properties": {
"description": "Specifies the allowed locations (regions) where Resource Groups can be deployed",
"displayName": "ES-Allowed-ResourceGroup-Locations",
"notScopes": [],
"parameters": {
"listOfAllowedLocations": {
"value": [
"uksouth",
"ukwest"
]
}
},
"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988",
"scope": "${current_scope_resource_id}"
},
"sku": {
"name": "A0",
"tier": "Free"
},
"location": "${default_location}",
"identity": {
"type": "None"
}
}

Просмотреть файл

@ -0,0 +1,28 @@
{
"name": "ES-Deploy-ASC-ContExport",
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"properties": {
"description": "Deploy ASC Continuous Export To Log Analytics Workspace.",
"displayName": "ES-Deploy-ASC-ContinuousExportToWorkspace",
"notScopes": [],
"parameters": {
"resourceGroupLocation": {
"value": null
},
"workspaceResourceId": {
"value": null
}
},
"policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-ContinuousExportToWorkspace",
"scope": "${current_scope_resource_id}"
},
"sku": {
"name": "A0",
"tier": "Free"
},
"location": "${default_location}",
"identity": {
"type": "SystemAssigned"
}
}

Просмотреть файл

@ -0,0 +1,88 @@
{
"name": "ES-Deploy-ASC-Monitoring",
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"properties": {
"description": "Enable Monitoring in Azure Security Center.",
"displayName": "ES-Deploy-ASC-Monitoring",
"notScopes": [],
"parameters": {
"aadAuthenticationInSqlServerMonitoringEffect": {
"value": "Disabled"
},
"diskEncryptionMonitoringEffect": {
"value": "Disabled"
},
"encryptionOfAutomationAccountMonitoringEffect": {
"value": "Disabled"
},
"identityDesignateLessThanOwnersMonitoringEffect": {
"value": "Disabled"
},
"identityDesignateMoreThanOneOwnerMonitoringEffect": {
"value": "Disabled"
},
"identityEnableMFAForWritePermissionsMonitoringEffect": {
"value": "Disabled"
},
"identityRemoveDeprecatedAccountMonitoringEffect": {
"value": "Disabled"
},
"identityRemoveDeprecatedAccountWithOwnerPermissionsMonitoringEffect": {
"value": "Disabled"
},
"identityRemoveExternalAccountWithOwnerPermissionsMonitoringEffect": {
"value": "Disabled"
},
"identityRemoveExternalAccountWithReadPermissionsMonitoringEffect": {
"value": "Disabled"
},
"identityRemoveExternalAccountWithWritePermissionsMonitoringEffect": {
"value": "Disabled"
},
"jitNetworkAccessMonitoringEffect": {
"value": "Disabled"
},
"networkSecurityGroupsOnSubnetsMonitoringEffect": {
"value": "AuditIfNotExists"
},
"sqlDbEncryptionMonitoringEffect": {
"value": "Disabled"
},
"sqlManagedInstanceAdvancedDataSecurityEmailAdminsMonitoringEffect": {
"value": "Disabled"
},
"sqlManagedInstanceAdvancedDataSecurityEmailsMonitoringEffect": {
"value": "Disabled"
},
"sqlServerAdvancedDataSecurityEmailAdminsMonitoringEffect": {
"value": "Disabled"
},
"sqlServerAdvancedDataSecurityMonitoringEffect": {
"value": "Disabled"
},
"systemUpdatesMonitoringEffect": {
"value": "Disabled"
},
"useRbacRulesMonitoringEffect": {
"value": "Disabled"
},
"vmssSystemUpdatesMonitoringEffect": {
"value": "Disabled"
},
"windowsDefenderExploitGuardMonitoringEffect": {
"value": "Disabled"
}
},
"policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8",
"scope": "${current_scope_resource_id}"
},
"sku": {
"name": "A0",
"tier": "Free"
},
"location": "${default_location}",
"identity": {
"type": "SystemAssigned"
}
}

Просмотреть файл

@ -0,0 +1,21 @@
{
"name": "ES-Deploy-ASC-Standard",
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"properties": {
"description": "Deploy Azure Security Center Standard Tier.",
"displayName": "ES-Deploy-ASC-Standard",
"notScopes": [],
"parameters": {},
"policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-Standard",
"scope": "${current_scope_resource_id}"
},
"sku": {
"name": "A0",
"tier": "Free"
},
"location": "${default_location}",
"identity": {
"type": "SystemAssigned"
}
}

Просмотреть файл

@ -0,0 +1,25 @@
{
"name": "ES-Deploy-ForwardActLogs",
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"properties": {
"description": "Ensures that Activity Log Diagnostics settings are set to push logs into Log Analytics workspace.",
"displayName": "ES-Deploy-Diagnostics-ForwardActivityLogs",
"notScopes": [],
"parameters": {
"logAnalytics": {
"value": null
}
},
"policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-Diagnostics-LogAnalytics",
"scope": "${current_scope_resource_id}"
},
"sku": {
"name": "A0",
"tier": "Free"
},
"location": "${default_location}",
"identity": {
"type": "SystemAssigned"
}
}

Просмотреть файл

@ -0,0 +1,25 @@
{
"name": "ES-Deploy-ForwardDiagLog",
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"properties": {
"description": "Ensures that Azure resources are configured to forward diagnostic logs and metrics to an Azure Log Analytics workspace.",
"displayName": "ES-Deploy-Diagnostics-ForwardDiagnosticLogs",
"notScopes": [],
"parameters": {
"logAnalytics": {
"value": null
}
},
"policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/ES-Deploy-Diagnostics-LogAnalytics",
"scope": "${current_scope_resource_id}"
},
"sku": {
"name": "A0",
"tier": "Free"
},
"location": "${default_location}",
"identity": {
"type": "SystemAssigned"
}
}

Просмотреть файл

@ -0,0 +1,284 @@
{
"name": "ES-Deploy-ASC-Standard",
"type": "Microsoft.Authorization/policyDefinitions",
"apiVersion": "2019-09-01",
"properties": {
"description": "Ensures that subscriptions have Security Center Standard enabled.",
"displayName": "ES-Deploy-ASC-Standard",
"mode": "All",
"parameters": {
"pricingTierVMs": {
"type": "String",
"metadata": {
"displayName": "pricingTierVMs",
"description": ""
},
"allowedValues": [
"Standard",
"Free"
],
"defaultValue": "Standard"
},
"pricingTierSqlServers": {
"type": "String",
"metadata": {
"displayName": "pricingTierSqlServers",
"description": ""
},
"allowedValues": [
"Standard",
"Free"
],
"defaultValue": "Standard"
},
"pricingTierAppServices": {
"type": "String",
"metadata": {
"displayName": "pricingTierAppServices",
"description": ""
},
"allowedValues": [
"Standard",
"Free"
],
"defaultValue": "Standard"
},
"pricingTierStorageAccounts": {
"type": "String",
"metadata": {
"displayName": "pricingTierStorageAccounts",
"description": ""
},
"allowedValues": [
"Standard",
"Free"
],
"defaultValue": "Standard"
},
"pricingTierContainerRegistry": {
"type": "String",
"metadata": {
"displayName": "pricingTierContainerRegistry",
"description": ""
},
"allowedValues": [
"Standard",
"Free"
],
"defaultValue": "Standard"
},
"pricingTierKeyVaults": {
"type": "String",
"metadata": {
"displayName": "pricingTierKeyVaults",
"description": ""
},
"allowedValues": [
"Standard",
"Free"
],
"defaultValue": "Standard"
},
"pricingTierKubernetesService": {
"type": "String",
"metadata": {
"displayName": "pricingTierKubernetesService",
"description": ""
},
"allowedValues": [
"Standard",
"Free"
],
"defaultValue": "Standard"
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions"
}
]
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "Microsoft.Security/pricings",
"deploymentScope": "subscription",
"existenceScope": "subscription",
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635"
],
"existenceCondition": {
"allOf": [
{
"field": "Microsoft.Security/pricings/pricingTier",
"equals": "Standard"
},
{
"field": "type",
"equals": "Microsoft.Security/pricings"
}
]
},
"deployment": {
"location": "northeurope",
"properties": {
"mode": "incremental",
"parameters": {
"pricingTierVMs": {
"value": "[parameters('pricingTierVMs')]"
},
"pricingTierSqlServers": {
"value": "[parameters('pricingTierSqlServers')]"
},
"pricingTierAppServices": {
"value": "[parameters('pricingTierAppServices')]"
},
"pricingTierStorageAccounts": {
"value": "[parameters('pricingTierStorageAccounts')]"
},
"pricingTierContainerRegistry": {
"value": "[parameters('pricingTierContainerRegistry')]"
},
"pricingTierKeyVaults": {
"value": "[parameters('pricingTierKeyVaults')]"
},
"pricingTierKubernetesService": {
"value": "[parameters('pricingTierKubernetesService')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"pricingTierVMs": {
"type": "string",
"metadata": {
"description": "pricingTierVMs"
}
},
"pricingTierSqlServers": {
"type": "string",
"metadata": {
"description": "pricingTierSqlServers"
}
},
"pricingTierAppServices": {
"type": "string",
"metadata": {
"description": "pricingTierAppServices"
}
},
"pricingTierStorageAccounts": {
"type": "string",
"metadata": {
"description": "pricingTierStorageAccounts"
}
},
"pricingTierContainerRegistry": {
"type": "string",
"metadata": {
"description": "ContainerRegistry"
}
},
"pricingTierKeyVaults": {
"type": "string",
"metadata": {
"description": "KeyVaults"
}
},
"pricingTierKubernetesService": {
"type": "string",
"metadata": {
"description": "KubernetesService"
}
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Security/pricings",
"apiVersion": "2018-06-01",
"name": "VirtualMachines",
"properties": {
"pricingTier": "[parameters('pricingTierVMs')]"
}
},
{
"type": "Microsoft.Security/pricings",
"apiVersion": "2018-06-01",
"name": "StorageAccounts",
"dependsOn": [
"[concat('Microsoft.Security/pricings/VirtualMachines')]"
],
"properties": {
"pricingTier": "[parameters('pricingTierStorageAccounts')]"
}
},
{
"type": "Microsoft.Security/pricings",
"apiVersion": "2018-06-01",
"name": "AppServices",
"dependsOn": [
"[concat('Microsoft.Security/pricings/StorageAccounts')]"
],
"properties": {
"pricingTier": "[parameters('pricingTierAppServices')]"
}
},
{
"type": "Microsoft.Security/pricings",
"apiVersion": "2018-06-01",
"name": "SqlServers",
"dependsOn": [
"[concat('Microsoft.Security/pricings/AppServices')]"
],
"properties": {
"pricingTier": "[parameters('pricingTierSqlServers')]"
}
},
{
"type": "Microsoft.Security/pricings",
"apiVersion": "2018-06-01",
"name": "KeyVaults",
"dependsOn": [
"[concat('Microsoft.Security/pricings/SqlServers')]"
],
"properties": {
"pricingTier": "[parameters('pricingTierKeyVaults')]"
}
},
{
"type": "Microsoft.Security/pricings",
"apiVersion": "2018-06-01",
"name": "KubernetesService",
"dependsOn": [
"[concat('Microsoft.Security/pricings/KeyVaults')]"
],
"properties": {
"pricingTier": "[parameters('pricingTierKubernetesService')]"
}
},
{
"type": "Microsoft.Security/pricings",
"apiVersion": "2018-06-01",
"name": "ContainerRegistry",
"dependsOn": [
"[concat('Microsoft.Security/pricings/KubernetesService')]"
],
"properties": {
"pricingTier": "[parameters('pricingTierContainerRegistry')]"
}
}
],
"outputs": {}
}
}
}
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,53 @@
# Map of the remote data state
variable lower_storage_account_name {}
variable lower_container_name {}
variable lower_resource_group_name {}
variable tfstate_storage_account_name {
description = "This value is propulated by the rover"
}
variable tfstate_container_name {
description = "This value is propulated by the rover"
}
variable tfstate_key {
description = "This value is propulated by the rover"
}
variable tfstate_resource_group_name {
description = "This value is propulated by the rover"
}
variable landingzone {
default = {
backend_type = "azurerm"
global_settings_key = "launchpad"
level = "level1"
key = "foundations"
tfstates = {
launchpad = {
level = "lower"
tfstate = "caf_launchpad.tfstate"
}
}
}
}
variable tenant_id {}
variable rover_version {}
variable logged_user_objectId {
default = null
}
variable logged_aad_app_objectId {
default = null
}
variable tags {
type = map
default = {}
}
variable enterprise_scale {
default = {}
}
variable diagnostics_definition {
default = {}
}

Просмотреть файл

@ -0,0 +1,15 @@
# The PAT token must be provisioned in a different deployment
provider "azuredevops" {
org_service_url = var.azure_devops.url
personal_access_token = data.azurerm_key_vault_secret.pat.value
}
data "azurerm_key_vault_secret" "pat" {
name = var.azure_devops.pats["admin"].secret_name
key_vault_id = local.remote.keyvaults[var.azure_devops.pats["admin"].lz_key][var.azure_devops.pats["admin"].keyvault_key].id
}
data "azuredevops_project" "project" {
project_name = var.azure_devops.project
}

Просмотреть файл

@ -0,0 +1,52 @@
locals {
organization_agent_pools = try(var.azure_devops.organization_agent_pools, {})
project_agent_pools = try(var.azure_devops.project_agent_pools, {})
}
## Agent pools
## Those pools are created in the organization, not the project
resource "azuredevops_agent_pool" "pool" {
for_each = try(var.azure_devops.organization_agent_pools, {})
name = each.value.name
auto_provision = lookup(each.value, "auto_provision", false)
}
#
# add the agent pools into the project
#
data "azuredevops_agent_pool" "pool" {
depends_on = [azuredevops_agent_pool.pool]
for_each = try(var.azure_devops.project_agent_pools, {})
name = each.value.name
}
resource "azuredevops_agent_queue" "agent_queue" {
for_each = data.azuredevops_agent_pool.pool
project_id = data.azuredevops_project.project.id
agent_pool_id = each.value.id
lifecycle {
ignore_changes = [
agent_pool_id
]
}
}
#
# Grant acccess to queue to all pipelines in the project
#
resource "azuredevops_resource_authorization" "queue" {
for_each = data.azuredevops_agent_pool.pool
project_id = data.azuredevops_project.project.id
resource_id = azuredevops_agent_queue.agent_queue[each.key].id
type = "queue"
authorized = true
}

Просмотреть файл

@ -0,0 +1,43 @@
data "azuredevops_git_repositories" "repos" {
project_id = data.azuredevops_project.project.id
}
locals {
repositories = zipmap(tolist(data.azuredevops_git_repositories.repos.repositories.*.name), tolist(data.azuredevops_git_repositories.repos.repositories))
}
resource "azuredevops_build_definition" "build_definition" {
for_each = try(var.azure_devops.pipelines, {})
project_id = data.azuredevops_project.project.id
name = each.value.name
path = each.value.folder
variable_groups = lookup(each.value, "variable_group_keys", null) == null ? null : [
for key in each.value.variable_group_keys :
azuredevops_variable_group.variable_group[key].id
]
repository {
repo_id = local.repositories[each.value.git_repo_name].id
repo_type = each.value.repo_type
yml_path = each.value.yaml
branch_name = lookup(each.value, "branch_name", null)
# service_connection_id = lookup(each.value, "repo_type", null) == "github" ? null : azuredevops_serviceendpoint_azurerm.github[each.value.service_connection_key].id
}
ci_trigger {
use_yaml = true
}
dynamic "variable" {
for_each = try(each.value.variables, {})
content {
name = variable.key
value = variable.value
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
data "azurerm_key_vault_secret" "client_secret" {
depends_on = [module.caf]
for_each = try(var.azure_devops.service_endpoints, {})
name = format("%s-client-secret", local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].keyvaults[each.value.secret_keyvault_key].secret_name_client_secret)
key_vault_id = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].keyvaults[each.value.secret_keyvault_key].id
}
resource "azuredevops_serviceendpoint_azurerm" "azure" {
depends_on = [module.caf]
for_each = try(var.azure_devops.service_endpoints, {})
project_id = data.azuredevops_project.project.id
service_endpoint_name = each.value.endpoint_name
credentials {
serviceprincipalid = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].azuread_application.application_id
serviceprincipalkey = data.azurerm_key_vault_secret.client_secret[each.key].value
}
azurerm_spn_tenantid = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].tenant_id
azurerm_subscription_id = each.value.subscription_id
azurerm_subscription_name = each.value.subscription_name
}
#
# Grant acccess to service endpoint to all pipelines in the project
#
resource "azuredevops_resource_authorization" "endpoint" {
for_each = azuredevops_serviceendpoint_azurerm.azure
project_id = data.azuredevops_project.project.id
resource_id = each.value.id
type = "endpoint"
authorized = true
}

Просмотреть файл

@ -0,0 +1,39 @@
#
# permissions required:
# - vso.variablegroups_manage (create)
# + vso.buid (update)
# + vso.build_execute (destroy)
#
resource "azuredevops_variable_group" "variable_group" {
for_each = try(var.azure_devops.variable_groups, {})
project_id = data.azuredevops_project.project.id
name = each.value.name
description = try(each.value.description, null)
allow_access = try(each.value.allow_access, false)
dynamic "key_vault" {
for_each = lookup(each.value, "keyvault", null) == null ? [] : [1]
content {
name = try(each.value.keyvault.lz_key, null) == null ? local.combined.keyvaults[var.landingzone.key][each.value.keyvault.keyvault_key].name : local.combined.keyvaults[each.value.keyvault.lz_key][each.value.keyvault.keyvault_key].name
service_endpoint_id = azuredevops_serviceendpoint_azurerm.azure[each.value.keyvault.serviceendpoint_key].id
}
}
dynamic "variable" {
for_each = {
for key, variable in each.value.variables : key => {
name = key == "name" ? variable : key
value = key == "name" ? null : variable
}
}
content {
# When used with Keyvault, the name must be the keyvault secret name and value must not be set
name = variable.value.name
value = variable.value.value
}
}
}

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 76 KiB

Просмотреть файл

@ -0,0 +1,84 @@
locals {
landingzone = {
current = {
storage_account_name = var.tfstate_storage_account_name
container_name = var.tfstate_container_name
resource_group_name = var.tfstate_resource_group_name
}
lower = {
storage_account_name = var.lower_storage_account_name
container_name = var.lower_container_name
resource_group_name = var.lower_resource_group_name
}
}
}
data "terraform_remote_state" "remote" {
for_each = try(var.landingzone.tfstates, {})
backend = var.landingzone.backend_type
config = {
storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name
container_name = local.landingzone[try(each.value.level, "current")].container_name
resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name
key = each.value.tfstate
}
}
locals {
landingzone_tag = {
"landingzone" = var.landingzone.key
}
tags = merge(var.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version })
global_settings = {
prefix = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings.prefix
prefix_with_hyphen = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings.prefix_with_hyphen
prefix_start_alpha = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings.prefix_start_alpha
default_region = try(var.global_settings.default_region, data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings.default_region)
environment = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings.environment
regions = try(var.global_settings.regions, data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings.regions)
passthrough = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings.passthrough
random_length = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings.random_length
}
diagnostics = {
diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition)
diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations
storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts
log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics
}
combined = {
aad_apps = merge(local.remote.aad_apps, map(var.landingzone.key, module.caf.aad_apps))
azuread_groups = merge(local.remote.azuread_groups, map(var.landingzone.key, module.caf.azuread_groups))
keyvaults = merge(local.remote.keyvaults, map(var.landingzone.key, module.caf.keyvaults))
managed_identities = merge(local.remote.managed_identities, map(var.landingzone.key, module.caf.managed_identities))
}
remote = {
aad_apps = {
for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aad_apps[key], {}))
}
azuread_groups = {
for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {}))
}
keyvaults = {
for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {}))
}
managed_identities = {
for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {}))
}
vnets = {
for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {}))
}
}
}

Просмотреть файл

@ -0,0 +1,69 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 2.32.0"
}
azuread = {
source = "hashicorp/azuread"
version = "~> 1.0.0"
}
random = {
source = "hashicorp/random"
version = "~> 2.2.1"
}
null = {
source = "hashicorp/null"
version = "~> 2.1.0"
}
external = {
source = "hashicorp/external"
version = "~> 1.2.0"
}
azuredevops = {
source = "terraform-providers/azuredevops"
version = "~> 0.0.1"
}
tls = {
source = "hashicorp/tls"
version = "~> 2.2.0"
}
azurecaf = {
source = "aztfmod/azurecaf"
version = "~>1.1.0"
}
}
required_version = ">= 0.13"
}
provider "azurerm" {
features {
key_vault {
purge_soft_delete_on_destroy = true
}
}
}
data "azurerm_client_config" "current" {}
locals {
tfstates = merge(
map(var.landingzone.backend_type,
map(
"storage_account_name", var.tfstate_storage_account_name,
"container_name", var.tfstate_container_name,
"resource_group_name", var.tfstate_resource_group_name,
"key", var.tfstate_key,
"level", var.landingzone.level,
"tenant_id", var.tenant_id,
"subscription_id", data.azurerm_client_config.current.subscription_id
)
)
,
data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates
)
}

Просмотреть файл

@ -0,0 +1,6 @@
output keyvaults {
value = map(
var.landingzone.key, module.caf.keyvaults
)
sensitive = true
}

Просмотреть файл

@ -0,0 +1,48 @@
# Cloud Adoption Framework for Azure - Landing zones on Terraform - Azure Devops add-on
The Azure Devops add-ons allow you to setup you Azure Devops environment as a platform to automate all your subsequent landing zone deployment from level 0 until level 4 through Azure pipelines with self hosted agents.
* Azure Devops:
- Agent Pools (Organization and Project Level)
- Service Endpoint
- Variables and Variable Groups
- Pipelines
* Azure (Connection with Azure Devops):
- Azure AD Application
- Custom Role
- Keyvault and access policies for Azure AD App
Azure Devops add-on landing zone operates at **level 0**
For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md).
## Dependencies
Landing zone:
* CAF Launchpad (Scenario 200 or above)
Azure Devops (example):
* Organization: https://dev.azure.com/azure-terraform
* Project : contoso_demo (https://dev.azure.com/azure-terraform/contoso_demo)
* Repo : caf-configuration (https://dev.azure.com/azure-terraform/contoso_demo/_git/caf-configuration)
- In order for pipeline to work properly, YAML file should be in this repo and referred accordingly under pipeline section in azure_devops.tfvars
- sample yaml attached [here](./scenario/200-contoso_demo/pipeline/rover.yaml).
Azure:
* PAT Token : PAT Token should be updated in keyvault secret that deployed by launchpad LZ as below
![](./documentation/images/pat_token.png)
## Deployment
```bash
rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops \
-tfstate azure_devops-contoso_demo.tfstate \
-var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo \
-parallelism 30 \
-level level0 \
-a apply -env sandpit
```
We are planning to release more examples on how to deploy the Azure Devops Agents.

Просмотреть файл

@ -0,0 +1,232 @@
azure_devops = {
url = "https://dev.azure.com/azure-terraform/"
project = "contoso_demo"
# PAT Token should be updated manually to the keyvault after running launchpad
pats = {
admin = {
secret_name = "azdo-pat-admin"
lz_key = "launchpad"
keyvault_key = "secrets"
}
}
organization_agent_pools = {
level0 = {
name = "caf-sandpit-level0"
auto_provision = false # When set to false the agent pool is not populated automatically into the devops projects (recommended)
}
level1 = {
name = "caf-sandpit-level1"
auto_provision = false
}
level2 = {
name = "caf-sandpit-level2"
auto_provision = false
}
level3 = {
name = "caf-sandpit-level3"
auto_provision = false
}
level4 = {
name = "caf-sandpit-level4"
auto_provision = false
}
}
project_agent_pools = {
level0 = {
name = "caf-sandpit-level0"
}
level1 = {
name = "caf-sandpit-level1"
}
level2 = {
name = "caf-sandpit-level2"
}
level3 = {
name = "caf-sandpit-level3"
}
level4 = {
name = "caf-sandpit-level4"
}
}
service_endpoints = {
contoso_demo = {
endpoint_name = "terraformdev (terraformdev.onmicrosoft.com) - contoso_demo"
subscription_name = "ase-landingzone"
subscription_id = "1d53e782-9f46-4720-b6b3-cff29106e9f6"
aad_app_key = "contoso_demo"
secret_keyvault_key = "devops"
}
}
variable_groups = {
global = {
name = "release-global" # changing that name requires to change it in the devops agents yaml variables group
allow_access = true
variables = {
HOME_FOLDER_USER = "vsts_azpcontainer"
ROVER_IMAGE = "aztfmod/rover:2010.2808"
TF_CLI_ARGS = "'-no-color'"
TF_CLI_ARGS_init = ""
TF_CLI_ARGS_plan = "'-input=false'"
TF_VAR_ARGS_destroy = "'-auto-approve -refresh=false'"
ENVIRONMENT = "sandpit"
LANDINGZONE_BRANCH = "2010.0.0"
}
}
level0 = {
name = "release-level0"
allow_access = true
variables = {
TF_VAR_pipeline_level = "level0"
ARM_USE_MSI = "true"
AGENT_POOL = "caf-sandpit-level0"
}
}
level0_kv = {
name = "release-level0-msi"
allow_access = true
keyvault = {
lz_key = "launchpad"
keyvault_key = "level0"
serviceendpoint_key = "contoso_demo"
}
variables = {
name = "msi-resource-id"
}
}
level1 = {
name = "release-level1"
allow_access = true
variables = {
TF_VAR_pipeline_level = "level1"
ARM_USE_MSI = "true"
AGENT_POOL = "caf-sandpit-level1"
}
}
level1_kv = {
name = "release-level1-msi"
allow_access = true
keyvault = {
lz_key = "launchpad"
keyvault_key = "level1"
serviceendpoint_key = "contoso_demo"
}
variables = {
name = "msi-resource-id"
}
}
level2 = {
name = "release-level2"
allow_access = true
variables = {
TF_VAR_pipeline_level = "level2"
ARM_USE_MSI = "true"
AGENT_POOL = "caf-sandpit-level2"
}
}
level2_kv = {
name = "release-level2-msi"
allow_access = true
keyvault = {
lz_key = "launchpad"
keyvault_key = "level2"
serviceendpoint_key = "contoso_demo"
}
variables = {
name = "msi-resource-id"
}
}
level3 = {
name = "release-level3"
allow_access = true
variables = {
TF_VAR_pipeline_level = "level3"
ARM_USE_MSI = "true"
AGENT_POOL = "caf-sandpit-level3"
}
}
level3_kv = {
name = "release-level3-msi"
allow_access = true
keyvault = {
lz_key = "launchpad"
keyvault_key = "level3"
serviceendpoint_key = "contoso_demo"
}
variables = {
name = "msi-resource-id"
}
}
}
pipelines = {
#
# Agent pools
#
devops_agent_level1_plan = {
name = "devops_agent_level1_plan"
folder = "\\configuration\\level1"
yaml = "configuration/pipeline/rover.yaml"
repo_type = "TfsGit"
git_repo_name = "caf-configuration"
variables = {
landingZoneName = "azdo-agent-level1",
terraformAction = "plan",
tfstateName = "azdo-agent-level1.tfstate"
configPath = "/configuration/level1/azuredevops/agent"
landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent"
level = "level1"
}
variable_group_keys = ["global", "level0", "level0_kv"]
}
devops_agent_level1_apply = {
name = "devops_agent_level1_apply"
folder = "\\configuration\\level1"
yaml = "configuration/pipeline/rover.yaml"
repo_type = "TfsGit"
git_repo_name = "caf-configuration"
variables = {
landingZoneName = "azdo-agent-level1",
terraformAction = "apply",
tfstateName = "azdo-agent-level1.tfstate"
configPath = "/configuration/level1/azuredevops/agent"
landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent"
level = "level1"
}
variable_group_keys = ["global", "level0", "level0_kv"]
}
devops_agent_level1_destroy = {
name = "devops_agent_level1_destroy"
folder = "\\configuration\\level1"
yaml = "configuration/pipeline/rover.yaml"
repo_type = "TfsGit"
git_repo_name = "caf-configuration"
variables = {
landingZoneName = "azdo-agent-level1",
terraformAction = "destroy",
tfstateName = "azdo-agent-level1.tfstate"
configPath = "/configuration/level1/azuredevops/agent"
landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent"
level = "level1"
}
variable_group_keys = ["global", "level0", "level0_kv"]
}
}
}

Просмотреть файл

@ -0,0 +1,123 @@
landingzone = {
backend_type = "azurerm"
global_settings_key = "launchpad"
level = "level0"
key = "azdo-contoso_demo"
tfstates = {
launchpad = {
level = "current"
tfstate = "caf_launchpad.tfstate"
}
}
}
resource_groups = {
rg1 = {
name = "devops-agents-security"
}
}
keyvaults = {
devops = {
name = "devops"
resource_group_key = "rg1"
sku_name = "standard"
creation_policies = {
keyvault_level0_rw = {
# Reference a key to an azure ad group
lz_key = "launchpad"
azuread_group_key = "keyvault_level0_rw"
secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"]
}
}
}
}
keyvault_access_policies_azuread_apps = {
level0 = {
contoso_demo = {
lz_key = "launchpad"
azuread_app_key = "contoso_demo"
secret_permissions = ["Get", "List"]
}
}
level1 = {
contoso_demo = {
lz_key = "launchpad"
azuread_app_key = "contoso_demo"
secret_permissions = ["Get", "List"]
}
}
level2 = {
contoso_demo = {
lz_key = "launchpad"
azuread_app_key = "contoso_demo"
secret_permissions = ["Get", "List"]
}
}
level3 = {
contoso_demo = {
lz_key = "launchpad"
azuread_app_key = "contoso_demo"
secret_permissions = ["Get", "List"]
}
}
level4 = {
contoso_demo = {
lz_key = "launchpad"
azuread_app_key = "contoso_demo"
secret_permissions = ["Get", "List"]
}
}
}
azuread_apps = {
contoso_demo = {
useprefix = true
application_name = "caf-level4-contoso_demo"
password_expire_in_days = 60
tenant_name = "terraformdev.onmicrosoft.com"
reply_urls = ["https://localhost"]
keyvaults = {
devops = {
secret_prefix = "aadapp-caf-level4-azdo-contoso_demo"
}
}
}
}
custom_role_definitions = {
caf-azdo-to-azure-subscription = {
name = "caf-azure-devops-azure-app-service-improvement-program-TO-azure-subscription"
useprefix = true
description = "CAF Custom role for service principal in Azure Devops to access resources"
permissions = {
actions = [
"Microsoft.Resources/subscriptions/read",
"Microsoft.KeyVault/vaults/read"
]
}
}
}
role_mapping = {
custom_role_mapping = {
subscriptions = {
logged_in_subscription = {
"caf-azdo-to-azure-subscription" = {
azuread_apps = {
keys = ["contoso_demo"]
}
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,71 @@
parameters:
- name: timeoutInMinutes
displayName: 'Timeout in minutes'
type: number
default: 60
variables:
- group: release-global
resources:
containers:
- container: rover
image: $(ROVER_IMAGE)
options: --user 0:0 -e TF_PLUGIN_CACHE_DIR="/home/$(HOME_FOLDER_USER)/plugin-cache" -e TF_DATA_DIR="/home/$(HOME_FOLDER_USER)"
trigger: none
jobs:
- job: CAF_Rover
displayName: Azure Landing Zone
pool: $(AGENT_POOL)
continueOnError: false
workspace:
clean: all
container: rover
timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
steps:
- checkout: self
- bash: |
git clone --branch $(LANDINGZONE_BRANCH) https://github.com/Azure/caf-terraform-landingzones.git ${BUILD_REPOSITORY_LOCALPATH}/public 2>/dev/null
az login --identity -u $(msi-resource-id)
/tf/rover/rover.sh -lz ${BUILD_REPOSITORY_LOCALPATH}$(landingZonePath) \
-tfstate $(tfstateName) \
-var-folder ${BUILD_REPOSITORY_LOCALPATH}$(configPath) \
-parallelism=30 \
-level $(level) \
-a $(terraformAction) \
-env $(ENVIRONMENT)
condition: ne(variables['terraformAction'], 'destroy')
failOnStderr: true
displayName: 'Terraform $(terraformAction)'
- bash: |
git clone --branch $(LANDINGZONE_BRANCH) https://github.com/Azure/caf-terraform-landingzones.git ${BUILD_REPOSITORY_LOCALPATH}/public 2>/dev/null
az login --identity -u $(msi-resource-id)
/tf/rover/rover.sh -lz ${BUILD_REPOSITORY_LOCALPATH}$(landingZonePath) \
-tfstate $(tfstateName) \
-var-folder ${BUILD_REPOSITORY_LOCALPATH}$(configPath) \
-parallelism=30 \
-level $(level) \
-a $(terraformAction) \
-auto-approve \
-env $(ENVIRONMENT)
condition: eq(variables['terraformAction'], 'destroy')
failOnStderr: true
displayName: 'Terraform destroy'

Просмотреть файл

@ -0,0 +1,36 @@
module "caf" {
source = "aztfmod/caf/azurerm"
version = "~> 0.4"
current_landingzone_key = var.landingzone.key
tenant_id = var.tenant_id
tfstates = local.tfstates
tags = local.tags
global_settings = local.global_settings
diagnostics = local.diagnostics
diagnostic_storage_accounts = var.diagnostic_storage_accounts
logged_user_objectId = var.logged_user_objectId
logged_aad_app_objectId = var.logged_aad_app_objectId
resource_groups = var.resource_groups
storage_accounts = var.storage_accounts
azuread_groups = var.azuread_groups
keyvaults = var.keyvaults
keyvault_access_policies = var.keyvault_access_policies
keyvault_access_policies_azuread_apps = var.keyvault_access_policies_azuread_apps
role_mapping = var.role_mapping
custom_role_definitions = var.custom_role_definitions
azuread_apps = var.azuread_apps
compute = {
virtual_machines = var.virtual_machines
}
storage = {
storage_account_blobs = var.storage_account_blobs
}
remote_objects = {
keyvaults = local.remote.keyvaults
vnets = local.remote.vnets
managed_identities = local.remote.managed_identities
azuread_groups = local.remote.azuread_groups
}
}

Просмотреть файл

@ -0,0 +1,98 @@
# Map of the remote data state for lower level
variable lower_storage_account_name {}
variable lower_container_name {}
variable lower_resource_group_name {}
variable tfstate_storage_account_name {}
variable tfstate_container_name {}
variable tfstate_key {}
variable tfstate_resource_group_name {}
variable global_settings {
default = {}
}
variable tenant_id {}
variable landingzone {
}
variable rover_version {
default = null
}
variable logged_user_objectId {
default = null
}
variable logged_aad_app_objectId {
default = null
}
variable tags {
default = null
}
variable app_service_environments {
default = {}
}
variable app_service_plans {
default = {}
}
variable app_services {
default = {}
}
variable diagnostics_definition {
default = {}
}
variable resource_groups {
default = {}
}
variable network_security_group_definition {
default = {}
}
variable vnets {
default = {}
}
variable azurerm_redis_caches {
default = {}
}
variable mssql_servers {
default = {}
}
variable storage_accounts {
default = {}
}
variable storage_account_blobs {
default = {}
}
variable azuread_groups {
default = {}
}
variable keyvaults {
default = {}
}
variable keyvault_access_policies {
default = {}
}
variable keyvault_access_policies_azuread_apps {
default = {}
}
variable virtual_machines {
default = {}
}
variable diagnostic_storage_accounts {
default = {}
}
variable virtual_machine_extension_scripts {
default = {}
}
variable azure_devops {
default = {}
}
variable role_mapping {
default = {}
}
variable custom_role_definitions {
default = {}
}
variable azuread_apps {
default = {}
}
variable dynamic_keyvault_secrets {
default = {}
}

Просмотреть файл

@ -0,0 +1,23 @@
module secret {
source = "./secret"
for_each = {
for key, value in var.settings : key => value
if try(value.value, null) == null
}
name = each.value.secret_name
value = try(each.value.value, null) == null ? try(var.objects[each.value.output_key][each.value.resource_key][each.value.attribute_key], var.objects[each.value.output_key][each.value.attribute_key]) : each.value.value
keyvault_id = var.keyvault_id
}
module secret_immutable {
source = "./secret_immutable"
for_each = {
for key, value in var.settings : key => value
if try(value.value, null) == ""
}
name = each.value.secret_name
value = try(each.value.value, null) == null ? try(var.objects[each.value.output_key][each.value.resource_key][each.value.attribute_key], var.objects[each.value.output_key][each.value.attribute_key]) : each.value.value
keyvault_id = var.keyvault_id
}

Просмотреть файл

@ -0,0 +1,5 @@
resource "azurerm_key_vault_secret" "secret" {
name = var.name
value = var.value
key_vault_id = var.keyvault_id
}

Просмотреть файл

@ -0,0 +1,3 @@
variable name {}
variable value {}
variable keyvault_id {}

Просмотреть файл

@ -0,0 +1,12 @@
resource "azurerm_key_vault_secret" "secret" {
count = var.value == "" ? 1 : 0
name = var.name
value = var.value
key_vault_id = var.keyvault_id
lifecycle {
ignore_changes = [
value
]
}
}

Просмотреть файл

@ -0,0 +1,3 @@
variable name {}
variable value {}
variable keyvault_id {}

Просмотреть файл

@ -0,0 +1,3 @@
variable settings {}
variable objects {}
variable keyvault_id {}

Просмотреть файл

@ -0,0 +1,9 @@
module dynamic_keyvault_secrets {
source = "./dynamic_keyvault_secrets"
for_each = try(var.dynamic_keyvault_secrets, {})
settings = each.value
keyvault_id = module.caf.keyvaults[each.key].id
objects = module.caf
}

Просмотреть файл

@ -0,0 +1,44 @@
resource "azurerm_virtual_machine_extension" "devops_selfhosted_agent" {
for_each = {
for key, value in var.extensions : key => value
if key == "devops_selfhosted_agent"
}
name = "install_azure_devops_agent"
virtual_machine_id = var.virtual_machine_id
publisher = "Microsoft.Azure.Extensions"
type = "CustomScript"
type_handler_version = "2.1"
#timestamp: use this field only to trigger a re-run of the script by changing value of this field.
# Any integer value is acceptable; it must only be different than the previous value.
settings = jsonencode(
{
"timestamp" : each.value.version,
"fileUris" : concat(local.devops_selfhosted_agent.file_uris, local.devops_selfhosted_agent.storage_account_blobs_urls),
}
)
protected_settings = jsonencode(
{
"commandToExecute" : format("bash %s '%s' '%s' '%s' '%s' '%s' '%s' '%s'", var.extensions[each.key].agent_init_script, var.settings[each.key].azure_devops.url, var.settings[each.key].agent_pat, var.settings[each.key].azure_devops.agent_pool.name, var.settings[each.key].azure_devops.agent_pool.agent_name_prefix, var.settings[each.key].azure_devops.agent_pool.num_agents, var.settings[each.key].admin_username, var.settings[each.key].azure_devops.rover_version)
}
)
}
locals {
devops_selfhosted_agent = {
file_uris = flatten(
[
for file_uris_key, file in try(var.extensions.devops_selfhosted_agent.fileUris, {}) : [
for file_uri_key in file.storage_blob_keys : var.settings.devops_selfhosted_agent.storage_accounts[file.storage_account_key].containers[file.container_key].blobs[file_uri_key].url
]
]
)
storage_account_blobs_urls = try(var.settings.devops_selfhosted_agent.storage_account_blobs_urls, [])
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше