diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 32fba61838..6537678615 100755 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -32,11 +32,11 @@ // "shutdownAction": "none", // Uncomment the next line to run commands after the container is created. - "postCreateCommand": "sudo 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 autoupdate", + "postCreateCommand": "sudo cp -R /tmp/.ssh-localhost/* ~/.ssh && sudo chown -R $(whoami):$(whoami) /tf/caf && sudo chmod 400 ~/.ssh/* && git config --global core.editor vi && pre-commit install && pre-commit autoupdate", // Add the IDs of extensions you want installed when the container is created in the array below. "extensions": [ - "4ops.terraform", + "hashicorp.terraform", "mutantdino.resourcemonitor", "ms-azure-devops.azure-pipelines", "omartawfik.github-actions-vscode" diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 71976c5d9c..e0260c630c 100755 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -6,7 +6,7 @@ version: '3.7' services: rover: - image: aztfmod/rover:0.15.4-2105.2603 + image: aztfmod/rover:1.0.1-2106.3012 user: vscode labels: diff --git a/.github/workflows/master-sql-mi-tf13.yaml b/.github/workflows/master-sql-mi-tf13.yaml deleted file mode 100644 index 32aa612af9..0000000000 --- a/.github/workflows/master-sql-mi-tf13.yaml +++ /dev/null @@ -1,173 +0,0 @@ -# -# Copyright (c) Microsoft Corporation -# Licensed under the MIT License. -# - -name: scenarios-sql-mi - -on: - schedule: - - cron: '0 2 * * 0' #2 AM on Sunday - -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 }} - ROVER_RUNNER: true - -jobs: - foundations: - name: foundations - runs-on: ubuntu-latest - - strategy: - fail-fast: true - max-parallel: 1 - matrix: - region: ["southeastasia"] - random_length: ['5'] - - container: - image: aztfmod/rover:0.13.7-2105.2603 - options: --user 0 - - steps: - - uses: actions/checkout@v2 - - - uses: actions/checkout@v2 - with: - repository: Azure/caf-terraform-landingzones - path: public - ref: '2104.3' - - - 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}/public/caf_launchpad -a apply \ - -var-folder ${GITHUB_WORKSPACE}/public/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 regions={region1="${{ matrix.region }}"}' \ - '-var tags={testing_job_id="${{ github.run_id }}"}' - - - examples: - name: examples - runs-on: ubuntu-latest - - needs: foundations - - strategy: - fail-fast: false - matrix: - config_files: [ - "examples/mssql_mi/200-mi" - ] - - container: - image: aztfmod/rover:0.13.7-2105.2603 - options: --user 0 - - steps: - - uses: actions/checkout@v2 - - - uses: actions/checkout@v2 - with: - repository: Azure/caf-terraform-landingzones - path: public - ref: 'patch.5.3.1' - - - 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}/public/caf_solution -a apply \ - -level level1 \ - -tfstate $(basename ${{ matrix.config_files }}).tfstate \ - -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ - --environment ${{ github.run_id }} - - - name: destroy example - if: always() - run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/public/caf_solution -a destroy \ - -level level1 \ - -tfstate $(basename ${{ matrix.config_files }}).tfstate \ - -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ - --environment ${{ github.run_id }} \ - -auto-approve - - - foundations_destroy: - name: foundations_destroy - runs-on: ubuntu-latest - if: always() - needs: examples - - strategy: - fail-fast: false - matrix: - region: ["southeastasia"] - - container: - image: aztfmod/rover:0.13.7-2105.2603 - options: --user 0 - - steps: - - uses: actions/checkout@v2 - - - uses: actions/checkout@v2 - with: - repository: Azure/caf-terraform-landingzones - path: public - ref: '2104.3' - - - 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: | - - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/public/caf_launchpad/ -a destroy \ - -level level0 \ - -var-folder ${GITHUB_WORKSPACE}/public/caf_launchpad/scenario/100 \ - -launchpad \ - --environment ${{ github.run_id }} \ - -parallelism=30 \ - '-var prefix=g${{ github.run_id }}' \ - '-var regions={region1="${{ matrix.region }}"}' \ - '-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.testing_job_id=='${{ github.run_id }}'].name" -o tsv`; do az keyvault purge --name $i; 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 diff --git a/.github/workflows/master-sql-mi-tf14.yaml b/.github/workflows/master-sql-mi-tf14.yaml deleted file mode 100755 index f1962ad5a5..0000000000 --- a/.github/workflows/master-sql-mi-tf14.yaml +++ /dev/null @@ -1,179 +0,0 @@ -# -# Copyright (c) Microsoft Corporation -# Licensed under the MIT License. -# - -name: scenarios-sql-mi-tf14 - -on: - pull_request: - paths: - - msssql_managed_instances.tf - - msssql_managed_databases.tf - - modules/databases/mssql_managed_instance/** - - modules/databases/mssql_managed_database/** - schedule: - - cron: '0 3 * * 0' #3 AM on sunday - -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 }} - ROVER_RUNNER: true - -jobs: - foundations: - name: foundations - runs-on: ubuntu-latest - - strategy: - fail-fast: true - max-parallel: 1 - matrix: - region: ["southeastasia"] - random_length: ['5'] - - container: - image: aztfmod/rover:0.14.11-2105.2603 - options: --user 0 - - steps: - - uses: actions/checkout@v2 - - - uses: actions/checkout@v2 - with: - repository: Azure/caf-terraform-landingzones - path: public - ref: '2104.3' - - - 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}/public/caf_launchpad -a apply \ - -var-folder ${GITHUB_WORKSPACE}/public/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 regions={region1="${{ matrix.region }}"}' \ - '-var tags={testing_job_id="${{ github.run_id }}"}' - - - examples: - name: examples - runs-on: ubuntu-latest - - needs: foundations - - strategy: - fail-fast: false - matrix: - config_files: [ - "examples/mssql_mi/200-mi" - ] - - container: - image: aztfmod/rover:0.14.11-2105.2603 - options: --user 0 - - steps: - - uses: actions/checkout@v2 - - - uses: actions/checkout@v2 - with: - repository: Azure/caf-terraform-landingzones - path: public - ref: '2104.3' - - - 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}/public/caf_example -a apply \ - -level level1 \ - -tfstate $(basename ${{ matrix.config_files }}).tfstate \ - -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ - --environment ${{ github.run_id }} - - - name: destroy example - if: always() - run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/public/caf_example -a destroy \ - -level level1 \ - -tfstate $(basename ${{ matrix.config_files }}).tfstate \ - -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ - --environment ${{ github.run_id }} \ - -auto-approve - - - foundations_destroy: - name: foundations_destroy - runs-on: ubuntu-latest - if: always() - needs: examples - - strategy: - fail-fast: false - matrix: - region: ["southeastasia"] - - container: - image: aztfmod/rover:0.14.9-2103.3107 - options: --user 0 - - steps: - - uses: actions/checkout@v2 - - - uses: actions/checkout@v2 - with: - repository: Azure/caf-terraform-landingzones - path: public - ref: '2104.3' - - - 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: | - - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/public/caf_launchpad/ -a destroy \ - -level level0 \ - -var-folder ${GITHUB_WORKSPACE}/public/caf_launchpad/scenario/100 \ - -launchpad \ - --environment ${{ github.run_id }} \ - -parallelism=30 \ - '-var prefix=g${{ github.run_id }}' \ - '-var regions={region1="${{ matrix.region }}"}' \ - '-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.testing_job_id=='${{ github.run_id }}'].name" -o tsv`; do az keyvault purge --name $i; 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 diff --git a/.github/workflows/master-sql-mi-tf15.yaml b/.github/workflows/master-sql-mi-tf15.yaml deleted file mode 100644 index e3a07b68f0..0000000000 --- a/.github/workflows/master-sql-mi-tf15.yaml +++ /dev/null @@ -1,173 +0,0 @@ -# -# Copyright (c) Microsoft Corporation -# Licensed under the MIT License. -# - -name: scenarios-sql-mi-tf15 - -on: - schedule: - - cron: '0 4 * * 0' #2 AM on Sunday - -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 }} - ROVER_RUNNER: true - -jobs: - foundations: - name: foundations - runs-on: ubuntu-latest - - strategy: - fail-fast: true - max-parallel: 1 - matrix: - region: ["southeastasia"] - random_length: ['5'] - - container: - image: aztfmod/rover:0.15.4-2105.2603 - options: --user 0 - - steps: - - uses: actions/checkout@v2 - - - uses: actions/checkout@v2 - with: - repository: Azure/caf-terraform-landingzones - path: public - ref: '2104.3' - - - 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}/public/caf_launchpad -a apply \ - -var-folder ${GITHUB_WORKSPACE}/public/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 regions={region1="${{ matrix.region }}"}' \ - '-var tags={testing_job_id="${{ github.run_id }}"}' - - - examples: - name: examples - runs-on: ubuntu-latest - - needs: foundations - - strategy: - fail-fast: false - matrix: - config_files: [ - "examples/mssql_mi/200-mi" - ] - - container: - image: aztfmod/rover:0.15.4-2105.2603 - options: --user 0 - - steps: - - uses: actions/checkout@v2 - - - uses: actions/checkout@v2 - with: - repository: Azure/caf-terraform-landingzones - path: public - ref: '2104.3' - - - 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}/public/caf_example -a apply \ - -level level1 \ - -tfstate $(basename ${{ matrix.config_files }}).tfstate \ - -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ - --environment ${{ github.run_id }} - - - name: destroy example - if: always() - run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/public/caf_example -a destroy \ - -level level1 \ - -tfstate $(basename ${{ matrix.config_files }}).tfstate \ - -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ - --environment ${{ github.run_id }} \ - -auto-approve - - - foundations_destroy: - name: foundations_destroy - runs-on: ubuntu-latest - if: always() - needs: examples - - strategy: - fail-fast: false - matrix: - region: ["southeastasia"] - - container: - image: aztfmod/rover:0.15.4-2105.2603 - options: --user 0 - - steps: - - uses: actions/checkout@v2 - - - uses: actions/checkout@v2 - with: - repository: Azure/caf-terraform-landingzones - path: public - ref: '2104.3' - - - 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: | - - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/public/caf_launchpad/ -a destroy \ - -level level0 \ - -var-folder ${GITHUB_WORKSPACE}/public/caf_launchpad/scenario/100 \ - -launchpad \ - --environment ${{ github.run_id }} \ - -parallelism=30 \ - '-var prefix=g${{ github.run_id }}' \ - '-var regions={region1="${{ matrix.region }}"}' \ - '-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.testing_job_id=='${{ github.run_id }}'].name" -o tsv`; do az keyvault purge --name $i; 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 diff --git a/.github/workflows/master-standalone-tf100-longrunners.yaml b/.github/workflows/master-standalone-tf100-longrunners.yaml new file mode 100755 index 0000000000..2f1329215c --- /dev/null +++ b/.github/workflows/master-standalone-tf100-longrunners.yaml @@ -0,0 +1,78 @@ +# +# Copyright (c) Microsoft Corporation +# Licensed under the MIT License. +# + +name: standalone-scenario-tf100-longrunners + +on: + schedule: + - cron: '0 4 * * 0' #2 AM on Sunday + +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 }} + ROVER_RUNNER: true + +jobs: + examples: + name: examples + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + config_files: [ + "mssql_mi/200-mi", + "mssql_mi/200-mi-two-regions" + ] + + container: + image: aztfmod/rover:1.0.1-2106.3012 + 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: | + cd ${GITHUB_WORKSPACE}/examples/${{ matrix.config_files }} + + ${GITHUB_WORKSPACE}/examples/ci.sh ${{ github.run_id }} ${GITHUB_WORKSPACE}/examples + + purge: + name: purge + runs-on: ubuntu-latest + if: ${{ failure() || cancelled() }} + + needs: examples + + container: + image: aztfmod/rover:1.0.1-2106.3012 + options: --user 0 + + steps: + - 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: Complete purge + 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.testing_job_id=='${{ github.run_id }}'].name" -o tsv`; do az keyvault purge --name $i; 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 diff --git a/.github/workflows/master-standalone-tf100.yaml b/.github/workflows/master-standalone-tf100.yaml new file mode 100755 index 0000000000..b18268c18f --- /dev/null +++ b/.github/workflows/master-standalone-tf100.yaml @@ -0,0 +1,96 @@ +# +# Copyright (c) Microsoft Corporation +# Licensed under the MIT License. +# + +name: standalone-scenario-tf100 + +on: + workflow_dispatch: + pull_request: + paths-ignore: + - .github/workflows/master-100.yaml + - 'documentation/**' + - '_pictures/**' + - 'README.md' + - 'examples/README.md' + - 'CHANGELOG.md' + schedule: + - cron: '0 0 * * 0' #1 AM on Sunday + +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 }} + ROVER_RUNNER: true + +jobs: + load_scenarios: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.load_scenarios.outputs.matrix }} + steps: + - uses: actions/checkout@v2 + - id: load_scenarios + run: | + cases=$(( + cat ./.github/workflows/standalone-scenarios.json) | jq -c .) + echo "::set-output name=matrix::${cases}" + + examples: + name: examples + runs-on: ubuntu-latest + needs: load_scenarios + + strategy: + fail-fast: false + matrix: ${{fromJSON(needs.load_scenarios.outputs.matrix)}} + + container: + image: aztfmod/rover:1.0.1-2106.3012 + 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: | + cd ${GITHUB_WORKSPACE}/examples/${{ matrix.config_files }} + + ${GITHUB_WORKSPACE}/examples/ci.sh ${{ github.run_id }} ${GITHUB_WORKSPACE}/examples + + purge: + name: purge + runs-on: ubuntu-latest + if: ${{ failure() || cancelled() }} + + needs: examples + + container: + image: aztfmod/rover:1.0.1-2106.3012 + options: --user 0 + + steps: + - 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: Complete purge + 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.testing_job_id=='${{ github.run_id }}'].name" -o tsv`; do az keyvault purge --name $i; 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 diff --git a/.github/workflows/master-standalone-tf13.yaml b/.github/workflows/master-standalone-tf13.yaml deleted file mode 100755 index 3f073b67c5..0000000000 --- a/.github/workflows/master-standalone-tf13.yaml +++ /dev/null @@ -1,187 +0,0 @@ -# -# Copyright (c) Microsoft Corporation -# Licensed under the MIT License. -# - -name: standalone-scenario - -on: - schedule: - - cron: '0 1 * * 0' #1 AM on Sunday - -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 }} - ROVER_RUNNER: true - -jobs: - examples: - name: examples - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - config_files: [ - "app_gateway/100-simple-app-gateway", - "app_gateway/101-private-public", - "app_insights/100-all-attributes", - "app_insights/100-simple", - "automation/100-simple-automation-account", - "azuread/100-sevice-principle-with-builtin-roles", - "azuread/101-service-principle-with-custom-roles", - "azuread/102-password-rotation", - "compute/availability_set/100-simple-availabilityset", - "compute/availability_set/101-availabilityset-with-proximity-placement-group", - "compute/container_groups/101-aci-rover", - "compute/container_registry/100-simple-acr", - "compute/kubernetes_services/101-single-cluster", - "compute/kubernetes_services/102-multi-nodepools", - "compute/proximity_placement_group", - "compute/virtual_machine/101-single-windows-vm", - "compute/virtual_machine/102-single-vm-data-disks", - "compute/virtual_machine/104-single-windows-backup", - "compute/virtual_machine/106-marketplace-image-with-plan", - "compute/virtual_machine/210-vm-bastion-winrm", - "compute/virtual_machine/211-vm-bastion-winrm-agents", - "compute/virtual_machine_scale_set/100-linux-win-vmss-lb", - "compute/virtual_machine_scale_set/101-linux-win-vmss-agw", - "compute/windows_virtual_desktop/wvd_resources", - "cosmos_db/100-simple-cosmos-db-cassandra", - "cosmos_db/100-simple-cosmos-db-cassandra", - "cosmos_db/100-simple-cosmos-db-gremlin", - "cosmos_db/100-simple-cosmos-db-gremlin", - "cosmos_db/100-simple-cosmos-db-sql", - "cosmos_db/100-simple-cosmos-db-table", - "cosmos_db/100-simple-cosmos-db-table", - "databricks/100-simple-databricks", - "datalake/101-datalake-storage", - "diagnostics_profiles/200-diagnostics-eventhub-namespaces", - "eventhub/100-simple-eventhub-namespace", - "eventhub/101-evh-namespace-with-private-endpoint", - "eventhub/102-namespace-and-evh-with-auth-rules", - "eventhub/103-eventhub-consumer-groups", - "keyvault/101-keyvault-policies", - "machine_learning/100-aml", - "managed_service_identity/100-msi-levels", - "mariadb_server/100-simple-mariadb", - "mariadb_server/101-vnet-rule-mariadb", - "mariadb_server/102-private-endpoint-mariadb", - "mariadb_server/103-private-endpoint-with-fw-rule-mariadb", - "monitoring/100-service-health-alerts", - "mssql_server/104-sqlserver-elastic_pools", - "mssql_server/105-sqlserver-failover_groups", - # "mssql_server/106-sqlserver-db-msi-authentication", - "mssql_server/107-sqlserver-db-retention-policy", - "mssql_server/108-sqlserver-db-diagnostics", - "mssql_server/109-sqlserver-network-firewall-rule", - "mysql_server/100-simple-mysql", - "mysql_server/101-vnet-rule-mysql", - "mysql_server/102-private-endpoint-mysql", - "mysql_server/103-private-endpoint-with-fw-rule-mysql", - "networking/dns_zones/100-simple-dns_zone", - "networking/express_routes", - "networking/firewall/100-standard-firewall-legacy-pip", - "networking/firewall/101-simple-firewall", - "networking/firewall/102-premium-firewall", - "networking/firewall/103-firewall-policies", - "networking/front_door/100-simple-front_door", - "networking/front_door/101-front_door_waf", - "networking/ip_group/100-simple-ip_group", - "networking/ip_group/101-firewall-ip_group", - "networking/load_balancers/100-simple-load-balancer-basic-sku", - "networking/load_balancers/101-load-balancer-with-rules", - "networking/load_balancers/102-internal-load-balancer", - "networking/load_balancers/103-load-balancer-nic-association", - "networking/load_balancers/104-load-balancer-diagnostics", - "networking/private_dns/100-private-dns-vnet-links", - "networking/private_links/endpoints/centralized", - "networking/virtual_network_gateway/100-expressroute-gateway", - "networking/virtual_network_gateway/101-vpn-site-to-site", - "networking/virtual_network_gateway/102-vpn-site-to-site-active-active", - "networking/virtual_network_gateway/103-vpn-site-to-site-connection", - "networking/virtual_network/100-import-rg", - "networking/virtual_network/100-simple-vnet-subnets-nsgs", - "networking/virtual_network/100-subnet-delegation", - "networking/virtual_network/101-vnet-peering-nsg", - "networking/virtual_network/200-nsg-flow-logs", - "networking/virtual_network/201-nsg-flow-logs-v1", - "networking/virtual_wan/100-vwan-multi-hubs", - "networking/virtual_wan/101-vwan-hub-firewall-legacy", - "networking/virtual_wan/102-vwan-hub-firewall-new", - "networking/virtual_wan/103-vwan-hub-gw", - "networking/virtual_wan/104-vwan-hub-gw-spp", - "networking/virtual_wan/105-vwan-hub-route-table", - "networking/virtual_wan/106-vwan-hub-routes", - "postgresql_server/100-simple-postgresql", - "postgresql_server/101-vnet-rule-postgresql", - "postgresql_server/102-private-endpoint-postgresql", - "postgresql_server/103-private-endpoint-with-fw-rule", - "recovery_vault/101-simple-asrv", - "recovery_vault/102-asr-protection", - "recovery_vault/103-asr-with-private-endpoint", - "redis_cache/100-redis-standard", - "redis_cache/101-redis-diagnostics", - "redis_cache/102-redis-private", - "storage_accounts/102-storage-account-advanced-options", - "synapse_analytics/100-synapse", - "synapse_analytics/101-synapse-sparkpool", - "webapps/appservice/101-appservice-simple", - "webapps/appservice/102-appservice-slots", - "webapps/appservice/103-appservice-extend", - "webapps/appservice/104-appservice-appinsight", - "webapps/appservice/105-appservice-backup", - "webapps/appservice/106-appservice-diagnostics", - "webapps/appservice/107-appservice-private", - "webapps/function_app/101-function_app-private" - ] - - container: - image: aztfmod/rover:0.13.7-2105.2603 - 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: | - cd ${GITHUB_WORKSPACE}/examples/${{ matrix.config_files }} - - ${GITHUB_WORKSPACE}/landingzones/caf_example/ci.sh ${{ github.run_id }} ${GITHUB_WORKSPACE}/landingzones/caf_example - - purge: - name: purge - runs-on: ubuntu-latest - if: ${{ failure() || cancelled() }} - - needs: examples - - container: - image: aztfmod/rover:0.13.7-2105.2603 - options: --user 0 - - steps: - - 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: Complete purge - 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.testing_job_id=='${{ github.run_id }}'].name" -o tsv`; do az keyvault purge --name $i; 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 \ No newline at end of file diff --git a/.github/workflows/master-standalone-tf14-longrunners.yaml b/.github/workflows/master-standalone-tf14-longrunners.yaml new file mode 100755 index 0000000000..45763b2fa0 --- /dev/null +++ b/.github/workflows/master-standalone-tf14-longrunners.yaml @@ -0,0 +1,78 @@ +# +# Copyright (c) Microsoft Corporation +# Licensed under the MIT License. +# + +name: standalone-scenario-tf14-longrunners + +on: + schedule: + - cron: '0 3 * * 0' #3 AM on sunday + +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 }} + ROVER_RUNNER: true + +jobs: + examples: + name: examples + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + config_files: [ + "mssql_mi/200-mi", + "mssql_mi/200-mi-two-regions" + ] + + container: + image: aztfmod/rover:0.14.11-2106.3012 + 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: | + cd ${GITHUB_WORKSPACE}/examples/${{ matrix.config_files }} + + ${GITHUB_WORKSPACE}/examples/ci.sh ${{ github.run_id }} ${GITHUB_WORKSPACE}/examples + + purge: + name: purge + runs-on: ubuntu-latest + if: ${{ failure() || cancelled() }} + + needs: examples + + container: + image: aztfmod/rover:0.14.11-2106.3007 + options: --user 0 + + steps: + - 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: Complete purge + 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.testing_job_id=='${{ github.run_id }}'].name" -o tsv`; do az keyvault purge --name $i; 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 \ No newline at end of file diff --git a/.github/workflows/master-standalone-tf14.yaml b/.github/workflows/master-standalone-tf14.yaml index bf2ae083ea..1b61c5c9fb 100755 --- a/.github/workflows/master-standalone-tf14.yaml +++ b/.github/workflows/master-standalone-tf14.yaml @@ -19,126 +19,29 @@ env: ROVER_RUNNER: true jobs: + load_scenarios: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.load_scenarios.outputs.matrix }} + steps: + - uses: actions/checkout@v2 + - id: load_scenarios + run: | + cases=$(( + cat ./.github/workflows/standalone-scenarios.json) | jq -c .) + echo "::set-output name=matrix::${cases}" + examples: name: examples runs-on: ubuntu-latest + needs: load_scenarios strategy: fail-fast: false - matrix: - config_files: [ - "app_gateway/100-simple-app-gateway", - "app_gateway/101-private-public", - "app_insights/100-all-attributes", - "app_insights/100-simple", - "automation/100-simple-automation-account", - "azuread/100-sevice-principle-with-builtin-roles", - "azuread/101-service-principle-with-custom-roles", - "azuread/102-password-rotation", - "compute/availability_set/100-simple-availabilityset", - "compute/availability_set/101-availabilityset-with-proximity-placement-group", - "compute/container_groups/101-aci-rover", - "compute/container_registry/100-simple-acr", - "compute/container_registry/200-acr-vnet", - "compute/kubernetes_services/101-single-cluster", - "compute/kubernetes_services/102-multi-nodepools", - "compute/proximity_placement_group", - "compute/virtual_machine/101-single-windows-vm", - "compute/virtual_machine/102-single-vm-data-disks", - "compute/virtual_machine/104-single-windows-backup", - "compute/virtual_machine/106-marketplace-image-with-plan", - "compute/virtual_machine/210-vm-bastion-winrm", - "compute/virtual_machine/211-vm-bastion-winrm-agents", - "compute/virtual_machine_scale_set/100-linux-win-vmss-lb", - "compute/virtual_machine_scale_set/101-linux-win-vmss-agw", - "compute/windows_virtual_desktop/wvd_resources", - "cosmos_db/100-simple-cosmos-db-cassandra", - "cosmos_db/100-simple-cosmos-db-gremlin", - "cosmos_db/100-simple-cosmos-db-sql", - "cosmos_db/100-simple-cosmos-db-table", - "databricks/100-simple-databricks", - "datalake/101-datalake-storage", - "eventhub/100-simple-eventhub-namespace", - "eventhub/101-evh-namespace-with-private-endpoint", - "eventhub/102-namespace-and-evh-with-auth-rules", - "eventhub/103-eventhub-consumer-groups", - "keyvault/101-keyvault-policies", - "machine_learning/100-aml", - "managed_service_identity/100-msi-levels", - "mariadb_server/100-simple-mariadb", - "mariadb_server/101-vnet-rule-mariadb", - "mariadb_server/102-private-endpoint-mariadb", - "mariadb_server/103-private-endpoint-with-fw-rule-mariadb", - "monitoring/100-service-health-alerts", - "mssql_server/104-sqlserver-elastic_pools", - "mssql_server/105-sqlserver-failover_groups", - # "mssql_server/106-sqlserver-db-msi-authentication", - "mssql_server/107-sqlserver-db-retention-policy", - "mssql_server/108-sqlserver-db-diagnostics", - "mssql_server/109-sqlserver-network-firewall-rule", - "mysql_server/100-simple-mysql", - "mysql_server/101-vnet-rule-mysql", - "mysql_server/102-private-endpoint-mysql", - "mysql_server/103-private-endpoint-with-fw-rule-mysql", - "networking/dns_zones/100-simple-dns_zone", - "networking/express_routes", - "networking/firewall/100-standard-firewall-legacy-pip", - "networking/firewall/101-simple-firewall", - "networking/firewall/102-premium-firewall", - "networking/firewall/103-firewall-policies", - "networking/front_door/100-simple-front_door", - "networking/front_door/101-front_door_waf", - "networking/ip_group/100-simple-ip_group", - "networking/ip_group/101-firewall-ip_group", - "networking/load_balancers/100-simple-load-balancer-basic-sku", - "networking/load_balancers/101-load-balancer-with-rules", - "networking/load_balancers/102-internal-load-balancer", - "networking/load_balancers/103-load-balancer-nic-association", - "networking/load_balancers/104-load-balancer-diagnostics", - "networking/private_dns/100-private-dns-vnet-links", - "networking/private_links/endpoints/centralized", - "networking/virtual_network_gateway/100-expressroute-gateway", - "networking/virtual_network_gateway/101-vpn-site-to-site", - "networking/virtual_network_gateway/102-vpn-site-to-site-active-active", - "networking/virtual_network_gateway/103-vpn-site-to-site-connection", - "networking/virtual_network/100-import-rg", - "networking/virtual_network/100-simple-vnet-subnets-nsgs", - "networking/virtual_network/100-subnet-delegation", - "networking/virtual_network/101-vnet-peering-nsg", - "networking/virtual_network/200-nsg-flow-logs", - "networking/virtual_network/201-nsg-flow-logs-v1", - "networking/virtual_wan/100-vwan-multi-hubs", - "networking/virtual_wan/101-vwan-hub-firewall-legacy", - "networking/virtual_wan/102-vwan-hub-firewall-new", - "networking/virtual_wan/103-vwan-hub-gw", - "networking/virtual_wan/104-vwan-hub-gw-spp", - "networking/virtual_wan/105-vwan-hub-route-table", - "networking/virtual_wan/106-vwan-hub-routes", - "postgresql_server/100-simple-postgresql", - "postgresql_server/101-vnet-rule-postgresql", - "postgresql_server/102-private-endpoint-postgresql", - "postgresql_server/103-private-endpoint-with-fw-rule", - "recovery_vault/101-simple-asrv", - "recovery_vault/102-asr-protection", - "recovery_vault/103-asr-with-private-endpoint", - "redis_cache/100-redis-standard", - "redis_cache/101-redis-diagnostics", - "redis_cache/102-redis-private", - "storage_accounts/102-storage-account-advanced-options", - "synapse_analytics/100-synapse", - "synapse_analytics/101-synapse-sparkpool", - "webapps/appservice/101-appservice-simple", - "webapps/appservice/102-appservice-slots", - "webapps/appservice/103-appservice-extend", - "webapps/appservice/104-appservice-appinsight", - "webapps/appservice/105-appservice-backup", - "webapps/appservice/106-appservice-diagnostics", - "webapps/appservice/107-appservice-private", - "webapps/function_app/101-function_app-private" - ] + matrix: ${{fromJSON(needs.load_scenarios.outputs.matrix)}} container: - image: aztfmod/rover:0.14.11-2105.2603 + image: aztfmod/rover:0.14.11-2106.3012 options: --user 0 steps: @@ -153,7 +56,7 @@ jobs: run: | cd ${GITHUB_WORKSPACE}/examples/${{ matrix.config_files }} - ${GITHUB_WORKSPACE}/landingzones/caf_example/ci.sh ${{ github.run_id }} ${GITHUB_WORKSPACE}/landingzones/caf_example + ${GITHUB_WORKSPACE}/examples/ci.sh ${{ github.run_id }} ${GITHUB_WORKSPACE}/examples purge: name: purge @@ -163,7 +66,7 @@ jobs: needs: examples container: - image: aztfmod/rover:0.14.11-2105.2603 + image: aztfmod/rover:0.14.11-2106.3012 options: --user 0 steps: diff --git a/.github/workflows/master-standalone-tf15-longrunners.yaml b/.github/workflows/master-standalone-tf15-longrunners.yaml new file mode 100755 index 0000000000..ae190b12b7 --- /dev/null +++ b/.github/workflows/master-standalone-tf15-longrunners.yaml @@ -0,0 +1,78 @@ +# +# Copyright (c) Microsoft Corporation +# Licensed under the MIT License. +# + +name: standalone-scenario-tf15-longrunners + +on: + schedule: + - cron: '0 4 * * 0' #2 AM on Sunday + +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 }} + ROVER_RUNNER: true + +jobs: + examples: + name: examples + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + config_files: [ + "mssql_mi/200-mi", + "mssql_mi/200-mi-two-regions" + ] + + container: + image: aztfmod/rover:0.15.5-2106.3012 + 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: | + cd ${GITHUB_WORKSPACE}/examples/${{ matrix.config_files }} + + ${GITHUB_WORKSPACE}/examples/ci.sh ${{ github.run_id }} ${GITHUB_WORKSPACE}/examples + + purge: + name: purge + runs-on: ubuntu-latest + if: ${{ failure() || cancelled() }} + + needs: examples + + container: + image: aztfmod/rover:0.15.5-2106.3012 + options: --user 0 + + steps: + - 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: Complete purge + 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.testing_job_id=='${{ github.run_id }}'].name" -o tsv`; do az keyvault purge --name $i; 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 diff --git a/.github/workflows/master-standalone-tf15.yaml b/.github/workflows/master-standalone-tf15.yaml index 22f2029bf4..ef42f97d08 100755 --- a/.github/workflows/master-standalone-tf15.yaml +++ b/.github/workflows/master-standalone-tf15.yaml @@ -6,13 +6,7 @@ name: standalone-scenario-tf15 on: - pull_request: - paths-ignore: - - .github/workflows/master-100.yaml - - 'documentation/**' - - '_pictures/**' - - 'README.md' - - 'CHANGELOG.md' + workflow_dispatch: schedule: - cron: '0 2 * * 0' #1 AM on Sunday @@ -26,126 +20,29 @@ env: ROVER_RUNNER: true jobs: + load_scenarios: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.load_scenarios.outputs.matrix }} + steps: + - uses: actions/checkout@v2 + - id: load_scenarios + run: | + cases=$(( + cat ${GITHUB_WORKSPACE}/.github/workflows/standalone-scenarios.json) | jq -c .) + echo "::set-output name=matrix::${cases}" + examples: name: examples runs-on: ubuntu-latest + needs: load_scenarios strategy: fail-fast: false - matrix: - config_files: [ - "app_gateway/100-simple-app-gateway", - "app_gateway/101-private-public", - "app_insights/100-all-attributes", - "app_insights/100-simple", - "automation/100-simple-automation-account", - "azuread/100-sevice-principle-with-builtin-roles", - "azuread/101-service-principle-with-custom-roles", - "azuread/102-password-rotation", - "compute/availability_set/100-simple-availabilityset", - "compute/availability_set/101-availabilityset-with-proximity-placement-group", - "compute/container_groups/101-aci-rover", - "compute/container_registry/100-simple-acr", - "compute/container_registry/200-acr-vnet", - "compute/kubernetes_services/101-single-cluster", - "compute/kubernetes_services/102-multi-nodepools", - "compute/proximity_placement_group", - "compute/virtual_machine/101-single-windows-vm", - "compute/virtual_machine/102-single-vm-data-disks", - "compute/virtual_machine/104-single-windows-backup", - "compute/virtual_machine/106-marketplace-image-with-plan", - "compute/virtual_machine/210-vm-bastion-winrm", - "compute/virtual_machine/211-vm-bastion-winrm-agents", - "compute/virtual_machine_scale_set/100-linux-win-vmss-lb", - "compute/virtual_machine_scale_set/101-linux-win-vmss-agw", - "compute/windows_virtual_desktop/wvd_resources", - "cosmos_db/100-simple-cosmos-db-cassandra", - "cosmos_db/100-simple-cosmos-db-gremlin", - "cosmos_db/100-simple-cosmos-db-sql", - "cosmos_db/100-simple-cosmos-db-table", - "databricks/100-simple-databricks", - "datalake/101-datalake-storage", - "eventhub/100-simple-eventhub-namespace", - "eventhub/101-evh-namespace-with-private-endpoint", - "eventhub/102-namespace-and-evh-with-auth-rules", - "eventhub/103-eventhub-consumer-groups", - "keyvault/101-keyvault-policies", - "machine_learning/100-aml", - "managed_service_identity/100-msi-levels", - "mariadb_server/100-simple-mariadb", - "mariadb_server/101-vnet-rule-mariadb", - "mariadb_server/102-private-endpoint-mariadb", - "mariadb_server/103-private-endpoint-with-fw-rule-mariadb", - "monitoring/100-service-health-alerts", - "mssql_server/104-sqlserver-elastic_pools", - "mssql_server/105-sqlserver-failover_groups", - # "mssql_server/106-sqlserver-db-msi-authentication", - "mssql_server/107-sqlserver-db-retention-policy", - "mssql_server/108-sqlserver-db-diagnostics", - "mssql_server/109-sqlserver-network-firewall-rule", - "mysql_server/100-simple-mysql", - "mysql_server/101-vnet-rule-mysql", - "mysql_server/102-private-endpoint-mysql", - "mysql_server/103-private-endpoint-with-fw-rule-mysql", - "networking/dns_zones/100-simple-dns_zone", - "networking/express_routes", - "networking/firewall/100-standard-firewall-legacy-pip", - "networking/firewall/101-simple-firewall", - "networking/firewall/102-premium-firewall", - "networking/firewall/103-firewall-policies", - "networking/front_door/100-simple-front_door", - "networking/front_door/101-front_door_waf", - "networking/ip_group/100-simple-ip_group", - "networking/ip_group/101-firewall-ip_group", - "networking/load_balancers/100-simple-load-balancer-basic-sku", - "networking/load_balancers/101-load-balancer-with-rules", - "networking/load_balancers/102-internal-load-balancer", - "networking/load_balancers/103-load-balancer-nic-association", - "networking/load_balancers/104-load-balancer-diagnostics", - "networking/private_dns/100-private-dns-vnet-links", - "networking/private_links/endpoints/centralized", - "networking/virtual_network_gateway/100-expressroute-gateway", - "networking/virtual_network_gateway/101-vpn-site-to-site", - "networking/virtual_network_gateway/102-vpn-site-to-site-active-active", - "networking/virtual_network_gateway/103-vpn-site-to-site-connection", - "networking/virtual_network/100-import-rg", - "networking/virtual_network/100-simple-vnet-subnets-nsgs", - "networking/virtual_network/100-subnet-delegation", - "networking/virtual_network/101-vnet-peering-nsg", - "networking/virtual_network/200-nsg-flow-logs", - "networking/virtual_network/201-nsg-flow-logs-v1", - "networking/virtual_wan/100-vwan-multi-hubs", - "networking/virtual_wan/101-vwan-hub-firewall-legacy", - "networking/virtual_wan/102-vwan-hub-firewall-new", - "networking/virtual_wan/103-vwan-hub-gw", - "networking/virtual_wan/104-vwan-hub-gw-spp", - "networking/virtual_wan/105-vwan-hub-route-table", - "networking/virtual_wan/106-vwan-hub-routes", - "postgresql_server/100-simple-postgresql", - "postgresql_server/101-vnet-rule-postgresql", - "postgresql_server/102-private-endpoint-postgresql", - "postgresql_server/103-private-endpoint-with-fw-rule", - "recovery_vault/101-simple-asrv", - "recovery_vault/102-asr-protection", - "recovery_vault/103-asr-with-private-endpoint", - "redis_cache/100-redis-standard", - "redis_cache/101-redis-diagnostics", - "redis_cache/102-redis-private", - "storage_accounts/102-storage-account-advanced-options", - "synapse_analytics/100-synapse", - "synapse_analytics/101-synapse-sparkpool", - "webapps/appservice/101-appservice-simple", - "webapps/appservice/102-appservice-slots", - "webapps/appservice/103-appservice-extend", - "webapps/appservice/104-appservice-appinsight", - "webapps/appservice/105-appservice-backup", - "webapps/appservice/106-appservice-diagnostics", - "webapps/appservice/107-appservice-private", - "webapps/function_app/101-function_app-private" - ] + matrix: ${{fromJSON(needs.load_scenarios.outputs.matrix)}} container: - image: aztfmod/rover:0.15.4-2105.2603 + image: aztfmod/rover:0.15.5-2106.3012 options: --user 0 steps: @@ -160,7 +57,7 @@ jobs: run: | cd ${GITHUB_WORKSPACE}/examples/${{ matrix.config_files }} - ${GITHUB_WORKSPACE}/landingzones/caf_example/ci.sh ${{ github.run_id }} ${GITHUB_WORKSPACE}/landingzones/caf_example + ${GITHUB_WORKSPACE}/examples/ci.sh ${{ github.run_id }} ${GITHUB_WORKSPACE}/examples purge: name: purge @@ -170,7 +67,7 @@ jobs: needs: examples container: - image: aztfmod/rover:0.15.4-2105.2603 + image: aztfmod/rover:0.15.5-2106.3012 options: --user 0 steps: diff --git a/.github/workflows/standalone-scenarios-longrunners.json b/.github/workflows/standalone-scenarios-longrunners.json new file mode 100644 index 0000000000..9b2b3efefa --- /dev/null +++ b/.github/workflows/standalone-scenarios-longrunners.json @@ -0,0 +1,17 @@ +{ + "config_files": [ + "mssql_mi/200-mi", + "mssql_mi/200-mi-two-regions", + "networking/virtual_network_gateway/100-expressroute-gateway", + "networking/virtual_network_gateway/101-vpn-site-to-site", + "networking/virtual_network_gateway/102-vpn-site-to-site-active-active", + "networking/virtual_network_gateway/103-vpn-site-to-site-connection", + "networking/virtual_wan/100-vwan-multi-hubs", + "networking/virtual_wan/101-vwan-hub-firewall-legacy", + "networking/virtual_wan/102-vwan-hub-firewall-new", + "networking/virtual_wan/103-vwan-hub-gw", + "networking/virtual_wan/104-vwan-hub-gw-spp", + "networking/virtual_wan/105-vwan-hub-route-table", + "networking/virtual_wan/106-vwan-hub-routes" + ] +} diff --git a/.github/workflows/master-100-testcases.json b/.github/workflows/standalone-scenarios.json similarity index 60% rename from .github/workflows/master-100-testcases.json rename to .github/workflows/standalone-scenarios.json index 44c9b41cea..68a2771c5e 100644 --- a/.github/workflows/master-100-testcases.json +++ b/.github/workflows/standalone-scenarios.json @@ -1,19 +1,39 @@ { "config_files": [ "app_gateway/100-simple-app-gateway", + "app_gateway/101-private-public", + "app_gateway/102-waf-policy", + "app_gateway/210-agw-with-keyvault", "app_insights/100-all-attributes", "app_insights/100-simple", "automation/100-simple-automation-account", + "azuread/100-sevice-principle-with-builtin-roles", + "azuread/101-service-principle-with-custom-roles", "azuread/102-password-rotation", + "azuread/201-groups-and-roles", + "azuread/100-azuread-application-with-sevice-principle-with-builtin-roles", + "azuread/101-azuread-application-with-service-principle-with-custom-roles", + "azuread/103-service-principal-only", "compute/availability_set/100-simple-availabilityset", "compute/availability_set/101-availabilityset-with-proximity-placement-group", "compute/container_groups/101-aci-rover", "compute/container_registry/100-simple-acr", + "compute/container_registry/200-acr-vnet", + "compute/container_registry/200-acr-private-link", + "compute/dedicated_hosts/101-dedicated-host", + "compute/dedicated_hosts/102-dedicated-host-vms", "compute/kubernetes_services/101-single-cluster", + "compute/kubernetes_services/102-multi-nodepools", "compute/proximity_placement_group", "compute/virtual_machine/101-single-windows-vm", + "compute/virtual_machine/102-single-vm-data-disks", "compute/virtual_machine/104-single-windows-backup", + "compute/virtual_machine/106-marketplace-image-with-plan", + "compute/virtual_machine/210-vm-bastion-winrm", "compute/virtual_machine/211-vm-bastion-winrm-agents", + "compute/virtual_machine_scale_set/100-linux-win-vmss-lb", + "compute/virtual_machine_scale_set/101-linux-win-vmss-agw", + "compute/windows_virtual_desktop/wvd_resources", "cosmos_db/100-simple-cosmos-db-cassandra", "cosmos_db/100-simple-cosmos-db-gremlin", "cosmos_db/100-simple-cosmos-db-mongo", @@ -21,29 +41,36 @@ "cosmos_db/100-simple-cosmos-db-table", "databricks/100-simple-databricks", "datalake/101-datalake-storage", + "diagnostics_profiles/200-diagnostics-eventhub-namespaces", + "diagnostics_profiles/201-multi-eventhub-diagnostics", "eventhub/100-simple-eventhub-namespace", "eventhub/101-evh-namespace-with-private-endpoint", "eventhub/102-namespace-and-evh-with-auth-rules", "eventhub/103-eventhub-consumer-groups", + "eventhub/104-namespace-and-evh-with-storage", + "keyvault/101-keyvault-policies", "keyvault/102-keyvault-cert-issuer", "machine_learning/100-aml", "machine_learning/101-aml-vnet", + "managed_service_identity/100-msi-levels", "mariadb_server/100-simple-mariadb", "mariadb_server/101-vnet-rule-mariadb", "mariadb_server/102-private-endpoint-mariadb", "mariadb_server/103-private-endpoint-with-fw-rule-mariadb", "monitoring/100-service-health-alerts", - "mssql_server/101-sqlserver-simple", - "mssql_server/102-sqlserver-extend", "mssql_server/104-sqlserver-elastic_pools", "mssql_server/105-sqlserver-failover_groups", + "mssql_server/107-sqlserver-db-retention-policy", + "mssql_server/108-sqlserver-db-diagnostics", + "mssql_server/109-sqlserver-network-firewall-rule", "mysql_server/100-simple-mysql", "mysql_server/101-vnet-rule-mysql", "mysql_server/102-private-endpoint-mysql", "mysql_server/103-private-endpoint-with-fw-rule-mysql", "netapp/101-nfs", + "networking/bastion/100-bastion-with-vm", "networking/dns_zones/100-simple-dns_zone", - "networking/domain_name_registrations/100-register-domain-default_domain_registrar_dns", + "networking/express_routes", "networking/firewall/100-standard-firewall-legacy-pip", "networking/firewall/101-simple-firewall", "networking/firewall/102-premium-firewall", @@ -55,11 +82,20 @@ "networking/load_balancers/100-simple-load-balancer-basic-sku", "networking/load_balancers/101-load-balancer-with-rules", "networking/load_balancers/102-internal-load-balancer", + "networking/load_balancers/103-load-balancer-nic-association", + "networking/load_balancers/104-load-balancer-diagnostics", "networking/private_dns/100-private-dns-vnet-links", "networking/private_links/endpoints/centralized", + "networking/virtual_network_gateway/100-expressroute-gateway", + "networking/virtual_network_gateway/101-vpn-site-to-site", + "networking/virtual_network_gateway/102-vpn-site-to-site-active-active", "networking/virtual_network_gateway/103-vpn-site-to-site-connection", + "networking/virtual_network/100-import-rg", + "networking/virtual_network/100-simple-vnet-subnets-nsgs", "networking/virtual_network/100-subnet-delegation", "networking/virtual_network/101-vnet-peering-nsg", + "networking/virtual_network/200-nsg-flow-logs", + "networking/virtual_network/201-nsg-flow-logs-v1", "networking/virtual_wan/100-vwan-multi-hubs", "networking/virtual_wan/101-vwan-hub-firewall-legacy", "networking/virtual_wan/102-vwan-hub-firewall-new", @@ -67,6 +103,8 @@ "networking/virtual_wan/104-vwan-hub-gw-spp", "networking/virtual_wan/105-vwan-hub-route-table", "networking/virtual_wan/106-vwan-hub-routes", + "networking/virtual_wan/108-vwan-vpn-site", + "networking/virtual_wan/109-vwan-vpn-gateway-connection", "postgresql_server/100-simple-postgresql", "postgresql_server/101-vnet-rule-postgresql", "postgresql_server/102-private-endpoint-postgresql", @@ -75,8 +113,14 @@ "recovery_vault/102-asr-protection", "recovery_vault/103-asr-with-private-endpoint", "redis_cache/100-redis-standard", + "redis_cache/101-redis-diagnostics", "redis_cache/102-redis-private", - "shared_image_gallery/101-packer_service_principal", + "storage_accounts/101-storage-account-with-protection", + "storage_accounts/102-storage-account-advanced-options", + "storage_accounts/103-storage-account-network-rules", + "storage_accounts/104-file-share-with-backup", + "storage_accounts/105-nfsv3", + "storage_accounts/106-storage-account-queue", "synapse_analytics/100-synapse", "synapse_analytics/101-synapse-sparkpool", "webapps/appservice/101-appservice-simple", @@ -84,6 +128,7 @@ "webapps/appservice/103-appservice-extend", "webapps/appservice/104-appservice-appinsight", "webapps/appservice/105-appservice-backup", + "webapps/appservice/106-appservice-diagnostics", "webapps/appservice/107-appservice-private", "webapps/function_app/101-function_app-private" ] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a4f392c8bf..65fdda0ade 100755 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,19 +6,24 @@ repos: hooks: - id: terraform_fmt - id: terraform_docs - # - id: terraform_tflint + - id: terraform_tflint # - id: terraform_validate # - id: terraform_tfsec # - id: checkov - repo: git://github.com/pre-commit/pre-commit-hooks - rev: v3.4.0 + rev: v4.0.1 hooks: - id: check-merge-conflict - id: trailing-whitespace - # - id: check-yaml + - id: check-yaml + - id: check-json - id: check-added-large-files - id: detect-private-key # - repo: git://github.com/markdownlint/markdownlint # rev: v0.9.0 # hooks: - # - id: markdownlint \ No newline at end of file + # - id: markdownlint + # - repo: git://github.com/ansible-community/ansible-lint + # rev: v5.0.11 + # hooks: + # - id: ansible-lint \ No newline at end of file diff --git a/README.md b/README.md index f14801b73e..dcb90382ef 100755 --- a/README.md +++ b/README.md @@ -4,11 +4,15 @@ Microsoft [Cloud Adoption Framework for Azure](https://aka.ms/caf) provides you This module allows you to create resources on Microsoft Azure, is used by the Cloud Adoption Framework for Azure (CAF) landing zones to provision resources in an Azure subscription and can deploy resources being directly invoked from the Terraform registry. -## Getting started +## Prerequisites + +- Setup your **environment** using the following guide [Getting Started](https://github.com/Azure/caf-terraform-landingzones/blob/master/documentation/getting_started/getting_started.md) or you use it online with [GitHub Codespaces](https://github.com/features/codespaces). +- Access to an **Azure subscription**. + -This module can be used to create resources on its own, or can be called from a CAF landing zone. +## Getting started -It can be invoked from the [Terraform registry](https://registry.terraform.io/modules/aztfmod/caf/azurerm/) +This module can be used inside [Cloud Adoption Framework Landing zones](https://github.com/Azure/caf-terraform-landingzones), or can be used as standalone, directly from the [Terraform registry](https://registry.terraform.io/modules/aztfmod/caf/azurerm/) ```terraform module "caf" { @@ -18,28 +22,16 @@ module "caf" { } ``` -## Prerequisites - -- Setup your **environment** using the following guide [Getting Started](https://github.com/Azure/caf-terraform-landingzones/blob/master/documentation/getting_started/getting_started.md) or you can alternatively use [Visual Studio Code Online]((https://online.visualstudio.com/environments/new?name=terraform-azurerm-caf&repo=aztfmod/terraform-azurerm-caf) -) or GitHub Codespaces. -- Access to an **Azure subscription**. +Fill the variables as needed and documented, there is a [quick example here](./examples/standalone.md). -## Deploying examples +For a complete set of examples you can review the [full library here](./examples). -You can deploy examples either directly from this module or via the Cloud Adoption Framework's rover, to get starter, please refer to the [examples readme](./examples) +

-We categorize the various examples in this repo as follow: - -| 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 | ## Community -Feel free to open an issue for feature or bug, or to submit a PR. +Feel free to open an issue for feature or bug, or to submit a PR, [please review the module contribution and conventions guidelines](./documentation/conventions.md) In case you have any question, you can reach out to tf-landingzones at microsoft dot com. @@ -47,8 +39,6 @@ You can also reach us on [Gitter](https://gitter.im/aztfmod/community?utm_source ## Contributing -In order to contribute to the project, [please review the module contribution and conventions guidelines](./documentation/conventions.md) - This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. diff --git a/UPGRADE.md b/UPGRADE.md index 02ed393eac..c82ac2061c 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -2,6 +2,70 @@ When ugrading to a newer version of the CAF module, some configuration structures must be updated before applying the modifications. +## 5.4.0 + +Upgrade to 5.4.0 includes support azurerm 2.64.0 provider and implements the following changes: +- Updated georeplications structure for Azure Container Registry configuration file. +- Updated structure for Azure Front Door configuration file. +- Updated parameter for Azure Public IP address. +- Updated RBAC structures that will in-place update RBAC assignement. This will create new model RBAC and delete old model RBAC assignments and therefore should not disrupt any operation. + +### Update for georeplications structure for ACR +The georeplications argument has replaced georeplication_locations in azurerm 2.57.0. Accordingly you need to change the configuration file from + +``` +georeplication_region_keys = ["region2", "region3"] +``` +to +``` + georeplications = { + region2 = { + tags = { + region = "eastasia" + type = "acr_replica" + } + } + region3 = { + tags = { + region = "westeurope" + type = "acr_replica" + } + } + } +``` + +### Update structure for Azure Front Door +The logic has moved out from the nested structure + +``` +resource "azurerm_frontdoor" "frontdoor" { + .... + dynamic "custom_https_configuration" { + ... + } +} +``` + +to the standalone resource creation. + +``` +resource "azurerm_frontdoor_custom_https_configuration" "frontdoor" { + ... +} +``` +This should not require a restructure of the configuration file. + +### Update for public IP address +The parameter ```zone``` is deprecated and replaced by ```availability_zone``` in the provider. + +In previous versions, ```var.zones``` was a list, we recommend that you migrate to use ```availability_zone``` as a string parameter. If not, we will try to cast as a string the first element of ```var.zones```. For more reference on the possible values: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip + + +## 5.3.0 + +The structure for Network Security Group has evolved. You will need to update the structure and we recommend you opt-in for the ```version = 1``` of Network Security Group, which allows standalone NSG configuration (outside of a Virtual Network) and direct NIC stitching. + + ## 4.21.0 ### Virtual machines diff --git a/aks_clusters.tf b/aks_clusters.tf index 2dabef4b92..607e9a85fe 100755 --- a/aks_clusters.tf +++ b/aks_clusters.tf @@ -4,7 +4,7 @@ output "aks_clusters" { module "aks_clusters" { source = "./modules/compute/aks" - depends_on = [module.networking, module.routes] + depends_on = [module.networking, module.routes, module.azurerm_firewall_policies] for_each = local.compute.aks_clusters global_settings = local.global_settings @@ -15,8 +15,11 @@ module "aks_clusters" { settings = each.value subnets = lookup(each.value, "lz_key", null) == null ? local.combined_objects_networking[local.client_config.landingzone_key][each.value.vnet_key].subnets : local.combined_objects_networking[each.value.lz_key][each.value.vnet_key].subnets resource_group = local.resource_groups[each.value.resource_group_key] + private_dns_zone_id = try(local.combined_objects_private_dns[try(each.value.private_dns_zone.lz_key, local.client_config.landingzone_key)][each.value.key].id, null) + admin_group_object_ids = try(each.value.admin_groups.azuread_group_keys, null) == null ? null : try(each.value.admin_groups.ids, [ for group_key in try(each.value.admin_groups.azuread_groups.keys, {}) : local.combined_objects_azuread_groups[local.client_config.landingzone_key][group_key].id ]) + } diff --git a/application_gateways.tf b/application_gateways.tf index 11b67da193..2a9797ad7a 100644 --- a/application_gateways.tf +++ b/application_gateways.tf @@ -3,29 +3,40 @@ module "application_gateways" { source = "./modules/networking/application_gateway" for_each = local.networking.application_gateways - global_settings = local.global_settings + app_services = local.combined_objects_app_services + application_gateway_waf_policies = local.combined_objects_application_gateway_waf_policies client_config = local.client_config diagnostics = local.combined_diagnostics - resource_group_name = local.resource_groups[each.value.resource_group_key].name - location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] + dns_zones = local.combined_objects_dns_zones + global_settings = local.global_settings + keyvault_certificate_requests = module.keyvault_certificate_requests + keyvault_certificates = module.keyvault_certificates + keyvaults = local.combined_objects_keyvaults + managed_identities = local.combined_objects_managed_identities + private_dns = lookup(each.value, "private_dns_records", null) == null ? {} : local.combined_objects_private_dns + public_ip_addresses = local.combined_objects_public_ip_addresses settings = each.value sku_name = each.value.sku_name sku_tier = each.value.sku_tier vnets = local.combined_objects_networking - base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} - private_dns = lookup(each.value, "private_dns_records", null) == null ? {} : local.combined_objects_private_dns - public_ip_addresses = local.combined_objects_public_ip_addresses - app_services = local.combined_objects_app_services - managed_identities = local.combined_objects_managed_identities - keyvaults = local.combined_objects_keyvaults - dns_zones = local.combined_objects_dns_zones - keyvault_certificates = module.keyvault_certificates - keyvault_certificate_requests = module.keyvault_certificate_requests + application_gateway_applications = { for key, value in local.networking.application_gateway_applications : key => value if value.application_gateway_key == each.key } - application_gateway_waf_policies = local.combined_objects_application_gateway_waf_policies + + resource_group_name = coalesce ( + try(local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][each.value.resource_group.key].name,null), + try(local.combined_objects_resource_groups[local.client_config.landingzone_key][each.value.resource_group_key].name,null) + ) + base_tags = try(local.global_settings.inherit_tags, false) ? coalesce( + try(local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][each.value.resource_group.key].tags,null), + try(local.combined_objects_resource_groups[local.client_config.landingzone_key][each.value.resource_group_key].tags,null) + ) : {} + location = lookup(each.value, "region", null) == null ? coalesce( + try(local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][each.value.resource_group.key].location,null), + try(local.combined_objects_resource_groups[local.client_config.landingzone_key][each.value.resource_group_key].location,null) + ) : local.global_settings.regions[each.value.region] } output "application_gateways" { diff --git a/azuread.tf b/azuread.tf deleted file mode 100755 index 08c3a03452..0000000000 --- a/azuread.tf +++ /dev/null @@ -1,69 +0,0 @@ -# -# Azure Active Directory Applications -# - -module "azuread_applications" { - source = "./modules/azuread/applications" - depends_on = [module.keyvault_access_policies] - for_each = var.azuread_apps - - azuread_api_permissions = try(var.azuread_api_permissions[each.key], {}) - client_config = local.client_config - global_settings = local.global_settings - keyvaults = local.combined_objects_keyvaults - settings = each.value - user_type = var.user_type -} - -output "aad_apps" { - value = module.azuread_applications - -} - -# -# Azure Active Directory Groups -# - -module "azuread_groups" { - source = "./modules/azuread/groups" - for_each = var.azuread_groups - - global_settings = local.global_settings - azuread_groups = each.value - tenant_id = local.client_config.tenant_id -} - -output "azuread_groups" { - value = module.azuread_groups - -} - -module "azuread_groups_members" { - source = "./modules/azuread/groups_members" - for_each = var.azuread_groups - - settings = each.value - azuread_groups = module.azuread_groups - group_id = module.azuread_groups[each.key].id - azuread_apps = module.azuread_applications -} - -# -# Azure Active Directory Users -# - -module "azuread_users" { - source = "./modules/azuread/users" - depends_on = [module.keyvault_access_policies] - for_each = var.azuread_users - - client_config = local.client_config - global_settings = local.global_settings - keyvaults = local.combined_objects_keyvaults - settings = each.value -} - -output "azuread_users" { - value = module.azuread_users - -} \ No newline at end of file diff --git a/azuread_applications.tf b/azuread_applications.tf new file mode 100755 index 0000000000..f434593c7e --- /dev/null +++ b/azuread_applications.tf @@ -0,0 +1,41 @@ +# +# Azure Active Directory Applications (original version with service principal combined in one object) +# +# +# + +# Module for the CAf variable azuread_apps +module "azuread_applications" { + source = "./modules/azuread/applications" + depends_on = [module.keyvault_access_policies] + for_each = local.azuread.azuread_apps + + azuread_api_permissions = try(local.azuread.azuread_api_permissions[each.key], {}) + client_config = local.client_config + global_settings = local.global_settings + keyvaults = local.combined_objects_keyvaults + settings = each.value + user_type = var.user_type +} + +output "aad_apps" { + value = module.azuread_applications + +} + + +# Module for the CAf variable azuread_applications +module "azuread_applications_v1" { + source = "./modules/azuread/applications_v1" + for_each = local.azuread.azuread_applications + + azuread_api_permissions = try(local.azuread.azuread_api_permissions[each.key], {}) + client_config = local.client_config + global_settings = local.global_settings + settings = each.value + user_type = var.user_type +} + +output "azuread_applications" { + value = module.azuread_applications_v1 +} diff --git a/azuread_credential_policies.tf b/azuread_credential_policies.tf new file mode 100644 index 0000000000..f49a7b64b7 --- /dev/null +++ b/azuread_credential_policies.tf @@ -0,0 +1,3 @@ +output "azuread_credential_policies" { + value = local.azuread.azuread_credential_policies +} \ No newline at end of file diff --git a/azuread_credentials.tf b/azuread_credentials.tf new file mode 100644 index 0000000000..4cde97e15b --- /dev/null +++ b/azuread_credentials.tf @@ -0,0 +1,23 @@ +# Module for the CAf variable azuread_apps +module "azuread_credentials" { + source = "./modules/azuread/credentials" + depends_on = [module.keyvault_access_policies] + for_each = local.azuread.azuread_credentials + + client_config = local.client_config + global_settings = local.global_settings + keyvaults = local.combined_objects_keyvaults + credential_policy = try(local.azuread.azuread_credential_policies[each.value.azuread_credential_policy_key], null) + settings = each.value + + resources = { + application = { + id = try(local.combined_objects_azuread_applications[try(each.value.azuread_application.lz_key, local.client_config.landingzone_key)][each.value.azuread_application.key].id, {}) + application_id = try(local.combined_objects_azuread_applications[try(each.value.azuread_application.lz_key, local.client_config.landingzone_key)][each.value.azuread_application.key].application_id, {}) + } + } +} + +output "azuread_credentials" { + value = module.azuread_credentials +} diff --git a/azuread_groups.tf b/azuread_groups.tf new file mode 100644 index 0000000000..36b4765efb --- /dev/null +++ b/azuread_groups.tf @@ -0,0 +1,41 @@ + +# +# Azure Active Directory Groups +# + +module "azuread_groups" { + source = "./modules/azuread/groups" + for_each = local.azuread.azuread_groups + + global_settings = local.global_settings + azuread_groups = each.value + tenant_id = local.client_config.tenant_id +} + +output "azuread_groups" { + value = module.azuread_groups + +} + +module "azuread_groups_members" { + source = "./modules/azuread/groups_members" + for_each = local.azuread.azuread_groups + + client_config = local.client_config + settings = each.value + azuread_groups = module.azuread_groups + group_id = module.azuread_groups[each.key].id + azuread_apps = module.azuread_applications + azuread_service_principals = local.combined_objects_azuread_service_principals[try(each.value.lz_key, local.client_config.landingzone_key)] +} + +# Module to decouple AD Group membership to remote AD Groups +module "azuread_groups_membership" { + source = "./modules/azuread/groups_members" + for_each = local.azuread.azuread_groups_membership + + client_config = local.client_config + settings = each.value + group_id = local.combined_objects_azuread_groups[try(each.value.lz_key, local.client_config.landingzone_key)][each.key].id + azuread_service_principals = local.combined_objects_azuread_service_principals +} diff --git a/azuread_roles.tf b/azuread_roles.tf index 18f63152b5..44c34b8cd1 100755 --- a/azuread_roles.tf +++ b/azuread_roles.tf @@ -1,15 +1,23 @@ module "azuread_roles_applications" { source = "./modules/azuread/roles" - for_each = try(var.azuread_roles.azuread_apps, {}) + for_each = try(local.azuread.azuread_roles.azuread_apps, {}) object_id = module.azuread_applications[each.key].azuread_service_principal.object_id azuread_roles = each.value.roles } +module "azuread_roles_service_principals" { + source = "./modules/azuread/roles" + for_each = try(local.azuread.azuread_roles.azuread_service_principals, {}) + + object_id = module.azuread_service_principals[each.key].object_id + azuread_roles = each.value.roles +} + module "azuread_roles_msi" { source = "./modules/azuread/roles" - for_each = try(var.azuread_roles.managed_identities, {}) + for_each = try(local.azuread.azuread_roles.managed_identities, {}) object_id = module.managed_identities[each.key].principal_id azuread_roles = each.value.roles @@ -17,7 +25,7 @@ module "azuread_roles_msi" { module "azuread_roles_sql_mi" { source = "./modules/azuread/roles" - for_each = try(var.azuread_roles.mssql_managed_instances, {}) + for_each = try(local.azuread.azuread_roles.mssql_managed_instances, {}) object_id = module.mssql_managed_instances[each.key].principal_id azuread_roles = each.value.roles @@ -25,7 +33,7 @@ module "azuread_roles_sql_mi" { module "azuread_roles_sql_mi_secondary" { source = "./modules/azuread/roles" - for_each = try(var.azuread_roles.mssql_managed_instances_secondary, {}) + for_each = try(local.azuread.azuread_roles.mssql_managed_instances_secondary, {}) object_id = module.mssql_managed_instances_secondary[each.key].principal_id azuread_roles = each.value.roles @@ -33,7 +41,7 @@ module "azuread_roles_sql_mi_secondary" { module "azuread_roles_mssql_server" { source = "./modules/azuread/roles" - for_each = try(var.azuread_roles.mssql_servers, {}) + for_each = try(local.azuread.azuread_roles.mssql_servers, {}) object_id = module.mssql_servers[each.key].rbac_id azuread_roles = each.value.roles diff --git a/azuread_service_principal_passwords.tf b/azuread_service_principal_passwords.tf new file mode 100755 index 0000000000..5ddeb66d97 --- /dev/null +++ b/azuread_service_principal_passwords.tf @@ -0,0 +1,29 @@ +# +# Azure Active Directory Applications +# + +module "azuread_service_principal_passwords" { + source = "./modules/azuread/service_principal_password" + depends_on = [module.keyvault_access_policies] + for_each = local.azuread.azuread_service_principal_passwords + + client_config = local.client_config + global_settings = local.global_settings + keyvaults = local.combined_objects_keyvaults + settings = each.value + + service_principal_id = coalesce( + try(each.value.azuread_service_principal.id, ""), + try(local.combined_objects_azuread_service_principals[try(each.value.azuread_service_principal.lz_key, local.client_config.landingzone_key)][each.value.azuread_service_principal.key].id, "") + ) + + service_principal_application_id = coalesce( + try(each.value.azuread_service_principal.application_id, ""), + try(local.combined_objects_azuread_service_principals[try(each.value.azuread_service_principal.lz_key, local.client_config.landingzone_key)][each.value.azuread_service_principal.key].application_id, "") + ) + +} + +output "azuread_service_principal_passwords" { + value = module.azuread_service_principal_passwords +} diff --git a/azuread_service_principals.tf b/azuread_service_principals.tf new file mode 100755 index 0000000000..d0c896ce2b --- /dev/null +++ b/azuread_service_principals.tf @@ -0,0 +1,25 @@ +# +# Azure Active Directory Applications +# + +module "azuread_service_principals" { + source = "./modules/azuread/service_principal" + for_each = local.azuread.azuread_service_principals + + client_config = local.client_config + global_settings = local.global_settings + settings = each.value + azuread_api_permissions = try(local.azuread.azuread_api_permissions[each.key], {}) + user_type = var.user_type + + application_id = coalesce( + try(each.value.azuread_application.application_id, ""), + try(local.combined_objects_azuread_applications[each.value.azuread_application.lz_key][each.value.azuread_application.key].application_id, ""), + try(local.combined_objects_azuread_applications[local.client_config.landingzone_key][each.value.azuread_application.key].application_id, "") + ) + +} + +output "azuread_service_principals" { + value = module.azuread_service_principals +} diff --git a/azuread_users.tf b/azuread_users.tf new file mode 100644 index 0000000000..3a0b68a982 --- /dev/null +++ b/azuread_users.tf @@ -0,0 +1,19 @@ +# +# Azure Active Directory Users +# + +module "azuread_users" { + source = "./modules/azuread/users" + depends_on = [module.keyvault_access_policies] + for_each = local.azuread.azuread_users + + client_config = local.client_config + global_settings = local.global_settings + keyvaults = local.combined_objects_keyvaults + settings = each.value +} + +output "azuread_users" { + value = module.azuread_users + +} \ No newline at end of file diff --git a/bastion_service.tf b/bastion_service.tf index d1089b93bb..2de820fd60 100755 --- a/bastion_service.tf +++ b/bastion_service.tf @@ -15,6 +15,9 @@ resource "azurecaf_name" "host" { use_slug = local.global_settings.use_slug } +# Last updated with : AzureRM version 2.64.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/bastion_host + resource "azurerm_bastion_host" "host" { for_each = try(local.compute.bastion_hosts, {}) diff --git a/container_registry.tf b/container_registry.tf index c58d70bfeb..89abb02e60 100755 --- a/container_registry.tf +++ b/container_registry.tf @@ -2,23 +2,23 @@ module "container_registry" { source = "./modules/compute/container_registry" for_each = local.compute.azure_container_registries - global_settings = local.global_settings - client_config = local.client_config - name = each.value.name - resource_group_name = local.resource_groups[each.value.resource_group_key].name - location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] - admin_enabled = try(each.value.admin_enabled, false) - sku = try(each.value.sku, "Basic") - tags = try(each.value.tags, {}) - network_rule_set = try(each.value.network_rule_set, {}) - vnets = local.combined_objects_networking - georeplication_locations = try(each.value.georeplication_region_keys, null) == null ? null : [for region in try(each.value.georeplication_region_keys, []) : local.global_settings.regions[region]] - diagnostics = local.combined_diagnostics - diagnostic_profiles = try(each.value.diagnostic_profiles, {}) - private_endpoints = try(each.value.private_endpoints, {}) - resource_groups = local.resource_groups - base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} - private_dns = local.combined_objects_private_dns + global_settings = local.global_settings + client_config = local.client_config + name = each.value.name + resource_group_name = local.resource_groups[each.value.resource_group_key].name + location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] + admin_enabled = try(each.value.admin_enabled, false) + sku = try(each.value.sku, "Basic") + tags = try(each.value.tags, {}) + network_rule_set = try(each.value.network_rule_set, {}) + vnets = local.combined_objects_networking + georeplications = try(each.value.georeplications, {}) + diagnostics = local.combined_diagnostics + diagnostic_profiles = try(each.value.diagnostic_profiles, {}) + private_endpoints = try(each.value.private_endpoints, {}) + resource_groups = local.resource_groups + base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} + private_dns = local.combined_objects_private_dns } output "azure_container_registries" { diff --git a/dedicated_hosts.tf b/dedicated_hosts.tf new file mode 100755 index 0000000000..49194105ce --- /dev/null +++ b/dedicated_hosts.tf @@ -0,0 +1,39 @@ +module "dedicated_host_groups" { + source = "./modules/compute/dedicated_host_groups" + for_each = local.compute.dedicated_host_groups + + global_settings = local.global_settings + client_config = local.client_config + settings = each.value + resource_group_name = local.resource_groups[each.value.resource_group_key].name + location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] + base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} +} + + +output "dedicated_host_groups" { + value = module.dedicated_host_groups + +} + + +module "dedicated_hosts" { + source = "./modules/compute/dedicated_hosts" + for_each = local.compute.dedicated_hosts + + global_settings = local.global_settings + client_config = local.client_config + settings = each.value + # resource_group_name = local.resource_groups[each.value.resource_group_key].name + location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] + base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} + dedicated_host_group_id = local.combined_objects_dedicated_host_groups[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.dedicated_host_group_key].id +} + + + +output "dedicated_hosts" { + value = module.dedicated_hosts + +} + diff --git a/diagnostics.tf b/diagnostics.tf index 62325787db..4dcc720552 100755 --- a/diagnostics.tf +++ b/diagnostics.tf @@ -56,6 +56,7 @@ module "diagnostic_event_hub_namespaces" { location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] client_config = local.client_config base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} + # storage_accounts = local.combined_objects_storage_accounts } module "diagnostic_event_hub_namespaces_diagnostics" { diff --git a/examples/README.md b/examples/README.md new file mode 100755 index 0000000000..8c12d67c34 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,83 @@ +# Cloud Adoption Framework for Azure - Terraform module examples + +The Cloud Adoption Framework for Azure - Terraform module can be used to deployed all components of CAF and compose those components together. It allows you to create complex architectures and composition relying on community contributions and proven patterns. You can leverage this module within a CAF landing zone, or straight from the Terraform registry. + +## Deploying examples with Terraform + +You can instantiate this module directly using the following syntax: + +```hcl +module "caf" { + source = "aztfmod/caf/azurerm" + version = "5.3.11" + # insert the 7 required variables here +} +``` + +### Compose your minimal example + +A minimal example could be: + +```hcl +module "caf" { + source = "aztfmod/caf/azurerm" + version = "5.3.11" + + global_settings = var.global_settings + resource_groups = var.resource_groups + keyvaults = var.keyvaults + + compute = { + virtual_machines = var.virtual_machines + } + + networking = { + public_ip_addresses = var.public_ip_addresses + vnets = var.vnets + } +} +``` + +You can [find here a minimal example](./standalone.md) + +### Run all the examples in this library + +The current folder contains an example of module with the whole features set of the module, to run all the examples in the subfolders. You can leverage it the following way: + +```bash +cd /tf/caf/examples +az login +terraform init +terraform plan -var-file +terraform apply +terraform destroy +``` + +## Deploying examples within a landing zone + +To get started with the deployment within rover, follow the steps: + +### 1. Log in the subscription with the rover + +```bash +rover login +### you can alternatively specify the tenant space and subscription ID on command line arguments: +rover login --tenant .onmicrosoft.com -s +``` + +### 2. Deploy the basic launchpad + +```bash +rover -lz /tf/caf/public/landingzones/caf_launchpad \ +-launchpad \ +-var-folder /tf/caf/public/landingzones/caf_launchpad/scenario/100 \ +-a apply +``` + +### 3. Test your example + +```bash +rover -lz /tf/caf/landingzones/caf_example \ +-var-folder /tf/caf/examples/ \ +-a plan|apply +``` diff --git a/examples/app_gateway/100-simple-app-gateway/configuration.tfvars b/examples/app_gateway/100-simple-app-gateway/configuration.tfvars index feb9f19cea..9ce87687af 100644 --- a/examples/app_gateway/100-simple-app-gateway/configuration.tfvars +++ b/examples/app_gateway/100-simple-app-gateway/configuration.tfvars @@ -86,7 +86,7 @@ public_ip_addresses = { sku = "Standard" allocation_method = "Static" ip_version = "IPv4" - zones = ["1"] + availability_zone = "1" idle_timeout_in_minutes = "4" } diff --git a/examples/app_gateway/main.tf b/examples/app_gateway/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/app_gateway/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/app_insights/main.tf b/examples/app_insights/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/app_insights/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/automation/100-simple-automation-account/README.md b/examples/automation/README.md similarity index 100% rename from examples/automation/100-simple-automation-account/README.md rename to examples/automation/README.md diff --git a/examples/automation/main.tf b/examples/automation/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/automation/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/azuread/100-azuread-application-with-sevice-principle-with-builtin-roles/configuration.tfvars b/examples/azuread/100-azuread-application-with-sevice-principle-with-builtin-roles/configuration.tfvars new file mode 100644 index 0000000000..8e3e2a8fac --- /dev/null +++ b/examples/azuread/100-azuread-application-with-sevice-principle-with-builtin-roles/configuration.tfvars @@ -0,0 +1,99 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } + random_length = 5 +} + +resource_groups = { + test = { #resource_group_key + name = "test" + } +} + +keyvaults = { + test_client = { + name = "testkv" + resource_group_key = "test" + sku_name = "standard" + soft_delete_enabled = true + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } +} + +keyvault_access_policies_azuread_apps = { + test_client = { + test_client = { + azuread_app_key = "test_client" + secret_permissions = ["Set", "Get", "List", "Delete"] + } + } +} + +azuread_apps = { + test_client = { + useprefix = true + application_name = "test-client" + password_policy = { + # Length of the password + length = 250 + special = false + upper = true + number = true + + # Define the number of days the password is valid. It must be more than the rotation frequency + expire_in_days = 10 + rotation = { + # + # Set how often the password must be rotated. When passed the renewal time, running the terraform plan / apply will change to a new password + # Only set one of the value + # + + # mins = 10 # only recommended for CI and demo + days = 7 + # months = 1 + } + } + app_role_assignment_required = true + keyvaults = { + test_client = { + secret_prefix = "test-client" + } + } + # Store the ${secret_prefix}-client-id, ${secret_prefix}-client-secret... + # Set the policy during the creation process of the launchpad + } +} + +#complete list of built-in-roles : https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles + +role_mapping = { + built_in_role_mapping = { + subscriptions = { + # subcription level access + logged_in_subscription = { + "Contributor" = { + azuread_apps = { + keys = ["test_client"] + } + } + } + } + } +} + +azuread_roles = { + packer_client = { + roles = [ + "Contributor" + ] + } +} + diff --git a/examples/azuread/101-azuread-application-with-service-principle-with-custom-roles/configuration.tfvars b/examples/azuread/101-azuread-application-with-service-principle-with-custom-roles/configuration.tfvars new file mode 100644 index 0000000000..abf68198b0 --- /dev/null +++ b/examples/azuread/101-azuread-application-with-service-principle-with-custom-roles/configuration.tfvars @@ -0,0 +1,119 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } + random_length = 5 +} + +resource_groups = { + test = { + name = "test" + } +} + +keyvaults = { + test_client = { #KeyVault Key + name = "testkv" + resource_group_key = "test" + sku_name = "standard" + soft_delete_enabled = true + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } +} + +keyvault_access_policies_azuread_apps = { + test_client = { + test_client = { #KeyVault Key + azuread_app_key = "test_client" + secret_permissions = ["Set", "Get", "List", "Delete"] + } + } +} + +# Complete list of Provider Operations : https://docs.microsoft.com/en-us/azure/role-based-access-control/resource-provider-operations + +custom_role_definitions = { + test_role = { + name = "test_role" + useprefix = true + description = "custom permissions for the app" + permissions = { + actions = [ + "Microsoft.KeyVault/vaults/delete", + "Microsoft.KeyVault/vaults/read", + "Microsoft.KeyVault/vaults/write", + "Microsoft.KeyVault/vaults/accessPolicies/write", + "Microsoft.Network/networkSecurityGroups/delete", + "Microsoft.Network/networkSecurityGroups/read", + "Microsoft.Network/networkSecurityGroups/write", + "Microsoft.Network/networkSecurityGroups/join/action", + "Microsoft.Network/virtualNetworks/subnets/delete", + "Microsoft.Network/virtualNetworks/subnets/read", + "Microsoft.Network/virtualNetworks/subnets/write", + "Microsoft.OperationalInsights/workspaces/delete", + "Microsoft.OperationalInsights/workspaces/read", + "Microsoft.OperationalInsights/workspaces/write", + "Microsoft.OperationalInsights/workspaces/sharedKeys/action", + "Microsoft.OperationsManagement/solutions/delete", + "Microsoft.OperationsManagement/solutions/read", + "Microsoft.OperationsManagement/solutions/write", + "Microsoft.Storage/storageAccounts/delete", + "Microsoft.Storage/storageAccounts/read", + "Microsoft.Storage/storageAccounts/write", + "Microsoft.Storage/storageAccounts/blobServices/containers/delete", + "Microsoft.Storage/storageAccounts/blobServices/containers/read", + "Microsoft.Storage/storageAccounts/blobServices/containers/write", + "Microsoft.Storage/storageAccounts/blobServices/containers/lease/action", + "Microsoft.Storage/storageAccounts/blobServices/read", + "Microsoft.Storage/storageAccounts/listKeys/action", + "Microsoft.Resources/subscriptions/providers/read", + "Microsoft.Resources/subscriptions/read", + "Microsoft.Resources/subscriptions/resourcegroups/delete", + "Microsoft.Resources/subscriptions/resourcegroups/read", + "Microsoft.Resources/subscriptions/resourcegroups/write", + "Microsoft.Network/virtualNetworks/delete", + "Microsoft.Network/virtualNetworks/read", + "Microsoft.Network/virtualNetworks/write", + ] + } + } +} + + +azuread_apps = { + test_client = { + useprefix = true + application_name = "test_client" + app_role_assignment_required = true + keyvaults = { + test_client = { + secret_prefix = "test-client" + } + } + # Store the ${secret_prefix}-client-id, ${secret_prefix}-client-secret... + # Set the policy during the creation process of the launchpad + } +} + +role_mapping = { + custom_role_mapping = { + subscriptions = { + logged_in_subscription = { + "test_role" = { + azuread_apps = { + keys = ["test_client"] + } + } + } + } + } + +} + diff --git a/examples/azuread/103-service-principal-only/configuration.tfvars b/examples/azuread/103-service-principal-only/configuration.tfvars new file mode 100644 index 0000000000..10f25da129 --- /dev/null +++ b/examples/azuread/103-service-principal-only/configuration.tfvars @@ -0,0 +1,109 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } + random_length = 5 +} + +resource_groups = { + test = { #resource_group_key + name = "test" + } +} + +keyvaults = { + test_client = { + name = "testkv" + resource_group_key = "test" + sku_name = "standard" + soft_delete_enabled = true + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } +} + +keyvault_access_policies_azuread_apps = { + test_client = { + test_client = { + azuread_app_key = "test_client" + secret_permissions = ["Set", "Get", "List", "Delete"] + } + } +} + + +azuread_applications = { + test_client = { + useprefix = true + application_name = "test-client" + } +} + + +azuread_service_principals = { + sp1 = { + azuread_application = { + key = "test_client" + } + app_role_assignment_required = true + } +} + +azuread_service_principal_passwords = { + sp1 = { + azuread_service_principal = { + key = "sp1" + } + password_policy = { + # Length of the password + length = 250 + special = false + upper = true + number = true + + # Define the number of days the password is valid. It must be more than the rotation frequency + expire_in_days = 10 + rotation = { + # + # Set how often the password must be rotated. When passed the renewal time, running the terraform plan / apply will change to a new password + # Only set one of the value + # + + mins = 3 # only recommended for CI and demo + # days = 7 + # months = 1 + } + } + keyvaults = { + test_client = { + secret_prefix = "test-client" + } + } + # Store the ${secret_prefix}-client-id, ${secret_prefix}-client-secret... + # Set the policy during the creation process of the launchpad + } +} + +#complete list of built-in-roles : https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles + +role_mapping = { + built_in_role_mapping = { + subscriptions = { + # subcription level access + logged_in_subscription = { + "Contributor" = { + azuread_service_principals = { + keys = ["sp1"] + } + } + } + } + } +} + diff --git a/examples/azuread/main.tf b/examples/azuread/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/azuread/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/landingzones/caf_example/backend.azurerm b/examples/backend.azurerm similarity index 100% rename from landingzones/caf_example/backend.azurerm rename to examples/backend.azurerm diff --git a/landingzones/caf_example/ci.sh b/examples/ci.sh similarity index 100% rename from landingzones/caf_example/ci.sh rename to examples/ci.sh diff --git a/examples/compute/availability_set/100-simple-availabilityset/configuration.tfvars b/examples/compute/availability_set/100-simple-availabilityset/configuration.tfvars index 221694d6b1..0f508840e3 100644 --- a/examples/compute/availability_set/100-simple-availabilityset/configuration.tfvars +++ b/examples/compute/availability_set/100-simple-availabilityset/configuration.tfvars @@ -65,7 +65,7 @@ virtual_machines = { size = "Standard_F2" admin_username = "adminuser" disable_password_authentication = true - custom_data = "../../examples/compute/availability_set/100-simple-availabilityset/scripts/cloud-init/install-rover-tools.config" + custom_data = "compute/availability_set/100-simple-availabilityset/scripts/cloud-init/install-rover-tools.config" # Value of the nic keys to attach the VM. The first one in the list is the default nic network_interface_keys = ["nic0"] @@ -119,7 +119,7 @@ virtual_machines = { size = "Standard_F2" admin_username = "adminuser" disable_password_authentication = true - custom_data = "../../examples/compute/availability_set/100-simple-availabilityset/scripts/cloud-init/install-rover-tools.config" + custom_data = "compute/availability_set/100-simple-availabilityset/scripts/cloud-init/install-rover-tools.config" # Value of the nic keys to attach the VM. The first one in the list is the default nic network_interface_keys = ["nic0"] diff --git a/examples/compute/availability_set/101-availabilityset-with-proximity-placement-group/configuration.tfvars b/examples/compute/availability_set/101-availabilityset-with-proximity-placement-group/configuration.tfvars index b3e4ba3adb..923c035290 100644 --- a/examples/compute/availability_set/101-availabilityset-with-proximity-placement-group/configuration.tfvars +++ b/examples/compute/availability_set/101-availabilityset-with-proximity-placement-group/configuration.tfvars @@ -71,7 +71,7 @@ virtual_machines = { size = "Standard_F2" admin_username = "adminuser" disable_password_authentication = true - custom_data = "../../examples/compute/availability_set/101-availabilityset-with-proximity-placement-group/scripts/cloud-init/install-rover-tools.config" + custom_data = "compute/availability_set/101-availabilityset-with-proximity-placement-group/scripts/cloud-init/install-rover-tools.config" # Value of the nic keys to attach the VM. The first one in the list is the default nic network_interface_keys = ["nic0"] @@ -126,7 +126,7 @@ virtual_machines = { size = "Standard_F2" admin_username = "adminuser" disable_password_authentication = true - custom_data = "../../examples/compute/availability_set/101-availabilityset-with-proximity-placement-group/scripts/cloud-init/install-rover-tools.config" + custom_data = "compute/availability_set/101-availabilityset-with-proximity-placement-group/scripts/cloud-init/install-rover-tools.config" # Value of the nic keys to attach the VM. The first one in the list is the default nic network_interface_keys = ["nic0"] diff --git a/examples/compute/container_groups/101-aci-rover/global_settings.tfvars b/examples/compute/container_groups/101-aci-rover/global_settings.tfvars index 76a9a27ac4..c915dad76e 100644 --- a/examples/compute/container_groups/101-aci-rover/global_settings.tfvars +++ b/examples/compute/container_groups/101-aci-rover/global_settings.tfvars @@ -1,6 +1,6 @@ global_settings = { default_region = "region1" regions = { - region1 = "southeastasia" + region1 = "westeurope" } } diff --git a/examples/compute/container_groups/101-aci-rover/readme.md b/examples/compute/container_groups/101-aci-rover/readme.md deleted file mode 100644 index adf4990087..0000000000 --- a/examples/compute/container_groups/101-aci-rover/readme.md +++ /dev/null @@ -1,31 +0,0 @@ -You can test this module outside of a landingzone using - -``` -configuration_folder=/tf/caf/examples/compute/container_groups/101-aci-rover -parameter_files=$(find ${configuration_folder} | grep .tfvars | sed 's/.*/-var-file &/' | xargs) - -cd /tf/caf/landingzones/caf_example - -terraform init - -eval terraform plan ${parameter_files} \ - -var var_folder_path="${configuration_folder}" - - -``` - -To test this deployment in the example landingzone. Make sure the launchpad has been deployed first - -```bash - -cd /tf/caf/examples/compute/container_groups/101-aci-rover -current_folder=$(pwd) -parameter_files=$(find ${current_folder} | grep .tfvars | sed 's/.*/-var-file &/' | xargs) - -rover \ - -lz /tf/caf/landingzones/caf_example \ - ${parameter_files} \ - -level level1 \ - -a plan - -``` \ No newline at end of file diff --git a/examples/compute/container_registry/100-simple-acr/configuration.tfvars b/examples/compute/container_registry/100-simple-acr/configuration.tfvars index 77aa50f2c9..f50cc4cbe7 100644 --- a/examples/compute/container_registry/100-simple-acr/configuration.tfvars +++ b/examples/compute/container_registry/100-simple-acr/configuration.tfvars @@ -18,10 +18,23 @@ resource_groups = { azure_container_registries = { acr1 = { - name = "acr-test" - resource_group_key = "acr_region1" - sku = "Premium" - georeplication_region_keys = ["region2", "region3"] + name = "acr-test" + resource_group_key = "acr_region1" + sku = "Premium" + # georeplications = { + # region2 = { + # tags = { + # region = "eastasia" + # type = "acr_replica" + # } + # } + # region3 = { + # tags = { + # region = "westeurope" + # type = "acr_replica" + # } + # } + # } } } diff --git a/examples/compute/container_registry/200-acr-private-link/configuration.tfvars b/examples/compute/container_registry/200-acr-private-link/configuration.tfvars index 11bdcc9093..619d2fe6ee 100644 --- a/examples/compute/container_registry/200-acr-private-link/configuration.tfvars +++ b/examples/compute/container_registry/200-acr-private-link/configuration.tfvars @@ -21,10 +21,23 @@ resource_groups = { azure_container_registries = { acr1 = { - name = "acr-test" - resource_group_key = "acr_region1" - sku = "Premium" - georeplication_region_keys = ["region2", "region3"] + name = "acr-test" + resource_group_key = "acr_region1" + sku = "Premium" + georeplications = { + region2 = { + tags = { + region = "eastasia" + type = "acr_replica" + } + } + region3 = { + tags = { + region = "westeurope" + type = "acr_replica" + } + } + } private_links = { hub_rg1-jumphost = { @@ -69,72 +82,4 @@ vnets = { } } -} - - -# -# Define the settings for log analytics workspace and solution map -# -log_analytics = { - central_logs_region1 = { - region = "region1" - name = "logs" - resource_group_key = "acr_region1" - - # you can setup up to 5 key - diagnostic_profiles = { - central_logs_region1 = { - definition_key = "azure_container_registry" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - } -} - - -diagnostics_destinations = { - log_analytics = { - central_logs = { - log_analytics_key = "central_logs_region1" - log_analytics_destination_type = "Dedicated" - } - } -} - -# -# Define the settings for the diagnostics settings -# Demonstrate how to log diagnostics in the correct region -# Different profiles to target different operational teams -# -diagnostics_definition = { - log_analytics = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["Audit", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - } - - azure_container_registry = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["ContainerRegistryRepositoryEvents", true, false, 7], - ["ContainerRegistryLoginEvents", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - } - -} +} \ No newline at end of file diff --git a/examples/compute/container_registry/200-acr-private-link/diagnostics.tfvars b/examples/compute/container_registry/200-acr-private-link/diagnostics.tfvars new file mode 100644 index 0000000000..bac09b4749 --- /dev/null +++ b/examples/compute/container_registry/200-acr-private-link/diagnostics.tfvars @@ -0,0 +1,66 @@ + +# +# Define the settings for log analytics workspace and solution map +# +diagnostic_log_analytics = { + central_logs_region1 = { + region = "region1" + name = "logs" + resource_group_key = "acr_region1" + + # you can setup up to 5 key + diagnostic_profiles = { + central_logs_region1 = { + definition_key = "log_analytics" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + } +} + +diagnostics_destinations = { + log_analytics = { + central_logs = { + log_analytics_key = "central_logs_region1" + log_analytics_destination_type = "Dedicated" + } + } +} + +# +# Define the settings for the diagnostics settings +# Demonstrate how to log diagnostics in the correct region +# Different profiles to target different operational teams +# +diagnostics_definition = { + log_analytics = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["Audit", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + } + + azure_container_registry = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["ContainerRegistryRepositoryEvents", true, false, 7], + ["ContainerRegistryLoginEvents", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + } + +} diff --git a/examples/compute/container_registry/200-acr-vnet/configuration.tfvars b/examples/compute/container_registry/200-acr-vnet/configuration.tfvars index 1a73c4d0f1..4223422c33 100644 --- a/examples/compute/container_registry/200-acr-vnet/configuration.tfvars +++ b/examples/compute/container_registry/200-acr-vnet/configuration.tfvars @@ -21,10 +21,23 @@ resource_groups = { azure_container_registries = { acr1 = { - name = "acr-test" - resource_group_key = "acr_region1" - sku = "Premium" - georeplication_region_keys = ["region2", "region3"] + name = "acr-test" + resource_group_key = "acr_region1" + sku = "Premium" + georeplications = { + region2 = { + tags = { + region = "eastasia" + type = "acr_replica" + } + } + region3 = { + tags = { + region = "westeurope" + type = "acr_replica" + } + } + } network_rule_set = { rule1 = { default_action = "Allow" diff --git a/examples/compute/dedicated_hosts/101-dedicated-host/configuration.tfvars b/examples/compute/dedicated_hosts/101-dedicated-host/configuration.tfvars new file mode 100644 index 0000000000..5c19edf728 --- /dev/null +++ b/examples/compute/dedicated_hosts/101-dedicated-host/configuration.tfvars @@ -0,0 +1,43 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } +} + +resource_groups = { + dhg = { + name = "dedicated-test" + region = "region1" + } +} + +dedicated_host_groups = { + dhg1 = { + name = "example-dhg" + resource_group_key = "dhg" + region = "region1" + platform_fault_domain_count = 2 + automatic_placement_enabled = true + zones = ["1"] + tags = { + test = "dhg" } + } +} + +dedicated_hosts = { + dh1 = { + name = "example-host-dhg" + dedicated_host_group_key = "dhg1" + #lz_key = "remote landing zone key" + region = "region1" + sku_name = "DSv3-Type1" + platform_fault_domain = 1 + auto_replace_on_failure = true + # license_type = "Windows_Server_Hybrid" + tags = { + test = "dhg" + } + } + +} \ No newline at end of file diff --git a/examples/compute/dedicated_hosts/102-dedicated-host-vms/configuration.tfvars b/examples/compute/dedicated_hosts/102-dedicated-host-vms/configuration.tfvars new file mode 100644 index 0000000000..2fb18d60a1 --- /dev/null +++ b/examples/compute/dedicated_hosts/102-dedicated-host-vms/configuration.tfvars @@ -0,0 +1,42 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } +} + +resource_groups = { + dhg = { + name = "dedicated-test" + region = "region1" + } +} + +dedicated_host_groups = { + dhg1 = { + name = "example-dhg" + resource_group_key = "dhg" + region = "region1" + platform_fault_domain_count = 2 + automatic_placement_enabled = true + tags = { + test = "dhg" } + } +} + +dedicated_hosts = { + dh1 = { + name = "example-host-dhg" + dedicated_host_group_key = "dhg1" + #lz_key = "remote landing zone key" + region = "region1" + sku_name = "DSv3-Type1" + platform_fault_domain = 1 + auto_replace_on_failure = true + # license_type = "Windows_Server_Hybrid" + tags = { + test = "dhg" + } + } +} + diff --git a/examples/compute/dedicated_hosts/102-dedicated-host-vms/vm.tfvars b/examples/compute/dedicated_hosts/102-dedicated-host-vms/vm.tfvars new file mode 100644 index 0000000000..48a90de64f --- /dev/null +++ b/examples/compute/dedicated_hosts/102-dedicated-host-vms/vm.tfvars @@ -0,0 +1,159 @@ + +# Virtual machines +virtual_machines = { + + # Configuration to deploy a bastion host linux virtual machine + example_vm1 = { + resource_group_key = "dhg" + provision_vm_agent = true + # when boot_diagnostics_storage_account_key is empty string "", boot diagnostics will be put on azure managed storage + # when boot_diagnostics_storage_account_key is a non-empty string, it needs to point to the key of a user managed storage defined in diagnostic_storage_accounts + # if boot_diagnostics_storage_account_key is not defined, but global_settings.resource_defaults.virtual_machines.use_azmanaged_storage_for_boot_diagnostics is true, boot diagnostics will be put on azure managed storage + + os_type = "windows" + + # the auto-generated ssh key in keyvault secret. Secret name being {VM name}-ssh-public and {VM name}-ssh-private + keyvault_key = "example_vm_rg1" + + # Define the number of networking cards to attach the virtual machine + networking_interfaces = { + nic0 = { + # Value of the keys from networking.tfvars + vnet_key = "vnet_region1" + subnet_key = "example" + name = "0-windows" + enable_ip_forwarding = false + internal_dns_name_label = "nic0-vm1" + } + } + + virtual_machine_settings = { + windows = { + name = "example_vm1" + size = "Standard_D2S_v3" + admin_username = "adminuser" + + dedicated_host = { + key = "dh1" + # lz_key = "remoteLZKey" + # id = "full resource ID" + } + + # Spot VM to save money + priority = "Spot" + eviction_policy = "Deallocate" + + # Value of the nic keys to attach the VM. The first one in the list is the default nic + network_interface_keys = ["nic0"] + + os_disk = { + name = "example_vm1-os" + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference = { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2019-Datacenter" + version = "latest" + } + + } + } + + } + example_vm2 = { + resource_group_key = "dhg" + provision_vm_agent = true + + os_type = "linux" + + # the auto-generated ssh key in keyvault secret. Secret name being {VM name}-ssh-public and {VM name}-ssh-private + keyvault_key = "example_vm_rg1" + + # Define the number of networking cards to attach the virtual machine + networking_interfaces = { + nic0 = { + # Value of the keys from networking.tfvars + vnet_key = "vnet_region1" + subnet_key = "example" + primary = true + name = "0-linux" + enable_ip_forwarding = false + internal_dns_name_label = "nic0-vm2" + + } + } + + virtual_machine_settings = { + linux = { + name = "example_vm2" + size = "Standard_D2S_v3" + admin_username = "adminuser" + disable_password_authentication = true + + dedicated_host = { + key = "dh1" + # lz_key = "remoteLZKey" + # id = "full resource ID" + } + + + # Spot VM to save money + priority = "Spot" + eviction_policy = "Deallocate" + + # Value of the nic keys to attach the VM. The first one in the list is the default nic + network_interface_keys = ["nic0"] + + os_disk = { + name = "example_vm2-os" + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference = { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "18.04-LTS" + version = "latest" + } + + } + } + } +} + + +keyvaults = { + example_vm_rg1 = { + name = "vmsecrets" + resource_group_key = "dhg" + sku_name = "standard" + creation_policies = { + logged_in_user = { + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } +} + + +vnets = { + vnet_region1 = { + resource_group_key = "dhg" + vnet = { + name = "virtual_machines" + address_space = ["10.100.100.0/24"] + } + specialsubnets = {} + subnets = { + example = { + name = "examples" + cidr = ["10.100.100.0/29"] + } + } + + } +} diff --git a/examples/compute/main.tf b/examples/compute/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/compute/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/compute/proximity_placement_group/configuration.tfvars b/examples/compute/proximity_placement_group/configuration.tfvars index 196f08c117..16087e032d 100644 --- a/examples/compute/proximity_placement_group/configuration.tfvars +++ b/examples/compute/proximity_placement_group/configuration.tfvars @@ -48,7 +48,7 @@ virtual_machines = { size = "Standard_F2" admin_username = "adminuser" disable_password_authentication = true - custom_data = "../../examples/compute/proximity_placement_group/scripts/cloud-init/install-rover-tools.config" + custom_data = "compute/proximity_placement_group/scripts/cloud-init/install-rover-tools.config" # Spot VM to save money priority = "Spot" @@ -101,7 +101,7 @@ virtual_machines = { size = "Standard_F2" admin_username = "adminuser" disable_password_authentication = true - custom_data = "../../examples/compute/proximity_placement_group/scripts/cloud-init/install-rover-tools.config" + custom_data = "compute/proximity_placement_group/scripts/cloud-init/install-rover-tools.config" # Spot VM to save money priority = "Spot" diff --git a/examples/compute/virtual_machine/100-single-linux-vm/configuration.tfvars b/examples/compute/virtual_machine/100-single-linux-vm/configuration.tfvars index 7f44341805..3dbcd1b430 100755 --- a/examples/compute/virtual_machine/100-single-linux-vm/configuration.tfvars +++ b/examples/compute/virtual_machine/100-single-linux-vm/configuration.tfvars @@ -63,7 +63,7 @@ virtual_machines = { disable_password_authentication = true #custom_data = "scripts/cloud-init/install-rover-tools.config" - custom_data = "../../examples/compute/virtual_machine/100-single-linux-vm/scripts/cloud-init/install-rover-tools.config" + custom_data = "compute/virtual_machine/100-single-linux-vm/scripts/cloud-init/install-rover-tools.config" # Spot VM to save money priority = "Spot" diff --git a/examples/compute/virtual_machine/106-marketplace-image-with-plan/configuration.tfvars b/examples/compute/virtual_machine/106-marketplace-image-with-plan/configuration.tfvars index 760703a3a1..59c338db08 100644 --- a/examples/compute/virtual_machine/106-marketplace-image-with-plan/configuration.tfvars +++ b/examples/compute/virtual_machine/106-marketplace-image-with-plan/configuration.tfvars @@ -95,7 +95,7 @@ virtual_machines = { keyvaults = { example_vm_rg1 = { - name = "vmlinux_marketplace_akv1" + name = "akvex" resource_group_key = "vm_region1" sku_name = "standard" tags = { @@ -137,4 +137,4 @@ public_ip_addresses = { idle_timeout_in_minutes = "4" } -} +} \ No newline at end of file diff --git a/examples/compute/virtual_machine/211-vm-bastion-winrm-agents/standalone/readme.md b/examples/compute/virtual_machine/211-vm-bastion-winrm-agents/standalone/readme.md deleted file mode 100644 index 3193a3a447..0000000000 --- a/examples/compute/virtual_machine/211-vm-bastion-winrm-agents/standalone/readme.md +++ /dev/null @@ -1,29 +0,0 @@ -You can test this module outside of a landingzone using - -```bash -configuration_folder=/tf/caf/examples/compute/virtual_machine/211-vm-bastion-winrm-agents -parameter_files=$(find ${configuration_folder} | grep .tfvars | sed 's/.*/-var-file &/' | xargs) - -cd /tf/caf/landingzones/caf_example - -terraform init - -eval terraform plan ${parameter_files} \ - -var var_folder_path="${configuration_folder}" - - -``` - -To test this deployment in the example landingzone. Make sure the launchpad has been deployed first - -```bash - -configuration_folder=/tf/caf/examples/compute/virtual_machine/211-vm-bastion-winrm-agents -rover \ - -lz /tf/caf/landingzones/caf_example \ - -var-folder ${configuration_folder} \ - -var var_folder_path="${configuration_folder}" \ - -level level1 \ - -a plan - -``` \ No newline at end of file diff --git a/examples/compute/virtual_machine/211-vm-bastion-winrm-agents/standalone/vm_extensions.tf b/examples/compute/virtual_machine/211-vm-bastion-winrm-agents/standalone/vm_extensions.tf deleted file mode 100644 index 3f3c8b2bc2..0000000000 --- a/examples/compute/virtual_machine/211-vm-bastion-winrm-agents/standalone/vm_extensions.tf +++ /dev/null @@ -1,40 +0,0 @@ -# -# microsoft_enterprise_cloud_monitoring - Install the monitoring agent in the virtual machine -# - -module "vm_extension_monitoring_agent" { - source = "../../../../../modules/compute/virtual_machine_extensions" - - for_each = { - for key, value in try(var.virtual_machines, {}) : key => value - if try(value.virtual_machine_extensions.microsoft_enterprise_cloud_monitoring, null) != null - } - - client_config = module.caf.client_config - virtual_machine_id = module.caf.virtual_machines[each.key].id - extension = each.value.virtual_machine_extensions.microsoft_enterprise_cloud_monitoring - extension_name = "microsoft_enterprise_cloud_monitoring" - settings = { - diagnostics = module.caf.diagnostics - } -} - -module "vm_extension_diagnostics" { - source = "../../../../../modules/compute/virtual_machine_extensions" - - for_each = { - for key, value in try(var.virtual_machines, {}) : key => value - if try(value.virtual_machine_extensions.microsoft_azure_diagnostics, null) != null - } - - client_config = module.caf.client_config - virtual_machine_id = module.caf.virtual_machines[each.key].id - extension = each.value.virtual_machine_extensions.microsoft_azure_diagnostics - extension_name = "microsoft_azure_diagnostics" - settings = { - var_folder_path = var.var_folder_path - diagnostics = module.caf.diagnostics - xml_diagnostics_file = try(each.value.virtual_machine_extensions.microsoft_azure_diagnostics.xml_diagnostics_file, null) - diagnostics_storage_account_keys = each.value.virtual_machine_extensions.microsoft_azure_diagnostics.diagnostics_storage_account_keys - } -} \ No newline at end of file diff --git a/examples/compute/virtual_machine_scale_set/100-linux-win-vmss-lb/configuration.tfvars b/examples/compute/virtual_machine_scale_set/100-linux-win-vmss-lb/configuration.tfvars index eee0dd0b71..3d6641b284 100644 --- a/examples/compute/virtual_machine_scale_set/100-linux-win-vmss-lb/configuration.tfvars +++ b/examples/compute/virtual_machine_scale_set/100-linux-win-vmss-lb/configuration.tfvars @@ -1,6 +1,5 @@ global_settings = { default_region = "region1" - prefix = "example" regions = { region1 = "southeastasia" } @@ -40,34 +39,22 @@ vnets = { keyvaults = { kv1 = { - name = "vmsslbexmpkv" + name = "vmsslbexmpkv1" resource_group_key = "rg1" sku_name = "standard" creation_policies = { logged_in_user = { secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - key_permissions = ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", "Decrypt", "Encrypt", "UnwrapKey", "WrapKey", "Verify", "Sign", "Purge"] } } } } -keyvault_keys = { - key1 = { - keyvault_key = "kv1" - resource_group_key = "rg1" - name = "vmsskey" - key_type = "RSA" - key_size = "2048" - key_opts = ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"] - } -} - diagnostic_storage_accounts = { # Stores boot diagnostic for region1 bootdiag1 = { - name = "vmsslbexamplebootdiag1" + name = "lebootdiag1" resource_group_key = "rg1" account_kind = "StorageV2" account_tier = "Standard" @@ -80,7 +67,7 @@ diagnostic_storage_accounts = { application_security_groups = { app_sg1 = { resource_group_key = "rg1" - name = "app_sg1" + name = "app_sg1" } } @@ -141,26 +128,26 @@ load_balancers = { virtual_machine_scale_sets = { vmss1 = { - resource_group_key = "rg1" + resource_group_key = "rg1" boot_diagnostics_storage_account_key = "bootdiag1" - os_type = "linux" - keyvault_key = "kv1" + os_type = "linux" + keyvault_key = "kv1" vmss_settings = { linux = { - name = "linux_vmss1" - computer_name_prefix = "lnx" - sku = "Standard_F2" - instances = 1 - admin_username = "adminuser" + name = "linux_vmss1" + computer_name_prefix = "lnx" + sku = "Standard_F2" + instances = 1 + admin_username = "adminuser" disable_password_authentication = true - provision_vm_agent = true - priority = "Spot" - eviction_policy = "Deallocate" - ultra_ssd_enabled = false # required if planning to use UltraSSD_LRS + provision_vm_agent = true + priority = "Spot" + eviction_policy = "Deallocate" + ultra_ssd_enabled = false # required if planning to use UltraSSD_LRS upgrade_mode = "Manual" # Automatic / Rolling / Manual - + # rolling_upgrade_policy = { # # Only for upgrade mode = "Automatic / Rolling " # max_batch_instance_percent = 20 @@ -169,23 +156,23 @@ virtual_machine_scale_sets = { # pause_time_between_batches = "" # } # automatic_os_upgrade_policy = { - # # Only for upgrade mode = "Automatic" + # # Only for upgrade mode = "Automatic" # disable_automatic_rollback = false # enable_automatic_os_upgrade = true # } os_disk = { - caching = "ReadWrite" + caching = "ReadWrite" storage_account_type = "Standard_LRS" - disk_size_gb = 128 + disk_size_gb = 128 # disk_encryption_set_key = "" # lz_key = "" } identity = { # type = "SystemAssigned" - type = "UserAssigned" + type = "UserAssigned" managed_identity_keys = ["example_mi"] remote = { @@ -212,10 +199,10 @@ virtual_machine_scale_sets = { nic0 = { - name = "0" - primary = true - vnet_key = "vnet1" - subnet_key = "subnet1" + name = "0" + primary = true + vnet_key = "vnet1" + subnet_key = "subnet1" load_balancers = { lb1 = { lb_key = "lb1" @@ -228,25 +215,25 @@ virtual_machine_scale_sets = { asg_key = "app_sg1" # lz_key = "" } - } - + } + enable_accelerated_networking = false - enable_ip_forwarding = false - internal_dns_name_label = "nic0" + enable_ip_forwarding = false + internal_dns_name_label = "nic0" } } - + data_disks = { data1 = { - caching = "None" # None / ReadOnly / ReadWrite - create_option = "Empty" # Empty / FromImage (only if source image includes data disks) - disk_size_gb = "10" - lun = 1 - storage_account_type = "Standard_LRS" # UltraSSD_LRS only possible when > additional_capabilities { ultra_ssd_enabled = true } - disk_iops_read_write = 100 # only for UltraSSD Disks - disk_mbps_read_write = 100 # only for UltraSSD Disks - write_accelerator_enabled = false # true requires Premium_LRS and caching = "None" + caching = "None" # None / ReadOnly / ReadWrite + create_option = "Empty" # Empty / FromImage (only if source image includes data disks) + disk_size_gb = "10" + lun = 1 + storage_account_type = "Standard_LRS" # UltraSSD_LRS only possible when > additional_capabilities { ultra_ssd_enabled = true } + disk_iops_read_write = 100 # only for UltraSSD Disks + disk_mbps_read_write = 100 # only for UltraSSD Disks + write_accelerator_enabled = false # true requires Premium_LRS and caching = "None" # disk_encryption_set_key = "set1" # lz_key = "" # lz_key for disk_encryption_set_key if remote } @@ -254,26 +241,26 @@ virtual_machine_scale_sets = { } -vmss2 = { - resource_group_key = "rg1" - provision_vm_agent = true + vmss2 = { + resource_group_key = "rg1" + provision_vm_agent = true boot_diagnostics_storage_account_key = "bootdiag1" - os_type = "windows" - keyvault_key = "kv1" + os_type = "windows" + keyvault_key = "kv1" vmss_settings = { windows = { - name = "win" - computer_name_prefix = "win" - sku = "Standard_F2" - instances = 1 - admin_username = "adminuser" + name = "win" + computer_name_prefix = "win" + sku = "Standard_F2" + instances = 1 + admin_username = "adminuser" disable_password_authentication = true - priority = "Spot" - eviction_policy = "Deallocate" + priority = "Spot" + eviction_policy = "Deallocate" upgrade_mode = "Manual" # Automatic / Rolling / Manual - + # rolling_upgrade_policy = { # # Only for upgrade mode = "Automatic / Rolling " # max_batch_instance_percent = 20 @@ -282,19 +269,19 @@ vmss2 = { # pause_time_between_batches = "" # } # automatic_os_upgrade_policy = { - # # Only for upgrade mode = "Automatic" + # # Only for upgrade mode = "Automatic" # disable_automatic_rollback = false # enable_automatic_os_upgrade = true # } os_disk = { - caching = "ReadWrite" + caching = "ReadWrite" storage_account_type = "Standard_LRS" - disk_size_gb = 128 + disk_size_gb = 128 } identity = { - type = "SystemAssigned" + type = "SystemAssigned" managed_identity_keys = [] } @@ -311,10 +298,10 @@ vmss2 = { network_interfaces = { nic0 = { # Value of the keys from networking.tfvars - name = "0" - primary = true - vnet_key = "vnet1" - subnet_key = "subnet1" + name = "0" + primary = true + vnet_key = "vnet1" + subnet_key = "subnet1" load_balancers = { lb2 = { @@ -331,22 +318,22 @@ vmss2 = { } enable_accelerated_networking = false - enable_ip_forwarding = false - internal_dns_name_label = "nic0" + enable_ip_forwarding = false + internal_dns_name_label = "nic0" } } ultra_ssd_enabled = false # required if planning to use UltraSSD_LRS data_disks = { data1 = { - caching = "None" # None / ReadOnly / ReadWrite - create_option = "Empty" # Empty / FromImage (only if source image includes data disks) - disk_size_gb = "10" - lun = 1 - storage_account_type = "Standard_LRS" # UltraSSD_LRS only possible when > additional_capabilities { ultra_ssd_enabled = true } - disk_iops_read_write = 100 # only for UltraSSD Disks - disk_mbps_read_write = 100 # only for UltraSSD Disks - write_accelerator_enabled = false # true requires Premium_LRS and caching = "None" + caching = "None" # None / ReadOnly / ReadWrite + create_option = "Empty" # Empty / FromImage (only if source image includes data disks) + disk_size_gb = "10" + lun = 1 + storage_account_type = "Standard_LRS" # UltraSSD_LRS only possible when > additional_capabilities { ultra_ssd_enabled = true } + disk_iops_read_write = 100 # only for UltraSSD Disks + disk_mbps_read_write = 100 # only for UltraSSD Disks + write_accelerator_enabled = false # true requires Premium_LRS and caching = "None" # disk_encryption_set_key = "set1" # lz_key = "" # lz_key for disk_encryption_set_key if remote } diff --git a/examples/compute/virtual_machine_scale_set/101-linux-win-vmss-agw/configuration.tfvars b/examples/compute/virtual_machine_scale_set/101-linux-win-vmss-agw/configuration.tfvars index e43b0eca74..e9f45b38bd 100644 --- a/examples/compute/virtual_machine_scale_set/101-linux-win-vmss-agw/configuration.tfvars +++ b/examples/compute/virtual_machine_scale_set/101-linux-win-vmss-agw/configuration.tfvars @@ -1,6 +1,5 @@ global_settings = { default_region = "region1" - prefix = "example" regions = { region1 = "southeastasia" } @@ -44,34 +43,22 @@ vnets = { keyvaults = { kv1 = { - name = "vmssagwexmpkv" + name = "gwexmpkv" resource_group_key = "rg1" sku_name = "standard" creation_policies = { logged_in_user = { secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - key_permissions = ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", "Decrypt", "Encrypt", "UnwrapKey", "WrapKey", "Verify", "Sign", "Purge"] } } } } -keyvault_keys = { - key1 = { - keyvault_key = "kv1" - resource_group_key = "rg1" - name = "vmsskey" - key_type = "RSA" - key_size = "2048" - key_opts = ["encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"] - } -} - diagnostic_storage_accounts = { # Stores boot diagnostic for region1 bootdiag1 = { - name = "vmssagwexamplebootdiag1" + name = "labootdiag1" resource_group_key = "rg1" account_kind = "StorageV2" account_tier = "Standard" @@ -84,7 +71,7 @@ diagnostic_storage_accounts = { application_security_groups = { app_sg1 = { resource_group_key = "rg1" - name = "app_sg1" + name = "app_sg1" } } @@ -93,10 +80,10 @@ application_security_groups = { # AppGW public_ip_addresses = { agw_pip = { - name = "agw_pip1" - resource_group_key = "rg1" - sku = "Standard" - allocation_method = "Static" + name = "agw_pip1" + resource_group_key = "rg1" + sku = "Standard" + allocation_method = "Static" ip_version = "IPv4" idle_timeout_in_minutes = "4" } @@ -218,26 +205,26 @@ application_gateway_applications = { virtual_machine_scale_sets = { vmss1 = { - resource_group_key = "rg1" + resource_group_key = "rg1" boot_diagnostics_storage_account_key = "bootdiag1" - os_type = "linux" - keyvault_key = "kv1" + os_type = "linux" + keyvault_key = "kv1" vmss_settings = { linux = { - name = "linux_vmss1" - computer_name_prefix = "lnx" - sku = "Standard_F2" - instances = 1 - admin_username = "adminuser" + name = "linux_vmss1" + computer_name_prefix = "lnx" + sku = "Standard_F2" + instances = 1 + admin_username = "adminuser" disable_password_authentication = true - provision_vm_agent = true - priority = "Spot" - eviction_policy = "Deallocate" - ultra_ssd_enabled = false # required if planning to use UltraSSD_LRS + provision_vm_agent = true + priority = "Spot" + eviction_policy = "Deallocate" + ultra_ssd_enabled = false # required if planning to use UltraSSD_LRS upgrade_mode = "Manual" # Automatic / Rolling / Manual - + # rolling_upgrade_policy = { # # Only for upgrade mode = "Automatic / Rolling " # max_batch_instance_percent = 20 @@ -246,23 +233,23 @@ virtual_machine_scale_sets = { # pause_time_between_batches = "" # } # automatic_os_upgrade_policy = { - # # Only for upgrade mode = "Automatic" + # # Only for upgrade mode = "Automatic" # disable_automatic_rollback = false # enable_automatic_os_upgrade = true # } os_disk = { - caching = "ReadWrite" + caching = "ReadWrite" storage_account_type = "Standard_LRS" - disk_size_gb = 128 + disk_size_gb = 128 # disk_encryption_set_key = "" # lz_key = "" } identity = { # type = "SystemAssigned" - type = "UserAssigned" + type = "UserAssigned" managed_identity_keys = ["example_mi"] remote = { @@ -295,19 +282,19 @@ virtual_machine_scale_sets = { nic0 = { - name = "0" - primary = true - vnet_key = "vnet1" - subnet_key = "subnet1" - # modify the following to handling multiple lbs, appgw, asg - + name = "0" + primary = true + vnet_key = "vnet1" + subnet_key = "subnet1" + # modify the following to handling multiple lbs, appgw, asg + # load_balancers = { # lb1 = { # lb_key = "" # lz_key = "" # } # } - + appgw_backend_pools = { appgw1 = { appgw_key = "agw1" @@ -324,22 +311,22 @@ virtual_machine_scale_sets = { } enable_accelerated_networking = false - enable_ip_forwarding = false - internal_dns_name_label = "nic0" + enable_ip_forwarding = false + internal_dns_name_label = "nic0" } } - + data_disks = { data1 = { - caching = "None" # None / ReadOnly / ReadWrite - create_option = "Empty" # Empty / FromImage (only if source image includes data disks) - disk_size_gb = "10" - lun = 1 - storage_account_type = "Standard_LRS" # UltraSSD_LRS only possible when > additional_capabilities { ultra_ssd_enabled = true } - disk_iops_read_write = 100 # only for UltraSSD Disks - disk_mbps_read_write = 100 # only for UltraSSD Disks - write_accelerator_enabled = false # true requires Premium_LRS and caching = "None" + caching = "None" # None / ReadOnly / ReadWrite + create_option = "Empty" # Empty / FromImage (only if source image includes data disks) + disk_size_gb = "10" + lun = 1 + storage_account_type = "Standard_LRS" # UltraSSD_LRS only possible when > additional_capabilities { ultra_ssd_enabled = true } + disk_iops_read_write = 100 # only for UltraSSD Disks + disk_mbps_read_write = 100 # only for UltraSSD Disks + write_accelerator_enabled = false # true requires Premium_LRS and caching = "None" # disk_encryption_set_key = "set1" # lz_key = "" # lz_key for disk_encryption_set_key if remote } @@ -347,26 +334,26 @@ virtual_machine_scale_sets = { } -vmss2 = { - resource_group_key = "rg1" - provision_vm_agent = true + vmss2 = { + resource_group_key = "rg1" + provision_vm_agent = true boot_diagnostics_storage_account_key = "bootdiag1" - os_type = "windows" - keyvault_key = "kv1" + os_type = "windows" + keyvault_key = "kv1" vmss_settings = { windows = { - name = "win" - computer_name_prefix = "win" - sku = "Standard_F2" - instances = 1 - admin_username = "adminuser" + name = "win" + computer_name_prefix = "win" + sku = "Standard_F2" + instances = 1 + admin_username = "adminuser" disable_password_authentication = true - priority = "Spot" - eviction_policy = "Deallocate" + priority = "Spot" + eviction_policy = "Deallocate" upgrade_mode = "Manual" # Automatic / Rolling / Manual - + # rolling_upgrade_policy = { # # Only for upgrade mode = "Automatic / Rolling " # max_batch_instance_percent = 20 @@ -375,19 +362,19 @@ vmss2 = { # pause_time_between_batches = "" # } # automatic_os_upgrade_policy = { - # # Only for upgrade mode = "Automatic" + # # Only for upgrade mode = "Automatic" # disable_automatic_rollback = false # enable_automatic_os_upgrade = true # } os_disk = { - caching = "ReadWrite" + caching = "ReadWrite" storage_account_type = "Standard_LRS" - disk_size_gb = 128 + disk_size_gb = 128 } identity = { - type = "SystemAssigned" + type = "SystemAssigned" managed_identity_keys = [] } @@ -404,10 +391,10 @@ vmss2 = { network_interfaces = { nic0 = { # Value of the keys from networking.tfvars - name = "0" - primary = true - vnet_key = "vnet1" - subnet_key = "subnet1" + name = "0" + primary = true + vnet_key = "vnet1" + subnet_key = "subnet1" appgw_backend_pools = { appgw1 = { @@ -422,25 +409,25 @@ vmss2 = { asg_key = "app_sg1" # lz_key = "" } - } - + } + enable_accelerated_networking = false - enable_ip_forwarding = false - internal_dns_name_label = "nic0" + enable_ip_forwarding = false + internal_dns_name_label = "nic0" } } ultra_ssd_enabled = false # required if planning to use UltraSSD_LRS data_disks = { data1 = { - caching = "None" # None / ReadOnly / ReadWrite - create_option = "Empty" # Empty / FromImage (only if source image includes data disks) - disk_size_gb = "10" - lun = 1 - storage_account_type = "Standard_LRS" # UltraSSD_LRS only possible when > additional_capabilities { ultra_ssd_enabled = true } - disk_iops_read_write = 100 # only for UltraSSD Disks - disk_mbps_read_write = 100 # only for UltraSSD Disks - write_accelerator_enabled = false # true requires Premium_LRS and caching = "None" + caching = "None" # None / ReadOnly / ReadWrite + create_option = "Empty" # Empty / FromImage (only if source image includes data disks) + disk_size_gb = "10" + lun = 1 + storage_account_type = "Standard_LRS" # UltraSSD_LRS only possible when > additional_capabilities { ultra_ssd_enabled = true } + disk_iops_read_write = 100 # only for UltraSSD Disks + disk_mbps_read_write = 100 # only for UltraSSD Disks + write_accelerator_enabled = false # true requires Premium_LRS and caching = "None" # disk_encryption_set_key = "set1" # lz_key = "" # lz_key for disk_encryption_set_key if remote } diff --git a/examples/compute/windows_virtual_desktop/wvd_resources/configuration.tfvars b/examples/compute/windows_virtual_desktop/wvd_resources/configuration.tfvars index b66ab79c18..9973f583d2 100644 --- a/examples/compute/windows_virtual_desktop/wvd_resources/configuration.tfvars +++ b/examples/compute/windows_virtual_desktop/wvd_resources/configuration.tfvars @@ -15,16 +15,41 @@ resource_groups = { } wvd_application_groups = { - wvd_app1 = { + wvd_app_group_1 = { resource_group_key = "wvd_region1" host_pool_key = "wvd_hp1" wvd_workspace_key = "wvd_ws1" - name = "firstapp" - friendly_name = "Desktopapp" + name = "desktopgroup" + friendly_name = "Published Desktop" description = "A description of my workspace" #Type of Virtual Desktop Application Group. Valid options are RemoteApp or Desktop. type = "Desktop" } + wvd_app_group_2 = { + resource_group_key = "wvd_region1" + host_pool_key = "wvd_hp1" + wvd_workspace_key = "wvd_ws1" + name = "appgroup" + friendly_name = "Published Application" + description = "Acceptance Test: An application group" + #Type of Virtual Desktop Application Group. Valid options are RemoteApp or Desktop. + type = "RemoteApp" + } +} + +wvd_applications = { + wvd_app1 = { + name = "googlechrome" + application_group_key = "wvd_app_group_2" + friendly_name = "Google Chrome" + description = "Chromium based web browser" + path = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" + command_line_argument_policy = "DoNotAllow" + command_line_arguments = "--incognito" + show_in_portal = false + icon_path = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" + icon_index = 0 + } } wvd_host_pools = { diff --git a/examples/compute/windows_virtual_desktop/wvd_resources_and_session_host/README.md b/examples/compute/windows_virtual_desktop/wvd_resources_and_session_host/README.md index d90562ce5f..b209b25d5e 100644 --- a/examples/compute/windows_virtual_desktop/wvd_resources_and_session_host/README.md +++ b/examples/compute/windows_virtual_desktop/wvd_resources_and_session_host/README.md @@ -1,4 +1,4 @@ -# Windows Virtual Desktop +# Windows Virtual Desktop This module is part of Cloud Adoption Framework landing zones for Azure on Terraform. diff --git a/examples/compute/windows_virtual_desktop/wvd_resources_and_session_host/wvd_compute_nodes.tfvars b/examples/compute/windows_virtual_desktop/wvd_resources_and_session_host/wvd_compute_nodes.tfvars index 757194f09e..cc5ad1f680 100644 --- a/examples/compute/windows_virtual_desktop/wvd_resources_and_session_host/wvd_compute_nodes.tfvars +++ b/examples/compute/windows_virtual_desktop/wvd_resources_and_session_host/wvd_compute_nodes.tfvars @@ -70,7 +70,7 @@ virtual_machines = { } } - ## REQUIRED EXTENSIONS FOR WVD SESSION HOSTS + ## REQUIRED EXTENSIONS FOR WVD SESSION HOSTS virtual_machine_extensions = { microsoft_azure_domainjoin = { diff --git a/examples/cosmos_db/main.tf b/examples/cosmos_db/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/cosmos_db/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/databricks/main.tf b/examples/databricks/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/databricks/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/datalake/101-datalake-storage/README.md b/examples/datalake/README.md similarity index 100% rename from examples/datalake/101-datalake-storage/README.md rename to examples/datalake/README.md diff --git a/examples/datalake/main.tf b/examples/datalake/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/datalake/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/configuration.tfvars b/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/configuration.tfvars new file mode 100755 index 0000000000..8bcb3f7139 --- /dev/null +++ b/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/configuration.tfvars @@ -0,0 +1,13 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } +} + + +resource_groups = { + ops = { + name = "operationlogs" + } +} diff --git a/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/diagnostic_event_hub_namespaces.tfvars b/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/diagnostic_event_hub_namespaces.tfvars new file mode 100755 index 0000000000..937bc1c6e4 --- /dev/null +++ b/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/diagnostic_event_hub_namespaces.tfvars @@ -0,0 +1,41 @@ + +# Event hub diagnostics +diagnostic_event_hub_namespaces = { + + central_logs_region1 = { + name = "centrallogs" + resource_group_key = "ops" + sku = "Standard" + region = "region1" + + event_hubs = { + hub1 = { + name = "eventhub1" + partition_count = 4 + message_retention = 7 + } + } + + } + + namespace2 = { + name = "logs" + resource_group_key = "ops" + sku = "Standard" + region = "region1" + + # eventhub namespace cannot reference itself, thus a secondary is used to send diagnostics logs to central eventhub namespace + diagnostic_profiles = { + central_logs_region1 = { + definition_key = "event_hub_namespace" + destination_type = "event_hub" + destination_key = "central_logs" + event_hub_key = "hub1" # only for event_hub_namespaces + } + } + } + + +} + + diff --git a/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/diagnostics_definition.tfvars b/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/diagnostics_definition.tfvars new file mode 100755 index 0000000000..7db5256540 --- /dev/null +++ b/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/diagnostics_definition.tfvars @@ -0,0 +1,28 @@ + +# +# Define a set of settings for the various type of Azure resources +# + +diagnostics_definition = { + event_hub_namespace = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["ArchiveLogs", true, false, 7], + ["OperationalLogs", true, false, 7], + ["AutoScaleLogs", true, false, 7], + ["KafkaCoordinatorLogs", true, false, 7], + ["KafkaUserErrorLogs", true, false, 7], + ["EventHubVNetConnectionEvent", true, false, 7], + ["CustomerManagedKeyUserLogs", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + +} \ No newline at end of file diff --git a/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/diagnostics_destinations.tfvars b/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/diagnostics_destinations.tfvars new file mode 100755 index 0000000000..89bb7b4766 --- /dev/null +++ b/examples/diagnostics_profiles/201-multi-eventhub-diagnostics/diagnostics_destinations.tfvars @@ -0,0 +1,15 @@ +# Defines the different destination for the different log profiles +# Different profiles to target different operational teams + +diagnostics_destinations = { + # Storage keys must reference the azure region name + # For storage, reference "all_regions" and we will send the logs to the storage account + # in the region of the deployment + + + event_hub_namespaces = { + central_logs = { + event_hub_namespace_key = "central_logs_region1" + } + } +} diff --git a/examples/diagnostics_profiles/README.md b/examples/diagnostics_profiles/README.md new file mode 100755 index 0000000000..f1cf86bf8f --- /dev/null +++ b/examples/diagnostics_profiles/README.md @@ -0,0 +1,13 @@ +# CAF Diagnostics profiles + +This module is part of Cloud Adoption Framework landing zones for Azure on Terraform. + +You can instantiate this directly using the following parameters: + +```hcl +module "caf" { + source = "aztfmod/caf/azurerm" + version = "5.1.0" + # insert the 7 required variables here +} +``` diff --git a/examples/diagnostics_profiles/main.tf b/examples/diagnostics_profiles/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/diagnostics_profiles/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/landingzones/caf_example/dynamic_secrets.tf b/examples/dynamic_secrets.tf similarity index 74% rename from landingzones/caf_example/dynamic_secrets.tf rename to examples/dynamic_secrets.tf index 7585f34633..5ca30eea1d 100644 --- a/landingzones/caf_example/dynamic_secrets.tf +++ b/examples/dynamic_secrets.tf @@ -1,6 +1,8 @@ module "dynamic_keyvault_secrets" { - source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" - version = "~>5.3.2" + # source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" + # version = "~>5.3.2" + + source = "../modules/security/dynamic_keyvault_secrets" # source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git//modules/security/dynamic_keyvault_secrets?ref=master" diff --git a/examples/eventhub/102-namespace-and-evh-with-auth-rules/configuration.tfvars b/examples/eventhub/102-namespace-and-evh-with-auth-rules/configuration.tfvars index 202bfe26b7..2b727bee42 100644 --- a/examples/eventhub/102-namespace-and-evh-with-auth-rules/configuration.tfvars +++ b/examples/eventhub/102-namespace-and-evh-with-auth-rules/configuration.tfvars @@ -1,5 +1,3 @@ -#scenario 200 has to be deployed - global_settings = { default_region = "region1" regions = { @@ -13,20 +11,6 @@ resource_groups = { } } -storage_accounts = { - evh1 = { - name = "evh1" - resource_group_key = "evh_examples" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "LRS" - containers = { - evh = { - name = "evh" - } - } - } -} event_hub_namespaces = { evh1 = { @@ -42,11 +26,10 @@ event_hubs = { name = "ev" resource_group_key = "evh_examples" event_hub_namespace_key = "evh1" - #destination_key = "central_logs" - storage_account_key = "evh1" - blob_container_name = "evh" - partition_count = "2" - message_retention = "2" + storage_account_key = "evh1" + blob_container_name = "evh" + partition_count = "2" + message_retention = "2" } } diff --git a/examples/eventhub/104-namespace-and-evh-with-storage/configuration.tfvars b/examples/eventhub/104-namespace-and-evh-with-storage/configuration.tfvars new file mode 100644 index 0000000000..6dfd675f87 --- /dev/null +++ b/examples/eventhub/104-namespace-and-evh-with-storage/configuration.tfvars @@ -0,0 +1,62 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } +} + +resource_groups = { + evh_examples = { + name = "evh_examples" + } +} + +storage_accounts = { + evh1 = { + name = "evh1" + resource_group_key = "evh_examples" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "LRS" + containers = { + evh = { + name = "evh" + } + } + } +} + +event_hub_namespaces = { + evh1 = { + name = "evh1" + resource_group_key = "evh_examples" + sku = "Standard" + region = "region1" + } +} + +event_hubs = { + ev = { + name = "ev" + resource_group_key = "evh_examples" + event_hub_namespace_key = "evh1" + storage_account_key = "evh1" + blob_container_name = "evh" + partition_count = "2" + message_retention = "2" + + capture_description = { + enabled = true + encoding = "Avro" + interval_in_seconds = 900 + + destination = { + name = "EventHubArchive.AzureBlockBlob" + archive_name_format = "{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}" + blob_container_name = "evh" + storage_account_key = "evh1" + } + } + + } +} \ No newline at end of file diff --git a/examples/eventhub/README.md b/examples/eventhub/README.md new file mode 100755 index 0000000000..660f36baec --- /dev/null +++ b/examples/eventhub/README.md @@ -0,0 +1,13 @@ +# Azure Event Hub + +This module is part of Cloud Adoption Framework landing zones for Azure on Terraform. + +You can instantiate this directly using the following parameters: + +```hcl +module "caf" { + source = "aztfmod/caf/azurerm" + version = "5.1.0" + # insert the 7 required variables here +} +``` diff --git a/examples/eventhub/main.tf b/examples/eventhub/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/eventhub/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/keyvault/main.tf b/examples/keyvault/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/keyvault/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/lighthouse/README.md b/examples/lighthouse/README.md new file mode 100755 index 0000000000..34c99f3d20 --- /dev/null +++ b/examples/lighthouse/README.md @@ -0,0 +1,13 @@ +# Azure Ligthouse + +This module is part of Cloud Adoption Framework landing zones for Azure on Terraform. + +You can instantiate this directly using the following parameters: + +```hcl +module "caf" { + source = "aztfmod/caf/azurerm" + version = "5.1.0" + # insert the 7 required variables here +} +``` diff --git a/examples/lighthouse/main.tf b/examples/lighthouse/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/lighthouse/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/machine_learning/main.tf b/examples/machine_learning/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/machine_learning/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/landingzones/caf_example/main.tf b/examples/main.tf similarity index 100% rename from landingzones/caf_example/main.tf rename to examples/main.tf diff --git a/examples/managed_service_identity/README.md b/examples/managed_service_identity/README.md new file mode 100755 index 0000000000..3dcb2c7e55 --- /dev/null +++ b/examples/managed_service_identity/README.md @@ -0,0 +1,13 @@ +# Azure Managed Identities + +This module is part of Cloud Adoption Framework landing zones for Azure on Terraform. + +You can instantiate this directly using the following parameters: + +```hcl +module "caf" { + source = "aztfmod/caf/azurerm" + version = "5.1.0" + # insert the 7 required variables here +} +``` diff --git a/examples/managed_service_identity/main.tf b/examples/managed_service_identity/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/managed_service_identity/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/mariadb_server/main.tf b/examples/mariadb_server/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/mariadb_server/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/landingzones/caf_example/module.tf b/examples/module.tf similarity index 57% rename from landingzones/caf_example/module.tf rename to examples/module.tf index 9d7633a8b9..1c50138e83 100644 --- a/landingzones/caf_example/module.tf +++ b/examples/module.tf @@ -1,84 +1,120 @@ module "example" { - source = "../.." + source = "../" - azuread_apps = var.azuread_apps - azuread_groups = var.azuread_groups - azuread_roles = var.azuread_roles - azuread_users = var.azuread_users - current_landingzone_key = var.landingzone.key - custom_role_definitions = var.custom_role_definitions - event_hub_auth_rules = var.event_hub_auth_rules - event_hub_consumer_groups = var.event_hub_consumer_groups - event_hub_namespace_auth_rules = var.event_hub_namespace_auth_rules - event_hub_namespaces = var.event_hub_namespaces - event_hubs = var.event_hubs - global_settings = var.global_settings - keyvault_access_policies = var.keyvault_access_policies - keyvault_certificate_issuers = var.keyvault_certificate_issuers - keyvaults = var.keyvaults - log_analytics = var.log_analytics - logged_aad_app_objectId = var.logged_aad_app_objectId - logged_user_objectId = var.logged_user_objectId - managed_identities = var.managed_identities - resource_groups = var.resource_groups - role_mapping = var.role_mapping - storage_accounts = var.storage_accounts - tags = local.tags + current_landingzone_key = var.landingzone.key + custom_role_definitions = var.custom_role_definitions + event_hub_auth_rules = var.event_hub_auth_rules + event_hub_consumer_groups = var.event_hub_consumer_groups + event_hub_namespace_auth_rules = var.event_hub_namespace_auth_rules + event_hub_namespaces = var.event_hub_namespaces + event_hubs = var.event_hubs + global_settings = var.global_settings + keyvault_access_policies = var.keyvault_access_policies + keyvault_certificate_issuers = var.keyvault_certificate_issuers + keyvaults = var.keyvaults + log_analytics = var.log_analytics + logged_aad_app_objectId = var.logged_aad_app_objectId + logged_user_objectId = var.logged_user_objectId + managed_identities = var.managed_identities + resource_groups = var.resource_groups + role_mapping = var.role_mapping + storage_accounts = var.storage_accounts + subscription_billing_role_assignments = var.subscription_billing_role_assignments + tags = local.tags - cloud = { - acrLoginServerEndpoint = var.acrLoginServerEndpoint - attestationEndpoint = var.attestationEndpoint - azureDatalakeAnalyticsCatalogAndJobEndpoint = var.azureDatalakeAnalyticsCatalogAndJobEndpoint - azureDatalakeStoreFileSystemEndpoint = var.azureDatalakeStoreFileSystemEndpoint - keyvaultDns = var.keyvaultDns - mariadbServerEndpoint = var.mariadbServerEndpoint - mhsmDns = var.mhsmDns - mysqlServerEndpoint = var.mysqlServerEndpoint - postgresqlServerEndpoint = var.postgresqlServerEndpoint - sqlServerHostname = var.sqlServerHostname - storageEndpoint = var.storageEndpoint - storageSyncEndpoint = var.storageSyncEndpoint - synapseAnalyticsEndpoint = var.synapseAnalyticsEndpoint - activeDirectory = var.activeDirectory - activeDirectoryDataLakeResourceId = var.activeDirectoryDataLakeResourceId - activeDirectoryGraphResourceId = var.activeDirectoryGraphResourceId - activeDirectoryResourceId = var.activeDirectoryResourceId - appInsightsResourceId = var.appInsightsResourceId - appInsightsTelemetryChannelResourceId = var.appInsightsTelemetryChannelResourceId - attestationResourceId = var.attestationResourceId - azmirrorStorageAccountResourceId = var.azmirrorStorageAccountResourceId - batchResourceId = var.batchResourceId - gallery = var.gallery - logAnalyticsResourceId = var.logAnalyticsResourceId - management = var.management - mediaResourceId = var.mediaResourceId - microsoftGraphResourceId = var.microsoftGraphResourceId - ossrdbmsResourceId = var.ossrdbmsResourceId - portal = var.portal - resourceManager = var.resourceManager - sqlManagement = var.sqlManagement - synapseAnalyticsResourceId = var.synapseAnalyticsResourceId - vmImageAliasDoc = var.vmImageAliasDoc - } - webapp = { - azurerm_application_insights = var.azurerm_application_insights - app_service_environments = var.app_service_environments - app_service_plans = var.app_service_plans - app_services = var.app_services + azuread = { + azuread_api_permissions = var.azuread_api_permissions + azuread_applications = var.azuread_applications + azuread_apps = var.azuread_apps + azuread_credentials = var.azuread_credentials + azuread_groups = var.azuread_groups + azuread_credential_policies = var.azuread_credential_policies + azuread_roles = var.azuread_roles + azuread_service_principal_passwords = var.azuread_service_principal_passwords + azuread_service_principals = var.azuread_service_principals + azuread_users = var.azuread_users } + # # Defaulted, you can declare an override if you dont target Azure public + # cloud = { + # acrLoginServerEndpoint = var.acrLoginServerEndpoint + # attestationEndpoint = var.attestationEndpoint + # azureDatalakeAnalyticsCatalogAndJobEndpoint = var.azureDatalakeAnalyticsCatalogAndJobEndpoint + # azureDatalakeStoreFileSystemEndpoint = var.azureDatalakeStoreFileSystemEndpoint + # keyvaultDns = var.keyvaultDns + # mariadbServerEndpoint = var.mariadbServerEndpoint + # mhsmDns = var.mhsmDns + # mysqlServerEndpoint = var.mysqlServerEndpoint + # postgresqlServerEndpoint = var.postgresqlServerEndpoint + # sqlServerHostname = var.sqlServerHostname + # storageEndpoint = var.storageEndpoint + # storageSyncEndpoint = var.storageSyncEndpoint + # synapseAnalyticsEndpoint = var.synapseAnalyticsEndpoint + # activeDirectory = var.activeDirectory + # activeDirectoryDataLakeResourceId = var.activeDirectoryDataLakeResourceId + # activeDirectoryGraphResourceId = var.activeDirectoryGraphResourceId + # activeDirectoryResourceId = var.activeDirectoryResourceId + # appInsightsResourceId = var.appInsightsResourceId + # appInsightsTelemetryChannelResourceId = var.appInsightsTelemetryChannelResourceId + # attestationResourceId = var.attestationResourceId + # azmirrorStorageAccountResourceId = var.azmirrorStorageAccountResourceId + # batchResourceId = var.batchResourceId + # gallery = var.gallery + # logAnalyticsResourceId = var.logAnalyticsResourceId + # management = var.management + # mediaResourceId = var.mediaResourceId + # microsoftGraphResourceId = var.microsoftGraphResourceId + # ossrdbmsResourceId = var.ossrdbmsResourceId + # portal = var.portal + # resourceManager = var.resourceManager + # sqlManagement = var.sqlManagement + # synapseAnalyticsResourceId = var.synapseAnalyticsResourceId + # vmImageAliasDoc = var.vmImageAliasDoc + # } compute = { aks_clusters = var.aks_clusters availability_sets = var.availability_sets azure_container_registries = var.azure_container_registries bastion_hosts = var.bastion_hosts container_groups = var.container_groups + dedicated_host_groups = var.dedicated_host_groups + dedicated_hosts = var.dedicated_hosts proximity_placement_groups = var.proximity_placement_groups - virtual_machines = var.virtual_machines virtual_machine_scale_sets = var.virtual_machine_scale_sets + virtual_machines = var.virtual_machines + wvd_applications = var.wvd_applications wvd_application_groups = var.wvd_application_groups wvd_host_pools = var.wvd_host_pools wvd_workspaces = var.wvd_workspaces } + diagnostics = { + diagnostic_event_hub_namespaces = var.diagnostic_event_hub_namespaces + diagnostic_log_analytics = var.diagnostic_log_analytics + diagnostic_storage_accounts = var.diagnostic_storage_accounts + diagnostics_definition = var.diagnostics_definition + diagnostics_destinations = var.diagnostics_destinations + } + database = { + azurerm_redis_caches = var.azurerm_redis_caches + cosmos_dbs = var.cosmos_dbs + databricks_workspaces = var.databricks_workspaces + machine_learning_workspaces = var.machine_learning_workspaces + mariadb_servers = var.mariadb_servers + mssql_databases = var.mssql_databases + mssql_elastic_pools = var.mssql_elastic_pools + mssql_failover_groups = var.mssql_failover_groups + mssql_managed_databases_backup_ltr = var.mssql_managed_databases_backup_ltr + mssql_managed_databases_restore = var.mssql_managed_databases_restore + mssql_managed_instances = var.mssql_managed_instances + mssql_managed_instances_secondary = var.mssql_managed_instances_secondary + mssql_mi_administrators = var.mssql_mi_administrators + mssql_mi_failover_groups = var.mssql_mi_failover_groups + mssql_mi_secondary_tdes = var.mssql_mi_secondary_tdes + mssql_mi_tdes = var.mssql_mi_tdes + mssql_servers = var.mssql_servers + mysql_servers = var.mysql_servers + postgresql_servers = var.postgresql_servers + synapse_workspaces = var.synapse_workspaces + } networking = { application_gateway_applications = var.application_gateway_applications application_gateway_waf_policies = var.application_gateway_waf_policies @@ -117,46 +153,8 @@ module "example" { virtual_wans = var.virtual_wans vnet_peerings = var.vnet_peerings vnets = var.vnets - } - - diagnostics = { - diagnostic_event_hub_namespaces = var.diagnostic_event_hub_namespaces - diagnostic_log_analytics = var.diagnostic_log_analytics - diagnostic_storage_accounts = var.diagnostic_storage_accounts - diagnostics_definition = var.diagnostics_definition - diagnostics_destinations = var.diagnostics_destinations - } - - database = { - azurerm_redis_caches = var.azurerm_redis_caches - cosmos_dbs = var.cosmos_dbs - databricks_workspaces = var.databricks_workspaces - machine_learning_workspaces = var.machine_learning_workspaces - mariadb_servers = var.mariadb_servers - mssql_databases = var.mssql_databases - mssql_elastic_pools = var.mssql_elastic_pools - mssql_failover_groups = var.mssql_failover_groups - mssql_managed_databases_backup_ltr = var.mssql_managed_databases_backup_ltr - mssql_managed_databases_restore = var.mssql_managed_databases_restore - mssql_managed_instances = var.mssql_managed_instances - mssql_managed_instances_secondary = var.mssql_managed_instances_secondary - mssql_mi_administrators = var.mssql_mi_administrators - mssql_mi_failover_groups = var.mssql_mi_failover_groups - mssql_mi_secondary_tdes = var.mssql_mi_secondary_tdes - mssql_mi_tdes = var.mssql_mi_tdes - mssql_servers = var.mssql_servers - mysql_servers = var.mysql_servers - postgresql_servers = var.postgresql_servers - synapse_workspaces = var.synapse_workspaces - } - - shared_services = { - image_definitions = var.image_definitions - monitoring = var.monitoring - packer_managed_identity = var.packer_managed_identity - packer_service_principal = var.packer_service_principal - recovery_vaults = var.recovery_vaults - shared_image_galleries = var.shared_image_galleries + vpn_gateway_connections = var.vpn_gateway_connections + vpn_sites = var.vpn_sites } security = { @@ -168,8 +166,24 @@ module "example" { keyvault_certificates = var.keyvault_certificates lighthouse_definitions = var.lighthouse_definitions } - + shared_services = { + image_definitions = var.image_definitions + monitoring = var.monitoring + packer_managed_identity = var.packer_managed_identity + packer_service_principal = var.packer_service_principal + recovery_vaults = var.recovery_vaults + shared_image_galleries = var.shared_image_galleries + } storage = { - netapp_accounts = var.netapp_accounts + netapp_accounts = var.netapp_accounts + storage_account_blobs = var.storage_account_blobs + storage_account_queues = var.storage_account_queues } + webapp = { + azurerm_application_insights = var.azurerm_application_insights + app_service_environments = var.app_service_environments + app_service_plans = var.app_service_plans + app_services = var.app_services + } + } diff --git a/examples/monitoring/100-service-health-alerts/README.md b/examples/monitoring/README.md similarity index 100% rename from examples/monitoring/100-service-health-alerts/README.md rename to examples/monitoring/README.md diff --git a/examples/monitoring/main.tf b/examples/monitoring/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/monitoring/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/mssql_mi/200-mi-two-regions/configuration.tfvars b/examples/mssql_mi/200-mi-two-regions/configuration.tfvars index 6818d97641..3c16903a8d 100644 --- a/examples/mssql_mi/200-mi-two-regions/configuration.tfvars +++ b/examples/mssql_mi/200-mi-two-regions/configuration.tfvars @@ -1,18 +1,26 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + region2 = "eastasia" + } +} + resource_groups = { networking_region1 = { - name = "mi-networking-rg1" + name = "mi-networking-re1" region = "region1" } networking_region2 = { - name = "mi-networking-rg2" + name = "mi-networking-re2" region = "region2" } sqlmi_region1 = { - name = "sqlmi-rg1" + name = "sqlmi-re1" region = "region1" } sqlmi_region2 = { - name = "sqlmi-rg2" + name = "sqlmi-re2" region = "region2" } } @@ -21,7 +29,7 @@ vnets = { sqlmi_region1 = { resource_group_key = "networking_region1" vnet = { - name = "sqlmi-rg1" + name = "sqlmi-re1" address_space = ["172.25.88.0/21"] } subnets = { @@ -45,7 +53,7 @@ vnets = { sqlmi_region2 = { resource_group_key = "networking_region2" vnet = { - name = "sqlmi-rg2" + name = "sqlmi-re2" address_space = ["172.25.96.0/21"] } subnets = { @@ -193,18 +201,18 @@ mssql_managed_databases = { # } # } -mssql_managed_databases_backup_ltr = { - sqlmi1 = { - resource_group_key = "sqlmi_region1" - mi_server_key = "sqlmi1" - database_key = "managed_db1" +# mssql_managed_databases_backup_ltr = { +# sqlmi1 = { +# resource_group_key = "sqlmi_region1" +# mi_server_key = "sqlmi1" +# database_key = "managed_db1" - weeklyRetention = "P12W" - monthlyRetention = "P12M" - yearlyRetention = "P5Y" - weekOfYear = 16 - } -} +# weeklyRetention = "P12W" +# monthlyRetention = "P12M" +# yearlyRetention = "P5Y" +# weekOfYear = 16 +# } +# } mssql_mi_failover_groups = { failover-mi = { diff --git a/examples/mssql_mi/200-mi/configuration.tfvars b/examples/mssql_mi/200-mi/configuration.tfvars index 5730a7b86e..f614f298ad 100644 --- a/examples/mssql_mi/200-mi/configuration.tfvars +++ b/examples/mssql_mi/200-mi/configuration.tfvars @@ -7,11 +7,11 @@ global_settings = { resource_groups = { networking_region1 = { - name = "mi-networking-rg1" + name = "mi-networking-re1" region = "region1" } sqlmi_region1 = { - name = "sqlmi-rg1" + name = "sqlmi-re1" region = "region1" } } diff --git a/examples/mssql_mi/200-mi/standalone/ci.sh b/examples/mssql_mi/200-mi/standalone/ci.sh deleted file mode 100755 index 58c1395ee5..0000000000 --- a/examples/mssql_mi/200-mi/standalone/ci.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -set -e - -current_folder=$(pwd) -cd standalone - -terraform init - -terraform apply \ - -var-file ../configuration.tfvars \ - -var-file ../nsg.tfvars \ - -var tags='{testing_job_id='"${1}"'}' \ - -var var_folder_path=${current_folder} \ - -input=false \ - -auto-approve - - -terraform destroy \ - -var-file ../configuration.tfvars \ - -var-file ../nsg.tfvars \ - -var tags='{testing_job_id='"${1}"'}' \ - -var var_folder_path=${current_folder} \ - -input=false \ - -auto-approve - diff --git a/examples/mssql_mi/200-mi/standalone/main.tf b/examples/mssql_mi/200-mi/standalone/main.tf deleted file mode 100644 index fbcbcb259d..0000000000 --- a/examples/mssql_mi/200-mi/standalone/main.tf +++ /dev/null @@ -1,43 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.52.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" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - diff --git a/examples/mssql_mi/200-mi/standalone/module.tf b/examples/mssql_mi/200-mi/standalone/module.tf deleted file mode 100644 index e3f7220cd3..0000000000 --- a/examples/mssql_mi/200-mi/standalone/module.tf +++ /dev/null @@ -1,21 +0,0 @@ -module "caf" { - source = "../../../../" - global_settings = var.global_settings - tags = var.tags - resource_groups = var.resource_groups - azuread_roles = var.azuread_roles - azuread_groups = var.azuread_groups - - networking = { - vnets = var.vnets - route_tables = var.route_tables - network_security_group_definition = var.network_security_group_definition - } - - database = { - mssql_managed_instances = var.mssql_managed_instances - mssql_managed_databases = var.mssql_managed_databases - mssql_mi_administrators = var.mssql_mi_administrators - } -} - diff --git a/examples/mssql_mi/200-mi/standalone/readme.md b/examples/mssql_mi/200-mi/standalone/readme.md deleted file mode 100644 index 5c6eda333c..0000000000 --- a/examples/mssql_mi/200-mi/standalone/readme.md +++ /dev/null @@ -1,28 +0,0 @@ -You can test this module outside of a landingzone using - -```bash -cd /tf/caf/examples/mssql_mi/200-mi/standalone - -terraform init - -terraform plan \ - -var-file ../configuration.tfvars \ - -var-file ../nsg.tfvars - - - - - -``` - -To test this deployment in the example landingzone. Make sure the launchpad has been deployed first - -```bash - -rover \ - -lz /tf/caf/landingzones/caf_example \ - -var-folder /tf/caf/examples/mssql_mi/200-mi/ \ - -level level1 \ - -a plan - -``` \ No newline at end of file diff --git a/examples/mssql_mi/200-mi/standalone/variables.tf b/examples/mssql_mi/200-mi/standalone/variables.tf deleted file mode 100755 index f6c3a7d448..0000000000 --- a/examples/mssql_mi/200-mi/standalone/variables.tf +++ /dev/null @@ -1,48 +0,0 @@ -variable "global_settings" { - default = {} -} - -variable "resource_groups" { - default = null -} - -variable "vnets" { - default = {} -} - -variable "route_tables" { - default = {} -} - -variable "tags" { - default = null - type = map(any) -} - -variable "mssql_managed_instances" { - default = {} -} - -variable "mssql_managed_databases" { - default = {} -} - -variable "mssql_mi_administrators" { - default = {} -} - -variable "network_security_group_definition" { - default = {} -} - -variable "azuread_roles" { - default = {} -} - -variable "azuread_groups" { - default = {} -} - -variable "var_folder_path" { - default = {} -} \ No newline at end of file diff --git a/examples/mssql_mi/main.tf b/examples/mssql_mi/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/mssql_mi/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/mssql_mi/standalone/main.tf b/examples/mssql_mi/standalone/main.tf deleted file mode 100644 index 303cabc1a5..0000000000 --- a/examples/mssql_mi/standalone/main.tf +++ /dev/null @@ -1,43 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.36.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" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - diff --git a/examples/mssql_mi/standalone/module.tf b/examples/mssql_mi/standalone/module.tf deleted file mode 100644 index 495cf9fe2f..0000000000 --- a/examples/mssql_mi/standalone/module.tf +++ /dev/null @@ -1,28 +0,0 @@ -module "caf" { - source = "../../../" - - global_settings = var.global_settings - resource_groups = var.resource_groups - azuread_groups = var.azuread_groups - azuread_roles = var.azuread_roles - - networking = { - vnets = var.vnets - vnet_peerings = var.vnet_peerings - network_security_group_definition = var.network_security_group_definition - route_tables = var.route_tables - azurerm_routes = var.azurerm_routes - } - - database = { - mssql_managed_instances = var.mssql_managed_instances - mssql_managed_instances_secondary = var.mssql_managed_instances_secondary - mssql_managed_databases = var.mssql_managed_databases - mssql_managed_databases_restore = var.mssql_managed_databases_restore - mssql_managed_databases_backup_ltr = var.mssql_managed_databases_backup_ltr - mssql_mi_failover_groups = var.mssql_mi_failover_groups - mssql_mi_administrators = var.mssql_mi_administrators - mssql_mi_tdes = var.mssql_mi_tdes - mssql_mi_secondary_tdes = var.mssql_mi_secondary_tdes - } -} \ No newline at end of file diff --git a/examples/mssql_mi/standalone/readme.md b/examples/mssql_mi/standalone/readme.md deleted file mode 100644 index cdd454d8ad..0000000000 --- a/examples/mssql_mi/standalone/readme.md +++ /dev/null @@ -1,11 +0,0 @@ -You can test this module outside of a landingzone using - -```bash -terraform init - -terraform [plan|apply|destroy] \ - -var-file ../200-mi-two-regions/configuration.tfvars \ - -var-file ../200-mi-two-regions/nsg.tfvars \ - - -``` diff --git a/examples/mssql_mi/standalone/variables.tf b/examples/mssql_mi/standalone/variables.tf deleted file mode 100755 index 04ff912dad..0000000000 --- a/examples/mssql_mi/standalone/variables.tf +++ /dev/null @@ -1,65 +0,0 @@ - -variable "global_settings" { - default = { - default_region = "region1" - regions = { - region1 = "southeastasia" - region2 = "eastasia" - } - } -} -variable "tags" { - default = null - type = map(any) -} -variable "resource_groups" { - default = null -} -variable "network_security_group_definition" { - default = {} -} -variable "route_tables" { - default = {} -} -variable "azurerm_routes" { - default = {} -} -variable "vnets" { - default = {} -} -variable "vnet_peerings" { - default = {} -} -variable "mssql_managed_instances" { - default = {} -} -variable "mssql_managed_instances_secondary" { - default = {} -} -variable "mssql_managed_databases" { - default = {} -} -variable "mssql_managed_databases_restore" { - default = {} -} -variable "mssql_managed_databases_backup_ltr" { - default = {} -} -variable "mssql_mi_failover_groups" { - default = {} -} -variable "mssql_mi_administrators" { - default = {} -} -variable "mssql_mi_tdes" { - default = {} -} -variable "mssql_mi_secondary_tdes" { - default = {} -} -variable "azuread_groups" { - default = {} -} -variable "azuread_roles" { - default = {} -} \ No newline at end of file diff --git a/examples/mssql_server/106-sqlserver-db-msi-authentication/configurations.tfvars b/examples/mssql_server/106-sqlserver-db-msi-authentication/configurations.tfvars index 4920734f1d..4df507fa48 100644 --- a/examples/mssql_server/106-sqlserver-db-msi-authentication/configurations.tfvars +++ b/examples/mssql_server/106-sqlserver-db-msi-authentication/configurations.tfvars @@ -47,7 +47,7 @@ azuread_groups = { user_principal_names = [] # NOTE: To ensure DB users can be created, sqlserver admin needs to add the rover agent's system assigned identity object ID added - # NOTE: since the authentication uses SQLCMD + DSN, UID cannot be supplied to the connection string, thus only system assigned identity is possible at this stage. + # NOTE: since the authentication uses SQLCMD + DSN, UID cannot be supplied to the connection string, thus only system assigned identity is possible at this stage. object_ids = [ # Add object id of rover agent with system assigned identity here. ] diff --git a/examples/mssql_server/109-sqlserver-network-firewall-rule/configurations.tfvars b/examples/mssql_server/109-sqlserver-network-firewall-rule/configurations.tfvars index b5bbb8413c..a493436d94 100644 --- a/examples/mssql_server/109-sqlserver-network-firewall-rule/configurations.tfvars +++ b/examples/mssql_server/109-sqlserver-network-firewall-rule/configurations.tfvars @@ -46,8 +46,9 @@ mssql_servers = { firewall_rules = { firewall_rule1 = { name = "firewallrule1" - start_ip_address = "124.82.37.221" - end_ip_address = "124.82.37.221" + start_ip_address = "0.0.0.0" + end_ip_address = "0.0.0.0" + # putting it to 0.0.0.0 enables the feature: Allow access to Azure services } } diff --git a/examples/mssql_server/main.tf b/examples/mssql_server/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/mssql_server/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/mysql_server/main.tf b/examples/mysql_server/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/mysql_server/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/netapp/101-nfs/README.md b/examples/netapp/README.md similarity index 100% rename from examples/netapp/101-nfs/README.md rename to examples/netapp/README.md diff --git a/examples/netapp/main.tf b/examples/netapp/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/netapp/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/networking/bastion/100-bastion-with-vm/bastion.tfvars b/examples/networking/bastion/100-bastion-with-vm/bastion.tfvars new file mode 100644 index 0000000000..49672259f2 --- /dev/null +++ b/examples/networking/bastion/100-bastion-with-vm/bastion.tfvars @@ -0,0 +1,20 @@ +bastion_hosts = { + bastion_hub_re1 = { + name = "bastion-rg1" + region = "region1" + resource_group_key = "vnet_hub_re1" + vnet_key = "hub_re1" + subnet_key = "AzureBastionSubnet" + public_ip_key = "bastion_host_rg1" + + # you can setup up to 5 profiles + diagnostic_profiles = { + central_logs_region1 = { + definition_key = "bastion_host" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + } + +} \ No newline at end of file diff --git a/examples/networking/bastion/100-bastion-with-vm/configuration.tfvars b/examples/networking/bastion/100-bastion-with-vm/configuration.tfvars new file mode 100644 index 0000000000..b4720b7084 --- /dev/null +++ b/examples/networking/bastion/100-bastion-with-vm/configuration.tfvars @@ -0,0 +1,15 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + region2 = "eastasia" + } +} + +resource_groups = { + vnet_hub_re1 = { + name = "vnet-hub-re1" + region = "region1" + } +} + diff --git a/examples/networking/bastion/100-bastion-with-vm/diagnostics_definitions.tfvars b/examples/networking/bastion/100-bastion-with-vm/diagnostics_definitions.tfvars new file mode 100644 index 0000000000..abf9c32133 --- /dev/null +++ b/examples/networking/bastion/100-bastion-with-vm/diagnostics_definitions.tfvars @@ -0,0 +1,61 @@ +# +# Define the settings for the diagnostics settings +# Demonstrate how to log diagnostics in the correct region +# Different profiles to target different operational teams +# +diagnostics_definition = { + network_security_group = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["NetworkSecurityGroupEvent", true, false, 14], + ["NetworkSecurityGroupRuleCounter", true, false, 14], + ] + } + } + + networking_all = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["VMProtectionAlerts", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + bastion_host = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["BastionAuditLogs", true, false, 7], + ] + metric = [ + ["AllMetrics", true, true, 7], + ] + } + + } + + public_ip_address = { + name = "operational_logs_and_metrics" + categories = { + log = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["DDoSProtectionNotifications", true, true, 7], + ["DDoSMitigationFlowLogs", true, true, 7], + ["DDoSMitigationReports", true, true, 7], + ] + metric = [ + ["AllMetrics", true, true, 7], + ] + } + } + +} diff --git a/examples/networking/bastion/100-bastion-with-vm/diagnostics_destinations.tfvars b/examples/networking/bastion/100-bastion-with-vm/diagnostics_destinations.tfvars new file mode 100644 index 0000000000..024c1d34f1 --- /dev/null +++ b/examples/networking/bastion/100-bastion-with-vm/diagnostics_destinations.tfvars @@ -0,0 +1,39 @@ +## resources deployment +diagnostic_log_analytics = { + central_logs_region1 = { + region = "region1" + name = "logs" + resource_group_key = "vnet_hub_re1" + } +} + +diagnostic_storage_accounts = { + # Stores diagnostic logging for region1 + diaglogs_region1 = { + name = "diaglogsre1" + region = "region1" + resource_group_key = "vnet_hub_re1" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Hot" + } +} + +## destinations definition +diagnostics_destinations = { + log_analytics = { + central_logs = { + log_analytics_key = "central_logs_region1" + log_analytics_destination_type = "Dedicated" + } + } + + storage = { + all_regions = { + southeastasia = { + storage_account_key = "diaglogs_region1" + } + } + } +} \ No newline at end of file diff --git a/examples/networking/bastion/100-bastion-with-vm/keyvaults.tfvars b/examples/networking/bastion/100-bastion-with-vm/keyvaults.tfvars new file mode 100644 index 0000000000..54b40fd439 --- /dev/null +++ b/examples/networking/bastion/100-bastion-with-vm/keyvaults.tfvars @@ -0,0 +1,17 @@ +keyvaults = { + ssh_keys = { + name = "vmsecrets" + resource_group_key = "vnet_hub_re1" + sku_name = "standard" + + enabled_for_deployment = true + + creation_policies = { + logged_in_user = { + certificate_permissions = ["Get", "List", "Update", "Create", "Import", "Delete", "Purge", "Recover"] + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } +} + diff --git a/examples/networking/bastion/100-bastion-with-vm/nsg_definitions.tfvars b/examples/networking/bastion/100-bastion-with-vm/nsg_definitions.tfvars new file mode 100644 index 0000000000..e2c487aca7 --- /dev/null +++ b/examples/networking/bastion/100-bastion-with-vm/nsg_definitions.tfvars @@ -0,0 +1,149 @@ + +# +# Definition of the networking security groups +# +network_security_group_definition = { + # This entry is applied to all subnets with no NSG defined + empty_nsg = { + resource_group_key = "vnet_hub_re1" + name = "empty_nsg" + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + nsg = [] + } + + azure_bastion_nsg = { + resource_group_key = "vnet_hub_re1" + name = "azure_bastion_nsg" + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + 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" + } + ] + } + + + jumpbox = { + resource_group_key = "vnet_hub_re1" + name = "jumpbox" + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "ssh-inbound-22", + priority = "200" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + +} diff --git a/examples/networking/bastion/100-bastion-with-vm/public_ip.tfvars b/examples/networking/bastion/100-bastion-with-vm/public_ip.tfvars new file mode 100644 index 0000000000..bf779907bb --- /dev/null +++ b/examples/networking/bastion/100-bastion-with-vm/public_ip.tfvars @@ -0,0 +1,24 @@ + +public_ip_addresses = { + + bastion_host_rg1 = { + name = "bastion-rg1-pip1" + region = "region1" + resource_group_key = "vnet_hub_re1" + sku = "Standard" + allocation_method = "Static" + ip_version = "IPv4" + idle_timeout_in_minutes = "4" + + # you can setup up to 5 key + diagnostic_profiles = { + central_logs_region1 = { + definition_key = "public_ip_address" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + } + +} + diff --git a/examples/networking/bastion/100-bastion-with-vm/virtual_machines.tfvars b/examples/networking/bastion/100-bastion-with-vm/virtual_machines.tfvars new file mode 100755 index 0000000000..397ca77c15 --- /dev/null +++ b/examples/networking/bastion/100-bastion-with-vm/virtual_machines.tfvars @@ -0,0 +1,58 @@ +# Virtual machines +virtual_machines = { + + # Configuration to deploy a bastion host linux virtual machine + private_vm = { + resource_group_key = "vnet_hub_re1" + provision_vm_agent = true + # when boot_diagnostics_storage_account_key is empty string "", boot diagnostics will be put on azure managed storage + # when boot_diagnostics_storage_account_key is a non-empty string, it needs to point to the key of a user managed storage defined in diagnostic_storage_accounts + # if boot_diagnostics_storage_account_key is not defined, but global_settings.resource_defaults.virtual_machines.use_azmanaged_storage_for_boot_diagnostics is true, boot diagnostics will be put on azure managed storage + + os_type = "linux" + + # the auto-generated ssh key in keyvault secret. Secret name being {VM name}-ssh-public and {VM name}-ssh-private + keyvault_key = "ssh_keys" + + # Define the number of networking cards to attach the virtual machine + networking_interfaces = { + nic0 = { + # Value of the keys from networking.tfvars + vnet_key = "hub_re1" + subnet_key = "vm" + name = "0-bastion_host" + enable_ip_forwarding = false + internal_dns_name_label = "bastion-host-nic0" + + } + } + + virtual_machine_settings = { + linux = { + name = "private_vm" + size = "Standard_F2s" + admin_username = "adminuser" + disable_password_authentication = true + + # Value of the nic keys to attach the VM. The first one in the list is the default nic + network_interface_keys = ["nic0"] + + os_disk = { + name = "bastion_host-os" + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference = { + publisher = "canonical" + offer = "0001-com-ubuntu-server-focal" + sku = "20_04-lts" + version = "latest" + } + + } + } + + } + +} diff --git a/examples/networking/bastion/100-bastion-with-vm/virtual_networks.tfvars b/examples/networking/bastion/100-bastion-with-vm/virtual_networks.tfvars new file mode 100644 index 0000000000..629f775287 --- /dev/null +++ b/examples/networking/bastion/100-bastion-with-vm/virtual_networks.tfvars @@ -0,0 +1,32 @@ +vnets = { + hub_re1 = { + resource_group_key = "vnet_hub_re1" + region = "region1" + vnet = { + name = "hub-re1" + address_space = ["100.64.92.0/22"] + } + subnets = { + AzureBastionSubnet = { + name = "AzureBastionSubnet" #Must be called AzureBastionSubnet + cidr = ["100.64.93.64/26"] + nsg_key = "azure_bastion_nsg" + } + vm = { + name = "vm" + cidr = ["100.64.94.0/27"] + nsg_key = "jumpbox" + } + } + + # you can setup up to 5 keys - vnet diganostic + diagnostic_profiles = { + central_logs_region1 = { + definition_key = "networking_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + } +} \ No newline at end of file diff --git a/examples/networking/firewall/100-simple-firewall-with-routes/standalone/variables.tf b/examples/networking/firewall/100-simple-firewall-with-routes/standalone/variables.tf deleted file mode 100755 index 657a71d7b4..0000000000 --- a/examples/networking/firewall/100-simple-firewall-with-routes/standalone/variables.tf +++ /dev/null @@ -1,28 +0,0 @@ -variable "global_settings" { - default = {} -} - -variable "resource_groups" { - default = null -} - -variable "vnets" { - default = {} -} - -variable "tags" { - default = null - type = map(any) -} - -variable "public_ip_addresses" { - default = {} -} - -variable "azurerm_firewalls" { - default = {} -} - -variable "var_folder_path" { - default = {} -} \ No newline at end of file diff --git a/examples/networking/firewall/101-simple-firewall/configuration.tfvars b/examples/networking/firewall/101-simple-firewall/configuration.tfvars index b260bccc72..986cd1ff76 100644 --- a/examples/networking/firewall/101-simple-firewall/configuration.tfvars +++ b/examples/networking/firewall/101-simple-firewall/configuration.tfvars @@ -61,5 +61,53 @@ azurerm_firewalls = { # subnet_id = "azure_resource_id" # } } + diagnostic_profiles = { + central_logs_region1 = { + definition_key = "azurerm_firewall" + destination_type = "event_hub" + destination_key = "central_logs" + } + } + } +} + +diagnostics_definition = { + azurerm_firewall = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AzureFirewallApplicationRule", true, false, 7], + ["AzureFirewallNetworkRule", true, false, 7], + ["AzureFirewallDnsProxy", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } +} + +diagnostic_event_hub_namespaces = { + central_logs_region1 = { + name = "logs" + resource_group_key = "test" + sku = "Standard" + region = "region1" } -} \ No newline at end of file +} + +diagnostics_destinations = { + # Storage keys must reference the azure region name + # For storage, reference "all_regions" and we will send the logs to the storage account + # in the region of the deployment + + + event_hub_namespaces = { + central_logs = { + event_hub_namespace_key = "central_logs_region1" + } + } +} diff --git a/examples/networking/load_balancers/104-load-balancer-diagnostics/configuration.tfvars b/examples/networking/load_balancers/104-load-balancer-diagnostics/configuration.tfvars index eb4f781ff3..698f8b93cd 100755 --- a/examples/networking/load_balancers/104-load-balancer-diagnostics/configuration.tfvars +++ b/examples/networking/load_balancers/104-load-balancer-diagnostics/configuration.tfvars @@ -11,23 +11,6 @@ resource_groups = { } } -diagnostic_event_hub_namespaces = { - event_hub_namespace1 = { - name = "security_operation_logs" - resource_group_key = "lb" - sku = "Standard" - region = "region1" - } -} - -diagnostics_destinations = { - event_hub_namespaces = { - central_logs_example = { - event_hub_namespace_key = "event_hub_namespace1" - } - } -} - public_ip_addresses = { lb_pip = { name = "lb_pip1" @@ -65,15 +48,3 @@ load_balancers = { } -diagnostics_definition = { - slb = { - name = "operational_logs_and_metrics" - - categories = { - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - } -} diff --git a/examples/networking/load_balancers/104-load-balancer-diagnostics/diagnostics.tfvars b/examples/networking/load_balancers/104-load-balancer-diagnostics/diagnostics.tfvars new file mode 100644 index 0000000000..39f78c2c2e --- /dev/null +++ b/examples/networking/load_balancers/104-load-balancer-diagnostics/diagnostics.tfvars @@ -0,0 +1,29 @@ +diagnostic_event_hub_namespaces = { + event_hub_namespace1 = { + name = "security_operation_logs" + resource_group_key = "lb" + sku = "Standard" + region = "region1" + } +} + +diagnostics_destinations = { + event_hub_namespaces = { + central_logs_example = { + event_hub_namespace_key = "event_hub_namespace1" + } + } +} + +diagnostics_definition = { + slb = { + name = "operational_logs_and_metrics" + + categories = { + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + } +} diff --git a/examples/networking/main.tf b/examples/networking/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/networking/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/networking/virtual_wan/108-vwan-vpn-site/virtual_wan.tfvars b/examples/networking/virtual_wan/108-vwan-vpn-site/virtual_wan.tfvars new file mode 100644 index 0000000000..599d79fcbf --- /dev/null +++ b/examples/networking/virtual_wan/108-vwan-vpn-site/virtual_wan.tfvars @@ -0,0 +1,64 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } +} + +resource_groups = { + hub_re1 = { + name = "vnet-hub-re1" + region = "region1" + } +} + +virtual_wans = { + vwan_re1 = { + resource_group_key = "hub_re1" + name = "contosovWAN-re1" + region = "region1" + } +} + +vpn_sites = { + vpn-site-1 = { + name = "vpn-site-1" + address_cidrs = ["1.2.3.0/24", "4.5.6.0/24"] + device_vendor = "Cisco" + device_model = "800" + + resource_group = { + # lz_key = "vwans" # Set the 'lz_key' of a Resource Group created in a remote deployment + key = "hub_re1" # Set the 'key' of the Resource Group created in this (or a remote) deployment + } + + virtual_wan = { + key = "vwan_re1" # Set the 'key' of the Virtual WAN created in this (or a remote) deployment + # lz_key = "vwans" # Set the 'lz_key' of a Virtual WAN created in a remote deployment + # + # or + # + # id = "/subscriptions/{subscriptionId}/resourceGroups/testRG/providers/Microsoft.Network/virtualHubs/westushub/hubRouteTables/defaultRouteTable" # Set the Resource ID of an existing Virtual WAN + # resource_id = "/subscriptions/[subscription_id]/resourceGroups/qaxu-rg-dns-domain-registrar/providers/Microsoft.Network/dnszones/ml0iaix4xgnz0jqd.com" # Set the Resource ID of an existing Virtual WAN + } + + links = { + primary = { + name = "primary" + ip_address = "1.2.3.4" + provider_name = "Microsoft" + speed_in_mbps = "150" + } + secondary = { + name = "secondary" + fqdn = "secondary.link.com" + provider_name = "Microsoft" + speed_in_mbps = "50" + bgp = { + asn = "65534" + peering_address = "169.254.1.2" + } + } + } + } +} diff --git a/examples/networking/virtual_wan/109-vwan-vpn-gateway-connection/virtual_wan.tfvars b/examples/networking/virtual_wan/109-vwan-vpn-gateway-connection/virtual_wan.tfvars new file mode 100644 index 0000000000..818c4bad9f --- /dev/null +++ b/examples/networking/virtual_wan/109-vwan-vpn-gateway-connection/virtual_wan.tfvars @@ -0,0 +1,167 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } +} + +resource_groups = { + hub_re1 = { + name = "vnet-hub-re1" + region = "region1" + } +} + +virtual_wans = { + vwan_re1 = { + resource_group_key = "hub_re1" + name = "contosovWAN-re1" + region = "region1" + + hubs = { + hub_re1 = { + hub_name = "hub-re1" + region = "region1" + hub_address_prefix = "10.0.3.0/24" + deploy_firewall = false + deploy_p2s = false + p2s_config = {} + deploy_s2s = true + s2s_config = { + name = "caf-sea-vpn-s2s" + scale_unit = 1 + } + deploy_er = false + } + } + } +} + +virtual_hub_route_tables = { + routetable1 = { + name = "example-vhubroutetable1" + + virtual_wan_key = "vwan_re1" + virtual_hub_key = "hub_re1" + + labels = ["label1"] + } + routetable2 = { + name = "example-vhubroutetable2" + + virtual_wan_key = "vwan_re1" + virtual_hub_key = "hub_re1" + + labels = ["label2"] + } +} + +vpn_sites = { + vpn-site-1 = { + name = "vpn-site-1" + address_cidrs = ["1.2.3.0/24", "4.5.6.0/24"] + device_vendor = "Cisco" + device_model = "800" + + resource_group = { + key = "hub_re1" + } + + virtual_wan = { + key = "vwan_re1" + } + + links = { + primary = { + name = "primary" + ip_address = "1.2.3.4" + provider_name = "Microsoft" + speed_in_mbps = "150" + } + secondary = { + name = "secondary" + fqdn = "secondary.link.com" + provider_name = "Microsoft" + speed_in_mbps = "50" + # bgp = { + # asn = "65534" + # peering_address = "169.254.1.2" + # } + } + } + } +} + +vpn_gateway_connections = { + connection-1 = { + name = "connection-1" + internet_security_enabled = false + + # vpn_site_id = "" # Set the Resource ID of an existing VPN Site + vpn_site = { + # lz_key = "vpns" # Set the 'lz_key' of a VPN Site created in a remote deployment + key = "vpn-site-1" # Set the 'key' of the VPN Site created in this (or a remote) deployment + } + virtual_wan = { + key = "vwan_re1" + } + # virtual_hub_gateway_id = "" # Set the Resource ID of an existing Virtual Hub's VPN Gateway + virtual_hub = { + # lz_key = "" # Set the 'lz_key' of a Virtual Hub created in a remote deployment + key = "hub_re1" # Set the 'key' of the Virtual Hub created in this (or a remote) deployment + } + + vpn_links = { + link-1 = { + link_index = 0 # Index order of VPN Site's Link + name = "link-1" + bandwidth_mbps = "100" # Optional + bgp_enabled = false # Optional + protocol = "IKEv2" # Optional + ratelimit_enabled = true # Optional + route_weight = "100" # Optional + shared_key = "abc123456" # Optional + local_azure_ip_address_enabled = false # Optional + policy_based_traffic_selectors_enabled = false # Optional + + ipsec_policies = { # Optional + policy1 = { + dh_group = "DHGroup14" + ike_encryption_algorithm = "AES256" + ike_integrity_algorithm = "SHA256" + encryption_algorithm = "AES256" + integrity_algorithm = "SHA256" + pfs_group = "PFS14" + sa_data_size_kb = "102400000" + sa_lifetime_sec = "27000" + } + } + } + # link-2 = { + # link_index = 1 + # name = "link-2" + # } + } + + routing = { # Optional + associated_route_table = { + # id = "" # Set the Resource ID of an existing Virtual WAN Route Table + # lz_key = "" # Set the 'lz_key' of a Route Table created in a remote deployment + key = "routetable1" # Set the 'key' of the Route Table created in this (or a remote) deployment + } + + propagated_route_tables = { + routetable1 = { + # id = "" # Set the Resource ID of an existing Virtual WAN Route Table + # lz_key = "" # Set the 'lz_key' of a Route Table created in a remote deployment + key = "routetable1" # Set the 'key' of the Route Table created in this (or a remote) deployment + } + routetable2 = { + # id = "" # Set the Resource ID of an existing Virtual WAN Route Table + # lz_key = "" # Set the 'lz_key' of a Route Table created in a remote deployment + key = "routetable2" # Set the 'key' of the Route Table created in this (or a remote) deployment + } + } + } + } +} diff --git a/landingzones/caf_example/outputs.tf b/examples/outputs.tf similarity index 100% rename from landingzones/caf_example/outputs.tf rename to examples/outputs.tf diff --git a/examples/postgresql_server/main.tf b/examples/postgresql_server/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/postgresql_server/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/random_string/configuration.tfvars b/examples/random_string/configuration.tfvars new file mode 100644 index 0000000000..dcb1afd029 --- /dev/null +++ b/examples/random_string/configuration.tfvars @@ -0,0 +1,8 @@ +random_strings = { + myRandomString = { + length = 20 + special = false + upper = false + number = false + } +} \ No newline at end of file diff --git a/examples/random_string/main.tf b/examples/random_string/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/random_string/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/recovery_vault/102-asr-protection/configuration.tfvars b/examples/recovery_vault/102-asr-protection/configuration.tfvars index 300963bc20..53af0ffea3 100644 --- a/examples/recovery_vault/102-asr-protection/configuration.tfvars +++ b/examples/recovery_vault/102-asr-protection/configuration.tfvars @@ -30,21 +30,21 @@ recovery_vaults = { } } - # recovery_fabrics = { - # fabric1 = { - # name = "fabric-primary" - # resource_group_key = "primary" - # region = "region1" - # } - # } - - # protection_containers = { - # container1 = { - # name = "protection_container1" - # resource_group_key = "primary" - # recovery_fabric_key = "fabric1" - # } - # } + recovery_fabrics = { + fabric1 = { + name = "fabric-primary" + resource_group_key = "primary" + region = "region1" + } + } + + protection_containers = { + container1 = { + name = "protection_container1" + resource_group_key = "primary" + recovery_fabric_key = "fabric1" + } + } } } \ No newline at end of file diff --git a/examples/recovery_vault/main.tf b/examples/recovery_vault/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/recovery_vault/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/redis_cache/README.md b/examples/redis_cache/README.md new file mode 100755 index 0000000000..03049c387d --- /dev/null +++ b/examples/redis_cache/README.md @@ -0,0 +1,13 @@ +# Azure Redis Cache + +This module is part of Cloud Adoption Framework landing zones for Azure on Terraform. + +You can instantiate this directly using the following parameters: + +```hcl +module "caf" { + source = "aztfmod/caf/azurerm" + version = "5.1.0" + # insert the 7 required variables here +} +``` diff --git a/examples/redis_cache/main.tf b/examples/redis_cache/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/redis_cache/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/shared_image_gallery/README.md b/examples/shared_image_gallery/README.md new file mode 100755 index 0000000000..7e658370d5 --- /dev/null +++ b/examples/shared_image_gallery/README.md @@ -0,0 +1,13 @@ +# Azure Shared Image Gallery with Packer + +This module is part of Cloud Adoption Framework landing zones for Azure on Terraform. + +You can instantiate this directly using the following parameters: + +```hcl +module "caf" { + source = "aztfmod/caf/azurerm" + version = "5.1.0" + # insert the 7 required variables here +} +``` diff --git a/examples/shared_image_gallery/main.tf b/examples/shared_image_gallery/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/shared_image_gallery/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/standalone.md b/examples/standalone.md new file mode 100644 index 0000000000..dc28cd908a --- /dev/null +++ b/examples/standalone.md @@ -0,0 +1,199 @@ +# Cloud Adoption Framework for Azure - Standalone module consumption + +You can use this module directly from the Terraform registry using a mininalistic ```main.tf``` as follow: + +```hcl +module "caf" { + source = "aztfmod/caf/azurerm" + version = "5.3.11" + + global_settings = var.global_settings + resource_groups = var.resource_groups + keyvaults = var.keyvaults + + compute = { + virtual_machines = var.virtual_machines + } + + networking = { + public_ip_addresses = var.public_ip_addresses + vnets = var.vnets + } +} +``` + +You will need to declare the ```variables.tf```: + +```hcl +variable "virtual_machines" { + default = {} + description = "Create a virtual machine from CAF module" +} +variable "resource_groups" { + default = {} +} +variable "vnets" { + default = {} +} +variable "public_ip_addresses" { + default = {} +} +variable "keyvaults" { + default = {} +} +variable "global_settings" { + default = {} +} +``` + +You can then feed the module with a ```example.auto.tfvars```: + +```hcl +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } + resource_defaults = { + virtual_machines = { + # set the below to enable az managed boot diagostics for vms + # this will be override if a user managed storage account is defined for the vm + # use_azmanaged_storage_for_boot_diagnostics = true + } + } +} + +resource_groups = { + vm_region1 = { + name = "example-virtual-machine-rg1" + } +} + +# Virtual machines +virtual_machines = { + + # Configuration to deploy a bastion host linux virtual machine + example_vm1 = { + resource_group_key = "vm_region1" + provision_vm_agent = true + # when boot_diagnostics_storage_account_key is empty string "", boot diagnostics will be put on azure managed storage + # when boot_diagnostics_storage_account_key is a non-empty string, it needs to point to the key of a user managed storage defined in diagnostic_storage_accounts + # if boot_diagnostics_storage_account_key is not defined, but global_settings.resource_defaults.virtual_machines.use_azmanaged_storage_for_boot_diagnostics is true, boot diagnostics will be put on azure managed storage + + os_type = "linux" + + # the auto-generated ssh key in keyvault secret. Secret name being {VM name}-ssh-public and {VM name}-ssh-private + keyvault_key = "example_vm_rg1" + + # Define the number of networking cards to attach the virtual machine + networking_interfaces = { + nic0 = { + # Value of the keys from networking.tfvars + vnet_key = "vnet_region1" + subnet_key = "example" + primary = true + name = "0" + enable_ip_forwarding = false + internal_dns_name_label = "nic0" + public_ip_address_key = "example_vm_pip1_rg1" + + } + } + + virtual_machine_settings = { + linux = { + name = "example_vm1" + size = "Standard_F2" + admin_username = "adminuser" + disable_password_authentication = true + + # Spot VM to save money + priority = "Spot" + eviction_policy = "Deallocate" + + # Value of the nic keys to attach the VM. The first one in the list is the default nic + network_interface_keys = ["nic0"] + + os_disk = { + name = "example_vm1-os" + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + identity = { + type = "SystemAssigned" + } + source_image_reference = { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "18.04-LTS" + version = "latest" + } + + } + } + data_disks = { + data1 = { + name = "server1-data1" + storage_account_type = "Standard_LRS" + # Only Empty is supported. More community contributions required to cover other scenarios + create_option = "Empty" + disk_size_gb = "10" + lun = 1 + zones = ["1"] + } + } + } +} + + +keyvaults = { + example_vm_rg1 = { + name = "vmlinuxakv" + resource_group_key = "vm_region1" + sku_name = "standard" + soft_delete_enabled = true + purge_protection_enabled = true + enabled_for_disk_encryption = true + tags = { + env = "Standalone" + } + creation_policies = { + logged_in_user = { + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } +} + + +vnets = { + vnet_region1 = { + resource_group_key = "vm_region1" + vnet = { + name = "virtual_machines" + address_space = ["10.100.100.0/24"] + } + subnets = { + example = { + name = "examples" + cidr = ["10.100.100.0/29"] + } + } + + } +} + +public_ip_addresses = { + example_vm_pip1_rg1 = { + name = "example_vm_pip1" + resource_group_key = "vm_region1" + sku = "Standard" + allocation_method = "Static" + ip_version = "IPv4" + idle_timeout_in_minutes = "4" + + } +} +``` + +For a complete example of standalone consumption of the module, you can use the example inside [./examples](../examples). This example contains the whole variable set to implemente all the examples present in this module. \ No newline at end of file diff --git a/examples/storage_accounts/101-storage-account-with-protection/configuration.tfvars b/examples/storage_accounts/101-storage-account-with-protection/configuration.tfvars new file mode 100755 index 0000000000..f578f4eb29 --- /dev/null +++ b/examples/storage_accounts/101-storage-account-with-protection/configuration.tfvars @@ -0,0 +1,71 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } +} + +resource_groups = { + test = { + name = "test" + } +} + +# https://docs.microsoft.com/en-us/azure/storage/ +storage_accounts = { + sa1 = { + name = "sa1dev" + resource_group_key = "test" + account_kind = "StorageV2" #Valid options are BlobStorage, BlockBlobStorage, FileStorage, Storage and StorageV2. Defaults to StorageV2 + account_tier = "Standard" #Valid options are Standard and Premium. For BlockBlobStorage and FileStorage accounts only Premium is valid + account_replication_type = "LRS" # https://docs.microsoft.com/en-us/azure/storage/common/storage-redundancy + min_tls_version = "TLS1_2" # Possible values are TLS1_0, TLS1_1, and TLS1_2. Defaults to TLS1_0 for new storage accounts. + allow_blob_public_access = false + is_hns_enabled = false + + # Enable this block, if you have a valid domain name + # custom_domain = { + # name = "any-valid-domain.name" #will be validated by Azure + # use_subdomain = true + # } + + enable_system_msi = { + type = "SystemAssigned" + } + + blob_properties = { + delete_retention_policy = { + days = "7" + } + + container_delete_retention_policy = { + days = "7" + } + } + + backup = { + vault_key = "asr1" + } + + tags = { + environment = "dev" + team = "IT" + } + + containers = { + dev = { + name = "random" + } + } + } +} + +recovery_vaults = { + asr1 = { + name = "asr-container-protection" + resource_group_key = "test" + + region = "region1" + + } +} \ No newline at end of file diff --git a/examples/storage_accounts/104-file-share-with-backup/configuration.tfvars b/examples/storage_accounts/104-file-share-with-backup/configuration.tfvars new file mode 100755 index 0000000000..b74eab432b --- /dev/null +++ b/examples/storage_accounts/104-file-share-with-backup/configuration.tfvars @@ -0,0 +1,85 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } +} + +resource_groups = { + test = { + name = "test" + } +} + +# https://docs.microsoft.com/en-us/azure/storage/ +storage_accounts = { + sa1 = { + name = "sa1dev" + resource_group_key = "test" + account_kind = "StorageV2" #Valid options are BlobStorage, BlockBlobStorage, FileStorage, Storage and StorageV2. Defaults to StorageV2 + account_tier = "Standard" #Valid options are Standard and Premium. For BlockBlobStorage and FileStorage accounts only Premium is valid + account_replication_type = "LRS" # https://docs.microsoft.com/en-us/azure/storage/common/storage-redundancy + min_tls_version = "TLS1_2" # Possible values are TLS1_0, TLS1_1, and TLS1_2. Defaults to TLS1_0 for new storage accounts. + large_file_share_enabled = true + + azure_files_authentication = { + directory_type = "AADDS" + } + + file_shares = { + share1 = { + name = "myfileshare" + quota = "10" + + directories = { + dir1 = { + name = "testdirectory" + } + } + + # backups = { + # policy_key = "policy1" + # } + # Issue: https://github.com/terraform-providers/terraform-provider-azurerm/issues/11184 + + } + } + + backup = { + vault_key = "asr1" + # lz_key = "" + } + + tags = { + environment = "dev" + team = "IT" + } + } +} + +recovery_vaults = { + asr1 = { + name = "asr-container-protection" + resource_group_key = "test" + + region = "region1" + backup_policies = { + + fs = { + policy1 = { + name = "FSBackupPolicy1" + vault_key = "asr1" + rg_key = "primary" + timezone = "UTC" + backup = { + frequency = "Daily" + time = "23:00" + } + retention_daily = { + count = 10 + } + } + } + } + } +} \ No newline at end of file diff --git a/examples/storage_accounts/105-nfsv3/configuration.tfvars b/examples/storage_accounts/105-nfsv3/configuration.tfvars new file mode 100755 index 0000000000..aa4c30f7ef --- /dev/null +++ b/examples/storage_accounts/105-nfsv3/configuration.tfvars @@ -0,0 +1,65 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } +} + +resource_groups = { + test = { + name = "test" + } +} + +# https://docs.microsoft.com/en-us/azure/storage/ +storage_accounts = { + sa1 = { + name = "sa1dev" + resource_group_key = "test" + account_kind = "StorageV2" #Valid options are BlobStorage, BlockBlobStorage, FileStorage, Storage and StorageV2. Defaults to StorageV2 + account_tier = "Standard" #Valid options are Standard and Premium. For BlockBlobStorage and FileStorage accounts only Premium is valid + account_replication_type = "LRS" # https://docs.microsoft.com/en-us/azure/storage/common/storage-redundancy + min_tls_version = "TLS1_2" # Possible values are TLS1_0, TLS1_1, and TLS1_2. Defaults to TLS1_0 for new storage accounts. + #enable_https_traffic_only = false #not needed as toggled automatically when nfsv3_enabled is selected. + is_hns_enabled = true + nfsv3_enabled = true + + tags = { + environment = "dev" + team = "IT" + } + + network = { + default_action = "Deny" + subnets = { + subnet1 = { + #lz_key = "" + vnet_key = "vnet1" + subnet_key = "subnet1" + } + #add multiple subnets by extending this block + } + + } + + } +} + +vnets = { + vnet1 = { + resource_group_key = "test" + vnet = { + name = "test-stg" + address_space = ["10.100.100.0/24"] + } + specialsubnets = {} + subnets = { + subnet1 = { + name = "test-stg" + cidr = ["10.100.100.0/29"] + service_endpoints = ["Microsoft.Storage"] + } + } + + } +} \ No newline at end of file diff --git a/examples/storage_accounts/106-storage-account-queue/configuration.tfvars b/examples/storage_accounts/106-storage-account-queue/configuration.tfvars new file mode 100644 index 0000000000..b89ce7d7b6 --- /dev/null +++ b/examples/storage_accounts/106-storage-account-queue/configuration.tfvars @@ -0,0 +1,35 @@ +global_settings = { + default_region = "region1" + regions = { + region1 = "southeastasia" + } +} + +resource_groups = { + test = { + name = "test" + } +} + +#Storage Queue requires a Storage Account to reference +storage_accounts = { + sa1 = { + name = "sa1dev" + resource_group_key = "test" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" # https://docs.microsoft.com/en-us/azure/storage/common/storage-redundancy + tags = { + environment = "dev" + team = "IT" + } + } +} + +# Be sure to declare the Storage Account Queue outside of the Storage Account object +storage_account_queues = { + samplequeue = { + name = "samplequeuename" + storage_account_key = "sa1" + } +} diff --git a/examples/storage_accounts/main.tf b/examples/storage_accounts/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/storage_accounts/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/examples/synapse_analytics/main.tf b/examples/synapse_analytics/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/synapse_analytics/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/landingzones/caf_example/variables.tf b/examples/variables.tf similarity index 66% rename from landingzones/caf_example/variables.tf rename to examples/variables.tf index 3d0a9070d3..f991235021 100755 --- a/landingzones/caf_example/variables.tf +++ b/examples/variables.tf @@ -1,7 +1,6 @@ variable "global_settings" { default = { default_region = "region1" - prefix = null regions = { region1 = "southeastasia" region2 = "eastasia" @@ -27,108 +26,108 @@ variable "provider_azurerm_features_keyvault" { purge_soft_delete_on_destroy = true } } -variable "cloud" { - default = {} -} -variable "acrLoginServerEndpoint" { - default = ".azurecr.io" -} -variable "attestationEndpoint" { - default = ".attest.azure.net" -} -variable "azureDatalakeAnalyticsCatalogAndJobEndpoint" { - default = "azuredatalakeanalytics.net" -} -variable "azureDatalakeStoreFileSystemEndpoint" { - default = "azuredatalakestore.net" -} -variable "keyvaultDns" { - default = ".vault.azure.net" -} -variable "mariadbServerEndpoint" { - default = ".mariadb.database.azure.com" -} -variable "mhsmDns" { - default = ".managedhsm.azure.net" -} -variable "mysqlServerEndpoint" { - default = ".mysql.database.azure.com" -} -variable "postgresqlServerEndpoint" { - default = ".postgres.database.azure.com" -} -variable "sqlServerHostname" { - default = ".database.windows.net" -} -variable "storageEndpoint" { - default = "core.windows.net" -} -variable "storageSyncEndpoint" { - default = "afs.azure.net" -} -variable "synapseAnalyticsEndpoint" { - default = ".dev.azuresynapse.net" -} -variable "activeDirectory" { - default = "https://login.microsoftonline.com" -} -variable "activeDirectoryDataLakeResourceId" { - default = "https://datalake.azure.net/" -} -variable "activeDirectoryGraphResourceId" { - default = "https://graph.windows.net/" -} -variable "activeDirectoryResourceId" { - default = "https://management.core.windows.net/" -} -variable "appInsightsResourceId" { - default = "https://api.applicationinsights.io" -} -variable "appInsightsTelemetryChannelResourceId" { - default = "https://dc.applicationinsights.azure.com/v2/track" -} -variable "attestationResourceId" { - default = "https://attest.azure.net" -} -variable "azmirrorStorageAccountResourceId" { - default = "null" -} -variable "batchResourceId" { - default = "https://batch.core.windows.net/" -} -variable "gallery" { - default = "https://gallery.azure.com/" -} -variable "logAnalyticsResourceId" { - default = "https://api.loganalytics.io" -} -variable "management" { - default = "https://management.core.windows.net/" -} -variable "mediaResourceId" { - default = "https://rest.media.azure.net" -} -variable "microsoftGraphResourceId" { - default = "https://graph.microsoft.com/" -} -variable "ossrdbmsResourceId" { - default = "https://ossrdbms-aad.database.windows.net" -} -variable "portal" { - default = "https://portal.azure.com" -} -variable "resourceManager" { - default = "https://management.azure.com/" -} -variable "sqlManagement" { - default = "https://management.core.windows.net:8443/" -} -variable "synapseAnalyticsResourceId" { - default = "https://dev.azuresynapse.net" -} -variable "vmImageAliasDoc" { - default = "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/arm-compute/quickstart-templates/aliases.json" -} +# variable "cloud" { +# default = {} +# } +# variable "acrLoginServerEndpoint" { +# default = ".azurecr.io" +# } +# variable "attestationEndpoint" { +# default = ".attest.azure.net" +# } +# variable "azureDatalakeAnalyticsCatalogAndJobEndpoint" { +# default = "azuredatalakeanalytics.net" +# } +# variable "azureDatalakeStoreFileSystemEndpoint" { +# default = "azuredatalakestore.net" +# } +# variable "keyvaultDns" { +# default = ".vault.azure.net" +# } +# variable "mariadbServerEndpoint" { +# default = ".mariadb.database.azure.com" +# } +# variable "mhsmDns" { +# default = ".managedhsm.azure.net" +# } +# variable "mysqlServerEndpoint" { +# default = ".mysql.database.azure.com" +# } +# variable "postgresqlServerEndpoint" { +# default = ".postgres.database.azure.com" +# } +# variable "sqlServerHostname" { +# default = ".database.windows.net" +# } +# variable "storageEndpoint" { +# default = "core.windows.net" +# } +# variable "storageSyncEndpoint" { +# default = "afs.azure.net" +# } +# variable "synapseAnalyticsEndpoint" { +# default = ".dev.azuresynapse.net" +# } +# variable "activeDirectory" { +# default = "https://login.microsoftonline.com" +# } +# variable "activeDirectoryDataLakeResourceId" { +# default = "https://datalake.azure.net/" +# } +# variable "activeDirectoryGraphResourceId" { +# default = "https://graph.windows.net/" +# } +# variable "activeDirectoryResourceId" { +# default = "https://management.core.windows.net/" +# } +# variable "appInsightsResourceId" { +# default = "https://api.applicationinsights.io" +# } +# variable "appInsightsTelemetryChannelResourceId" { +# default = "https://dc.applicationinsights.azure.com/v2/track" +# } +# variable "attestationResourceId" { +# default = "https://attest.azure.net" +# } +# variable "azmirrorStorageAccountResourceId" { +# default = "null" +# } +# variable "batchResourceId" { +# default = "https://batch.core.windows.net/" +# } +# variable "gallery" { +# default = "https://gallery.azure.com/" +# } +# variable "logAnalyticsResourceId" { +# default = "https://api.loganalytics.io" +# } +# variable "management" { +# default = "https://management.core.windows.net/" +# } +# variable "mediaResourceId" { +# default = "https://rest.media.azure.net" +# } +# variable "microsoftGraphResourceId" { +# default = "https://graph.microsoft.com/" +# } +# variable "ossrdbmsResourceId" { +# default = "https://ossrdbms-aad.database.windows.net" +# } +# variable "portal" { +# default = "https://portal.azure.com" +# } +# variable "resourceManager" { +# default = "https://management.azure.com/" +# } +# variable "sqlManagement" { +# default = "https://management.core.windows.net:8443/" +# } +# variable "synapseAnalyticsResourceId" { +# default = "https://dev.azuresynapse.net" +# } +# variable "vmImageAliasDoc" { +# default = "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/arm-compute/quickstart-templates/aliases.json" +# } variable "environment" { default = "sandpit" } @@ -145,6 +144,9 @@ variable "tags" { default = null type = map(any) } +variable "subscription_billing_role_assignments" { + default = {} +} variable "app_service_environments" { default = {} } @@ -223,6 +225,21 @@ variable "mssql_mi_secondary_tdes" { variable "storage_accounts" { default = {} } +variable "azuread_credential_policies" { + default = {} +} +variable "azuread_applications" { + default = {} +} +variable "azuread_credentials" { + default = {} +} +variable "azuread_service_principals" { + default = {} +} +variable "azuread_service_principal_passwords" { + default = {} +} variable "azuread_groups" { default = {} } @@ -505,6 +522,27 @@ variable "wvd_workspaces" { variable "wvd_host_pools" { default = {} } +variable "wvd_applications" { + default = {} +} variable "lighthouse_definitions" { default = {} } +variable "dedicated_host_groups" { + default = {} +} +variable "dedicated_hosts" { + default = {} +} +variable "vpn_sites" { + default = {} +} +variable "vpn_gateway_connections" { + default = {} +} +variable "storage_account_queues" { + default = {} +} +variable "storage_account_blobs" { + default = {} +} \ No newline at end of file diff --git a/landingzones/caf_example/vm_extensions.tf b/examples/vm_extensions.tf similarity index 92% rename from landingzones/caf_example/vm_extensions.tf rename to examples/vm_extensions.tf index 820f995b15..0274ba9a7e 100644 --- a/landingzones/caf_example/vm_extensions.tf +++ b/examples/vm_extensions.tf @@ -3,7 +3,7 @@ # module "vm_extension_monitoring_agent" { - source = "../../modules/compute/virtual_machine_extensions" + source = "../modules/compute/virtual_machine_extensions" depends_on = [module.example] for_each = { @@ -21,7 +21,7 @@ module "vm_extension_monitoring_agent" { } module "vm_extension_diagnostics" { - source = "../../modules/compute/virtual_machine_extensions" + source = "../modules/compute/virtual_machine_extensions" depends_on = [module.example] for_each = { @@ -42,7 +42,7 @@ module "vm_extension_diagnostics" { } module "vm_extension_microsoft_azure_domainjoin" { - source = "../../modules/compute/virtual_machine_extensions" + source = "../modules/compute/virtual_machine_extensions" depends_on = [module.example] #refer landingzone.tf for the correct module name. for_each = { @@ -58,7 +58,7 @@ module "vm_extension_microsoft_azure_domainjoin" { } module "vm_extension_session_host_dscextension" { - source = "../../modules/compute/virtual_machine_extensions" + source = "../modules/compute/virtual_machine_extensions" depends_on = [module.example, module.vm_extension_microsoft_azure_domainjoin] #refer landingzone.tf for the correct module name. for_each = { diff --git a/examples/webapps/main.tf b/examples/webapps/main.tf new file mode 100644 index 0000000000..b3c3234b5e --- /dev/null +++ b/examples/webapps/main.tf @@ -0,0 +1,2 @@ +# This is an empty file for Terraform registry visibility. +# For examples on how to consume the CAF module, please refer to https://github.com/aztfmod/terraform-azurerm-caf/tree/master/examples \ No newline at end of file diff --git a/keyvault.tf b/keyvault.tf index 019c63d1cf..d2f516d948 100755 --- a/keyvault.tf +++ b/keyvault.tf @@ -6,12 +6,12 @@ module "keyvaults" { global_settings = local.global_settings client_config = local.client_config settings = each.value - resource_groups = local.resource_groups + resource_groups = local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)] diagnostics = local.combined_diagnostics vnets = local.combined_objects_networking azuread_groups = local.combined_objects_azuread_groups managed_identities = local.combined_objects_managed_identities - base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} + base_tags = try(local.global_settings.inherit_tags, false) ? local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].tags : {} private_dns = local.combined_objects_private_dns } @@ -35,6 +35,7 @@ module "keyvault_access_policies" { mssql_managed_instances_secondary = local.combined_objects_mssql_managed_instances_secondary storage_accounts = local.combined_objects_storage_accounts diagnostic_storage_accounts = local.combined_objects_diagnostic_storage_accounts + azuread_service_principals = local.combined_objects_azuread_service_principals } } @@ -49,7 +50,7 @@ module "keyvault_access_policies_azuread_apps" { keyvaults = local.combined_objects_keyvaults access_policies = each.value client_config = local.client_config - azuread_apps = local.combined_objects_azuread_applications + azuread_apps = local.combined_objects_azuread_apps } diff --git a/keyvault_certificate_issuers.tf b/keyvault_certificate_issuers.tf index c51c1b2aca..1ecaff4de8 100755 --- a/keyvault_certificate_issuers.tf +++ b/keyvault_certificate_issuers.tf @@ -3,12 +3,12 @@ module "keyvault_certificate_issuers" { depends_on = [module.keyvaults] for_each = local.security.keyvault_certificate_issuers - resource_group_name = local.resource_groups[each.value.resource_group_key].name - location = local.resource_groups[each.value.resource_group_key].location + resource_group_name = local.combined_objects_resource_groups[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.resource_group_key].name + location = local.combined_objects_resource_groups[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.resource_group_key].location global_settings = local.global_settings settings = each.value keyvault_id = try(local.combined_objects_keyvaults[each.value.lz_key][each.value.keyvault_key].id, local.combined_objects_keyvaults[local.client_config.landingzone_key][each.value.keyvault_key].id) - base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} + base_tags = try(local.global_settings.inherit_tags, false) ? local.combined_objects_resource_groups[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.resource_group_key].tags : {} password = try(data.azurerm_key_vault_secret.certificate_issuer_password[each.key].value, each.value.cert_issuer_password) } diff --git a/landingzones/caf_example/README.md b/landingzones/caf_example/README.md deleted file mode 100755 index 379d6303d5..0000000000 --- a/landingzones/caf_example/README.md +++ /dev/null @@ -1,238 +0,0 @@ -# Cloud Adoption Framework for Azure - Terraform module examples - -Getting started with examples, once you have cloned this repository locally - -## Deploying examples with Terraform - -Each module can be deployed outside of the rover using native Terraform. - -You can instantiate this directly using the following syntax: - -```hcl -module "caf" { - source = "aztfmod/caf/azurerm" - version = "5.1.0" - # insert the 7 required variables here -} -``` - -Please refer to the instructions within each example directory, whenever you have a /standalone subdirectory. - - -## Deploying examples with rover - -To get started with the deployment within rover, follow the steps: - -1. Log in the subscription with the rover - -```bash -rover login -### you can alternatively specify the tenant space and subscription ID on command line arguments: -rover login --tenant .onmicrosoft.com -s -``` - -2. Deploy the basic launchpad - -```bash -rover -lz /tf/caf/public/landingzones/caf_launchpad \ --launchpad \ --var-folder /tf/caf/public/landingzones/caf_launchpad/scenario/100 \ --a apply -``` - -3. Test your example - -```bash -rover -lz /tf/caf/landingzones/caf_example \ --var-folder /tf/caf/examples/ \ --a plan|apply -``` - -## Developing and testing module for landing zones - -Use those instructions only if you want to test, and develop features for landing zones with this module. You will need to add landing zones locally: - -1. Clone the Azure landing zones repo - -```bash -git clone --branch https://github.com/Azure/caf-terraform-landingzones.git /tf/caf/public -``` - -This will clone the logic of landing zones in your local repository without committing your landing zones changes (we have put for you a filter on /public for landing zones.) - -2. Change the module path in your landing zone - -By default the landing zone will source the module from the registry. - -For each landing zone you want to edit, go to the ```landingzone.tf``` file: - -``` -module "networking" { - source = "aztfmod/caf/azurerm" - version = "~> 0.4" -``` - -You can replace it with your local path, typically here: - -``` -module "networking" { - source = "../../.." -``` - -You should now be able to run landing zones as usual, except it will source the module locally, so you can test the features you introduced in the module. - -## Using the examples - -You can customize the examples execution by modifying the variables as follow: - - -## Requirements - -| Name | Version | -|------|---------| -| terraform | >= 0.13 | - -## Providers - -No provider. - -## Modules - -| Name | Source | Version | -|------|--------|---------| -| example | ../.. | | -| vm_extension_diagnostics | ../../modules/compute/virtual_machine_extensions | | -| vm_extension_monitoring_agent | ../../modules/compute/virtual_machine_extensions | | - -## Resources - -No resources. - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| aks\_clusters | n/a | `map` | `{}` | no | -| app\_service\_environments | n/a | `map` | `{}` | no | -| app\_service\_plans | n/a | `map` | `{}` | no | -| app\_services | n/a | `map` | `{}` | no | -| application\_gateway\_applications | n/a | `map` | `{}` | no | -| application\_gateways | n/a | `map` | `{}` | no | -| application\_security\_groups | n/a | `map` | `{}` | no | -| automations | n/a | `map` | `{}` | no | -| availability\_sets | n/a | `map` | `{}` | no | -| azure\_container\_registries | n/a | `map` | `{}` | no | -| azuread\_api\_permissions | n/a | `map` | `{}` | no | -| azuread\_apps | n/a | `map(any)` | `{}` | no | -| azuread\_groups | n/a | `map` | `{}` | no | -| azuread\_roles | n/a | `map` | `{}` | no | -| azuread\_users | n/a | `map(any)` | `{}` | no | -| azurerm\_application\_insights | n/a | `map` | `{}` | no | -| azurerm\_firewall\_application\_rule\_collection\_definition | n/a | `map` | `{}` | no | -| azurerm\_firewall\_nat\_rule\_collection\_definition | n/a | `map` | `{}` | no | -| azurerm\_firewall\_network\_rule\_collection\_definition | n/a | `map` | `{}` | no | -| azurerm\_firewall\_policies | n/a | `map` | `{}` | no | -| azurerm\_firewall\_policy\_rule\_collection\_groups | n/a | `map` | `{}` | no | -| azurerm\_firewalls | n/a | `map` | `{}` | no | -| azurerm\_redis\_caches | n/a | `map` | `{}` | no | -| azurerm\_routes | n/a | `map` | `{}` | no | -| bastion\_hosts | n/a | `map` | `{}` | no | -| container\_groups | n/a | `map` | `{}` | no | -| cosmos\_db | n/a | `map` | `{}` | no | -| cosmos\_dbs | n/a | `map` | `{}` | no | -| custom\_role\_definitions | n/a | `map` | `{}` | no | -| databricks\_workspaces | n/a | `map` | `{}` | no | -| diagnostic\_event\_hub\_namespaces | n/a | `map` | `{}` | no | -| diagnostic\_log\_analytics | n/a | `map` | `{}` | no | -| diagnostic\_storage\_accounts | n/a | `map` | `{}` | no | -| diagnostics\_definition | n/a | `any` | `null` | no | -| diagnostics\_destinations | n/a | `map` | `{}` | no | -| disk\_encryption\_sets | n/a | `map` | `{}` | no | -| dns\_zone\_records | n/a | `map` | `{}` | no | -| dns\_zones | n/a | `map` | `{}` | no | -| domain\_name\_registrations | n/a | `map` | `{}` | no | -| dynamic\_keyvault\_secrets | n/a | `map` | `{}` | no | -| environment | n/a | `string` | `"sandpit"` | no | -| event\_hub\_auth\_rules | n/a | `map` | `{}` | no | -| event\_hub\_consumer\_groups | n/a | `map` | `{}` | no | -| event\_hub\_namespace\_auth\_rules | n/a | `map` | `{}` | no | -| event\_hub\_namespaces | n/a | `map` | `{}` | no | -| event\_hubs | n/a | `map` | `{}` | no | -| express\_route\_circuit\_authorizations | n/a | `map` | `{}` | no | -| express\_route\_circuits | n/a | `map` | `{}` | no | -| front\_door\_waf\_policies | n/a | `map` | `{}` | no | -| front\_doors | n/a | `map` | `{}` | no | -| global\_settings | n/a | `map` |
{
"default_region": "region1",
"prefix": null,
"regions": {
"region1": "southeastasia",
"region2": "eastasia"
}
}
| no | -| image\_definitions | n/a | `map` | `{}` | no | -| ip\_groups | n/a | `map` | `{}` | no | -| keyvault\_access\_policies | n/a | `map` | `{}` | no | -| keyvault\_access\_policies\_azuread\_apps | n/a | `map` | `{}` | no | -| keyvault\_certificate\_issuers | n/a | `map` | `{}` | no | -| keyvault\_certificate\_requests | n/a | `map` | `{}` | no | -| keyvault\_certificates | n/a | `map` | `{}` | no | -| keyvault\_keys | n/a | `map` | `{}` | no | -| keyvaults | n/a | `map` | `{}` | no | -| landingzone | n/a | `map` |
{
"backend_type": "azurerm",
"global_settings_key": "launchpad",
"key": "examples",
"level": "level0"
}
| no | -| lighthouse\_definitions | n/a | `map` | `{}` | no | -| load\_balancers | n/a | `map` | `{}` | no | -| local\_network\_gateways | n/a | `map` | `{}` | no | -| log\_analytics | n/a | `map` | `{}` | no | -| logged\_aad\_app\_objectId | n/a | `any` | `null` | no | -| logged\_user\_objectId | n/a | `any` | `null` | no | -| machine\_learning\_workspaces | n/a | `map` | `{}` | no | -| managed\_identities | n/a | `map` | `{}` | no | -| mariadb\_databases | n/a | `map` | `{}` | no | -| mariadb\_servers | n/a | `map` | `{}` | no | -| monitoring | n/a | `map` | `{}` | no | -| mssql\_databases | n/a | `map` | `{}` | no | -| mssql\_elastic\_pools | n/a | `map` | `{}` | no | -| mssql\_failover\_groups | n/a | `map` | `{}` | no | -| mssql\_managed\_databases | n/a | `map` | `{}` | no | -| mssql\_managed\_databases\_backup\_ltr | n/a | `map` | `{}` | no | -| mssql\_managed\_databases\_restore | n/a | `map` | `{}` | no | -| mssql\_managed\_instances | n/a | `map` | `{}` | no | -| mssql\_managed\_instances\_secondary | n/a | `map` | `{}` | no | -| mssql\_mi\_administrators | n/a | `map` | `{}` | no | -| mssql\_mi\_failover\_groups | n/a | `map` | `{}` | no | -| mssql\_mi\_secondary\_tdes | n/a | `map` | `{}` | no | -| mssql\_mi\_tdes | n/a | `map` | `{}` | no | -| mssql\_servers | n/a | `map` | `{}` | no | -| mysql\_servers | n/a | `map` | `{}` | no | -| netapp\_accounts | n/a | `map` | `{}` | no | -| network\_security\_group\_definition | n/a | `map` | `{}` | no | -| network\_watchers | n/a | `map` | `{}` | no | -| packer\_managed\_identity | n/a | `map` | `{}` | no | -| packer\_service\_principal | n/a | `map` | `{}` | no | -| postgresql\_servers | n/a | `map` | `{}` | no | -| private\_dns | n/a | `map` | `{}` | no | -| private\_endpoints | n/a | `map` | `{}` | no | -| provider\_azurerm\_features\_keyvault | n/a | `map` |
{
"purge_soft_delete_on_destroy": true
}
| no | -| proximity\_placement\_groups | n/a | `map` | `{}` | no | -| public\_ip\_addresses | n/a | `map` | `{}` | no | -| recovery\_vaults | n/a | `map` | `{}` | no | -| resource\_groups | n/a | `map` | `{}` | no | -| role\_mapping | n/a | `map` | `{}` | no | -| route\_tables | n/a | `map` | `{}` | no | -| rover\_version | n/a | `any` | `null` | no | -| shared\_image\_galleries | n/a | `map` | `{}` | no | -| storage\_accounts | n/a | `map` | `{}` | no | -| synapse\_workspaces | n/a | `map` | `{}` | no | -| tags | n/a | `map(any)` | `null` | no | -| var\_folder\_path | n/a | `map` | `{}` | no | -| vhub\_peerings | Use virtual\_hub\_connections instead of vhub\_peerings. It will be removed in version 6.0 | `map` | `{}` | no | -| virtual\_hub\_connections | n/a | `map` | `{}` | no | -| virtual\_hub\_er\_gateway\_connections | n/a | `map` | `{}` | no | -| virtual\_hub\_route\_tables | n/a | `map` | `{}` | no | -| virtual\_machines | n/a | `map` | `{}` | no | -| virtual\_network\_gateway\_connections | n/a | `map` | `{}` | no | -| virtual\_network\_gateways | n/a | `map` | `{}` | no | -| virtual\_wans | n/a | `map` | `{}` | no | -| vnet\_peerings | n/a | `map` | `{}` | no | -| vnets | n/a | `map` | `{}` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| objects | n/a | - diff --git a/load_balancers.tf b/load_balancers.tf index a1e36a1eb6..707f0ce521 100755 --- a/load_balancers.tf +++ b/load_balancers.tf @@ -2,8 +2,8 @@ module "load_balancers" { source = "./modules/networking/load_balancers" for_each = try(local.networking.load_balancers, {}) - resource_group_name = local.resource_groups[each.value.resource_group_key].name - location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] + resource_group_name = local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].name + location = lookup(each.value, "region", null) == null ? local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].location : local.global_settings.regions[each.value.region] public_ip_addresses = local.combined_objects_public_ip_addresses client_config = local.client_config vnets = local.combined_objects_networking @@ -11,7 +11,7 @@ module "load_balancers" { diagnostics = local.combined_diagnostics global_settings = local.global_settings settings = each.value - base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} + base_tags = try(local.global_settings.inherit_tags, false) ? local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].tags : {} existing_resources = { virtual_machines = try(module.virtual_machines, {}) #vm scale set will be added later diff --git a/locals.combined_objects.tf b/locals.combined_objects.tf index 8f7aa4bf18..587d1c2889 100644 --- a/locals.combined_objects.tf +++ b/locals.combined_objects.tf @@ -11,13 +11,18 @@ locals { combined_objects_application_security_groups = merge(tomap({ (local.client_config.landingzone_key) = module.application_security_groups }), try(var.remote_objects.application_security_groups, {})) combined_objects_availability_sets = merge(tomap({ (local.client_config.landingzone_key) = module.availability_sets }), try(var.remote_objects.availability_sets, {})) combined_objects_azure_container_registries = merge(tomap({ (local.client_config.landingzone_key) = module.container_registry }), try(var.remote_objects.container_registry, {})) - combined_objects_azuread_applications = merge(tomap({ (local.client_config.landingzone_key) = module.azuread_applications }), try(var.remote_objects.azuread_applications, {})) + combined_objects_azuread_apps = merge(tomap({ (local.client_config.landingzone_key) = module.azuread_applications }), try(var.remote_objects.azuread_apps, {})) + combined_objects_azuread_applications = merge(tomap({ (local.client_config.landingzone_key) = module.azuread_applications_v1 }), try(var.remote_objects.azuread_applications, {})) + combined_objects_azuread_service_principals = merge(tomap({ (local.client_config.landingzone_key) = module.azuread_service_principals }), try(var.remote_objects.azuread_service_principals, {})) combined_objects_azuread_groups = merge(tomap({ (local.client_config.landingzone_key) = module.azuread_groups }), try(var.remote_objects.azuread_groups, {})) combined_objects_azuread_users = merge(tomap({ (local.client_config.landingzone_key) = module.azuread_users }), try(var.remote_objects.azuread_users, {})) combined_objects_azurerm_firewalls = merge(tomap({ (local.client_config.landingzone_key) = module.azurerm_firewalls }), try(var.remote_objects.azurerm_firewalls, {})) + combined_objects_container_registry = merge(tomap({ (local.client_config.landingzone_key) = module.container_registry }), try(var.remote_objects.container_registry, {})) combined_objects_diagnostic_storage_accounts = merge(tomap({ (local.client_config.landingzone_key) = module.diagnostic_storage_accounts }), try(var.remote_objects.diagnostic_storage_accounts, {})) combined_objects_disk_encryption_sets = merge(tomap({ (local.client_config.landingzone_key) = module.disk_encryption_sets }), try(var.remote_objects.disk_encryption_sets, {})) combined_objects_dns_zones = merge(tomap({ (local.client_config.landingzone_key) = module.dns_zones }), try(var.remote_objects.dns_zones, {})) + combined_objects_dedicated_hosts = merge(tomap({ (local.client_config.landingzone_key) = module.dedicated_hosts }), try(var.remote_objects.dedicated_hosts, {})) + combined_objects_dedicated_host_groups = merge(tomap({ (local.client_config.landingzone_key) = module.dedicated_host_groups }), try(var.remote_objects.dedicated_host_groups, {})) combined_objects_event_hub_namespaces = merge(tomap({ (local.client_config.landingzone_key) = module.event_hub_namespaces }), try(var.remote_objects.event_hub_namespaces, {})) combined_objects_front_door_waf_policies = merge(tomap({ (local.client_config.landingzone_key) = module.front_door_waf_policies }), try(var.remote_objects.front_door_waf_policies, {})) combined_objects_integration_service_environment = merge(tomap({ (local.client_config.landingzone_key) = module.integration_service_environment }), try(var.remote_objects.integration_service_environment, {})) @@ -36,17 +41,17 @@ locals { combined_objects_mssql_managed_instances_secondary = merge(tomap({ (local.client_config.landingzone_key) = module.mssql_managed_instances_secondary }), try(var.remote_objects.mssql_managed_instances_secondary, {})) combined_objects_mssql_servers = merge(tomap({ (local.client_config.landingzone_key) = module.mssql_servers }), try(var.remote_objects.mssql_servers, {})) combined_objects_mysql_servers = merge(tomap({ (local.client_config.landingzone_key) = module.mysql_servers }), try(var.remote_objects.mysql_servers, {})) + combined_objects_network_security_groups = merge(tomap({ (local.client_config.landingzone_key) = module.network_security_groups }), try(var.remote_objects.network_security_groups, {})) combined_objects_network_watchers = merge(tomap({ (local.client_config.landingzone_key) = module.network_watchers }), try(var.remote_objects.network_watchers, {})) combined_objects_networking = merge(tomap({ (local.client_config.landingzone_key) = module.networking }), try(var.remote_objects.vnets, {})) combined_objects_postgresql_servers = merge(tomap({ (local.client_config.landingzone_key) = module.postgresql_servers }), try(var.remote_objects.postgresql_servers, {})) - combined_objects_network_security_groups = merge(tomap({ (local.client_config.landingzone_key) = module.network_security_groups }), try(var.remote_objects.network_security_groups, {})) + combined_objects_azurerm_firewall_policies = merge(tomap({ (local.client_config.landingzone_key) = module.azurerm_firewall_policies }), try(var.remote_objects.azurerm_firewall_policies, {})) combined_objects_private_dns = merge(tomap({ (local.client_config.landingzone_key) = module.private_dns }), try(var.remote_objects.private_dns, {})) combined_objects_proximity_placement_groups = merge(tomap({ (local.client_config.landingzone_key) = module.proximity_placement_groups }), try(var.remote_objects.proximity_placement_groups, {})) combined_objects_public_ip_addresses = merge(tomap({ (local.client_config.landingzone_key) = module.public_ip_addresses }), try(var.remote_objects.public_ip_addresses, {})) combined_objects_recovery_vaults = merge(tomap({ (local.client_config.landingzone_key) = module.recovery_vaults }), try(var.remote_objects.recovery_vaults, {})) combined_objects_resource_groups = merge(tomap({ (local.client_config.landingzone_key) = local.resource_groups }), try(var.remote_objects.resource_groups, {})) combined_objects_storage_accounts = merge(tomap({ (local.client_config.landingzone_key) = module.storage_accounts }), try(var.remote_objects.storage_accounts, {})) - combined_objects_subscriptions = merge(tomap({ (local.client_config.landingzone_key) = module.subscriptions }), try(var.remote_objects.subscriptions, {})) combined_objects_synapse_workspaces = merge(tomap({ (local.client_config.landingzone_key) = module.synapse_workspaces }), try(var.remote_objects.synapse_workspaces, {})) combined_objects_virtual_machines = merge(tomap({ (local.client_config.landingzone_key) = module.virtual_machines }), try(var.remote_objects.virtual_machines, {})) combined_objects_virtual_machine_scale_sets = merge(tomap({ (local.client_config.landingzone_key) = module.virtual_machine_scale_sets }), try(var.remote_objects.virtual_machine_scale_sets, {})) @@ -54,7 +59,23 @@ locals { combined_objects_virtual_hub_route_tables = merge(tomap({ (local.client_config.landingzone_key) = azurerm_virtual_hub_route_table.route_table }), try(var.remote_objects.virtual_hub_route_tables, {})) combined_objects_virtual_hubs = merge(tomap({ (local.client_config.landingzone_key) = module.virtual_hubs }), try(var.remote_objects.virtual_hubs, {})) combined_objects_virtual_wans = merge(tomap({ (local.client_config.landingzone_key) = module.virtual_wans }), try(var.remote_objects.virtual_wans, {})) + combined_objects_vpn_gateway_connections = merge(tomap({ (local.client_config.landingzone_key) = module.vpn_gateway_connections }), try(var.remote_objects.vpn_gateway_connections, {})) + combined_objects_vpn_sites = merge(tomap({ (local.client_config.landingzone_key) = module.vpn_sites }), try(var.remote_objects.vpn_sites, {})) + combined_objects_wvd_applications = merge(tomap({ (local.client_config.landingzone_key) = module.wvd_applications }), try(var.remote_objects.wvd_applications, {})) combined_objects_wvd_application_groups = merge(tomap({ (local.client_config.landingzone_key) = module.wvd_application_groups }), try(var.remote_objects.wvd_application_groups, {})) combined_objects_wvd_host_pools = merge(tomap({ (local.client_config.landingzone_key) = module.wvd_host_pools }), try(var.remote_objects.wvd_host_pools, {})) combined_objects_wvd_workspaces = merge(tomap({ (local.client_config.landingzone_key) = module.wvd_workspaces }), try(var.remote_objects.wvd_workspaces, {})) + + combined_objects_subscriptions = merge( + tomap( + { + (local.client_config.landingzone_key) = merge( + try(module.subscriptions, {}), + { ("logged_in_subscription") = { id = data.azurerm_subscription.primary.id } } + ) + } + ), + try(var.remote_objects.subscriptions, {}) + ) + } diff --git a/locals.tf b/locals.tf index caf88c8d12..a93a564798 100755 --- a/locals.tf +++ b/locals.tf @@ -7,6 +7,20 @@ resource "random_string" "prefix" { } locals { + azuread = { + azuread_api_permissions = try(var.azuread.azuread_api_permissions, {}) + azuread_applications = try(var.azuread.azuread_applications, {}) + azuread_apps = try(var.azuread.azuread_apps, {}) + azuread_credential_policies = try(var.azuread.azuread_credential_policies, {}) + azuread_credentials = try(var.azuread.azuread_credentials, {}) + azuread_groups = try(var.azuread.azuread_groups, {}) + azuread_groups_membership = try(var.azuread.azuread_groups_membership, {}) + azuread_roles = try(var.azuread.azuread_roles, {}) + azuread_service_principal_passwords = try(var.azuread.azuread_service_principal_passwords, {}) + azuread_service_principals = try(var.azuread.azuread_service_principals, {}) + azuread_users = try(var.azuread.azuread_users, {}) + } + client_config = var.client_config == {} ? { client_id = data.azurerm_client_config.current.client_id landingzone_key = var.current_landingzone_key @@ -59,7 +73,10 @@ locals { azure_container_registries = try(var.compute.azure_container_registries, {}) bastion_hosts = try(var.compute.bastion_hosts, {}) container_groups = try(var.compute.container_groups, {}) + dedicated_hosts = try(var.compute.dedicated_hosts, {}) + dedicated_host_groups = try(var.compute.dedicated_host_groups, {}) proximity_placement_groups = try(var.compute.proximity_placement_groups, {}) + wvd_applications = try(var.compute.wvd_applications, {}) wvd_application_groups = try(var.compute.wvd_application_groups, {}) wvd_host_pools = try(var.compute.wvd_host_pools, {}) wvd_workspaces = try(var.compute.wvd_workspaces, {}) @@ -138,17 +155,15 @@ locals { } global_settings = merge({ - default_region = try(var.global_settings.default_region, "region1") - environment = try(var.global_settings.environment, var.environment) - inherit_tags = try(var.global_settings.inherit_tags, false) - passthrough = try(var.global_settings.passthrough, false) - prefix = try(var.global_settings.prefix, null) - # prefix_with_hyphen = try(var.global_settings.prefix_with_hyphen, format("%s-", try(var.global_settings.prefixes[0], random_string.prefix.0.result))) - # prefixes = var.global_settings.prefix == "" ? null : try(var.global_settings.prefixes, [random_string.prefix.0.result]) + default_region = try(var.global_settings.default_region, "region1") + environment = try(var.global_settings.environment, var.environment) + inherit_tags = try(var.global_settings.inherit_tags, false) + passthrough = try(var.global_settings.passthrough, false) + prefix = try(var.global_settings.prefix, null) prefix_with_hyphen = try(var.global_settings.prefix_with_hyphen, format("%s-", try(var.global_settings.prefix, try(var.global_settings.prefixes[0], random_string.prefix.0.result)))) prefixes = try(var.global_settings.prefix, null) == "" ? null : try([var.global_settings.prefix], try(var.global_settings.prefixes, [random_string.prefix.0.result])) random_length = try(var.global_settings.random_length, 0) - regions = var.global_settings.regions + regions = try(var.global_settings.regions, null) tags = try(var.global_settings.tags, null) use_slug = try(var.global_settings.use_slug, true) }, var.global_settings) @@ -202,6 +217,8 @@ locals { virtual_wans = try(var.networking.virtual_wans, {}) vnet_peerings = try(var.networking.vnet_peerings, {}) vnets = try(var.networking.vnets, {}) + vpn_gateway_connections = try(var.networking.vpn_gateway_connections, {}) + vpn_sites = try(var.networking.vpn_sites, {}) } object_id = coalesce(var.logged_user_objectId, var.logged_aad_app_objectId, try(data.azurerm_client_config.current.object_id, null), try(data.azuread_service_principal.logged_in_app.0.object_id, null)) @@ -227,8 +244,9 @@ locals { } storage = { - netapp_accounts = try(var.storage.netapp_accounts, {}) - storage_account_blobs = try(var.storage.storage_account_blobs, {}) + netapp_accounts = try(var.storage.netapp_accounts, {}) + storage_account_blobs = try(var.storage.storage_account_blobs, {}) + storage_account_queues = try(var.storage.storage_account_queues, {}) } webapp = { diff --git a/machine_learning.tf b/machine_learning.tf index 4ce984a7be..85ce0b6d73 100755 --- a/machine_learning.tf +++ b/machine_learning.tf @@ -11,11 +11,11 @@ module "machine_learning_workspaces" { storage_account_id = lookup(each.value, "storage_account_key") == null ? null : module.storage_accounts[each.value.storage_account_key].id keyvault_id = lookup(each.value, "keyvault_key") == null ? null : module.keyvaults[each.value.keyvault_key].id application_insights_id = lookup(each.value, "application_insights_key") == null ? null : module.azurerm_application_insights[each.value.application_insights_key].id + container_registry_id = try(each.value.container_registry_key, null) == null ? null : try(local.combined_objects_container_registry[each.value.lz_key][each.value.container_registry_key].id, local.combined_objects_container_registry[local.client_config.landingzone_key][each.value.container_registry_key].id) base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} } output "machine_learning_workspaces" { value = module.machine_learning_workspaces - } diff --git a/main.tf b/main.tf index 7aba315ca9..467a050ac8 100755 --- a/main.tf +++ b/main.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "~> 2.55.0" + version = "~> 2.64.0" } azuread = { source = "hashicorp/azuread" @@ -40,7 +40,7 @@ data "azurerm_client_config" "current" {} # 1 - running launchpad from vscode # In this bootstrap scenario the launchpad is executed under a logged in user azure session. The rover sets the logged_user_objectId through environment variable. During that initial run an Azure AD application (refered as launchpad_app_level0) is created to support any execution from a pipeline. # 2 - deploying a landing zone or a solution from vscode -# Step 1 has been executed. The rover is still connect to a logged in user azure session. The rover use the user's credentials to connect the default azure subscription to identity the storage account and the keyvault holding the tfstate and the launchpad_app_level0 credentials. The rover set the terraform ARM_* variables to change the terraform provider Azure context (client id, secret, tenant and subscription). The logged_aad_app_objectId is set to the launchpad_app_level0's client_id. Note in that scenario the azure session does not change. Meaning when terraform execute some local execution scripts they are executed in the context of the logged_in_user and not the azure ad application. To simulate from vscode the execution of a local exec with the launchpad_app_level0 credentials, the rover must be executed with the parameter --impersonate (cannot be used during the launchpad initial deployment and destruciton) +# Step 1 has been executed. The rover is still connected to a logged in user azure session. The rover use the user's credentials to connect the default azure subscription to identity the storage account and the keyvault holding the tfstate and the launchpad_app_level0 credentials. The rover set the terraform ARM_* variables to change the terraform provider Azure context (client id, secret, tenant and subscription). The logged_aad_app_objectId is set to the launchpad_app_level0's client_id. Note in that scenario the azure session does not change. Meaning when terraform execute some local execution scripts they are executed in the context of the logged_in_user and not the azure ad application. To simulate from vscode the execution of a local exec with the launchpad_app_level0 credentials, the rover must be executed with the parameter --impersonate (cannot be used during the launchpad initial deployment and destruciton) data "azuread_service_principal" "logged_in_app" { diff --git a/modules/analytics/databricks_workspace/workspace.tf b/modules/analytics/databricks_workspace/workspace.tf index 5a7362ec0a..0fe6a36dc4 100644 --- a/modules/analytics/databricks_workspace/workspace.tf +++ b/modules/analytics/databricks_workspace/workspace.tf @@ -1,5 +1,7 @@ -# naming convention -#TODO rename object from wp to ws for consistency + +# Tested with : AzureRM version 2.57.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace + resource "azurecaf_name" "wp" { name = var.settings.name resource_type = "azurerm_databricks_workspace" @@ -10,7 +12,8 @@ resource "azurecaf_name" "wp" { use_slug = var.global_settings.use_slug } -# Databricks workspace + + resource "azurerm_databricks_workspace" "ws" { name = azurecaf_name.wp.result resource_group_name = var.resource_group_name diff --git a/modules/analytics/machine_learning/variables.tf b/modules/analytics/machine_learning/variables.tf index 63174622b1..51659d627f 100755 --- a/modules/analytics/machine_learning/variables.tf +++ b/modules/analytics/machine_learning/variables.tf @@ -52,4 +52,8 @@ variable "base_tags" { variable "vnets" { description = "Virtual networks objects - contains all virtual networks that could potentially be used by the module." +} + +variable "container_registry_id" { + default = "" } \ No newline at end of file diff --git a/modules/analytics/machine_learning/workspace.tf b/modules/analytics/machine_learning/workspace.tf index a8fa6b5c31..91f59d7233 100644 --- a/modules/analytics/machine_learning/workspace.tf +++ b/modules/analytics/machine_learning/workspace.tf @@ -9,7 +9,9 @@ resource "azurecaf_name" "ws" { use_slug = var.global_settings.use_slug } -# ML Workspace +# Tested with : AzureRM version 2.57.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/machine_learning_workspace + resource "azurerm_machine_learning_workspace" "ws" { name = azurecaf_name.ws.result location = var.location @@ -17,8 +19,12 @@ resource "azurerm_machine_learning_workspace" "ws" { application_insights_id = var.application_insights_id key_vault_id = var.keyvault_id storage_account_id = var.storage_account_id + container_registry_id = var.container_registry_id tags = try(local.tags, null) sku_name = try(var.settings.sku_name, "Basic") + description = try(var.settings.description, null) + friendly_name = try(var.settings.friendly_name, null) + high_business_impact = try(var.settings.high_business_impact, null) identity { #Hardcoded as the only supported value is SystemAssigned as per azurerm 2.40 diff --git a/modules/analytics/synapse/spark_pool/spark_pool.tf b/modules/analytics/synapse/spark_pool/spark_pool.tf index ebc5b05dc6..fe1f6aff27 100644 --- a/modules/analytics/synapse/spark_pool/spark_pool.tf +++ b/modules/analytics/synapse/spark_pool/spark_pool.tf @@ -8,11 +8,18 @@ resource "azurecaf_name" "sparkpool" { use_slug = var.global_settings.use_slug } +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/synapse_spark_pool +# Tested with: AzureRM provider 2.57.0 + resource "azurerm_synapse_spark_pool" "spark_pool" { name = azurecaf_name.sparkpool.result synapse_workspace_id = var.synapse_workspace_id node_size_family = var.settings.node_size_family node_size = var.settings.node_size + node_count = try(var.settings.node_count, null) + spark_log_folder = try(var.settings.spark_log_folder, "/logs") + spark_events_folder = try(var.settings.spark_events_folder, "/events") + spark_version = try(var.settings.spark_version, "2.4") auto_scale { max_node_count = var.settings.auto_scale.max_node_count @@ -23,6 +30,15 @@ resource "azurerm_synapse_spark_pool" "spark_pool" { delay_in_minutes = var.settings.auto_pause.delay_in_minutes } + dynamic "library_requirement" { + for_each = try(var.settings.library_requirement, {}) + + content { + content = var.settings.library_requirement.content + filename = var.settings.library_requirement.filename + } + } + tags = local.tags } diff --git a/modules/analytics/synapse/workspace.tf b/modules/analytics/synapse/workspace.tf index 3dddc46271..85439034f8 100644 --- a/modules/analytics/synapse/workspace.tf +++ b/modules/analytics/synapse/workspace.tf @@ -9,7 +9,8 @@ resource "azurecaf_name" "ws" { use_slug = var.global_settings.use_slug } -# synapse workspace +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/synapse_workspace +# Tested with : AzureRM 2.57.0 resource "azurerm_synapse_workspace" "ws" { name = azurecaf_name.ws.result resource_group_name = var.resource_group_name @@ -17,7 +18,46 @@ resource "azurerm_synapse_workspace" "ws" { storage_data_lake_gen2_filesystem_id = var.storage_data_lake_gen2_filesystem_id sql_administrator_login = var.settings.sql_administrator_login sql_administrator_login_password = try(var.settings.sql_administrator_login_password, random_password.sql_admin.0.result) + managed_virtual_network_enabled = try(var.settings.managed_virtual_network_enabled, false) + sql_identity_control_enabled = try(var.settings.sql_identity_control_enabled, null) + managed_resource_group_name = try(var.settings.managed_resource_group_name, null) + customer_managed_key_versionless_id = try(var.settings.customer_managed_key_versionless_id, null) tags = local.tags + + dynamic "aad_admin" { + for_each = try(var.settings.aad_admin, {}) + + content { + login = var.settings.aad_admin.login + object_id = var.settings.aad_admin.object_id + tenant_id = var.settings.aad_admin.tenant_id + } + } + + dynamic "azure_devops_repo" { + for_each = try(var.settings.azure_devops_repo, {}) + + content { + account_name = var.settings.azure_devops_repo.account_name + branch_name = var.settings.azure_devops_repo.branch_name + project_name = var.settings.azure_devops_repo.project_name + repository_name = var.settings.azure_devops_repo.branch_name + root_folder = var.settings.azure_devops_repo.root_folder + } + } + + dynamic "github_repo" { + for_each = try(var.settings.github_repo, {}) + + content { + account_name = var.settings.github_repo.account_name + branch_name = var.settings.github_repo.project_name + repository_name = var.settings.github_repo.branch_name + root_folder = var.settings.github_repo.root_folder + git_url = var.settings.github_repo.git_url + } + } + } # Generate sql server random admin password if not provided in the attribute administrator_login_password @@ -71,6 +111,8 @@ resource "azurerm_key_vault_secret" "synapse_rg_name" { } # for backwards compatibility to create single firewall rule +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/synapse_firewall_rule +# Tested with : AzureRm 2.57.0 resource "azurerm_synapse_firewall_rule" "wrkspc_firewall" { count = try(var.settings.workspace_firewall, null) == null ? 0 : 1 @@ -81,6 +123,8 @@ resource "azurerm_synapse_firewall_rule" "wrkspc_firewall" { } # supports adding multiple synapse firewall rules +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/synapse_firewall_rule +# Tested with : AzureRm 2.57.0 resource "azurerm_synapse_firewall_rule" "wrkspc_firewalls" { for_each = try(var.settings.workspace_firewalls, {}) diff --git a/modules/azuread/applications/scripts/grant_consent.sh b/modules/azuread/applications/scripts/grant_consent.sh index 3b80c01557..7409cde31e 100755 --- a/modules/azuread/applications/scripts/grant_consent.sh +++ b/modules/azuread/applications/scripts/grant_consent.sh @@ -2,29 +2,31 @@ set -e - user_type=$(az account show --query user.type -o tsv) if [ "${user_type}" = "user" ]; then az ad app permission admin-consent --id ${applicationId} - else - resourceId=$(az ad sp show --id "${resourceAppId}" --query "objectId" -o tsv) echo " -resourceId: ${resourceId}" microsoft_graph_endpoint=$(az cloud show | jq -r ".endpoints.microsoftGraphResourceId") - URI=$(echo "${microsoft_graph_endpoint}beta/servicePrincipals/${resourceId}/appRoleAssignments") && echo " - uri: $URI" + URI=$(echo "${microsoft_graph_endpoint}v1.0/servicePrincipals/${resourceId}/appRoleAssignedTo") && echo " - uri: $URI" - # grant consent (Application.ReadWrite.OwnedBy) - JSON=$( jq -n \ - --arg principalId "${principalId}" \ - --arg resourceId "${resourceId}" \ - --arg appRoleId "${appRoleId}" \ - '{principalId: $principalId, resourceId: $resourceId, appRoleId: $appRoleId}' ) && echo " - body: $JSON" + existingAppRoleId=$(az rest --method GET --uri ${URI} \ + --query "value[?appRoleId=='${appRoleId}' && principalId=='${principalId}' && resourceId=='${resourceId}'].appRoleId" -o tsv) - az rest --method POST --uri $URI --header Content-Type=application/json --body "$JSON" + if [ -z ${existingAppRoleId} ]; then + JSON=$( jq -n \ + --arg principalId "${principalId}" \ + --arg resourceId "${resourceId}" \ + --arg appRoleId "${appRoleId}" \ + '{principalId: $principalId, resourceId: $resourceId, appRoleId: $appRoleId}' ) && echo " - body: $JSON" -fi + az rest --method POST --uri $URI --header Content-Type=application/json --body "$JSON" + else + echo "API permission already granted." + fi +fi \ No newline at end of file diff --git a/modules/azuread/applications/variables.tf b/modules/azuread/applications/variables.tf index ac4e2d6244..6dee0767d5 100755 --- a/modules/azuread/applications/variables.tf +++ b/modules/azuread/applications/variables.tf @@ -14,6 +14,7 @@ variable "user_type" {} variable "keyvaults" { default = {} } + variable "password_policy" { description = "Default password policy applies when not set in tfvars." default = { diff --git a/modules/azuread/applications_v1/azuread_application.tf b/modules/azuread/applications_v1/azuread_application.tf new file mode 100755 index 0000000000..c8e93d96bd --- /dev/null +++ b/modules/azuread/applications_v1/azuread_application.tf @@ -0,0 +1,41 @@ +resource "azuread_application" "app" { + + display_name = var.global_settings.passthrough || try(var.settings.global_settings.passthrough, false) ? var.settings.application_name : format("%v-%s", try(var.global_settings.prefixes[0], ""), var.settings.application_name) + + owners = coalescelist( + [ + var.client_config.object_id + ], + try(var.settings.owners, []) + ) + + available_to_other_tenants = try(var.settings.available_to_other_tenants, false) + homepage = try(var.settings.homepage, null) + group_membership_claims = try(var.settings.group_membership_claims, "All") + identifier_uris = try(var.settings.identifier_uris, null) + logout_url = try(var.settings.logout_url, null) + oauth2_allow_implicit_flow = try(var.settings.oauth2_allow_implicit_flow, false) + prevent_duplicate_names = try(var.settings.identifier_uris, false) + public_client = try(var.settings.public_client, false) + reply_urls = try(var.settings.reply_urls, null) + + dynamic "required_resource_access" { + for_each = var.azuread_api_permissions + + content { + resource_app_id = required_resource_access.value.resource_app_id + + dynamic "resource_access" { + for_each = { + for key, resource in required_resource_access.value.resource_access : key => resource + } + + content { + id = resource_access.value.id + type = resource_access.value.type + } + } + } + } + +} diff --git a/modules/azuread/applications_v1/output.tf b/modules/azuread/applications_v1/output.tf new file mode 100755 index 0000000000..cd8c6a2de9 --- /dev/null +++ b/modules/azuread/applications_v1/output.tf @@ -0,0 +1,49 @@ + +output "id" { + value = azuread_application.app.id +} +output "tenant_id" { + value = var.client_config.tenant_id +} +output "object_id" { + value = azuread_application.app.object_id +} +output "application_id" { + value = azuread_application.app.application_id +} +output "available_to_other_tenants" { + value = azuread_application.app.available_to_other_tenants +} +output "display_name" { + value = azuread_application.app.display_name +} +output "group_membership_claims" { + value = azuread_application.app.group_membership_claims +} +output "homepage" { + value = azuread_application.app.homepage +} +output "identifier_uris" { + value = azuread_application.app.identifier_uris +} +output "logout_url" { + value = azuread_application.app.logout_url +} +output "oauth2_allow_implicit_flow" { + value = azuread_application.app.oauth2_allow_implicit_flow +} +output "owners" { + value = azuread_application.app.owners +} +output "prevent_duplicate_names" { + value = azuread_application.app.prevent_duplicate_names +} +output "public_client" { + value = azuread_application.app.public_client +} +output "reply_urls" { + value = azuread_application.app.reply_urls +} +output "type" { + value = azuread_application.app.type +} \ No newline at end of file diff --git a/modules/azuread/applications_v1/variables.tf b/modules/azuread/applications_v1/variables.tf new file mode 100755 index 0000000000..97532fdbf6 --- /dev/null +++ b/modules/azuread/applications_v1/variables.tf @@ -0,0 +1,13 @@ +variable "global_settings" { + default = {} +} +variable "settings" { + default = {} +} +variable "client_config" { + description = "Client configuration object (see module README.md)." +} +variable "azuread_api_permissions" { + default = {} +} +variable "user_type" {} diff --git a/modules/azuread/credentials/keyvault_secrets.tf b/modules/azuread/credentials/keyvault_secrets.tf new file mode 100755 index 0000000000..6a3aa1ed81 --- /dev/null +++ b/modules/azuread/credentials/keyvault_secrets.tf @@ -0,0 +1,19 @@ + +resource "azurerm_key_vault_secret" "client_id" { + for_each = try(var.settings.keyvaults, {}) + + name = format("%s-client-id", each.value.secret_prefix) + key_vault_id = try(each.value.lz_key, null) == null ? var.keyvaults[var.client_config.landingzone_key][each.key].id : var.keyvaults[each.value.lz_key][each.key].id + + value = coalesce( + try(var.resources.application.application_id, null) + ) +} + +resource "azurerm_key_vault_secret" "tenant_id" { + for_each = try(var.settings.keyvaults, {}) + name = format("%s-tenant-id", each.value.secret_prefix) + value = try(each.value.tenant_id, var.client_config.tenant_id) + key_vault_id = try(each.value.lz_key, null) == null ? var.keyvaults[var.client_config.landingzone_key][each.key].id : var.keyvaults[each.value.lz_key][each.key].id +} + diff --git a/modules/azuread/credentials/password.tf b/modules/azuread/credentials/password.tf new file mode 100644 index 0000000000..ff1add2a2d --- /dev/null +++ b/modules/azuread/credentials/password.tf @@ -0,0 +1,68 @@ + +resource "azuread_application_password" "key" { + count = try(var.settings.azuread_application, null) != null && lower(var.settings.type) == "password" && try(var.settings.azuread_credential_policy_key, null) == null ? 1 : 0 + description = try(var.settings.description, local.description.key) + value = random_password.key.0.result + end_date = local.expiration_date.key + + application_object_id = coalesce( + try(var.resources.application.id, null) + ) + + lifecycle { + create_before_destroy = true + } +} + +resource "azuread_application_password" "key0" { + count = try(var.settings.azuread_application, null) != null && lower(var.settings.type) == "password" && try(var.settings.azuread_credential_policy_key, null) != null ? 1 : 0 + description = try(var.settings.description, local.description.key0) + value = random_password.key0.0.result + end_date = local.expiration_date.key0 + + application_object_id = coalesce( + try(var.resources.application.id, null) + ) + + lifecycle { + create_before_destroy = true + } +} + +resource "azuread_application_password" "key1" { + count = try(var.settings.azuread_application, null) != null && lower(var.settings.type) == "password" && try(var.settings.azuread_credential_policy_key, null) != null ? 1 : 0 + description = try(var.settings.description, local.description.key1) + value = random_password.key1.0.result + end_date = local.expiration_date.key1 + + application_object_id = coalesce( + try(var.resources.application.id, null) + ) + + lifecycle { + create_before_destroy = true + } +} + +# +# Everytime the code run it re-evalute the key to store in the keyvault secret +# +locals { + # Used to set the key with the longest expiring date into the keyvault + random_key = try(tonumber(formatdate("YYYYMMDDhhmmss", local.expiration_date.key0)) > tonumber(formatdate("YYYYMMDDhhmmss", local.expiration_date.key1)) ? "key0" : "key1", "key") +} + +resource "azurerm_key_vault_secret" "client_secret" { + for_each = { + for key, value in try(var.settings.keyvaults, {}) : key => value + if try(var.settings.azuread_application, null) != null && lower(local.password_type) == "password" + } + name = format("%s-client-secret", each.value.secret_prefix) + value = local.random_key == "key0" ? sensitive(azuread_application_password.key0.0.value) : try(sensitive(azuread_application_password.key1.0.value), sensitive(azuread_application_password.key.0.value)) + key_vault_id = try(each.value.lz_key, null) == null ? var.keyvaults[var.client_config.landingzone_key][each.key].id : var.keyvaults[each.value.lz_key][each.key].id + expiration_date = local.random_key == "key0" ? local.expiration_date.key0 : try(local.expiration_date.key1, local.expiration_date.key) + + tags = { + key = local.random_key + } +} \ No newline at end of file diff --git a/modules/azuread/credentials/password_rotation.tf b/modules/azuread/credentials/password_rotation.tf new file mode 100644 index 0000000000..d213e583f4 --- /dev/null +++ b/modules/azuread/credentials/password_rotation.tf @@ -0,0 +1,98 @@ +# +# key is used when +# +# Keys generated when using the password policy +# Key0 password_policy.rotation.days is an odd number +# Key1 password_policy.rotation.days is an even number +# + +locals { + password_type = try(var.settings.type, "password") + password_policy = try(var.settings.azuread_credential_policy_key, null) == null ? var.policy : var.credential_policy + + expiration_date = { + key = try(var.settings.azuread_credential_policy_key, null) == null ? timeadd(time_rotating.key.0.id, format("%sh", local.key.days * 24)) : null + key0 = try(var.settings.azuread_credential_policy_key, null) != null ? timeadd(time_rotating.key0.0.id, format("%sh", local.key0.days * 24)) : null + key1 = try(var.settings.azuread_credential_policy_key, null) != null ? timeadd(time_rotating.key1.0.id, format("%sh", local.key1.days * 24)) : null + } + + description = { + key = try(format( + "key-%s-%s", + formatdate("YYMMDDhhmmss", time_rotating.key.0.id), + formatdate("YYMMDDhhmmss", local.expiration_date.key) + ), null) + key0 = try(format( + "key0-%s-%s", + formatdate("YYMMDDhhmmss", time_rotating.key0.0.id), + formatdate("YYMMDDhhmmss", local.expiration_date.key0) + ), null) + key1 = try(format( + "key1-%s-%s", + formatdate("YYMMDDhhmmss", time_rotating.key1.0.id), + formatdate("YYMMDDhhmmss", local.expiration_date.key1) + ), null) + } + + key = { + # Coming from the default variables.tf + days = try(local.password_policy.rotation_key0.days, null) + } + + key0 = { + days = try(local.password_policy.rotation_key0.days, null) + } + + key1 = { + days = try(local.password_policy.rotation_key1.days, null) + } +} + +resource "time_rotating" "key" { + count = lower(local.password_type) == "password" && try(var.settings.azuread_credential_policy_key, null) == null ? 1 : 0 + rotation_days = local.key.days +} + +resource "random_password" "key" { + count = lower(local.password_type) == "password" && try(var.settings.azuread_credential_policy_key, null) == null ? 1 : 0 + keepers = { + frequency = time_rotating.key.0.id + } + length = local.password_policy.length + special = local.password_policy.special + upper = local.password_policy.upper + number = local.password_policy.number +} + +resource "time_rotating" "key0" { + count = lower(local.password_type) == "password" && try(var.settings.azuread_credential_policy_key, null) != null ? 1 : 0 + rotation_days = local.key0.days +} + +resource "random_password" "key0" { + count = lower(local.password_type) == "password" && try(var.settings.azuread_credential_policy_key, null) != null ? 1 : 0 + keepers = { + frequency = time_rotating.key0.0.id + } + length = local.password_policy.length + special = local.password_policy.special + upper = local.password_policy.upper + number = local.password_policy.number +} + + +resource "time_rotating" "key1" { + count = lower(local.password_type) == "password" && try(var.settings.azuread_credential_policy_key, null) != null ? 1 : 0 + rotation_days = local.key1.days +} + +resource "random_password" "key1" { + count = lower(local.password_type) == "password" && try(var.settings.azuread_credential_policy_key, null) != null ? 1 : 0 + keepers = { + frequency = time_rotating.key1.0.id + } + length = local.password_policy.length + special = local.password_policy.special + upper = local.password_policy.upper + number = local.password_policy.number +} \ No newline at end of file diff --git a/modules/azuread/credentials/variables.tf b/modules/azuread/credentials/variables.tf new file mode 100755 index 0000000000..3e2f09f03e --- /dev/null +++ b/modules/azuread/credentials/variables.tf @@ -0,0 +1,59 @@ +variable "global_settings" { + default = {} +} +variable "settings" { + default = {} +} +variable "client_config" { + description = "Client configuration object (see module README.md)." +} +variable "keyvaults" { + default = {} +} + +variable "resources" { + description = "Application ID the credentials will be attached to." +} + +variable "credential_policy" { + description = "Custom credential policy to apply." + default = null +} + +variable "policy" { + description = "Default credential policy to apply." + default = { + # Length of the password + length = 250 + special = false + upper = true + number = true + + # Define the number of days the password is valid. It must be more than the rotation frequency + expire_in_days = 380 + rotation_key0 = { + # Odd number + # + # Set how often the password must be rotated. When passed the renewal time, running the terraform plan / apply will change to a new password + # Only set one of the value + # Note - once set cannot switch between mins/days/months. Only the value can be adjusted. + # + + # mins = 10 # only recommended for CI and demo + days = 180 + # months = 1 + } + rotation_key1 = { + # Even number + # + # Set how often the password must be rotated. When passed the renewal time, running the terraform plan / apply will change to a new password + # Only set one of the value + # Note - once set cannot switch between mins/days/months. Only the value can be adjusted. + # + + # mins = 10 # only recommended for CI and demo + days = 361 + # months = 1 + } + } +} \ No newline at end of file diff --git a/modules/azuread/groups_members/members.tf b/modules/azuread/groups_members/groups_members.tf similarity index 68% rename from modules/azuread/groups_members/members.tf rename to modules/azuread/groups_members/groups_members.tf index 197e8c1995..21e1a01267 100755 --- a/modules/azuread/groups_members/members.tf +++ b/modules/azuread/groups_members/groups_members.tf @@ -12,7 +12,6 @@ module "user_principal_names" { member_object_id = data.azuread_user.upn[each.key].id } - module "service_principals" { source = "./member" for_each = toset(try(var.settings.members.service_principal_keys, [])) @@ -21,6 +20,22 @@ module "service_principals" { member_object_id = var.azuread_apps[each.key].azuread_service_principal.object_id } +module "azuread_service_principals" { + source = "./member" + for_each = toset(try(var.settings.members.azuread_service_principal_keys, [])) + + group_object_id = var.group_id + member_object_id = var.azuread_service_principals[each.key].object_id +} + +module "azuread_service_principals_membership" { + source = "./membership" + for_each = try(var.settings.azuread_service_principals, {}) + + group_object_id = var.group_id + azuread_service_principals = var.azuread_service_principals[try(each.value.lz_key, var.client_config.landingzone_key)] + members = each.value +} module "object_id" { source = "./member" diff --git a/modules/azuread/groups_members/member/member.tf b/modules/azuread/groups_members/member/member.tf index ad997183c3..f404596591 100755 --- a/modules/azuread/groups_members/member/member.tf +++ b/modules/azuread/groups_members/member/member.tf @@ -1,7 +1,4 @@ -variable "group_object_id" {} -variable "member_object_id" {} - resource "azuread_group_member" "id" { group_object_id = var.group_object_id member_object_id = var.member_object_id -} +} \ No newline at end of file diff --git a/modules/azuread/groups_members/member/variables.tf b/modules/azuread/groups_members/member/variables.tf new file mode 100644 index 0000000000..e81440228c --- /dev/null +++ b/modules/azuread/groups_members/member/variables.tf @@ -0,0 +1,4 @@ +variable "group_object_id" {} +variable "member_object_id" { + default = null +} \ No newline at end of file diff --git a/modules/azuread/groups_members/membership/membership.tf b/modules/azuread/groups_members/membership/membership.tf new file mode 100755 index 0000000000..f10cb944fa --- /dev/null +++ b/modules/azuread/groups_members/membership/membership.tf @@ -0,0 +1,6 @@ +resource "azuread_group_member" "ids" { + for_each = toset(try(var.members.keys, [])) + + group_object_id = var.group_object_id + member_object_id = var.azuread_service_principals[each.key].object_id +} \ No newline at end of file diff --git a/modules/azuread/groups_members/membership/variables.tf b/modules/azuread/groups_members/membership/variables.tf new file mode 100644 index 0000000000..db250692e4 --- /dev/null +++ b/modules/azuread/groups_members/membership/variables.tf @@ -0,0 +1,10 @@ +variable "group_object_id" {} +variable "member_object_id" { + default = null +} +variable "azuread_service_principals" { + default = {} +} +variable "members" { + default = {} +} \ No newline at end of file diff --git a/modules/azuread/groups_members/variables.tf b/modules/azuread/groups_members/variables.tf index 24c8ff6e87..2b13c8d9e1 100755 --- a/modules/azuread/groups_members/variables.tf +++ b/modules/azuread/groups_members/variables.tf @@ -1,8 +1,12 @@ +variable "settings" {} variable "group_id" {} +variable "client_config" {} variable "azuread_groups" { default = {} } variable "azuread_apps" { default = {} } -variable "settings" {} \ No newline at end of file +variable "azuread_service_principals" { + default = {} +} \ No newline at end of file diff --git a/modules/azuread/roles/scripts/set_ad_role.sh b/modules/azuread/roles/scripts/set_ad_role.sh index 2fafd35cf5..68a822eca9 100755 --- a/modules/azuread/roles/scripts/set_ad_role.sh +++ b/modules/azuread/roles/scripts/set_ad_role.sh @@ -46,12 +46,12 @@ case "${METHOD}" in az rest --method ${METHOD} --uri $URI --header Content-Type=application/json --body "$JSON" - echo "Role '${AD_ROLE_NAME}' assigned to azure ad application" + echo "Role '${AD_ROLE_NAME}' assigned to azure ad principal" ;; DELETE) URI=$(echo "${microsoft_graph_endpoint}v1.0/directoryRoles/${ROLE_AAD}/members/${SERVICE_PRINCIPAL_OBJECT_ID}/\$ref") && echo " - uri: $URI" - az rest --method ${METHOD} --uri ${URI} - echo "Role '${AD_ROLE_NAME}' unassigned to azure ad application ${SERVICE_PRINCIPAL_OBJECT_ID}" + az rest --method ${METHOD} --uri ${URI} || true + echo "Role '${AD_ROLE_NAME}' unassigned to azure ad principal ${SERVICE_PRINCIPAL_OBJECT_ID}" ;; esac diff --git a/modules/azuread/service_principal/grant_api_permissions.tf b/modules/azuread/service_principal/grant_api_permissions.tf new file mode 100755 index 0000000000..881ab89bb0 --- /dev/null +++ b/modules/azuread/service_principal/grant_api_permissions.tf @@ -0,0 +1,46 @@ +# Admin consent management is not performed in the same way if the logged in user is a service principal or a user +# We have two local variables to accomodate that. +locals { + api_permissions = { + for api_permission in + flatten( + [ + for key, resources in var.azuread_api_permissions : [ + for resource_name, resource in resources.resource_access : { + aad_app_key = key + resource_name = resource_name + resource_app_id = resources.resource_app_id + id = resource.id + type = resource.type + } if resource.type == "Role" + ] + ] + ) : format("%s-%s", api_permission.aad_app_key, api_permission.resource_name) => api_permission + } +} + + +resource "null_resource" "grant_admin_consent" { + + triggers = { + resourceAppId = each.value.resource_app_id + appRoleId = each.value.id + principalId = azuread_service_principal.app.object_id + } + + for_each = { + for key, permission in local.api_permissions : key => permission + } + + provisioner "local-exec" { + command = format("%s/scripts/grant_consent.sh", path.module) + interpreter = ["/bin/bash"] + on_failure = fail + + environment = { + resourceAppId = self.triggers.resourceAppId + appRoleId = self.triggers.appRoleId + principalId = self.triggers.principalId + } + } +} diff --git a/modules/azuread/service_principal/module.tf b/modules/azuread/service_principal/module.tf new file mode 100755 index 0000000000..d9f06adbe4 --- /dev/null +++ b/modules/azuread/service_principal/module.tf @@ -0,0 +1,18 @@ + +resource "azuread_service_principal" "app" { + application_id = var.application_id + app_role_assignment_required = try(var.settings.app_role_assignment_required, false) + + lifecycle { + ignore_changes = [application_id] + } +} + +resource "null_resource" "propagate_to_azuread" { + depends_on = [azuread_service_principal.app] + + provisioner "local-exec" { + command = "/bin/bash -c '/usr/bin/sleep 30'" + on_failure = fail + } +} \ No newline at end of file diff --git a/modules/azuread/service_principal/output.tf b/modules/azuread/service_principal/output.tf new file mode 100755 index 0000000000..25c875ec7e --- /dev/null +++ b/modules/azuread/service_principal/output.tf @@ -0,0 +1,28 @@ + +output "tenant_id" { + value = var.client_config.tenant_id +} + +output "id" { + value = azuread_service_principal.app.id +} + +output "application_id" { + value = azuread_service_principal.app.application_id +} + +output "object_id" { + value = azuread_service_principal.app.object_id +} + +output "display_name" { + value = azuread_service_principal.app.object_id +} + +output "oauth2_permissions" { + value = azuread_service_principal.app.oauth2_permissions +} +output "rbac_id" { + value = azuread_service_principal.app.object_id + description = "This attribute is used to set the role assignment" +} \ No newline at end of file diff --git a/modules/azuread/service_principal/scripts/grant_consent.sh b/modules/azuread/service_principal/scripts/grant_consent.sh new file mode 100755 index 0000000000..9a422583c9 --- /dev/null +++ b/modules/azuread/service_principal/scripts/grant_consent.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +user_type=$(az account show --query user.type -o tsv) + +if [ "${user_type}" = "user" ]; then + + az ad app permission admin-consent --id ${applicationId} + +else + resourceId=$(az ad sp show --id "${resourceAppId}" --query "objectId" -o tsv) + echo " -resourceId: ${resourceId}" + + microsoft_graph_endpoint=$(az cloud show | jq -r ".endpoints.microsoftGraphResourceId") + + URI=$(echo "${microsoft_graph_endpoint}v1.0/servicePrincipals/${resourceId}/appRoleAssignedTo") && echo " - uri: $URI" + + existingAppRoleId=$(az rest --method GET --uri ${URI} \ + --query "value[?appRoleId=='${appRoleId}' && principalId=='${principalId}' && resourceId=='${resourceId}'].appRoleId" -o tsv) + + if [ -z ${existingAppRoleId} ]; then + JSON=$( jq -n \ + --arg principalId "${principalId}" \ + --arg resourceId "${resourceId}" \ + --arg appRoleId "${appRoleId}" \ + '{principalId: $principalId, resourceId: $resourceId, appRoleId: $appRoleId}' ) && echo " - body: $JSON" + + az rest --method POST --uri $URI --header Content-Type=application/json --body "$JSON" + else + echo "API permission already granted." + fi +fi \ No newline at end of file diff --git a/modules/azuread/service_principal/variables.tf b/modules/azuread/service_principal/variables.tf new file mode 100755 index 0000000000..8fe49f1612 --- /dev/null +++ b/modules/azuread/service_principal/variables.tf @@ -0,0 +1,16 @@ +variable "global_settings" { + default = {} +} +variable "settings" { + default = {} +} +variable "client_config" { + description = "Client configuration object (see module README.md)." +} +variable "application_id" { + description = "Application ID of the service principal to create." +} +variable "azuread_api_permissions" { + default = {} +} +variable "user_type" {} diff --git a/modules/azuread/service_principal_password/keyvault_secrets.tf b/modules/azuread/service_principal_password/keyvault_secrets.tf new file mode 100755 index 0000000000..826101ad1d --- /dev/null +++ b/modules/azuread/service_principal_password/keyvault_secrets.tf @@ -0,0 +1,23 @@ + +resource "azurerm_key_vault_secret" "client_id" { + for_each = try(var.settings.keyvaults, {}) + + name = format("%s-client-id", each.value.secret_prefix) + value = var.service_principal_application_id + key_vault_id = try(each.value.lz_key, null) == null ? var.keyvaults[var.client_config.landingzone_key][each.key].id : var.keyvaults[each.value.lz_key][each.key].id +} + +resource "azurerm_key_vault_secret" "client_secret" { + for_each = try(var.settings.keyvaults, {}) + name = format("%s-client-secret", each.value.secret_prefix) + value = azuread_service_principal_password.pwd.value + key_vault_id = try(each.value.lz_key, null) == null ? var.keyvaults[var.client_config.landingzone_key][each.key].id : var.keyvaults[each.value.lz_key][each.key].id + expiration_date = timeadd(time_rotating.pwd.id, format("%sh", local.password_policy.expire_in_days * 24)) +} + +resource "azurerm_key_vault_secret" "tenant_id" { + for_each = try(var.settings.keyvaults, {}) + name = format("%s-tenant-id", each.value.secret_prefix) + value = var.client_config.tenant_id + key_vault_id = try(each.value.lz_key, null) == null ? var.keyvaults[var.client_config.landingzone_key][each.key].id : var.keyvaults[each.value.lz_key][each.key].id +} diff --git a/modules/azuread/service_principal_password/module.tf b/modules/azuread/service_principal_password/module.tf new file mode 100755 index 0000000000..454c07ec32 --- /dev/null +++ b/modules/azuread/service_principal_password/module.tf @@ -0,0 +1,32 @@ + +resource "azuread_service_principal_password" "pwd" { + service_principal_id = var.service_principal_id + value = random_password.pwd.result + end_date = timeadd(time_rotating.pwd.id, format("%sh", local.password_policy.expire_in_days * 24)) + + lifecycle { + create_before_destroy = false + } +} + +locals { + password_policy = try(var.settings.password_policy, var.password_policy) +} + +resource "time_rotating" "pwd" { + rotation_minutes = try(local.password_policy.rotation.mins, null) + rotation_days = try(local.password_policy.rotation.days, null) + rotation_months = try(local.password_policy.rotation.months, null) + rotation_years = try(local.password_policy.rotation.years, null) +} + +# Will force the password to change every month +resource "random_password" "pwd" { + keepers = { + frequency = time_rotating.pwd.id + } + length = local.password_policy.length + special = local.password_policy.special + upper = local.password_policy.upper + number = local.password_policy.number +} diff --git a/modules/azuread/service_principal_password/output.tf b/modules/azuread/service_principal_password/output.tf new file mode 100755 index 0000000000..06c9d50a32 --- /dev/null +++ b/modules/azuread/service_principal_password/output.tf @@ -0,0 +1,28 @@ + +output "tenant_id" { + value = var.client_config.tenant_id +} +output "key_id" { + value = azuread_service_principal_password.pwd.key_id +} +output "service_principal_id" { + value = azuread_service_principal_password.pwd.service_principal_id +} +output "end_date" { + value = azuread_service_principal_password.pwd.end_date +} +output "end_date_relative" { + value = azuread_service_principal_password.pwd.end_date_relative +} +output "start_date" { + value = azuread_service_principal_password.pwd.start_date +} +output "keyvaults" { + value = { + for key, value in try(var.settings.keyvaults, {}) : key => { + id = azurerm_key_vault_secret.client_id[key].key_vault_id + secret_name_client_secret = value.secret_prefix + } + } + description = "Keyvaults storing the passwords. Store the secret_prefix-client-id, secret_prefix-client-secret" +} \ No newline at end of file diff --git a/modules/azuread/service_principal_password/variables.tf b/modules/azuread/service_principal_password/variables.tf new file mode 100755 index 0000000000..edd83bd959 --- /dev/null +++ b/modules/azuread/service_principal_password/variables.tf @@ -0,0 +1,44 @@ +variable "global_settings" { + default = {} +} +variable "settings" { + default = {} +} +variable "client_config" { + description = "Client configuration object (see module README.md)." +} +variable "keyvaults" { + default = {} +} + +variable "service_principal_id" { + description = "(Required) The ID of the Service Principal for which this password should be created." +} + +variable "service_principal_application_id" { + description = "(Required) The App ID of the Application for which to create a Service Principal." +} + +variable "password_policy" { + description = "Default password policy applies when not set in tfvars." + default = { + # Length of the password + length = 250 + special = false + upper = true + number = true + + # Define the number of days the password is valid. It must be more than the rotation frequency + expire_in_days = 180 + rotation = { + # + # Set how often the password must be rotated. When passed the renewal time, running the terraform plan / apply will change to a new password + # Only set one of the value + # + + # mins = 10 # only recommended for CI and demo + # days = 7 + months = 1 + } + } +} \ No newline at end of file diff --git a/modules/compute/aks/aks.tf b/modules/compute/aks/aks.tf index dcdd5e8c4d..1777e018b4 100644 --- a/modules/compute/aks/aks.tf +++ b/modules/compute/aks/aks.tf @@ -212,6 +212,7 @@ resource "azurerm_kubernetes_cluster" "aks" { node_resource_group = azurecaf_name.rg_node.result private_cluster_enabled = try(var.settings.private_cluster_enabled, false) + private_dns_zone_id = try(var.settings.private_dns_zone_id, null) lifecycle { ignore_changes = [ diff --git a/modules/compute/aks/variables.tf b/modules/compute/aks/variables.tf index 7cfb14c2e3..8b704dfe74 100755 --- a/modules/compute/aks/variables.tf +++ b/modules/compute/aks/variables.tf @@ -14,4 +14,7 @@ variable "base_tags" { } variable "diagnostic_profiles" { default = null +} +variable "private_dns_zone_id" { + default = null } \ No newline at end of file diff --git a/modules/compute/container_registry/registry.tf b/modules/compute/container_registry/registry.tf index 6f1156add0..8abd39b3f5 100755 --- a/modules/compute/container_registry/registry.tf +++ b/modules/compute/container_registry/registry.tf @@ -9,16 +9,15 @@ resource "azurecaf_name" "acr" { } resource "azurerm_container_registry" "acr" { - name = azurecaf_name.acr.result - resource_group_name = var.resource_group_name - location = var.location - sku = var.sku - admin_enabled = var.admin_enabled - georeplication_locations = var.georeplication_locations - tags = local.tags + name = azurecaf_name.acr.result + resource_group_name = var.resource_group_name + location = var.location + sku = var.sku + admin_enabled = var.admin_enabled + tags = local.tags dynamic "network_rule_set" { - for_each = var.network_rule_set + for_each = try(var.network_rule_set, {}) content { default_action = try(var.network_rule_set.default_action, "Allow") @@ -41,5 +40,14 @@ resource "azurerm_container_registry" "acr" { } } } + + dynamic "georeplications" { + for_each = try(var.georeplications, {}) + + content { + location = var.global_settings.regions[georeplications.key] + tags = try(georeplications.value.tags) + } + } } diff --git a/modules/compute/container_registry/variables.tf b/modules/compute/container_registry/variables.tf index 328a872b91..c6ee4d5052 100755 --- a/modules/compute/container_registry/variables.tf +++ b/modules/compute/container_registry/variables.tf @@ -34,9 +34,9 @@ variable "tags" { default = {} } -variable "georeplication_locations" { - description = "(Optional) A list of Azure locations where the container registry should be geo-replicated." - default = null +variable "georeplications" { + description = "(Optional) Updated structure for Azure locations where the container registry should be geo-replicated." + default = {} } variable "vnets" { diff --git a/modules/compute/dedicated_host_groups/main.tf b/modules/compute/dedicated_host_groups/main.tf new file mode 100755 index 0000000000..d1edf5b78b --- /dev/null +++ b/modules/compute/dedicated_host_groups/main.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + azurecaf = { + source = "aztfmod/azurecaf" + } + } + required_version = ">= 0.13" +} + + +locals { + module_tag = { + "module" = basename(abspath(path.module)) + } + tags = merge(var.base_tags, local.module_tag, try(var.tags, null)) +} \ No newline at end of file diff --git a/modules/compute/dedicated_host_groups/module.tf b/modules/compute/dedicated_host_groups/module.tf new file mode 100644 index 0000000000..241e9ccc58 --- /dev/null +++ b/modules/compute/dedicated_host_groups/module.tf @@ -0,0 +1,23 @@ +resource "azurecaf_name" "dhg" { + name = var.settings.name + resource_type = "azurerm_dedicated_host_group" + prefixes = var.global_settings.prefixes + random_length = var.global_settings.random_length + clean_input = true + passthrough = var.global_settings.passthrough + use_slug = var.global_settings.use_slug +} + +# Last review : AzureRM version 2.63.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/dedicated_host_group + + +resource "azurerm_dedicated_host_group" "dhg" { + name = azurecaf_name.dhg.result + resource_group_name = var.resource_group_name + location = var.location + platform_fault_domain_count = var.settings.platform_fault_domain_count + automatic_placement_enabled = try(var.settings.automatic_placement_enabled, false) + zones = try(var.settings.zones, null) + tags = local.tags +} \ No newline at end of file diff --git a/modules/compute/dedicated_host_groups/output.tf b/modules/compute/dedicated_host_groups/output.tf new file mode 100644 index 0000000000..2d568029f9 --- /dev/null +++ b/modules/compute/dedicated_host_groups/output.tf @@ -0,0 +1,4 @@ +output "id" { + value = azurerm_dedicated_host_group.dhg.id + description = "The ID of the Dedicated Host Group." +} \ No newline at end of file diff --git a/modules/compute/dedicated_host_groups/variables.tf b/modules/compute/dedicated_host_groups/variables.tf new file mode 100644 index 0000000000..5b9e0dce63 --- /dev/null +++ b/modules/compute/dedicated_host_groups/variables.tf @@ -0,0 +1,21 @@ +variable "global_settings" { + description = "Global settings object (see module README.md)" +} +variable "client_config" { + description = "Client configuration object (see module README.md)." +} +variable "location" { + description = "(Required) Specifies the supported Azure location where to create the resource. Changing this forces a new resource to be created." + type = string +} +variable "resource_group_name" { + description = "Name of the existing resource group to deploy the virtual machine" +} +variable "base_tags" { + description = "Base tags for the resource to be inherited from the resource group." + type = map(any) +} +variable "settings" {} +variable "tags" { + default = null +} \ No newline at end of file diff --git a/modules/compute/dedicated_hosts/main.tf b/modules/compute/dedicated_hosts/main.tf new file mode 100755 index 0000000000..d1edf5b78b --- /dev/null +++ b/modules/compute/dedicated_hosts/main.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + azurecaf = { + source = "aztfmod/azurecaf" + } + } + required_version = ">= 0.13" +} + + +locals { + module_tag = { + "module" = basename(abspath(path.module)) + } + tags = merge(var.base_tags, local.module_tag, try(var.tags, null)) +} \ No newline at end of file diff --git a/modules/compute/dedicated_hosts/module.tf b/modules/compute/dedicated_hosts/module.tf new file mode 100644 index 0000000000..1397f5e0da --- /dev/null +++ b/modules/compute/dedicated_hosts/module.tf @@ -0,0 +1,23 @@ +resource "azurecaf_name" "dh" { + name = var.settings.name + resource_type = "azurerm_dedicated_host" + prefixes = var.global_settings.prefixes + random_length = var.global_settings.random_length + clean_input = true + passthrough = var.global_settings.passthrough + use_slug = var.global_settings.use_slug +} + +# Last review : AzureRM version 2.63.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/dedicated_host + +resource "azurerm_dedicated_host" "dh" { + name = azurecaf_name.dh.result + dedicated_host_group_id = var.dedicated_host_group_id + location = var.location + sku_name = var.settings.sku_name + platform_fault_domain = var.settings.platform_fault_domain + auto_replace_on_failure = try(var.settings.auto_replace_on_failure, true) + license_type = try(var.settings.license_type, "None") + tags = local.tags +} \ No newline at end of file diff --git a/modules/compute/dedicated_hosts/output.tf b/modules/compute/dedicated_hosts/output.tf new file mode 100644 index 0000000000..16cc17a66d --- /dev/null +++ b/modules/compute/dedicated_hosts/output.tf @@ -0,0 +1,4 @@ +output "id" { + value = azurerm_dedicated_host.dh.id + description = "The ID of the Dedicated Host." +} \ No newline at end of file diff --git a/modules/compute/dedicated_hosts/variables.tf b/modules/compute/dedicated_hosts/variables.tf new file mode 100644 index 0000000000..83d54a6b4d --- /dev/null +++ b/modules/compute/dedicated_hosts/variables.tf @@ -0,0 +1,25 @@ +variable "global_settings" { + description = "Global settings object (see module README.md)" +} +variable "client_config" { + description = "Client configuration object (see module README.md)." +} +variable "location" { + description = "(Required) Specifies the supported Azure location where to create the resource. Changing this forces a new resource to be created." + type = string +} +# variable "resource_group_name" { +# description = "Name of the existing resource group to deploy the virtual machine" +# } +variable "base_tags" { + description = "Base tags for the resource to be inherited from the resource group." + type = map(any) +} +variable "settings" {} +variable "tags" { + default = null +} +variable "dedicated_host_group_id" { + description = "The ID of the dedicated host group" + type = string +} \ No newline at end of file diff --git a/modules/compute/virtual_machine/network_interface.tf b/modules/compute/virtual_machine/network_interface.tf index 07fa742080..d8866cb54d 100755 --- a/modules/compute/virtual_machine/network_interface.tf +++ b/modules/compute/virtual_machine/network_interface.tf @@ -83,12 +83,12 @@ resource "azurerm_network_interface" "nic" { # internal_dns_name_label = "nic0" # // Prefer network_security_group orver nsg_key. Will be removed in version 6 # nsg_key = "data" // requires a version 1 nsg definition (see compute/vm/210-vm-bastion-winrm example) -# +# # network_security_group = { # # lz_key = "" # key = "data" # } -# +# # ip_configurations = { # conf2 = { # name = "nic0-conf2" diff --git a/modules/compute/virtual_machine/variables.tf b/modules/compute/virtual_machine/variables.tf index de0d5eb2c2..f5d1d1fa63 100755 --- a/modules/compute/virtual_machine/variables.tf +++ b/modules/compute/virtual_machine/variables.tf @@ -81,4 +81,7 @@ variable "network_security_groups" { description = "Require a version 1 NSG definition to be attached to a nic." } +variable "dedicated_hosts" { + default = {} +} diff --git a/modules/compute/virtual_machine/vm_linux.tf b/modules/compute/virtual_machine/vm_linux.tf index d160ad2f8e..c4557ae660 100755 --- a/modules/compute/virtual_machine/vm_linux.tf +++ b/modules/compute/virtual_machine/vm_linux.tf @@ -68,6 +68,12 @@ resource "azurerm_linux_virtual_machine" "vm" { custom_data = try(each.value.custom_data, null) == null ? null : filebase64(format("%s/%s", path.cwd, each.value.custom_data)) availability_set_id = try(var.availability_sets[var.client_config.landingzone_key][each.value.availability_set_key].id, var.availability_sets[each.value.availability_sets].id, null) proximity_placement_group_id = try(var.proximity_placement_groups[var.client_config.landingzone_key][each.value.proximity_placement_group_key].id, var.proximity_placement_groups[each.value.proximity_placement_groups].id, null) + dedicated_host_id = try(coalesce( + try(each.value.dedicated_host.id, null), + var.dedicated_hosts[try(each.value.dedicated_host.lz_key, var.client_config.landingzone_key)][each.value.dedicated_host.key].id, + ), + null + ) dynamic "admin_ssh_key" { for_each = lookup(each.value, "disable_password_authentication", true) == true ? [1] : [] diff --git a/modules/compute/virtual_machine/vm_windows.tf b/modules/compute/virtual_machine/vm_windows.tf index e010b13068..2f9cf972b4 100755 --- a/modules/compute/virtual_machine/vm_windows.tf +++ b/modules/compute/virtual_machine/vm_windows.tf @@ -62,6 +62,12 @@ resource "azurerm_windows_virtual_machine" "vm" { timezone = try(each.value.timezone, null) availability_set_id = try(var.availability_sets[var.client_config.landingzone_key][each.value.availability_set_key].id, var.availability_sets[each.value.availability_sets].id, null) proximity_placement_group_id = try(var.proximity_placement_groups[var.client_config.landingzone_key][each.value.proximity_placement_group_key].id, var.proximity_placement_groups[each.value.proximity_placement_groups].id, null) + dedicated_host_id = try(coalesce( + try(each.value.dedicated_host.id, null), + var.dedicated_hosts[try(each.value.dedicated_host.lz_key, var.client_config.landingzone_key)][each.value.dedicated_host.key].id, + ), + null + ) os_disk { caching = each.value.os_disk.caching diff --git a/modules/compute/virtual_machine_extensions/domain_join.tf b/modules/compute/virtual_machine_extensions/domain_join.tf index 7b898081f6..716796589a 100644 --- a/modules/compute/virtual_machine_extensions/domain_join.tf +++ b/modules/compute/virtual_machine_extensions/domain_join.tf @@ -32,13 +32,20 @@ resource "azurerm_virtual_machine_extension" "domainjoin" { } data "azurerm_key_vault_secret" "domain_join_password" { - for_each = var.extension_name == "microsoft_azure_domainJoin" ? toset(["enabled"]) : toset([]) - name = var.extension.domain_join_password_keyvault.secret_name - key_vault_id = try(var.extension.domain_join_password_keyvault.key_vault_id, var.keyvaults[var.extension.domain_join_password_keyvault.keyvault_key].id) + for_each = var.extension_name == "microsoft_azure_domainJoin" ? toset(["enabled"]) : toset([]) + name = var.extension.domain_join_password_keyvault.secret_name + key_vault_id = try( + var.extension.domain_join_password_keyvault.key_vault_id, + try(var.keyvaults[var.extension.domain_join_password_keyvault.lz_key][var.extension.domain_join_password_keyvault.keyvault_key].id, var.keyvaults[var.client_config.landingzone_key][var.extension.domain_join_password_keyvault.keyvault_key].id) + ) } data "azurerm_key_vault_secret" "domain_join_username" { - for_each = var.extension_name == "microsoft_azure_domainJoin" ? toset(["enabled"]) : toset([]) - name = var.extension.domain_join_username_keyvault.secret_name - key_vault_id = try(var.extension.domain_join_username_keyvault.key_vault_id, var.keyvaults[var.extension.domain_join_username_keyvault.keyvault_key].id) -} \ No newline at end of file + for_each = var.extension_name == "microsoft_azure_domainJoin" ? toset(["enabled"]) : toset([]) + name = var.extension.domain_join_username_keyvault.secret_name + key_vault_id = try( + var.extension.domain_join_username_keyvault.key_vault_id, + try(var.keyvaults[var.extension.domain_join_username_keyvault.lz_key][var.extension.domain_join_username_keyvault.keyvault_key].id, var.keyvaults[var.client_config.landingzone_key][var.extension.domain_join_username_keyvault.keyvault_key].id) + ) +} + diff --git a/modules/compute/virtual_machine_extensions/wvd_dsc.tf b/modules/compute/virtual_machine_extensions/wvd_dsc.tf index 6dc645211a..6f843e0c76 100644 --- a/modules/compute/virtual_machine_extensions/wvd_dsc.tf +++ b/modules/compute/virtual_machine_extensions/wvd_dsc.tf @@ -12,7 +12,10 @@ resource "azurerm_virtual_machine_extension" "session_host_dscextension" { "modulesURL" : format("%s/DSC/Configuration.zip", var.extension.base_url), "configurationFunction" : "Configuration.ps1\\AddSessionHost", "properties" : { - "HostPoolName" : try(var.extension.host_pool_name, var.wvd_host_pools[var.extension.host_pool.host_pool_key].name) + "HostPoolName" : coalesce( + try(var.extension.host_pool_name, ""), + try(var.wvd_host_pools[var.extension.host_pool.lz_key][var.extension.host_pool.keyvault_key].name, var.wvd_host_pools[var.client_config.landingzone_key][var.extension.host_pool.host_pool_key].name) + ) } } ) @@ -26,7 +29,11 @@ resource "azurerm_virtual_machine_extension" "session_host_dscextension" { } data "azurerm_key_vault_secret" "host_pool_token" { - for_each = var.extension_name == "session_host_dscextension" && try(var.extension.host_pool_token, null) == null ? toset(["enabled"]) : toset([]) - name = var.extension.host_pool.secret_name - key_vault_id = try(var.extension.host_pool.key_vault_id, var.keyvaults[var.extension.host_pool.keyvault_key].id) -} \ No newline at end of file + for_each = var.extension_name == "session_host_dscextension" && try(var.extension.host_pool_token, null) == null ? toset(["enabled"]) : toset([]) + name = var.extension.host_pool.secret_name + key_vault_id = try( + var.extension.host_pool.key_vault_id, + try(var.keyvaults[var.extension.host_pool.lz_key][var.extension.host_pool.keyvault_key].id, var.keyvaults[var.client_config.landingzone_key][var.extension.host_pool.keyvault_key].id) + ) +} + diff --git a/modules/compute/virtual_machine_scale_set/main.tf b/modules/compute/virtual_machine_scale_set/main.tf index 99fbccab91..e84fec87fa 100644 --- a/modules/compute/virtual_machine_scale_set/main.tf +++ b/modules/compute/virtual_machine_scale_set/main.tf @@ -17,28 +17,28 @@ locals { } tags = merge(var.base_tags, local.module_tag, try(var.settings.tags, null)) - application_gateway_backend_address_pool_ids = flatten ([ + application_gateway_backend_address_pool_ids = flatten([ for nic, nic_value in var.settings.network_interfaces : [ - for appgw, appgw_value in try(nic_value.appgw_backend_pools,{}): [ + for appgw, appgw_value in try(nic_value.appgw_backend_pools, {}) : [ for pool_name in appgw_value.pool_names : [ - try(var.application_gateways[try(var.client_config.landingzone_key, appgw_value.lz_key)][appgw_value.appgw_key].backend_address_pools[pool_name],null) + try(var.application_gateways[try(var.client_config.landingzone_key, appgw_value.lz_key)][appgw_value.appgw_key].backend_address_pools[pool_name], null) ] ] ] ]) - load_balancer_backend_address_pool_ids = flatten ([ + load_balancer_backend_address_pool_ids = flatten([ for nic, nic_value in var.settings.network_interfaces : [ - for lb, lb_value in try(nic_value.load_balancers,{}) : [ - try(var.load_balancers[try(var.client_config.landingzone_key, lb_value.lz_key)][lb_value.lb_key].backend_address_pool_id,null) + for lb, lb_value in try(nic_value.load_balancers, {}) : [ + try(var.load_balancers[try(var.client_config.landingzone_key, lb_value.lz_key)][lb_value.lb_key].backend_address_pool_id, null) ] ] ]) - - application_security_group_ids = flatten ([ + + application_security_group_ids = flatten([ for nic, nic_value in var.settings.network_interfaces : [ - for asg, asg_value in try(nic_value.application_security_groups,{}) : [ - try(var.application_security_groups[try(var.client_config.landingzone_key, asg_value.lz_key)][asg_value.asg_key].id,null) + for asg, asg_value in try(nic_value.application_security_groups, {}) : [ + try(var.application_security_groups[try(var.client_config.landingzone_key, asg_value.lz_key)][asg_value.asg_key].id, null) ] ] ]) diff --git a/modules/compute/virtual_machine_scale_set/output.tf b/modules/compute/virtual_machine_scale_set/output.tf index c4a847e507..a1ae6890fd 100644 --- a/modules/compute/virtual_machine_scale_set/output.tf +++ b/modules/compute/virtual_machine_scale_set/output.tf @@ -1,4 +1,4 @@ -output id { +output "id" { value = local.os_type == "linux" ? try(azurerm_linux_virtual_machine_scale_set.vmss["linux"].id, null) : try(azurerm_linux_virtual_machine_scale_set.vmss["windows"].id, null) } @@ -6,17 +6,17 @@ output "os_type" { value = local.os_type } -output admin_username { +output "admin_username" { value = try(local.admin_username, null) == null ? var.settings.vmss_settings[local.os_type].admin_username : local.admin_username description = "Local admin username" } -output admin_password_secret_id { +output "admin_password_secret_id" { value = try(azurerm_key_vault_secret.admin_password[local.os_type].id, null) description = "Local admin password Key Vault secret id" } -output winrm { +output "winrm" { value = local.os_type == "windows" ? { keyvault_id = local.keyvault.id certificate_url = try(azurerm_key_vault_certificate.self_signed_winrm[local.os_type].secret_id, null) diff --git a/modules/compute/virtual_machine_scale_set/vmss_linux.tf b/modules/compute/virtual_machine_scale_set/vmss_linux.tf index 05fc02e75a..ed8e18dea7 100644 --- a/modules/compute/virtual_machine_scale_set/vmss_linux.tf +++ b/modules/compute/virtual_machine_scale_set/vmss_linux.tf @@ -102,12 +102,12 @@ resource "azurerm_linux_virtual_machine_scale_set" "vmss" { network_security_group_id = try(network_interface.value.network_security_group_id, null) ip_configuration { - name = azurecaf_name.linux_nic[network_interface.key].result - primary = try(network_interface.value.primary, false) - subnet_id = try(var.vnets[var.client_config.landingzone_key][network_interface.value.vnet_key].subnets[network_interface.value.subnet_key].id, var.vnets[network_interface.value.lz_key][network_interface.value.vnet_key].subnets[network_interface.value.subnet_key].id) - load_balancer_backend_address_pool_ids = try(local.load_balancer_backend_address_pool_ids, null) + name = azurecaf_name.linux_nic[network_interface.key].result + primary = try(network_interface.value.primary, false) + subnet_id = try(var.vnets[var.client_config.landingzone_key][network_interface.value.vnet_key].subnets[network_interface.value.subnet_key].id, var.vnets[network_interface.value.lz_key][network_interface.value.vnet_key].subnets[network_interface.value.subnet_key].id) + load_balancer_backend_address_pool_ids = try(local.load_balancer_backend_address_pool_ids, null) application_gateway_backend_address_pool_ids = try(local.application_gateway_backend_address_pool_ids, null) - application_security_group_ids = try(local.application_security_group_ids,null) + application_security_group_ids = try(local.application_security_group_ids, null) } } } diff --git a/modules/compute/virtual_machine_scale_set/vmss_windows.tf b/modules/compute/virtual_machine_scale_set/vmss_windows.tf index 3f9e03389e..abca6a8bc1 100644 --- a/modules/compute/virtual_machine_scale_set/vmss_windows.tf +++ b/modules/compute/virtual_machine_scale_set/vmss_windows.tf @@ -17,7 +17,7 @@ resource "azurecaf_name" "windows_computer_name_prefix" { for_each = local.os_type == "windows" ? var.settings.vmss_settings : {} name = try(each.value.computer_name_prefix, each.value.name) - resource_type = "azurerm_vm_windows_computer_name_prefix" + resource_type = "azurerm_vm_windows_computer_name_prefix" prefixes = var.global_settings.prefixes random_length = var.global_settings.random_length clean_input = true @@ -87,12 +87,12 @@ resource "azurerm_windows_virtual_machine_scale_set" "vmss" { network_security_group_id = try(network_interface.value.network_security_group_id, null) ip_configuration { - name = azurecaf_name.windows_nic[network_interface.key].result - primary = try(network_interface.value.primary, false) - subnet_id = try(var.vnets[var.client_config.landingzone_key][network_interface.value.vnet_key].subnets[network_interface.value.subnet_key].id, var.vnets[network_interface.value.lz_key][network_interface.value.vnet_key].subnets[network_interface.value.subnet_key].id) - load_balancer_backend_address_pool_ids = try(local.load_balancer_backend_address_pool_ids, null) + name = azurecaf_name.windows_nic[network_interface.key].result + primary = try(network_interface.value.primary, false) + subnet_id = try(var.vnets[var.client_config.landingzone_key][network_interface.value.vnet_key].subnets[network_interface.value.subnet_key].id, var.vnets[network_interface.value.lz_key][network_interface.value.vnet_key].subnets[network_interface.value.subnet_key].id) + load_balancer_backend_address_pool_ids = try(local.load_balancer_backend_address_pool_ids, null) application_gateway_backend_address_pool_ids = try(local.application_gateway_backend_address_pool_ids, null) - application_security_group_ids = try(local.application_security_group_ids,null) + application_security_group_ids = try(local.application_security_group_ids, null) } } } @@ -133,7 +133,7 @@ resource "azurerm_windows_virtual_machine_scale_set" "vmss" { } source_image_id = try(each.value.custom_image_id, var.custom_image_ids[each.value.lz_key][each.value.custom_image_key].id, null) - + dynamic "plan" { for_each = try(each.value.plan, null) != null ? [1] : [] @@ -200,10 +200,10 @@ resource "azurerm_windows_virtual_machine_scale_set" "vmss" { for_each = try(each.value.automatic_os_upgrade_policy, false) == false ? [] : [1] content { - disable_automatic_rollback = each.value.automatic_os_upgrade_policy.disable_automatic_rollback + disable_automatic_rollback = each.value.automatic_os_upgrade_policy.disable_automatic_rollback enable_automatic_os_upgrade = each.value.automatic_os_upgrade_policy.enable_automatic_os_upgrade } - } + } dynamic "additional_unattend_content" { for_each = try(each.value.additional_unattend_content, false) == false ? [] : [1] diff --git a/modules/compute/wvd_applications/main.tf b/modules/compute/wvd_applications/main.tf new file mode 100644 index 0000000000..b3f47d413b --- /dev/null +++ b/modules/compute/wvd_applications/main.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + azurecaf = { + source = "aztfmod/azurecaf" + } + } + required_version = ">= 0.13" +} diff --git a/modules/compute/wvd_applications/output.tf b/modules/compute/wvd_applications/output.tf new file mode 100644 index 0000000000..5a4aa46f95 --- /dev/null +++ b/modules/compute/wvd_applications/output.tf @@ -0,0 +1,5 @@ +output "id" { + value = azurerm_virtual_desktop_application.da.id + description = "The ID of the Virtual Desktop Application." +} + diff --git a/modules/compute/wvd_applications/variables.tf b/modules/compute/wvd_applications/variables.tf new file mode 100644 index 0000000000..a62a23366d --- /dev/null +++ b/modules/compute/wvd_applications/variables.tf @@ -0,0 +1,11 @@ +variable "settings" {} +variable "global_settings" {} + +variable "application_group_id" { + default = {} +} + +variable "diagnostic_profiles" { + default = null +} +variable "diagnostics" {} diff --git a/modules/compute/wvd_applications/virtual_desktop_application.tf b/modules/compute/wvd_applications/virtual_desktop_application.tf new file mode 100644 index 0000000000..da8611a5e4 --- /dev/null +++ b/modules/compute/wvd_applications/virtual_desktop_application.tf @@ -0,0 +1,13 @@ +resource "azurerm_virtual_desktop_application" "da" { + name = var.settings.name + application_group_id = var.application_group_id + friendly_name = try(var.settings.friendly_name, null) + description = try(var.settings.description, null) + path = var.settings.path + command_line_argument_policy = var.settings.command_line_argument_policy + command_line_arguments = try(var.settings.command_line_arguments, null) + show_in_portal = try(var.settings.show_in_portal, null) + icon_path = try(var.settings.icon_path, null) + icon_index = try(var.settings.icon_index, null) +} + diff --git a/modules/compute/wvd_host_pool/virtual_desktop_host_pool.tf b/modules/compute/wvd_host_pool/virtual_desktop_host_pool.tf index ee17ee4cea..763d5cda46 100644 --- a/modules/compute/wvd_host_pool/virtual_desktop_host_pool.tf +++ b/modules/compute/wvd_host_pool/virtual_desktop_host_pool.tf @@ -8,6 +8,10 @@ resource "azurecaf_name" "wvdpool" { use_slug = var.global_settings.use_slug } + +# Last review : AzureRM version 2.63.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_desktop_host_pool + resource "azurerm_virtual_desktop_host_pool" "wvdpool" { location = var.location resource_group_name = var.resource_group_name @@ -21,6 +25,7 @@ resource "azurerm_virtual_desktop_host_pool" "wvdpool" { personal_desktop_assignment_type = try(var.settings.personal_desktop_assignment_type, null) preferred_app_group_type = try(var.settings.preferred_app_group_type, null) custom_rdp_properties = try(var.settings.custom_rdp_properties, null) + start_vm_on_connect = try(var.settings.start_vm_on_connect, null) tags = local.tags dynamic "registration_info" { diff --git a/modules/databases/cosmos_dbs/README.md b/modules/databases/cosmos_dbs/README.md deleted file mode 100755 index 76d36cb767..0000000000 --- a/modules/databases/cosmos_dbs/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# Azure Cosmos DB - -This submodule is part of Cloud Adoption Framework landing zones for Azure on Terraform. - -You can instantiate this submodule directly using the following parameters: - -``` -module "caf_cosmos_db" { - source = "aztfmod/caf/azurerm//modules/databases/cosmos_db" - version = "4.21.2" - # insert the 5 required variables here -} -``` - - -## Requirements - -No requirements. - -## Providers - -| Name | Version | -|------|---------| -| azurecaf | n/a | -| azurerm | n/a | - -## Modules - -| Name | Source | Version | -|------|--------|---------| -| cassandra_keyspaces | ./cassandra_keyspace | | -| gremlin_databases | ./gremlin_database | | -| mongo_databases | ./mongo_database | | -| sql_databases | ./sql_database | | -| tables | ./table | | - -## Resources - -| Name | -|------| -| [azurecaf_name](https://registry.terraform.io/providers/aztfmod/azurecaf/latest/docs/resources/name) | -| [azurerm_cosmosdb_account](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/cosmosdb_account) | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| base\_tags | Base tags for the resource to be inherited from the resource group. | `map(any)` | n/a | yes | -| global\_settings | Global settings object (see module README.md) | `any` | n/a | yes | -| location | (Required) Specifies the supported Azure location where to create the resource. Changing this forces a new resource to be created. | `string` | n/a | yes | -| resource\_group\_name | (Required) The name of the resource group where to create the resource. | `string` | n/a | yes | -| settings | n/a | `any` | n/a | yes | - -## Outputs - -| Name | Description | -|------|-------------| -| cassandra\_keyspaces | n/a | -| connection\_string | n/a | -| cosmos\_account | n/a | -| endpoint | n/a | -| gremlin\_databases | n/a | -| mongo\_databases | n/a | -| primary\_key | n/a | -| sql\_databases | n/a | -| tables | n/a | - \ No newline at end of file diff --git a/modules/databases/mssql_managed_database/variables.tf b/modules/databases/mssql_managed_database/variables.tf index f4be403b91..62423c0e05 100755 --- a/modules/databases/mssql_managed_database/variables.tf +++ b/modules/databases/mssql_managed_database/variables.tf @@ -17,4 +17,4 @@ variable "location" { } variable "sourceDatabaseId" { default = "" -} +} \ No newline at end of file diff --git a/modules/databases/mssql_managed_instance/managed_instance.tf b/modules/databases/mssql_managed_instance/managed_instance.tf index a7a104203b..8ef7f0228c 100644 --- a/modules/databases/mssql_managed_instance/managed_instance.tf +++ b/modules/databases/mssql_managed_instance/managed_instance.tf @@ -44,4 +44,4 @@ resource "null_resource" "destroy_sqlmi" { } } -} +} \ No newline at end of file diff --git a/modules/diagnostics/module.tf b/modules/diagnostics/module.tf index 65d55512d3..ec7230aab7 100755 --- a/modules/diagnostics/module.tf +++ b/modules/diagnostics/module.tf @@ -8,7 +8,11 @@ resource "azurerm_monitor_diagnostic_setting" "diagnostics" { name = try(format("%s%s", try(var.global_settings.prefix_with_hyphen, ""), each.value.name), format("%s%s", try(var.global_settings.prefix_with_hyphen, ""), var.diagnostics.diagnostics_definition[each.value.definition_key].name)) target_resource_id = var.resource_id - eventhub_name = each.value.destination_type == "event_hub" ? try(var.diagnostics.event_hub_namespaces[var.diagnostics.diagnostics_destinations.event_hub_namespaces[each.value.destination_key].event_hub_namespace_key].name, null) : null + eventhub_name = each.value.destination_type == "event_hub" ? coalesce( + try(var.diagnostics.event_hub_namespaces[var.diagnostics.diagnostics_destinations.event_hub_namespaces[each.value.destination_key].event_hub_namespace_key].event_hubs[each.value.event_hub_key].name, null), + var.diagnostics.event_hub_namespaces[var.diagnostics.diagnostics_destinations.event_hub_namespaces[each.value.destination_key].event_hub_namespace_key].name + ) : null + eventhub_authorization_rule_id = each.value.destination_type == "event_hub" ? format("%s/authorizationRules/RootManageSharedAccessKey", var.diagnostics.event_hub_namespaces[var.diagnostics.diagnostics_destinations.event_hub_namespaces[each.value.destination_key].event_hub_namespace_key].id) : null log_analytics_workspace_id = each.value.destination_type == "log_analytics" ? var.diagnostics.log_analytics[var.diagnostics.diagnostics_destinations.log_analytics[each.value.destination_key].log_analytics_key].id : null diff --git a/modules/event_hubs/consumer_groups/consumer_groups.tf b/modules/event_hubs/consumer_groups/consumer_groups.tf index 15134aabfb..a24a77dfea 100644 --- a/modules/event_hubs/consumer_groups/consumer_groups.tf +++ b/modules/event_hubs/consumer_groups/consumer_groups.tf @@ -8,10 +8,13 @@ resource "azurecaf_name" "evhcg_name" { use_slug = var.global_settings.use_slug } +# Last reviewed : AzureRM version 2.64.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/eventhub_consumer_group + resource "azurerm_eventhub_consumer_group" "evhcg" { name = azurecaf_name.evhcg_name.result namespace_name = var.namespace_name eventhub_name = var.eventhub_name resource_group_name = var.resource_group_name - user_metadata = var.settings.user_metadata + user_metadata = try(var.settings.user_metadata, null) } \ No newline at end of file diff --git a/modules/event_hubs/consumer_groups/output.tf b/modules/event_hubs/consumer_groups/output.tf index 441b20fe71..1cff7b3b94 100755 --- a/modules/event_hubs/consumer_groups/output.tf +++ b/modules/event_hubs/consumer_groups/output.tf @@ -1,3 +1,4 @@ output "id" { - value = azurerm_eventhub_consumer_group.evhcg.id + description = "The ID of the EventHub Consumer Group." + value = azurerm_eventhub_consumer_group.evhcg.id } \ No newline at end of file diff --git a/modules/event_hubs/consumer_groups/variables.tf b/modules/event_hubs/consumer_groups/variables.tf index 9c21a58212..9e95a7073a 100755 --- a/modules/event_hubs/consumer_groups/variables.tf +++ b/modules/event_hubs/consumer_groups/variables.tf @@ -1,7 +1,16 @@ variable "global_settings" {} variable "settings" {} -variable "resource_group_name" {} +variable "resource_group_name" { + description = "Name of the resource group." + type = string +} variable "client_config" {} -variable "namespace_name" {} -variable "eventhub_name" {} +variable "namespace_name" { + description = "Name of the Event Hub Namespace." + type = string +} +variable "eventhub_name" { + description = "Name of the Event Hub." + type = string +} diff --git a/modules/event_hubs/hubs/auth_rules/auth_rules.tf b/modules/event_hubs/hubs/auth_rules/auth_rules.tf index c54337bc50..537aa05e5f 100644 --- a/modules/event_hubs/hubs/auth_rules/auth_rules.tf +++ b/modules/event_hubs/hubs/auth_rules/auth_rules.tf @@ -8,12 +8,15 @@ resource "azurecaf_name" "evh_rule" { use_slug = var.global_settings.use_slug } +# Last reviewed : AzureRM version 2.64.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/eventhub_authorization_rule + resource "azurerm_eventhub_authorization_rule" "evhub_rule" { name = azurecaf_name.evh_rule.result namespace_name = var.namespace_name eventhub_name = var.eventhub_name resource_group_name = var.resource_group_name - listen = var.settings.listen - send = var.settings.send - manage = var.settings.manage + listen = try(var.settings.listen, false) + send = try(var.settings.send, false) + manage = try(var.settings.manage, false) } \ No newline at end of file diff --git a/modules/event_hubs/hubs/event_hub.tf b/modules/event_hubs/hubs/event_hub.tf index bf655a7af6..1ee6f71f12 100644 --- a/modules/event_hubs/hubs/event_hub.tf +++ b/modules/event_hubs/hubs/event_hub.tf @@ -8,27 +8,32 @@ resource "azurecaf_name" "evhub" { use_slug = var.global_settings.use_slug } +# Last reviewed : AzureRM version 2.64.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/eventhub_authorization_rule + resource "azurerm_eventhub" "evhub" { name = azurecaf_name.evhub.result namespace_name = var.namespace_name resource_group_name = var.resource_group_name partition_count = var.settings.partition_count message_retention = var.settings.message_retention + status = try(var.settings.status, null) dynamic "capture_description" { - for_each = try(var.settings.capture_description, {}) + for_each = try(var.settings.capture_description, false) == false ? [] : [1] content { - enabled = capture_description.value.enabled - encoding = capture_description.value.encoding - interval_in_seconds = try(capture_description.value.interval_in_seconds, null) - size_limit_in_bytes = try(capture_description.value.size_limit_in_bytes, null) - skip_empty_archives = try(capture_description.value.skip_empty_archives, null) + enabled = var.settings.capture_description.enabled + encoding = var.settings.capture_description.encoding + interval_in_seconds = try(var.settings.capture_description.interval_in_seconds, null) + size_limit_in_bytes = try(var.settings.capture_description.size_limit_in_bytes, null) + skip_empty_archives = try(var.settings.capture_description.skip_empty_archives, null) + dynamic "destination" { # required if capture_description is set - for_each = try(var.settings.capture_description.destination, {}) + for_each = try(var.settings.capture_description.destination, false) == false ? [] : [1] content { - name = destination.value.name # At this time(12/2020), the only supported value is EventHubArchive.AzureBlockBlob - archive_name_format = destination.value.archive_name_format # e.g. {Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second} - blob_container_name = destination.value.blob_container_name + name = var.settings.capture_description.destination.name # At this time(12/2020), the only supported value is EventHubArchive.AzureBlockBlob + archive_name_format = var.settings.capture_description.destination.archive_name_format # e.g. {Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second} + blob_container_name = var.settings.capture_description.destination.blob_container_name storage_account_id = var.storage_account_id } } diff --git a/modules/event_hubs/hubs/output.tf b/modules/event_hubs/hubs/output.tf index 89514334c1..bc28258e59 100755 --- a/modules/event_hubs/hubs/output.tf +++ b/modules/event_hubs/hubs/output.tf @@ -1,8 +1,9 @@ output "id" { - value = azurerm_eventhub.evhub.id + description = "The ID of the EventHub." + value = azurerm_eventhub.evhub.id } output "name" { - description = "The EventHub name." + description = "The name of the EventHub." value = azurerm_eventhub.evhub.name } \ No newline at end of file diff --git a/modules/event_hubs/hubs/variables.tf b/modules/event_hubs/hubs/variables.tf index 7b794dae15..8113b24c8c 100755 --- a/modules/event_hubs/hubs/variables.tf +++ b/modules/event_hubs/hubs/variables.tf @@ -1,7 +1,16 @@ variable "global_settings" {} variable "settings" {} -variable "resource_group_name" {} +variable "resource_group_name" { + description = "Name of the resource group." + type = string +} variable "base_tags" {} variable "client_config" {} -variable "namespace_name" {} -variable "storage_account_id" {} +variable "namespace_name" { + description = "Name of the Event Hub Namespace." + type = string +} +variable "storage_account_id" { + description = "Identifier of the storage account ID to be used." + type = string +} diff --git a/modules/event_hubs/namespaces/README.md b/modules/event_hubs/namespaces/README.md deleted file mode 100755 index 970ecd3729..0000000000 --- a/modules/event_hubs/namespaces/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# Azure Event Hub Namespace - -This submodule is part of Cloud Adoption Framework landing zones for Azure on Terraform. - -You can instantiate this submodule directly using the following parameters: - -``` -module "caf_event_hub_namespaces" { - source = "aztfmod/caf/azurerm//modules/event_hub_namespaces" - version = "4.21.2" - # insert the 5 required variables here -} -``` - - -## Requirements - -| Name | Version | -|------|---------| -| terraform | >= 0.13 | - -## Providers - -| Name | Version | -|------|---------| -| azurecaf | n/a | -| azurerm | n/a | - -## Modules - -| Name | Source | Version | -|------|--------|---------| -| event_hub_namespace_auth_rules | ./auth_rules | | -| event_hubs | ../hubs | | - -## Resources - -| Name | -|------| -| [azurecaf_name](https://registry.terraform.io/providers/aztfmod/azurecaf/latest/docs/resources/name) | -| [azurerm_eventhub_namespace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/eventhub_namespace) | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| base\_tags | Base tags for the resource to be inherited from the resource group. | `map(any)` | n/a | yes | -| client\_config | Client configuration object (see module README.md). | `any` | n/a | yes | -| global\_settings | Global settings object (see module README.md) | `any` | n/a | yes | -| location | n/a | `any` | n/a | yes | -| resource\_group\_name | n/a | `any` | n/a | yes | -| settings | n/a | `any` | n/a | yes | -| storage\_accounts | n/a | `map` | `{}` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| id | The EventHub Namespace ID. | -| location | Location of the service | -| name | The EventHub Namespace name. | -| resource\_group\_name | Name of the resource group | - \ No newline at end of file diff --git a/modules/event_hubs/namespaces/event_hubs.tf b/modules/event_hubs/namespaces/event_hubs.tf index d021a733a3..c127c05b44 100755 --- a/modules/event_hubs/namespaces/event_hubs.tf +++ b/modules/event_hubs/namespaces/event_hubs.tf @@ -7,6 +7,6 @@ module "event_hubs" { global_settings = var.global_settings settings = each.value namespace_name = azurerm_eventhub_namespace.evh.name - storage_account_id = var.storage_accounts[try(each.value.storage_account.lz_key, var.client_config.landingzone_key)][each.value.storage_account.key].id + storage_account_id = try(var.storage_accounts[try(each.value.storage_account.lz_key, var.client_config.landingzone_key)][each.value.storage_account.key].id, null) base_tags = merge(var.base_tags, try(each.value.tags, {})) } \ No newline at end of file diff --git a/modules/event_hubs/namespaces/output.tf b/modules/event_hubs/namespaces/output.tf index d4e22e6246..c74b1be454 100755 --- a/modules/event_hubs/namespaces/output.tf +++ b/modules/event_hubs/namespaces/output.tf @@ -17,3 +17,7 @@ output "location" { value = var.location description = "Location of the service" } + +output "event_hubs" { + value = module.event_hubs +} \ No newline at end of file diff --git a/modules/networking/application_gateway/application_gateway.tf b/modules/networking/application_gateway/application_gateway.tf index 871a8fc0b8..f7b17a7e07 100644 --- a/modules/networking/application_gateway/application_gateway.tf +++ b/modules/networking/application_gateway/application_gateway.tf @@ -47,6 +47,17 @@ resource "azurerm_application_gateway" "agw" { subnet_id = local.ip_configuration["gateway"].subnet_id } + dynamic "ssl_policy" { + for_each = try(var.settings.ssl_policy, null) == null ? [] : [1] + content { + disabled_protocols = try(var.settings.ssl_policy.disabled_protocols, null) + policy_type = try(var.settings.ssl_policy.policy_type, null) + policy_name = try(var.settings.ssl_policy.policy_name, null) + cipher_suites = try(var.settings.ssl_policy.cipher_suites, null) + min_protocol_version = try(var.settings.ssl_policy.min_protocol_version, null) + } + } + dynamic "autoscale_configuration" { for_each = try(var.settings.capacity.autoscale, null) == null ? [] : [1] diff --git a/modules/networking/application_gateway/locals.backend_pools.tf b/modules/networking/application_gateway/locals.backend_pools.tf index 5ee6f22b74..70536a5a19 100644 --- a/modules/networking/application_gateway/locals.backend_pools.tf +++ b/modules/networking/application_gateway/locals.backend_pools.tf @@ -33,7 +33,7 @@ locals { local.backend_pools_app_services[key], local.backend_pools_fqdn[key] ] - ),null) + ), null) ip_addresses = try(value.backend_pool.ip_addresses, null) } } diff --git a/modules/networking/application_gateway/locals.networking.tf b/modules/networking/application_gateway/locals.networking.tf index 790d273582..8606f118ee 100644 --- a/modules/networking/application_gateway/locals.networking.tf +++ b/modules/networking/application_gateway/locals.networking.tf @@ -1,10 +1,18 @@ locals { - gateway_vnet_local = try(var.vnets[var.client_config.landingzone_key][var.settings.vnet_key], null) + gateway_vnet_local = try(coalesce( + try(var.vnets[var.client_config.landingzone_key][var.settings.vnet_key], null), + try(var.vnets[var.client_config.landingzone_key][var.settings.subnet.vnet_key], null) + ), null ) + private_vnet_local = try(var.vnets[var.client_config.landingzone_key][var.settings.front_end_ip_configurations.private.vnet_key], null) public_vnet_local = try(var.vnets[var.client_config.landingzone_key][var.settings.front_end_ip_configurations.public.vnet_key], null) - gateway_vnet_remote = try(var.vnets[var.settings.lz_key][var.settings.vnet_key], null) + gateway_vnet_remote = try(coalesce( + try(var.vnets[var.settings.lz_key][var.settings.vnet_key], null), + try(var.vnets[var.settings.subnet.lz_key][var.settings.subnet.vnet_key], null) + ), null ) + private_vnet_remote = try(var.vnets[var.settings.front_end_ip_configurations.private.lz_key][var.settings.front_end_ip_configurations.private.vnet_key], null) public_vnet_remote = try(var.vnets[var.settings.front_end_ip_configurations.public.lz_key][var.settings.front_end_ip_configurations.public.vnet_key], null) diff --git a/modules/networking/domain_name_registrations/arm_domain.json b/modules/networking/domain_name_registrations/arm_domain.json index a7e8236887..ce2dc460da 100644 --- a/modules/networking/domain_name_registrations/arm_domain.json +++ b/modules/networking/domain_name_registrations/arm_domain.json @@ -33,8 +33,8 @@ "agreedAt": "${consent.agreedAt}", "agreedBy": "${consent.agreedBy}" }, - "privacy": ${privacy}, - "autoRenew": ${autoRenew}, + "privacy": "${privacy}", + "autoRenew": "${autoRenew}", "targetDnsType": "[if(empty(parameters('targetDnsType')), variables('empty'), parameters('targetDnsType'))]", "dnsType": "[if(empty(parameters('dnsType')), variables('empty'), parameters('dnsType'))]", "dnsZoneId": "[if(empty(parameters('dnsZoneId')), variables('empty'), parameters('dnsZoneId'))]", diff --git a/modules/networking/firewall/module.tf b/modules/networking/firewall/module.tf index 4537a2859e..cf2ec6adf8 100755 --- a/modules/networking/firewall/module.tf +++ b/modules/networking/firewall/module.tf @@ -19,7 +19,7 @@ resource "azurerm_firewall" "fw" { zones = try(var.settings.zones, null) sku_name = try(var.settings.sku_name, "AZFW_VNet") sku_tier = try(var.settings.sku_tier, "Standard") - firewall_policy_id = try(var.settings.firewall_policy_id, null) != null ? var.settings.firewall_policy_id : try(var.firewall_policies[var.settings.firewall_policy_key].id, null) + firewall_policy_id = var.firewall_policy_id dns_servers = try(var.settings.dns_servers, null) tags = local.tags diff --git a/modules/networking/firewall/variables.tf b/modules/networking/firewall/variables.tf index 192997c958..44ab61f3bc 100755 --- a/modules/networking/firewall/variables.tf +++ b/modules/networking/firewall/variables.tf @@ -61,6 +61,6 @@ variable "client_config" { default = {} } -variable "firewall_policies" { - default = {} +variable "firewall_policy_id" { + default = null } \ No newline at end of file diff --git a/modules/networking/firewall_dashboard/module.tf b/modules/networking/firewall_dashboard/module.txt similarity index 100% rename from modules/networking/firewall_dashboard/module.tf rename to modules/networking/firewall_dashboard/module.txt diff --git a/modules/networking/firewall_policies/firewall_policy.tf b/modules/networking/firewall_policies/firewall_policy.tf index f43665ac41..9faffdb6d9 100755 --- a/modules/networking/firewall_policies/firewall_policy.tf +++ b/modules/networking/firewall_policies/firewall_policy.tf @@ -17,7 +17,7 @@ resource "azurerm_firewall_policy" "fwpol" { location = var.location sku = try(var.policy_settings.sku, null) - base_policy_id = try(var.policy_settings.base_policy_id, null) + base_policy_id = var.base_policy_id threat_intelligence_mode = try(var.policy_settings.threat_intelligence_mode, "Alert") tags = local.tags diff --git a/modules/networking/firewall_policies/main.tf b/modules/networking/firewall_policies/main.tf index b33020ad7e..c1945ebfeb 100644 --- a/modules/networking/firewall_policies/main.tf +++ b/modules/networking/firewall_policies/main.tf @@ -11,5 +11,6 @@ locals { module_tag = { "module" = basename(abspath(path.module)) } - tags = merge(var.base_tags, local.module_tag, var.tags) + # tags = merge(var.base_tags, local.module_tag, var.tags) + tags = var.tags # temporal use until tag uppercase fixed } diff --git a/modules/networking/firewall_policies/variables.tf b/modules/networking/firewall_policies/variables.tf index 92da17a758..5fdcd07289 100755 --- a/modules/networking/firewall_policies/variables.tf +++ b/modules/networking/firewall_policies/variables.tf @@ -24,3 +24,9 @@ variable "base_tags" {} variable "name" { } + +variable "base_policy_id" { + type = string + default = null + description = "(Optional) The ID of the base Firewall Policy." +} diff --git a/modules/networking/firewall_policy_rule_collection_groups/firewall_policy_rule_collection_groups.tf b/modules/networking/firewall_policy_rule_collection_groups/firewall_policy_rule_collection_groups.tf index adaca05c7d..b496874535 100755 --- a/modules/networking/firewall_policy_rule_collection_groups/firewall_policy_rule_collection_groups.tf +++ b/modules/networking/firewall_policy_rule_collection_groups/firewall_policy_rule_collection_groups.tf @@ -48,7 +48,7 @@ resource "azurecaf_name" "nat_rule" { resource "azurerm_firewall_policy_rule_collection_group" "polgroup" { name = azurecaf_name.polgroup.result priority = var.policy_settings.priority - firewall_policy_id = try(var.policy_settings.firewall_policy_id, null) != null ? var.policy_settings.firewall_policy_id : try(var.firewall_policies[var.policy_settings.firewall_policy_key].id, null) + firewall_policy_id = var.firewall_policy_id dynamic "application_rule_collection" { for_each = try(var.policy_settings.application_rule_collections, {}) diff --git a/modules/networking/firewall_policy_rule_collection_groups/variables.tf b/modules/networking/firewall_policy_rule_collection_groups/variables.tf index b358e470a3..9feff5e1e2 100755 --- a/modules/networking/firewall_policy_rule_collection_groups/variables.tf +++ b/modules/networking/firewall_policy_rule_collection_groups/variables.tf @@ -6,14 +6,16 @@ variable "global_settings" { description = "Global settings object (see module README.md)" } -variable "firewall_policies" { - +variable "firewall_policy_id" { + description = "(Required) The ID of the Firewall Policy where the Firewall Policy Rule Collection Group should exist. Changing this forces a new Firewall Policy Rule Collection Group to be created." } variable "ip_groups" { - + description = "(Optional) Specifies a map of source IP groups." + default = {} } variable "public_ip_addresses" { - + description = "(Optional) A map of destination IP addresses (including CIDR)." + default = {} } \ No newline at end of file diff --git a/modules/networking/front_door/front_door.tf b/modules/networking/front_door/front_door.tf index 21270c1cd4..e28c051a15 100644 --- a/modules/networking/front_door/front_door.tf +++ b/modules/networking/front_door/front_door.tf @@ -8,6 +8,9 @@ resource "azurecaf_name" "frontdoor" { use_slug = try(var.settings.global_settings.use_slug, var.global_settings.use_slug) } +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/frontdoor +# Tested with AzureRM 2.57.0 + resource "azurerm_frontdoor" "frontdoor" { name = azurecaf_name.frontdoor.result resource_group_name = var.resource_group_name @@ -115,20 +118,25 @@ resource "azurerm_frontdoor" "frontdoor" { host_name = try(frontend_endpoint.value.host_name, format("%s.azurefd.net", azurecaf_name.frontdoor.result)) session_affinity_enabled = frontend_endpoint.value.session_affinity_enabled session_affinity_ttl_seconds = frontend_endpoint.value.session_affinity_ttl_seconds - custom_https_provisioning_enabled = try(frontend_endpoint.value.custom_https_provisioning_enabled, false) web_application_firewall_policy_link_id = try(frontend_endpoint.value.front_door_waf_policy.key, null) == null ? null : var.front_door_waf_policies[try(frontend_endpoint.value.front_door_waf_policy.lz_key, var.client_config.landingzone_key)][frontend_endpoint.value.front_door_waf_policy.key].id + } + } +} - dynamic "custom_https_configuration" { - for_each = try(frontend_endpoint.value.custom_https_provisioning_enabled, false) == true ? [frontend_endpoint.value.custom_https_configuration] : [] - content { - certificate_source = custom_https_configuration.value.certificate_source - azure_key_vault_certificate_vault_id = lookup(custom_https_configuration.value, "azure_key_vault_certificate_vault_id", null) == null ? try(var.keyvault_certificate_requests[var.client_config.landingzone_key][custom_https_configuration.value.certificate.key].keyvault_id, var.keyvault_certificate_requests[custom_https_configuration.value.certificate.lz_key][custom_https_configuration.value.certificate.key].keyvault_id) : custom_https_configuration.value.azure_key_vault_certificate_vault_id - azure_key_vault_certificate_secret_name = lookup(custom_https_configuration.value, "azure_key_vault_certificate_secret_name", null) == null ? try(var.keyvault_certificate_requests[var.client_config.landingzone_key][custom_https_configuration.value.certificate.key].name, var.keyvault_certificate_requests[custom_https_configuration.value.certificate.lz_key][custom_https_configuration.value.certificate.key].name) : custom_https_configuration.value.azure_key_vault_certificate_secret_name - azure_key_vault_certificate_secret_version = lookup(custom_https_configuration.value, "azure_key_vault_certificate_secret_version", null) == null ? try(var.keyvault_certificate_requests[var.client_config.landingzone_key][custom_https_configuration.value.certificate.key].version, var.keyvault_certificate_requests[custom_https_configuration.value.certificate.lz_key][custom_https_configuration.value.certificate.key].version) : custom_https_configuration.value.azure_key_vault_certificate_secret_version - } - } - } +resource "azurerm_frontdoor_custom_https_configuration" "frontdoor" { + for_each = { + for key, value in var.settings.frontend_endpoints : key => value + if try(value.custom_https_provisioning_enabled, false) } -} + frontend_endpoint_id = azurerm_frontdoor.frontdoor.frontend_endpoint[0].id + custom_https_provisioning_enabled = try(each.value.custom_https_provisioning_enabled, false) + + custom_https_configuration { + certificate_source = each.value.custom_https_configuration.certificate_source + azure_key_vault_certificate_vault_id = try(each.value.custom_https_configuration.azure_key_vault_certificate_vault_id, null) == null ? try(var.keyvault_certificate_requests[var.client_config.landingzone_key][each.value.custom_https_configuration.certificate.key].keyvault_id, var.keyvault_certificate_requests[each.value.custom_https_configuration.certificate.lz_key][each.value.custom_https_configuration.certificate.key].keyvault_id) : each.value.custom_https_configuration.azure_key_vault_certificate_vault_id + azure_key_vault_certificate_secret_name = try(each.value.custom_https_configuration.azure_key_vault_certificate_secret_name, null) == null ? try(var.keyvault_certificate_requests[var.client_config.landingzone_key][each.value.custom_https_configuration.certificate.key].name, var.keyvault_certificate_requests[each.value.custom_https_configuration.certificate.lz_key][each.value.custom_https_configuration.certificate.key].name) : each.value.custom_https_configuration.azure_key_vault_certificate_secret_name + azure_key_vault_certificate_secret_version = try(each.value.custom_https_configuration.azure_key_vault_certificate_secret_version, null) == null ? try(var.keyvault_certificate_requests[var.client_config.landingzone_key][each.value.custom_https_configuration.certificate.key].version, var.keyvault_certificate_requests[each.value.custom_https_configuration.certificate.lz_key][each.value.custom_https_configuration.certificate.key].version) : each.value.custom_https_configuration.azure_key_vault_certificate_secret_version + } +} \ No newline at end of file diff --git a/modules/networking/public_ip_addresses/module.tf b/modules/networking/public_ip_addresses/module.tf index 80bce8edeb..9c26ba0c8a 100755 --- a/modules/networking/public_ip_addresses/module.tf +++ b/modules/networking/public_ip_addresses/module.tf @@ -1,3 +1,6 @@ +# Last review : AzureRM version 2.63.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_desktop_host_pool + resource "azurerm_public_ip" "pip" { name = var.name resource_group_name = var.resource_group_name @@ -8,6 +11,8 @@ resource "azurerm_public_ip" "pip" { idle_timeout_in_minutes = var.idle_timeout_in_minutes domain_name_label = var.generate_domain_name_label ? var.name : var.domain_name_label reverse_fqdn = var.reverse_fqdn - zones = var.zones + availability_zone = var.zones tags = local.tags + public_ip_prefix_id = var.public_ip_prefix_id + ip_tags = var.ip_tags } \ No newline at end of file diff --git a/modules/networking/public_ip_addresses/output.tf b/modules/networking/public_ip_addresses/output.tf index 540fde6702..43f512fc81 100755 --- a/modules/networking/public_ip_addresses/output.tf +++ b/modules/networking/public_ip_addresses/output.tf @@ -1,14 +1,17 @@ output "id" { - value = azurerm_public_ip.pip.id + description = "The Public IP ID." + value = azurerm_public_ip.pip.id } output "ip_address" { - value = azurerm_public_ip.pip.ip_address + description = "The IP address value that was allocated." + value = azurerm_public_ip.pip.ip_address } output "fqdn" { - value = azurerm_public_ip.pip.fqdn + description = "Fully qualified domain name of the A DNS record associated with the public IP. domain_name_label must be specified to get the fqdn. This is the concatenation of the domain_name_label and the regionalized DNS zone." + value = azurerm_public_ip.pip.fqdn } diff --git a/modules/networking/public_ip_addresses/variables.tf b/modules/networking/public_ip_addresses/variables.tf index f35702ca80..8a1fc9e5bd 100755 --- a/modules/networking/public_ip_addresses/variables.tf +++ b/modules/networking/public_ip_addresses/variables.tf @@ -1,4 +1,7 @@ -variable "name" {} +variable "name" { + description = "(Required) Specifies the name of the Public IP resource . Changing this forces a new resource to be created." + type = string +} variable "resource_group_name" { description = "(Required) The name of the resource group where to create the resource." type = string @@ -8,39 +11,104 @@ variable "location" { type = string } variable "sku" { - default = "Basic" + description = "(Optional) The SKU of the Public IP. Accepted values are Basic and Standard. Defaults to Basic." + type = string + default = "Basic" + validation { + condition = contains(["Basic", "Standard"], var.sku) + error_message = "Provide an allowed value as defined in https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip#sku." + } } + variable "allocation_method" { - default = "Dynamic" + description = "(Required) Defines the allocation method for this IP address. Possible values are Static or Dynamic." + type = string + default = "Dynamic" + + validation { + condition = contains(["Dynamic", "Static"], var.allocation_method) + error_message = "Provide an allowed value as defined in https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip#allocation_method." + } } variable "ip_version" { - default = "IPv4" + description = "(Optional) The IP Version to use, IPv6 or IPv4." + type = string + default = "IPv4" + + validation { + condition = contains(["IPv4", "IPv6"], var.ip_version) + error_message = "Provide an allowed value as defined in https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip#ip_version." + } } + variable "idle_timeout_in_minutes" { - default = null + description = "(Optional) Specifies the timeout for the TCP idle connection. The value can be set between 4 and 30 minutes." + type = number + default = null + + validation { + condition = (try(var.idle_timeout_in_minutes, false) == true ? (var.idle_timeout_in_minutes.value >= 4 || var.idle_timeout_in_minutes.value <= 30) : true) + error_message = "Provide an allowed value as defined in https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip#idle_timeout_in_minutes." + } } + variable "domain_name_label" { - default = null + description = "(Optional) Label for the Domain Name. Will be used to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." + default = null + type = string } -# if set to true, automatically generate a domain name label with the name + variable "generate_domain_name_label" { - default = false + description = "Generate automatically the domain name label, if set to true, automatically generate a domain name label with the name" + type = bool + default = false } + variable "reverse_fqdn" { - default = null + description = "(Optional) A fully qualified domain name that resolves to this public IP address. If the reverseFqdn is specified, then a PTR DNS record is created pointing from the IP address in the in-addr.arpa domain to the reverse FQDN." + type = bool + default = null } + variable "tags" { - default = null + description = "(Optional) Tags for the resource to be deployed." + default = null + type = map(any) } + variable "zones" { - default = null + description = "(Optional) The availability zone to allocate the Public IP in. Possible values are Zone-Redundant, 1, 2, 3, and No-Zone. Defaults to Zone-Redundant." + type = string + default = "Zone-Redundant" + + validation { + condition = contains(["Zone-Redundant", "No-Zone", "1", "2", "3"], var.zones) + error_message = "Provide an allowed value as defined in https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip#availability_zone." + } } + variable "diagnostics" { - default = {} + description = "(Optional) Diagnostics objects where to deploy the diagnostics profiles." + default = {} } + variable "diagnostic_profiles" { - default = {} + description = "(Optional) Diagnostics profile settings to be deployed for the resource." + default = {} +} + +variable "ip_tags" { + description = "(Optional) A mapping of IP tags to assign to the public IP." + default = {} + type = map(any) +} + +variable "public_ip_prefix_id" { + description = "(Optional) If specified then public IP address allocated will be provided from the public IP prefix resource." + default = "" + type = string } + variable "base_tags" { description = "Base tags for the resource to be inherited from the resource group." type = map(any) diff --git a/modules/networking/virtual_wan/virtual_hub/site_to_site_gateway.tf b/modules/networking/virtual_wan/virtual_hub/site_to_site_gateway.tf index 270d0091f2..da3c99ff12 100644 --- a/modules/networking/virtual_wan/virtual_hub/site_to_site_gateway.tf +++ b/modules/networking/virtual_wan/virtual_hub/site_to_site_gateway.tf @@ -38,7 +38,7 @@ resource "azurerm_vpn_gateway" "s2s_gateway" { custom_ips = var.virtual_hub_config.s2s_config.bgp_settings.instance_0_bgp_peering_address.custom_ips } } - + dynamic "instance_1_bgp_peering_address" { for_each = try(var.virtual_hub_config.s2s_config.bgp_settings.instance_1_bgp_peering_address, null) == null ? [] : [1] @@ -46,7 +46,7 @@ resource "azurerm_vpn_gateway" "s2s_gateway" { custom_ips = var.virtual_hub_config.s2s_config.bgp_settings.instance_1_bgp_peering_address.custom_ips } } - + } } diff --git a/modules/networking/vpn_gateway_connection/main.tf b/modules/networking/vpn_gateway_connection/main.tf new file mode 100644 index 0000000000..1fbfa06797 --- /dev/null +++ b/modules/networking/vpn_gateway_connection/main.tf @@ -0,0 +1,7 @@ +terraform { + required_providers { + azurecaf = { + source = "aztfmod/azurecaf" + } + } +} diff --git a/modules/networking/vpn_gateway_connection/module.tf b/modules/networking/vpn_gateway_connection/module.tf new file mode 100644 index 0000000000..aebdd66367 --- /dev/null +++ b/modules/networking/vpn_gateway_connection/module.tf @@ -0,0 +1,71 @@ +resource "azurecaf_name" "vpn_gateway_connection" { + name = var.settings.name + resource_type = "azurerm_vpn_gateway_connection" + prefixes = var.global_settings.prefixes + random_length = var.global_settings.random_length + clean_input = true + passthrough = var.global_settings.passthrough + use_slug = var.global_settings.use_slug +} + +resource "azurerm_vpn_gateway_connection" "vpn_gateway_connection" { + name = azurecaf_name.vpn_gateway_connection.result + vpn_gateway_id = var.vpn_gateway_id + internet_security_enabled = var.settings.internet_security_enabled + + remote_vpn_site_id = coalesce( + try(var.vpn_sites[try(var.settings.vpn_site.lz_key, var.client_config.landingzone_key)][var.settings.vpn_site.key].vpn_site.id, null), + try(var.settings.vpn_site_id, null) + ) + + dynamic "vpn_link" { + for_each = var.settings.vpn_links + content { + name = vpn_link.value.name + bandwidth_mbps = try(vpn_link.value.bandwidth_mbps, null) + bgp_enabled = try(vpn_link.value.bgp_enabled, null) + protocol = try(vpn_link.value.protocol, null) + ratelimit_enabled = try(vpn_link.value.ratelimit_enabled, null) + route_weight = try(vpn_link.value.route_weight, null) + shared_key = try(vpn_link.value.shared_key, null) + local_azure_ip_address_enabled = try(vpn_link.value.local_azure_ip_address_enabled, null) + policy_based_traffic_selector_enabled = try(vpn_link.value.policy_based_traffic_selector_enabled, null) + + vpn_site_link_id = coalesce( + try(var.vpn_sites[try(var.settings.vpn_site.lz_key, var.client_config.landingzone_key)][var.settings.vpn_site.key].vpn_site.link[vpn_link.value.link_index].id, null), + try(vpn_link.value.vpn_link_id, null) + ) + + dynamic "ipsec_policy" { + for_each = vpn_link.value.ipsec_policies + content { + dh_group = ipsec_policy.value.dh_group + ike_encryption_algorithm = ipsec_policy.value.ike_encryption_algorithm + ike_integrity_algorithm = ipsec_policy.value.ike_integrity_algorithm + encryption_algorithm = ipsec_policy.value.encryption_algorithm + integrity_algorithm = ipsec_policy.value.integrity_algorithm + pfs_group = ipsec_policy.value.pfs_group + sa_data_size_kb = ipsec_policy.value.sa_data_size_kb + sa_lifetime_sec = ipsec_policy.value.sa_lifetime_sec + } + } + } + } + + dynamic "routing" { + for_each = lookup(var.settings, "routing", null) == null ? [] : [1] + content { + associated_route_table = coalesce( + try(var.route_tables[try(var.settings.routing.associated_route_table.lz_key, var.client_config.landingzone_key)][var.settings.routing.associated_route_table.key].id, null), + try(var.settings.routing.associated_route_table.id, null) + ) + + propagated_route_tables = [ + for key, value in var.settings.routing.propagated_route_tables : coalesce( + try(var.route_tables[try(value.lz_key, var.client_config.landingzone_key)][value.key].id, null), + try(value.id, null) + ) + ] + } + } +} diff --git a/modules/networking/vpn_gateway_connection/output.tf b/modules/networking/vpn_gateway_connection/output.tf new file mode 100755 index 0000000000..a136b5ef4b --- /dev/null +++ b/modules/networking/vpn_gateway_connection/output.tf @@ -0,0 +1,4 @@ +output "vpn_gateway_connection" { + value = azurerm_vpn_gateway_connection.vpn_gateway_connection + description = "VPN Gateway Connection object" +} diff --git a/modules/networking/vpn_gateway_connection/variables.tf b/modules/networking/vpn_gateway_connection/variables.tf new file mode 100755 index 0000000000..abb3037c16 --- /dev/null +++ b/modules/networking/vpn_gateway_connection/variables.tf @@ -0,0 +1,8 @@ +variable "settings" {} +variable "global_settings" { + description = "Global settings object (see module README.md)" +} +variable "vpn_gateway_id" {} +variable "vpn_sites" {} +variable "client_config" {} +variable "route_tables" {} diff --git a/modules/networking/vpn_site/main.tf b/modules/networking/vpn_site/main.tf new file mode 100644 index 0000000000..4a54194d01 --- /dev/null +++ b/modules/networking/vpn_site/main.tf @@ -0,0 +1,14 @@ +locals { + module_tag = { + "module" = basename(abspath(path.module)) + } + tags = merge(var.base_tags, local.module_tag, try(var.settings.tags, null)) +} + +terraform { + required_providers { + azurecaf = { + source = "aztfmod/azurecaf" + } + } +} diff --git a/modules/networking/vpn_site/module.tf b/modules/networking/vpn_site/module.tf new file mode 100644 index 0000000000..42014668fe --- /dev/null +++ b/modules/networking/vpn_site/module.tf @@ -0,0 +1,39 @@ +resource "azurecaf_name" "vpn_site" { + name = var.settings.name + resource_type = "azurerm_vpn_site" + prefixes = var.global_settings.prefixes + random_length = var.global_settings.random_length + clean_input = true + passthrough = var.global_settings.passthrough + use_slug = var.global_settings.use_slug +} + +resource "azurerm_vpn_site" "vpn_site" { + name = azurecaf_name.vpn_site.result + location = var.location + resource_group_name = var.resource_group_name + virtual_wan_id = var.virtual_wan_id + address_cidrs = try(var.settings.address_cidrs, null) + device_model = try(var.settings.device_model, null) + device_vendor = try(var.settings.device_vendor, null) + tags = local.tags + + dynamic "link" { + for_each = try(var.settings.links, {}) + content { + name = link.value.name + ip_address = try(link.value.ip_address, null) + fqdn = try(link.value.fqdn, null) + provider_name = try(link.value.provider_name, null) + speed_in_mbps = try(link.value.speed_in_mbps, null) + + dynamic "bgp" { + for_each = try([link.value.bgp], []) # TODO - Check this works + content { + asn = bgp.value.asn + peering_address = bgp.value.peering_address + } + } + } + } +} diff --git a/modules/networking/vpn_site/output.tf b/modules/networking/vpn_site/output.tf new file mode 100755 index 0000000000..36e43817e5 --- /dev/null +++ b/modules/networking/vpn_site/output.tf @@ -0,0 +1,4 @@ +output "vpn_site" { + value = azurerm_vpn_site.vpn_site + description = "VPN Site object" +} diff --git a/modules/networking/vpn_site/variables.tf b/modules/networking/vpn_site/variables.tf new file mode 100755 index 0000000000..f494c1be93 --- /dev/null +++ b/modules/networking/vpn_site/variables.tf @@ -0,0 +1,17 @@ +variable "resource_group_name" { + description = "(Required) The name of the resource group where to create the resource." + type = string +} +variable "location" { + description = "(Required) Specifies the supported Azure location where to create the resource. Changing this forces a new resource to be created." + type = string +} +variable "base_tags" { + description = "Base tags for the resource to be inherited from the resource group." + type = map(any) +} +variable "settings" {} +variable "global_settings" { + description = "Global settings object (see module README.md)" +} +variable "virtual_wan_id" {} diff --git a/modules/random_string/main.tf b/modules/random_string/main.tf new file mode 100644 index 0000000000..b3f47d413b --- /dev/null +++ b/modules/random_string/main.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + azurecaf = { + source = "aztfmod/azurecaf" + } + } + required_version = ">= 0.13" +} diff --git a/modules/random_string/module.tf b/modules/random_string/module.tf new file mode 100644 index 0000000000..b268a3eb1c --- /dev/null +++ b/modules/random_string/module.tf @@ -0,0 +1,6 @@ +resource "random_string" "rs" { + length = var.random_string_length + special = var.random_string_allow_special_characters + upper = var.random_string_allow_upper_case + number = var.random_string_allow_numbers +} diff --git a/modules/random_string/output.tf b/modules/random_string/output.tf new file mode 100755 index 0000000000..f9ecfed5fe --- /dev/null +++ b/modules/random_string/output.tf @@ -0,0 +1,9 @@ +output "result" { + value = random_string.rs.result + +} + +output "id" { + value = random_string.rs.id + +} diff --git a/modules/random_string/variables.tf b/modules/random_string/variables.tf new file mode 100755 index 0000000000..5cdf002349 --- /dev/null +++ b/modules/random_string/variables.tf @@ -0,0 +1,15 @@ +variable "random_string_length" { + description = "(Required) The length of the random string to be created" +} +variable "random_string_allow_special_characters" { + description = "Allows special characters in the random string to be created" + default = false +} +variable "random_string_allow_upper_case" { + description = "Allows upper case letters in the random string to be created" + default = false +} +variable "random_string_allow_numbers" { + description = "Allows numbers in the random string to be created" + default = false +} diff --git a/modules/recovery_vault/azure_recovery_fabric.tf b/modules/recovery_vault/azure_recovery_fabric.tf index e9d4bfc914..07a159958a 100644 --- a/modules/recovery_vault/azure_recovery_fabric.tf +++ b/modules/recovery_vault/azure_recovery_fabric.tf @@ -1,9 +1,12 @@ +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/site_recovery_fabric + resource "azurerm_site_recovery_fabric" "recovery_fabric" { - depends_on = [azurerm_recovery_services_vault.asr, time_sleep.delay_create] + depends_on = [time_sleep.delay_create] for_each = try(var.settings.recovery_fabrics, {}) name = each.value.name resource_group_name = var.resource_group_name - recovery_vault_name = azurecaf_name.asr_rg_vault.result + recovery_vault_name = azurerm_recovery_services_vault.asr.name location = var.global_settings.regions[each.value.region] } \ No newline at end of file diff --git a/modules/recovery_vault/backup_policies_file_share.tf b/modules/recovery_vault/backup_policies_file_share.tf index 3008a91298..472680fb52 100644 --- a/modules/recovery_vault/backup_policies_file_share.tf +++ b/modules/recovery_vault/backup_policies_file_share.tf @@ -1,10 +1,12 @@ +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_policy_file_share + resource "azurerm_backup_policy_file_share" "fs" { - depends_on = [azurerm_recovery_services_vault.asr] - for_each = try(var.settings.backup_policies.fs, {}) + for_each = try(var.settings.backup_policies.fs, {}) name = each.value.name resource_group_name = var.resource_group_name - recovery_vault_name = azurecaf_name.asr_rg_vault.result + recovery_vault_name = azurerm_recovery_services_vault.asr.name timezone = try(each.value.timezone, null) diff --git a/modules/recovery_vault/backup_policies_vm.tf b/modules/recovery_vault/backup_policies_vm.tf index 1bbd5a5fec..2bf21ed6ff 100644 --- a/modules/recovery_vault/backup_policies_vm.tf +++ b/modules/recovery_vault/backup_policies_vm.tf @@ -1,11 +1,12 @@ +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_policy_vm resource "azurerm_backup_policy_vm" "vm" { - depends_on = [azurerm_recovery_services_vault.asr] - for_each = try(var.settings.backup_policies.vms, {}) + for_each = try(var.settings.backup_policies.vms, {}) name = each.value.name resource_group_name = var.resource_group_name - recovery_vault_name = azurecaf_name.asr_rg_vault.result + recovery_vault_name = azurerm_recovery_services_vault.asr.name timezone = try(each.value.timezone, null) diff --git a/modules/recovery_vault/main.tf b/modules/recovery_vault/main.tf index aec15841cb..49a9a5eed3 100644 --- a/modules/recovery_vault/main.tf +++ b/modules/recovery_vault/main.tf @@ -14,7 +14,6 @@ terraform { } } - resource "time_sleep" "delay_create" { depends_on = [azurerm_recovery_services_vault.asr] diff --git a/modules/recovery_vault/protection_container.tf b/modules/recovery_vault/protection_container.tf index f97669c261..9458b43537 100644 --- a/modules/recovery_vault/protection_container.tf +++ b/modules/recovery_vault/protection_container.tf @@ -1,21 +1,24 @@ +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/site_recovery_protection_container + resource "azurerm_site_recovery_protection_container" "protection_container" { - depends_on = [azurerm_recovery_services_vault.asr, azurerm_site_recovery_fabric.recovery_fabric] - # depends_on = [time_sleep.delay_create] for_each = try(var.settings.protection_containers, {}) name = each.value.name resource_group_name = var.resource_group_name - recovery_vault_name = azurecaf_name.asr_rg_vault.result + recovery_vault_name = azurerm_recovery_services_vault.asr.name recovery_fabric_name = azurerm_site_recovery_fabric.recovery_fabric[each.value.recovery_fabric_key].name } +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/site_recovery_protection_container_mapping + resource "azurerm_site_recovery_protection_container_mapping" "container-mapping" { - depends_on = [azurerm_recovery_services_vault.asr, azurerm_site_recovery_fabric.recovery_fabric] - for_each = try(var.settings.protection_container_mapping, {}) + for_each = try(var.settings.protection_container_mapping, {}) name = each.value.name resource_group_name = var.resource_group_name - recovery_vault_name = azurecaf_name.asr_rg_vault.result + recovery_vault_name = azurerm_recovery_services_vault.asr.name recovery_fabric_name = azurerm_site_recovery_fabric.recovery_fabric[each.value.fabric_key].name recovery_source_protection_container_name = azurerm_site_recovery_protection_container.protection_container[each.value.source_protection_container_key].name recovery_target_protection_container_id = azurerm_site_recovery_protection_container.protection_container[each.value.target_protection_container_key].id diff --git a/modules/recovery_vault/recovery_vault.tf b/modules/recovery_vault/recovery_vault.tf index 284aaf67ac..5a7dca4c6b 100644 --- a/modules/recovery_vault/recovery_vault.tf +++ b/modules/recovery_vault/recovery_vault.tf @@ -1,3 +1,5 @@ +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/recovery_services_vault resource "azurecaf_name" "asr_rg_vault" { name = var.settings.name diff --git a/modules/recovery_vault/replication_policy.tf b/modules/recovery_vault/replication_policy.tf index 8e4e439579..c1f941fc7b 100644 --- a/modules/recovery_vault/replication_policy.tf +++ b/modules/recovery_vault/replication_policy.tf @@ -1,11 +1,13 @@ +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/site_recovery_replication_policy resource "azurerm_site_recovery_replication_policy" "policy" { - depends_on = [azurerm_recovery_services_vault.asr, time_sleep.delay_create] + depends_on = [time_sleep.delay_create] for_each = try(var.settings.replication_policies, {}) name = each.value.name resource_group_name = var.resource_group_name - recovery_vault_name = azurecaf_name.asr_rg_vault.result + recovery_vault_name = azurerm_recovery_services_vault.asr.name recovery_point_retention_in_minutes = each.value.recovery_point_retention_in_minutes application_consistent_snapshot_frequency_in_minutes = each.value.application_consistent_snapshot_frequency_in_minutes } \ No newline at end of file diff --git a/modules/resource_group/module.tf b/modules/resource_group/module.tf index 59d8605648..c84d835a22 100644 --- a/modules/resource_group/module.tf +++ b/modules/resource_group/module.tf @@ -13,5 +13,8 @@ resource "azurecaf_name" "rg" { resource "azurerm_resource_group" "rg" { name = azurecaf_name.rg.result location = var.global_settings.regions[lookup(var.settings, "region", var.global_settings.default_region)] - tags = merge(var.tags, lookup(var.settings, "tags", {})) -} + tags = merge( + var.tags, + lookup(var.settings, "tags", {}) + ) +} \ No newline at end of file diff --git a/modules/security/keyvault/examples/101-simple/configuration.tfvars b/modules/security/keyvault/examples/101-simple/configuration.tfvars deleted file mode 100755 index d6d0542600..0000000000 --- a/modules/security/keyvault/examples/101-simple/configuration.tfvars +++ /dev/null @@ -1,61 +0,0 @@ -global_settings = { - prefix = "dsde" - default_location = "southeastasia" - environment = "demo" -} - -resource_groups = { - security = { - name = "launchpad-security" - useprefix = true - } -} - - -keyvaults = { - launchpad = { - name = "launchpad" - resource_group_key = "security" - region = "southeastasia" - sku_name = "standard" - tags = { - environment = "demo" - tfstate = "level0" - } - } -} - - -## Networking configuration -networking = { - hub_sg = { - resource_group_key = "vnet_sg" - location = "southeastasia" - vnet = { - name = "hub" - address_space = ["10.10.100.0/24"] - } - specialsubnets = { - } - subnets = { - jumpbox = { - name = "jumpbox" - cidr = ["10.10.100.0/25"] - nsg_name = "jumpbox_nsg" - nsg = [] - } - - } - diags = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["VMProtectionAlerts", true, true, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, true, 7], - ] - } - } - -} \ No newline at end of file diff --git a/modules/security/keyvault/examples/101-simple/landingzone.tf b/modules/security/keyvault/examples/101-simple/landingzone.tf deleted file mode 100755 index d255da1b20..0000000000 --- a/modules/security/keyvault/examples/101-simple/landingzone.tf +++ /dev/null @@ -1,8 +0,0 @@ -module "keyvault" { - source = "/tf/caf" - - global_settings = var.global_settings - resource_groups = var.resource_groups - keyvaults = var.keyvaults - networking = var.networking -} \ No newline at end of file diff --git a/modules/security/keyvault/examples/101-simple/main.tf b/modules/security/keyvault/examples/101-simple/main.tf deleted file mode 100755 index e1e4a52fae..0000000000 --- a/modules/security/keyvault/examples/101-simple/main.tf +++ /dev/null @@ -1,27 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.19.0" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~>0.4.3" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features {} -} - -# data "azurerm_client_config" "current" {} - - - diff --git a/modules/security/keyvault/examples/101-simple/variables.tf b/modules/security/keyvault/examples/101-simple/variables.tf deleted file mode 100755 index 47213a4165..0000000000 --- a/modules/security/keyvault/examples/101-simple/variables.tf +++ /dev/null @@ -1,5 +0,0 @@ -variable "global_settings" { - description = "Global settings object (see module README.md)" -} -variable "resource_groups" {} -variable "keyvaults" {} \ No newline at end of file diff --git a/modules/security/keyvault/examples/102-with-networking/configuration.tfvars b/modules/security/keyvault/examples/102-with-networking/configuration.tfvars deleted file mode 100755 index 83e46bb0c1..0000000000 --- a/modules/security/keyvault/examples/102-with-networking/configuration.tfvars +++ /dev/null @@ -1,26 +0,0 @@ -global_settings = { - prefix = "dsde" - default_location = "southeastasia" - environment = "demo" -} - -resource_groups = { - security = { - name = "launchpad-security" - useprefix = true - } -} - - -keyvaults = { - launchpad = { - name = "launchpad" - resource_group_key = "security" - region = "southeastasia" - sku_name = "standard" - tags = { - environment = "demo" - tfstate = "level0" - } - } -} \ No newline at end of file diff --git a/modules/security/keyvault/examples/102-with-networking/landingzone.tf b/modules/security/keyvault/examples/102-with-networking/landingzone.tf deleted file mode 100755 index eac0347dff..0000000000 --- a/modules/security/keyvault/examples/102-with-networking/landingzone.tf +++ /dev/null @@ -1,8 +0,0 @@ -module "keyvault" { - source = "/tf/caf" - - global_settings = var.global_settings - resource_groups = var.resource_groups - keyvaults = var.keyvaults - # networking = var.vnets -} \ No newline at end of file diff --git a/modules/security/keyvault/examples/102-with-networking/main.tf b/modules/security/keyvault/examples/102-with-networking/main.tf deleted file mode 100755 index e1e4a52fae..0000000000 --- a/modules/security/keyvault/examples/102-with-networking/main.tf +++ /dev/null @@ -1,27 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.19.0" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~>0.4.3" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features {} -} - -# data "azurerm_client_config" "current" {} - - - diff --git a/modules/security/keyvault/examples/102-with-networking/variables.tf b/modules/security/keyvault/examples/102-with-networking/variables.tf deleted file mode 100755 index df07937fa5..0000000000 --- a/modules/security/keyvault/examples/102-with-networking/variables.tf +++ /dev/null @@ -1,7 +0,0 @@ -variable "global_settings" { - description = "Global settings object (see module README.md)" -} -variable "resource_groups" {} -variable "keyvaults" {} -variable "keyvault_id" {} -variable "org_id" {} \ No newline at end of file diff --git a/modules/security/keyvault/keyvault.tf b/modules/security/keyvault/keyvault.tf index 93153c2bde..b6a558da2b 100755 --- a/modules/security/keyvault/keyvault.tf +++ b/modules/security/keyvault/keyvault.tf @@ -17,8 +17,8 @@ resource "azurecaf_name" "keyvault" { resource "azurerm_key_vault" "keyvault" { name = azurecaf_name.keyvault.result - location = lookup(var.settings, "region", null) == null ? var.resource_groups[var.settings.resource_group_key].location : var.global_settings.regions[var.settings.region] - resource_group_name = var.resource_groups[var.settings.resource_group_key].name + location = lookup(var.settings, "region", null) == null ? var.resource_groups[try(var.settings.resource_group.key, var.settings.resource_group_key)].location : var.global_settings.regions[var.settings.region] + resource_group_name = var.resource_groups[try(var.settings.resource_group.key, var.settings.resource_group_key)].name tenant_id = var.client_config.tenant_id sku_name = try(var.settings.sku_name, "standard") tags = try(merge(var.base_tags, local.tags), {}) diff --git a/modules/security/keyvault/private_endpoints.tf b/modules/security/keyvault/private_endpoints.tf index bdead77d62..82828f3eec 100755 --- a/modules/security/keyvault/private_endpoints.tf +++ b/modules/security/keyvault/private_endpoints.tf @@ -10,8 +10,8 @@ module "private_endpoint" { resource_id = azurerm_key_vault.keyvault.id name = each.value.name - location = var.resource_groups[each.value.resource_group_key].location - resource_group_name = var.resource_groups[each.value.resource_group_key].name + location = var.resource_groups[try(each.value.resource_group.key, each.value.resource_group_key)].location + resource_group_name = var.resource_groups[try(each.value.resource_group.key, each.value.resource_group_key)].name subnet_id = try(var.vnets[var.client_config.landingzone_key][each.value.vnet_key].subnets[each.value.subnet_key].id, var.vnets[each.value.lz_key][each.value.vnet_key].subnets[each.value.subnet_key].id) settings = each.value global_settings = var.global_settings diff --git a/modules/security/keyvault_access_policies/access_policy/access_policy.tf b/modules/security/keyvault_access_policies/access_policy/access_policy.tf index 2a41f112b8..449cdc77cf 100755 --- a/modules/security/keyvault_access_policies/access_policy/access_policy.tf +++ b/modules/security/keyvault_access_policies/access_policy/access_policy.tf @@ -10,6 +10,9 @@ resource "azurerm_key_vault_access_policy" "policy" { timeouts { delete = "60m" + } + lifecycle { + ignore_changes = [key_vault_id] } } diff --git a/modules/security/keyvault_access_policies/policies.tf b/modules/security/keyvault_access_policies/policies.tf index c0c76fcbee..45b6f94d4f 100755 --- a/modules/security/keyvault_access_policies/policies.tf +++ b/modules/security/keyvault_access_policies/policies.tf @@ -6,12 +6,35 @@ module "azuread_apps" { if try(access_policy.azuread_app_key, null) != null } - keyvault_id = var.keyvault_id == null ? var.keyvaults[try(try(each.value.keyvault_lz_key, each.value.lz_key), var.client_config.landingzone_key)][var.keyvault_key].id : var.keyvault_id + keyvault_id = var.keyvault_id == null ? var.keyvaults[try(each.value.keyvault_lz_key, each.value.lz_key, var.client_config.landingzone_key)][var.keyvault_key].id : var.keyvault_id access_policy = each.value tenant_id = var.client_config.tenant_id object_id = var.azuread_apps[try(try(each.value.azuread_app_lz_key, each.value.lz_key), var.client_config.landingzone_key)][each.value.azuread_app_key].azuread_service_principal.object_id } +module "azuread_service_principals" { + source = "./access_policy" + for_each = { + for key, access_policy in var.access_policies : key => access_policy + if try(access_policy.azuread_service_principal_key, null) != null + } + + keyvault_id = coalesce( + var.keyvault_id, + try(var.keyvaults[each.value.keyvault_lz_key][var.keyvault_key].id, null), + try(var.keyvaults[each.value.lz_key][var.keyvault_key].id, null), + try(var.keyvaults[var.client_config.landingzone_key][var.keyvault_key].id, null) + ) + + access_policy = each.value + tenant_id = var.resources.azuread_service_principals[try(each.value.lz_key, var.client_config.landingzone_key)][each.value.azuread_service_principal_key].tenant_id + + object_id = coalesce( + try(var.resources.azuread_service_principals[each.value.lz_key][each.value.azuread_service_principal_key].object_id, null), + try(var.resources.azuread_service_principals[var.client_config.landingzone_key][each.value.azuread_service_principal_key].object_id, null) + ) +} + module "azuread_group" { source = "./access_policy" for_each = { @@ -71,10 +94,20 @@ module "managed_identity" { if try(access_policy.managed_identity_key, null) != null } - keyvault_id = var.keyvault_id == null ? try(var.keyvaults[var.client_config.landingzone_key][var.keyvault_key].id, var.keyvaults[each.value.lz_key][var.keyvault_key].id) : var.keyvault_id + keyvault_id = coalesce( + var.keyvault_id, + try(var.keyvaults[each.value.keyvault_lz_key][var.keyvault_key].id, null), + try(var.keyvaults[each.value.lz_key][var.keyvault_key].id, null), + try(var.keyvaults[var.client_config.landingzone_key][var.keyvault_key].id, null) + ) + access_policy = each.value tenant_id = var.client_config.tenant_id - object_id = try(each.value.lz_key, null) == null ? var.resources.managed_identities[var.client_config.landingzone_key][each.value.managed_identity_key].principal_id : var.resources.managed_identities[each.value.lz_key][each.value.managed_identity_key].principal_id + + object_id = coalesce( + try(var.resources.managed_identities[each.value.lz_key][each.value.managed_identity_key].principal_id, null), + try(var.resources.managed_identities[var.client_config.landingzone_key][each.value.managed_identity_key].principal_id, null) + ) } module "mssql_managed_instance" { diff --git a/modules/security/managed_identity/managed_identity.tf b/modules/security/managed_identity/managed_identity.tf index 6af0fc63a4..3210d7c057 100644 --- a/modules/security/managed_identity/managed_identity.tf +++ b/modules/security/managed_identity/managed_identity.tf @@ -4,11 +4,11 @@ locals { resource "azurecaf_name" "msi" { name = var.name resource_type = "azurerm_user_assigned_identity" - prefixes = var.global_settings.prefixes - random_length = var.global_settings.random_length + prefixes = try(var.settings.naming_convention.prefixes, var.global_settings.prefixes) + random_length = try(var.settings.naming_convention.random_length, var.global_settings.random_length) clean_input = true - passthrough = var.global_settings.passthrough - use_slug = var.global_settings.use_slug + passthrough = try(var.settings.naming_convention.passthrough, var.global_settings.passthrough) + use_slug = try(var.settings.naming_convention.use_slug, var.global_settings.use_slug) } resource "azurerm_user_assigned_identity" "msi" { @@ -16,5 +16,4 @@ resource "azurerm_user_assigned_identity" "msi" { resource_group_name = var.resource_group_name location = var.location tags = try(merge(var.base_tags, local.tags), {}) -} - +} \ No newline at end of file diff --git a/modules/storage_account/backup_container.tf b/modules/storage_account/backup_container.tf index 6adfbd83de..b4601a5b6b 100644 --- a/modules/storage_account/backup_container.tf +++ b/modules/storage_account/backup_container.tf @@ -1,11 +1,16 @@ +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_container_storage_account + locals { recovery_vault = try(var.storage_account.backup, null) == null ? null : try(var.recovery_vaults[var.client_config.landingzone_key][var.storage_account.backup.vault_key], var.recovery_vaults[var.storage_account.backup.lz_key][var.storage_account.backup.vault_key]) } resource "azurerm_backup_container_storage_account" "container" { - count = try(var.storage_account.backup, null) == null ? 0 : 1 + + for_each = try(var.storage_account.backup, null) == null ? toset([]) : toset(["enabled"]) + resource_group_name = local.recovery_vault.resource_group_name recovery_vault_name = local.recovery_vault.name storage_account_id = azurerm_storage_account.stg.id -} \ No newline at end of file +} diff --git a/modules/storage_account/blob/module.tf b/modules/storage_account/blob/module.tf index ed7ed2dcf3..366c765c8b 100644 --- a/modules/storage_account/blob/module.tf +++ b/modules/storage_account/blob/module.tf @@ -1,3 +1,5 @@ +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_blob resource "azurerm_storage_blob" "blob" { @@ -8,6 +10,7 @@ resource "azurerm_storage_blob" "blob" { size = try(var.settings.size, null) access_tier = try(var.settings.access_tier, "Hot") content_type = try(var.settings.content_type, null) + content_md5 = try(var.settings.content_md5, null) source = try(var.settings.source, null) source_content = try(var.settings.source_content, null) source_uri = try(var.settings.source_uri, null) diff --git a/modules/storage_account/blob/output.tf b/modules/storage_account/blob/output.tf index 3c5e82a92f..d0947944ce 100755 --- a/modules/storage_account/blob/output.tf +++ b/modules/storage_account/blob/output.tf @@ -1,7 +1,9 @@ output "id" { - value = azurerm_storage_blob.blob.id + description = "The ID of the Storage Blob" + value = azurerm_storage_blob.blob.id } output "url" { - value = azurerm_storage_blob.blob.url + description = "The URL of the blob" + value = azurerm_storage_blob.blob.url } diff --git a/modules/storage_account/container/container.tf b/modules/storage_account/container/container.tf index f1cd1e807a..bbc2c217cc 100644 --- a/modules/storage_account/container/container.tf +++ b/modules/storage_account/container/container.tf @@ -1,3 +1,6 @@ +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_container + resource "azurerm_storage_container" "stg" { name = var.settings.name storage_account_name = var.storage_account_name diff --git a/modules/storage_account/container/output.tf b/modules/storage_account/container/output.tf index 2b39e9388e..b0c70ba21e 100755 --- a/modules/storage_account/container/output.tf +++ b/modules/storage_account/container/output.tf @@ -1,8 +1,14 @@ output "blobs" { - value = module.blob + description = "Exports the content of the blob module." + value = module.blob } - output "name" { - value = azurerm_storage_container.stg.name + description = "The ID of the Storage Container." + value = azurerm_storage_container.stg.name +} + +output "resource_manager_id" { + description = "The Resource Manager ID of this Storage Container." + value = azurerm_storage_container.stg.resource_manager_id } \ No newline at end of file diff --git a/modules/storage_account/data_lake_filesystem/gen2_filesystem.tf b/modules/storage_account/data_lake_filesystem/gen2_filesystem.tf index 27c4dd20b2..92d53c1857 100644 --- a/modules/storage_account/data_lake_filesystem/gen2_filesystem.tf +++ b/modules/storage_account/data_lake_filesystem/gen2_filesystem.tf @@ -1,3 +1,6 @@ +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_data_lake_gen2_filesystem + resource "azurerm_storage_data_lake_gen2_filesystem" "gen2" { name = var.settings.name storage_account_id = var.storage_account_id diff --git a/modules/storage_account/data_lake_filesystem/output.tf b/modules/storage_account/data_lake_filesystem/output.tf index fee227bfb3..4b852124bc 100755 --- a/modules/storage_account/data_lake_filesystem/output.tf +++ b/modules/storage_account/data_lake_filesystem/output.tf @@ -1,3 +1,4 @@ output "id" { - value = azurerm_storage_data_lake_gen2_filesystem.gen2.id + description = "The ID of the Data Lake Gen2 File System." + value = azurerm_storage_data_lake_gen2_filesystem.gen2.id } diff --git a/modules/storage_account/examples/101-single.tfvars b/modules/storage_account/examples/101-single.tfvars deleted file mode 100755 index b2fb99d101..0000000000 --- a/modules/storage_account/examples/101-single.tfvars +++ /dev/null @@ -1,14 +0,0 @@ -resource_groups = { - test_sg = { - name = "test-caf_storage_account-sg" - location = "southeastasia" - useprefix = true - } -} - -storage_accounts = { - media = { - name = "media" - resource_group_key = "test_sg" - } -} \ No newline at end of file diff --git a/modules/storage_account/examples/102-storage_with_vnet.tfvars b/modules/storage_account/examples/102-storage_with_vnet.tfvars deleted file mode 100755 index 42ba4c6975..0000000000 --- a/modules/storage_account/examples/102-storage_with_vnet.tfvars +++ /dev/null @@ -1,59 +0,0 @@ -resource_groups = { - test_sg = { - name = "test-caf_storage_account-sg" - location = "southeastasia" - useprefix = true - } - vnet_sg = { - name = "test-networking-sg" - location = "southeastasia" - useprefix = true - } -} - -storage_accounts = { - media = { - name = "media" - resource_group_key = "test_sg" - network_rules = { - default_action = "Allow" - bypass = "Logging" - vnet_key = "hub_sg" - subnet_key = "jumpbox" - } - } -} - -## Networking configuration -networking = { - hub_sg = { - resource_group_key = "vnet_sg" - location = "southeastasia" - vnet = { - name = "hub" - address_space = ["10.10.100.0/24"] - } - specialsubnets = { - } - subnets = { - jumpbox = { - name = "jumpbox" - cidr = ["10.10.100.0/25"] - nsg_name = "jumpbox_nsg" - nsg = [] - } - - } - diags = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["VMProtectionAlerts", true, true, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, true, 7], - ] - } - } - -} \ No newline at end of file diff --git a/modules/storage_account/file_share/file_share.tf b/modules/storage_account/file_share/file_share.tf new file mode 100644 index 0000000000..96a7814cbf --- /dev/null +++ b/modules/storage_account/file_share/file_share.tf @@ -0,0 +1,21 @@ +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_share + +resource "azurerm_storage_share" "fs" { + name = var.settings.name + storage_account_name = var.storage_account_name + quota = try(var.settings.quota, null) + metadata = try(var.settings.metadata, null) +} + +# Issue open in 2.61 : https://github.com/terraform-providers/terraform-provider-azurerm/issues/11184 +resource "azurerm_backup_protected_file_share" "fs_backup" { + for_each = try(var.settings.backups, null) != null ? toset(["enabled"]) : toset([]) + + resource_group_name = var.resource_group_name + recovery_vault_name = var.recovery_vault.name + source_storage_account_id = var.storage_account_id + source_file_share_name = azurerm_storage_share.fs.name + backup_policy_id = var.recovery_vault.backup_policies.file_shares[var.settings.backups.policy_key].id +} + diff --git a/modules/storage_account/file_share/output.tf b/modules/storage_account/file_share/output.tf new file mode 100755 index 0000000000..e46ac07dcc --- /dev/null +++ b/modules/storage_account/file_share/output.tf @@ -0,0 +1,19 @@ +output "id" { + description = "The ID of the File Share" + value = azurerm_storage_share.fs.id +} + +output "url" { + description = "The URL of the File Share" + value = azurerm_storage_share.fs.url +} + +output "resource_manager_id" { + description = "The Resource Manager ID of this File Share" + value = azurerm_storage_share.fs.resource_manager_id +} + +output "file_share_directories" { + description = "Output of directories in the file share" + value = module.file_share_directory +} \ No newline at end of file diff --git a/modules/storage_account/file_share/share_directory.tf b/modules/storage_account/file_share/share_directory.tf new file mode 100644 index 0000000000..5f3310531b --- /dev/null +++ b/modules/storage_account/file_share/share_directory.tf @@ -0,0 +1,8 @@ +module "file_share_directory" { + source = "../file_share_directory" + for_each = try(var.settings.directories, {}) + + storage_account_name = var.storage_account_name + share_name = azurerm_storage_share.fs.name + settings = each.value +} \ No newline at end of file diff --git a/modules/storage_account/file_share/variables.tf b/modules/storage_account/file_share/variables.tf new file mode 100755 index 0000000000..1774aaceba --- /dev/null +++ b/modules/storage_account/file_share/variables.tf @@ -0,0 +1,9 @@ +variable "settings" {} +variable "storage_account_name" {} +variable "storage_account_id" {} +variable "recovery_vault" { + default = {} +} +variable "resource_group_name" { + default = "" +} diff --git a/modules/storage_account/file_share_directory/directory.tf b/modules/storage_account/file_share_directory/directory.tf new file mode 100644 index 0000000000..3119425c6e --- /dev/null +++ b/modules/storage_account/file_share_directory/directory.tf @@ -0,0 +1,6 @@ +resource "azurerm_storage_share_directory" "share_directory" { + name = var.settings.name + share_name = var.share_name + storage_account_name = var.storage_account_name + metadata = try(var.settings.metadata, null) +} \ No newline at end of file diff --git a/modules/storage_account/file_share_directory/output.tf b/modules/storage_account/file_share_directory/output.tf new file mode 100644 index 0000000000..55ca2d98c4 --- /dev/null +++ b/modules/storage_account/file_share_directory/output.tf @@ -0,0 +1,4 @@ +output "id" { + value = azurerm_storage_share_directory.share_directory.id +} + diff --git a/modules/storage_account/file_share_directory/variables.tf b/modules/storage_account/file_share_directory/variables.tf new file mode 100644 index 0000000000..db1436f686 --- /dev/null +++ b/modules/storage_account/file_share_directory/variables.tf @@ -0,0 +1,3 @@ +variable "storage_account_name" {} +variable "share_name" {} +variable "settings" {} \ No newline at end of file diff --git a/modules/storage_account/output.tf b/modules/storage_account/output.tf index 42b443a82e..bcf439eadb 100755 --- a/modules/storage_account/output.tf +++ b/modules/storage_account/output.tf @@ -1,36 +1,67 @@ output "id" { - value = azurerm_storage_account.stg.id + description = "The ID of the Storage Account" + value = azurerm_storage_account.stg.id } output "name" { - value = azurerm_storage_account.stg.name + description = "The name of the Storage Account" + value = azurerm_storage_account.stg.name } output "location" { - value = var.location - + description = "The location of the Storage Account" + value = var.location } output "resource_group_name" { - value = var.resource_group_name + description = "The resource group name of the Storage Account" + value = var.resource_group_name } output "primary_blob_endpoint" { - value = azurerm_storage_account.stg.primary_blob_endpoint + description = "The endpoint URL for blob storage in the primary location." + value = azurerm_storage_account.stg.primary_blob_endpoint } output "containers" { - value = module.container + description = "The containers output objects as created by the container submodule." + value = module.container +} + +output "queues" { + description = "The queues output objects as created by the queues submodule." + value = module.queue } output "data_lake_filesystems" { - value = module.data_lake_filesystem + description = "The data lake filesystem output objects as created by the data lake filesystem submodule." + value = module.data_lake_filesystem +} + +output "file_share" { + description = "The file shares output objects as created by the file shares submodule." + value = module.file_share } output "identity" { - value = try(azurerm_storage_account.stg.identity, null) + description = " An identity block, which contains the Identity information for this Storage Account. Exports principal_id (The Principal ID for the Service Principal associated with the Identity of this Storage Account), tenand_id (The Tenant ID for the Service Principal associated with the Identity of this Storage Account)" + value = try(azurerm_storage_account.stg.identity, null) } output "rbac_id" { - value = try(azurerm_storage_account.stg.identity.0, null) -} \ No newline at end of file + description = " The Principal ID for the Service Principal associated with the Identity of this Storage Account. (Extracted from the identity block)" + value = try(azurerm_storage_account.stg.identity.0.principal_id, null) +} + +output "backup_container_id" { + description = "The ID of the Backup Storage Account Container" + value = try(azurerm_backup_container_storage_account.container["enabled"].id, null) +} + +#output "primary_connection_string" { +# value = try(azurerm_storage_account.stg.primary_connection_string, null) +#} + +#output "primary_queue_endpoint" { +# value = try(azurerm_storage_account.stg.primary_queue_endpoint, null) +#} \ No newline at end of file diff --git a/modules/storage_account/queue/output.tf b/modules/storage_account/queue/output.tf new file mode 100644 index 0000000000..962d8bef0e --- /dev/null +++ b/modules/storage_account/queue/output.tf @@ -0,0 +1,9 @@ +output "name" { + description = "The name of the Storage Queue." + value = azurerm_storage_queue.queue.name +} + +output "id" { + description = "The ID of the Storage Queue." + value = azurerm_storage_queue.queue.id +} \ No newline at end of file diff --git a/modules/storage_account/queue/queue.tf b/modules/storage_account/queue/queue.tf new file mode 100644 index 0000000000..4eeebba24b --- /dev/null +++ b/modules/storage_account/queue/queue.tf @@ -0,0 +1,5 @@ +resource "azurerm_storage_queue" "queue" { + name = var.settings.name + storage_account_name = var.storage_account_name + metadata = try(var.settings.metadata, null) +} \ No newline at end of file diff --git a/modules/storage_account/queue/variables.tf b/modules/storage_account/queue/variables.tf new file mode 100644 index 0000000000..d36597c16c --- /dev/null +++ b/modules/storage_account/queue/variables.tf @@ -0,0 +1,2 @@ +variable "settings" {} +variable "storage_account_name" {} diff --git a/modules/storage_account/storage_account.tf b/modules/storage_account/storage_account.tf index 82e393d74e..243937c771 100755 --- a/modules/storage_account/storage_account.tf +++ b/modules/storage_account/storage_account.tf @@ -14,19 +14,25 @@ resource "azurecaf_name" "stg" { use_slug = var.global_settings.use_slug } +# Tested with : AzureRM version 2.61.0 +# Ref : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account + resource "azurerm_storage_account" "stg" { name = azurecaf_name.stg.result resource_group_name = var.resource_group_name location = var.location - account_tier = lookup(var.storage_account, "account_tier", "Standard") - account_replication_type = lookup(var.storage_account, "account_replication_type", "LRS") - account_kind = lookup(var.storage_account, "account_kind", "StorageV2") - access_tier = lookup(var.storage_account, "access_tier", "Hot") - enable_https_traffic_only = true - min_tls_version = lookup(var.storage_account, "min_tls_version", "TLS1_2") - allow_blob_public_access = lookup(var.storage_account, "allow_blob_public_access", false) - is_hns_enabled = lookup(var.storage_account, "is_hns_enabled", false) - tags = merge(var.base_tags, local.tags) + account_tier = try(var.storage_account.account_tier, "Standard") + account_replication_type = try(var.storage_account.account_replication_type, "LRS") + account_kind = try(var.storage_account.account_kind, "StorageV2") + access_tier = try(var.storage_account.access_tier, "Hot") + enable_https_traffic_only = try(var.storage_account.nfsv3_enabled, false) ? false : true + #if using nfsv3_enabled, then https must be disabled + min_tls_version = try(var.storage_account.min_tls_version, "TLS1_2") + allow_blob_public_access = try(var.storage_account.allow_blob_public_access, false) + is_hns_enabled = try(var.storage_account.is_hns_enabled, false) + nfsv3_enabled = try(var.storage_account.nfsv3_enabled, false) + large_file_share_enabled = try(var.storage_account.large_file_share_enabled, null) + tags = merge(var.base_tags, local.tags) dynamic "custom_domain" { @@ -34,7 +40,7 @@ resource "azurerm_storage_account" "stg" { content { name = var.storage_account.custom_domain.name - use_subdomain = var.storage_account.custom_domain.use_subdomain + use_subdomain = try(var.storage_account.custom_domain.use_subdomain, null) } } @@ -50,6 +56,11 @@ resource "azurerm_storage_account" "stg" { for_each = lookup(var.storage_account, "blob_properties", false) == false ? [] : [1] content { + versioning_enabled = try(var.storage_account.blob_properties.versioning_enabled, false) + change_feed_enabled = try(var.storage_account.blob_properties.change_feed_enabled, false) + default_service_version = try(var.storage_account.blob_properties.default_service_version, "2020-06-12") + last_access_time_enabled = try(var.storage_account.blob_properties.last_access_time_enabled, false) + dynamic "cors_rule" { for_each = lookup(var.storage_account.blob_properties, "cors_rule", false) == false ? [] : [1] @@ -66,11 +77,18 @@ resource "azurerm_storage_account" "stg" { for_each = lookup(var.storage_account.blob_properties, "delete_retention_policy", false) == false ? [] : [1] content { - days = lookup(var.storage_account.blob_properties.delete_retention_policy, "delete_retention_policy", 7) + days = try(var.storage_account.blob_properties.delete_retention_policy.delete_retention_policy, 7) } } - } + dynamic "container_delete_retention_policy" { + for_each = lookup(var.storage_account.blob_properties, "container_delete_retention_policy", false) == false ? [] : [1] + + content { + days = try(var.storage_account.blob_properties.container_delete_retention_policy.container_delete_retention_policy, 7) + } + } + } } dynamic "queue_properties" { @@ -97,7 +115,7 @@ resource "azurerm_storage_account" "stg" { read = var.storage_account.queue_properties.logging.read write = var.storage_account.queue_properties.logging.write version = var.storage_account.queue_properties.logging.version - retention_policy_days = lookup(var.storage_account.queue_properties.logging, "retention_policy_days", 7) + retention_policy_days = try(var.storage_account.queue_properties.logging.retention_policy_days, 7) } } @@ -107,8 +125,8 @@ resource "azurerm_storage_account" "stg" { content { enabled = var.storage_account.queue_properties.minute_metrics.enabled version = var.storage_account.queue_properties.minute_metrics.version - include_apis = lookup(var.storage_account.queue_properties.minute_metrics, "include_apis", null) - retention_policy_days = lookup(var.storage_account.queue_properties.minute_metrics, "retention_policy_days", 7) + include_apis = try(var.storage_account.queue_properties.minute_metrics.include_apis, null) + retention_policy_days = try(var.storage_account.queue_properties.minute_metrics.retention_policy_days, 7) } } @@ -118,8 +136,8 @@ resource "azurerm_storage_account" "stg" { content { enabled = var.storage_account.queue_properties.hour_metrics.enabled version = var.storage_account.queue_properties.hour_metrics.version - include_apis = lookup(var.storage_account.queue_properties.hour_metrics, "include_apis", null) - retention_policy_days = lookup(var.storage_account.queue_properties.hour_metrics, "retention_policy_days", 7) + include_apis = try(var.storage_account.queue_properties.hour_metrics.include_apis, null) + retention_policy_days = try(var.storage_account.queue_properties.hour_metrics.retention_policy_days, 7) } } } @@ -129,8 +147,8 @@ resource "azurerm_storage_account" "stg" { for_each = lookup(var.storage_account, "static_website", false) == false ? [] : [1] content { - index_document = var.storage_account.static_website.index_document - error_404_document = var.storage_account.static_website.error_404_document + index_document = try(var.storage_account.static_website.index_document, null) + error_404_document = try(var.storage_account.static_website.error_404_document, null) } } @@ -145,9 +163,46 @@ resource "azurerm_storage_account" "stg" { ] } } + + dynamic "azure_files_authentication" { + for_each = lookup(var.storage_account, "azure_files_authentication", false) == false ? [] : [1] + + content { + directory_type = var.storage_account.azure_files_authentication.directory_type + + dynamic "active_directory" { + for_each = lookup(var.storage_account.azure_files_authentication, "active_directory", false) == false ? [] : [1] + + content { + storage_sid = var.storage_account.azure_files_authentication.active_directory.storage_sid + domain_name = var.storage_account.azure_files_authentication.active_directory.domain_name + domain_sid = var.storage_account.azure_files_authentication.active_directory.domain_sid + domain_guid = var.storage_account.azure_files_authentication.active_directory.domain_guid + forest_name = var.storage_account.azure_files_authentication.active_directory.forest_name + netbios_domain_name = var.storage_account.azure_files_authentication.active_directory.netbios_domain_name + } + } + } + } + + dynamic "routing" { + for_each = lookup(var.storage_account, "routing", false) == false ? [] : [1] + + content { + publish_internet_endpoints = try(var.storage_account.routing.publish_internet_endpoints, false) + publish_microsoft_endpoints = try(var.storage_account.routing.publish_microsoft_endpoints, false) + choice = try(var.storage_account.routing.choice, "MicrosoftRouting") + } + } } +module "queue" { + source = "./queue" + for_each = try(var.storage_account.queues, {}) + storage_account_name = azurerm_storage_account.stg.name + settings = each.value +} module "container" { source = "./container" @@ -164,3 +219,15 @@ module "data_lake_filesystem" { storage_account_id = azurerm_storage_account.stg.id settings = each.value } + +module "file_share" { + source = "./file_share" + for_each = try(var.storage_account.file_shares, {}) + depends_on = [azurerm_backup_container_storage_account.container] + + storage_account_name = azurerm_storage_account.stg.name + storage_account_id = azurerm_storage_account.stg.id + settings = each.value + recovery_vault = local.recovery_vault + resource_group_name = var.resource_group_name +} \ No newline at end of file diff --git a/modules/subscription_billing_role_assignment/billing_role_assignment.tf b/modules/subscription_billing_role_assignment/billing_role_assignment.tf index 5d7dc55636..b61d726a85 100755 --- a/modules/subscription_billing_role_assignment/billing_role_assignment.tf +++ b/modules/subscription_billing_role_assignment/billing_role_assignment.tf @@ -47,3 +47,18 @@ module "role_assignment_msi" { cloud = var.cloud } + +module "role_assignment_azuread_service_principals" { + source = "./role_assignment" + for_each = try(var.settings.principals.azuread_service_principals, {}) + depends_on = [module.role_assignment_azuread_users, module.role_assignment_msi] + + aad_user_impersonate = try(var.keyvaults[try(each.value.lz_key, var.client_config.landingzone_key)][var.settings.aad_user_impersonate.keyvault.key], null) + billing_scope_id = local.billing_scope_id + tenant_id = try(var.principals.azuread_service_principals[try(each.value.lz_key, var.client_config.landingzone_key)][each.value.key].tenant_id, var.client_config.tenant_id) + principal_id = var.principals.azuread_service_principals[try(each.value.lz_key, var.client_config.landingzone_key)][each.value.key].object_id + role_definition_id = data.external.role_definition.result.id + settings = each.value + cloud = var.cloud +} + diff --git a/modules/subscriptions/README.md b/modules/subscriptions/README.md index d10f3a630c..0c9c3af64f 100755 --- a/modules/subscriptions/README.md +++ b/modules/subscriptions/README.md @@ -44,14 +44,14 @@ principalId="" billing_role_definition_id=$(az rest --method GET --url https://management.azure.com${enrollmentAccount}/billingRoleDefinitions?api-version=2019-10-01-preview --query "value[?properties.roleName=='Enrollment account subscription creator'].{id:id}" -o tsv) -az rest --method PUT --url https://management.azure.com/${enrollmentAccount}/billingRoleAssignments/0525cbc2-c84e-4279-b639-adab918a96b8?api-version=2019-10-01-preview --body "{\"properties\": {\"principalId\": \"${principalId}\",\"principalTenantId\": \"${tenantId}\",\"roleDefinitionId\": \"${enrollmentAccount}/billingRoleDefinitions/${billing_role_definition_id}\"}} +az rest --method PUT --url https://management.azure.com/${enrollmentAccount}/billingRoleAssignments/${principalId}?api-version=2019-10-01-preview --body "{\"properties\": {\"principalId\": \"${principalId}\",\"principalTenantId\": \"${tenantId}\",\"roleDefinitionId\": \"${enrollmentAccount}/billingRoleDefinitions/${billing_role_definition_id}\"}}" # Login as the principalId and create a subscription to confirm the delegation of permission is effective. az account alias create \ - --name "alias_name" \ + --name "spike1" \ --billing-scope "${enrollmentAccount}" \ - --display-name "name of the subscription" \ + --display-name "spike1" \ --workload "Production" ``` diff --git a/modules/subscriptions/output.tf b/modules/subscriptions/output.tf index 9656a3e852..67508007d3 100755 --- a/modules/subscriptions/output.tf +++ b/modules/subscriptions/output.tf @@ -1,3 +1,6 @@ +output "id" { + value = format("/subscriptions/%s", try(azurerm_subscription.sub.0.subscription_id, var.client_config.subscription_id)) +} output "subscription_id" { value = try(azurerm_subscription.sub.0.subscription_id, var.client_config.subscription_id) } diff --git a/modules/subscriptions/scripts/refresh_access_token.sh b/modules/subscriptions/scripts/refresh_access_token.sh index 8b20e3b629..8361ce4366 100755 --- a/modules/subscriptions/scripts/refresh_access_token.sh +++ b/modules/subscriptions/scripts/refresh_access_token.sh @@ -9,8 +9,20 @@ tenant_id=$(az account show --query tenantId -o tsv) subscription_id=$(az account show --query id -o tsv) if [ ${user_type} == "user" ]; then - - az login --tenant ${tenant_id} --use-device-code > /dev/null + echo "User type ${user_type}" + if [ "${ROVER_RUNNER}" == "true" ]; then + echo "Rover is runner mode." + if [ -z "${ACCOUNT_OWNER_USERNAME}" ] || [ -z "${ACCOUNT_OWNER_PASSWORD}" ] || [ -z "${tenant-id}" ]; then + echo "Subscription creation from pipeline with AE account owner requires the variables ACCOUNT_OWNER_USERNAME, ACCOUNT_OWNER_PASSWORD to be set in the bash pipeline context." + exit 3001 + else + echo "Login to ${ACCOUNT_OWNER_USERNAME} in tenant ${tenant_id}." + az login -u ${ACCOUNT_OWNER_USERNAME} -p "${ACCOUNT_OWNER_PASSWORD}" --tenant ${tenant_id} -o table + fi + else + echo "Rover is running in interactive mode." + az login --tenant ${tenant_id} --use-device-code > /dev/null + fi else diff --git a/modules/webapps/appservice/output.tf b/modules/webapps/appservice/output.tf index b3b9a8b4df..3f92cade91 100755 --- a/modules/webapps/appservice/output.tf +++ b/modules/webapps/appservice/output.tf @@ -14,3 +14,7 @@ output "possible_outbound_ip_addresses" { value = azurerm_app_service.app_service.possible_outbound_ip_addresses description = "A comma separated list of outbound IP addresses. not all of which are necessarily in use" } +output "rbac_id" { + value = try(azurerm_app_service.app_service.identity.0.principal_id, null) + description = "The Principal ID of the App Service." +} \ No newline at end of file diff --git a/networking.tf b/networking.tf index aefc05c88e..e210eb971f 100755 --- a/networking.tf +++ b/networking.tf @@ -21,19 +21,20 @@ module "networking" { for_each = local.networking.vnets application_security_groups = local.combined_objects_application_security_groups - base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} client_config = local.client_config ddos_id = try(azurerm_network_ddos_protection_plan.ddos_protection_plan[each.value.ddos_services_key].id, "") diagnostics = local.combined_diagnostics global_settings = local.global_settings - location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] network_security_groups = module.network_security_groups network_security_group_definition = local.networking.network_security_group_definition - network_watchers = try(local.combined_objects_network_watchers, null) - resource_group_name = local.resource_groups[each.value.resource_group_key].name + network_watchers = try(local.combined_objects_network_watchers, null) route_tables = module.route_tables settings = each.value tags = try(each.value.tags, null) + + resource_group_name = local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].name + location = lookup(each.value, "region", null) == null ? local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].location : local.global_settings.regions[each.value.region] + base_tags = try(local.global_settings.inherit_tags, false) ? local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].tags : {} } # @@ -60,8 +61,8 @@ module "public_ip_addresses" { for_each = local.networking.public_ip_addresses name = azurecaf_name.public_ip_addresses[each.key].result - resource_group_name = local.resource_groups[each.value.resource_group_key].name - location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] + resource_group_name = local.combined_objects_resource_groups[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.resource_group_key].name + location = lookup(each.value, "region", null) == null ? local.combined_objects_resource_groups[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.resource_group_key].location : local.global_settings.regions[each.value.region] sku = try(each.value.sku, "Basic") allocation_method = try(each.value.allocation_method, "Dynamic") ip_version = try(each.value.ip_version, "IPv4") @@ -70,10 +71,16 @@ module "public_ip_addresses" { reverse_fqdn = try(each.value.reverse_fqdn, null) generate_domain_name_label = try(each.value.generate_domain_name_label, false) tags = try(each.value.tags, null) - zones = try(each.value.zones, null) - diagnostic_profiles = try(each.value.diagnostic_profiles, {}) - diagnostics = local.combined_diagnostics - base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} + ip_tags = try(each.value.ip_tags, null) + public_ip_prefix_id = try(each.value.public_ip_prefix_id, null) + zones = coalesce( + try(each.value.availability_zone, ""), + try(tostring(each.value.zones[0]), ""), + try(each.value.sku, "Basic") == "Basic" ? "No-Zone" : "Zone-Redundant" + ) + diagnostic_profiles = try(each.value.diagnostic_profiles, {}) + diagnostics = local.combined_diagnostics + base_tags = try(local.global_settings.inherit_tags, false) ? local.combined_objects_resource_groups[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.resource_group_key].tags : {} } @@ -133,11 +140,11 @@ module "route_tables" { for_each = local.networking.route_tables name = azurecaf_name.route_tables[each.key].result - resource_group_name = local.resource_groups[each.value.resource_group_key].name - location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] + resource_group_name = local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].name + location = lookup(each.value, "region", null) == null ? local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].location : local.global_settings.regions[each.value.region] + base_tags = try(local.global_settings.inherit_tags, false) ? local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].tags : {} disable_bgp_route_propagation = try(each.value.disable_bgp_route_propagation, null) tags = try(each.value.tags, null) - base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} } resource "azurecaf_name" "routes" { @@ -157,17 +164,17 @@ module "routes" { source = "./modules/networking/routes" for_each = local.networking.azurerm_routes - name = azurecaf_name.routes[each.key].result - resource_group_name = local.resource_groups[each.value.resource_group_key].name - route_table_name = module.route_tables[each.value.route_table_key].name - address_prefix = each.value.address_prefix - next_hop_type = each.value.next_hop_type - next_hop_in_ip_address = try(lower(each.value.next_hop_type), null) == "virtualappliance" ? try(each.value.next_hop_in_ip_address, null) : null + name = azurecaf_name.routes[each.key].result + resource_group_name = local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].name + route_table_name = module.route_tables[each.value.route_table_key].name + address_prefix = each.value.address_prefix + next_hop_type = each.value.next_hop_type + next_hop_in_ip_address = try(lower(each.value.next_hop_type), null) == "virtualappliance" ? try(each.value.next_hop_in_ip_address, null) : null next_hop_in_ip_address_fw = try(lower(each.value.next_hop_type), null) == "virtualappliance" ? coalesce( try(local.combined_objects_azurerm_firewalls[try(each.value.private_ip_keys.azurerm_firewall.lz_key, local.client_config.landingzone_key)][each.value.private_ip_keys.azurerm_firewall.key].ip_configuration[each.value.private_ip_keys.azurerm_firewall.interface_index].private_ip_address, null), try(local.combined_objects_azurerm_firewalls[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.private_ip_keys.azurerm_firewall.key].ip_configuration[each.value.private_ip_keys.azurerm_firewall.interface_index].private_ip_address, null) ) : null - + } # @@ -193,9 +200,9 @@ resource "azurerm_network_ddos_protection_plan" "ddos_protection_plan" { for_each = local.networking.ddos_services name = azurecaf_name.ddos_protection_plan[each.key].result - location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] - resource_group_name = local.resource_groups[each.value.resource_group_key].name - tags = try(local.global_settings.inherit_tags, false) ? merge(local.resource_groups[each.value.resource_group_key].tags, each.value.tags) : try(each.value.tags, null) + location = lookup(each.value, "region", null) == null ? local.combined_objects_resource_groups[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.resource_group_key].location : local.global_settings.regions[each.value.region] + resource_group_name = local.combined_objects_resource_groups[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.resource_group_key].name + tags = try(local.global_settings.inherit_tags, false) ? merge(local.combined_objects_resource_groups[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.resource_group_key].tags, each.value.tags) : try(each.value.tags, null) } # @@ -207,10 +214,10 @@ module "network_watchers" { source = "./modules/networking/network_watcher" for_each = local.networking.network_watchers - resource_group_name = local.resource_groups[each.value.resource_group_key].name - location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] + resource_group_name = local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].name + location = lookup(each.value, "region", null) == null ? local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].location : local.global_settings.regions[each.value.region] + base_tags = try(local.global_settings.inherit_tags, false) ? local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].tags : {} settings = each.value tags = try(each.value.tags, null) - base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} global_settings = local.global_settings } \ No newline at end of file diff --git a/networking_firewall.tf b/networking_firewall.tf index fac9d2ca09..eff8a93982 100755 --- a/networking_firewall.tf +++ b/networking_firewall.tf @@ -6,27 +6,31 @@ module "azurerm_firewalls" { source = "./modules/networking/firewall" for_each = local.networking.azurerm_firewalls + base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} client_config = local.client_config + diagnostics = local.combined_diagnostics + diagnostic_profiles = try(each.value.diagnostic_profiles, null) + firewall_policy_id = try(each.value.firewall_policy_key, null) == null ? null : local.combined_objects_azurerm_firewall_policies[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.firewall_policy_key].id global_settings = local.global_settings - name = each.value.name - resource_group_name = local.resource_groups[each.value.resource_group_key].name location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] - tags = try(each.value.tags, null) - base_tags = try(local.global_settings.inherit_tags, false) ? local.resource_groups[each.value.resource_group_key].tags : {} - subnet_id = module.networking[each.value.vnet_key].subnets["AzureFirewallSubnet"].id - public_ip_id = try(module.public_ip_addresses[each.value.public_ip_key].id, null) + name = each.value.name public_ip_addresses = try(module.public_ip_addresses, null) + public_ip_id = try(module.public_ip_addresses[each.value.public_ip_key].id, null) public_ip_keys = try(each.value.public_ip_keys, null) - diagnostics = local.combined_diagnostics + resource_group_name = local.resource_groups[each.value.resource_group_key].name settings = each.value - virtual_wans = module.virtual_wans + subnet_id = module.networking[each.value.vnet_key].subnets["AzureFirewallSubnet"].id + tags = try(each.value.tags, null) virtual_networks = local.combined_objects_networking - firewall_policies = module.azurerm_firewall_policies + virtual_wans = module.virtual_wans } module "azurerm_firewall_policies" { - source = "./modules/networking/firewall_policies" - for_each = local.networking.azurerm_firewall_policies + source = "./modules/networking/firewall_policies" + for_each = { + for key, value in local.networking.azurerm_firewall_policies : key => value + if try(value.base_policy, null) == null + } global_settings = local.global_settings name = each.value.name @@ -37,17 +41,22 @@ module "azurerm_firewall_policies" { policy_settings = each.value } + module "azurerm_firewall_policy_rule_collection_groups" { source = "./modules/networking/firewall_policy_rule_collection_groups" for_each = local.networking.azurerm_firewall_policy_rule_collection_groups global_settings = local.global_settings - policy_settings = each.value - firewall_policies = module.azurerm_firewall_policies ip_groups = module.ip_groups + policy_settings = each.value public_ip_addresses = module.public_ip_addresses + firewall_policy_id = coalesce( + try(local.combined_objects_azurerm_firewall_policies[try(each.value.firewall_policy.lz_key, local.client_config.landingzone_key)][each.value.firewall_policy.key].id, null), + try(local.combined_objects_azurerm_firewall_policies[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.firewall_policy_key].id, null) + ) } + module "azurerm_firewall_network_rule_collections" { source = "./modules/networking/firewall_network_rule_collections" for_each = { @@ -102,7 +111,6 @@ output "azurerm_firewalls" { output "azurerm_firewall_policies" { value = module.azurerm_firewall_policies - } output "azurerm_firewall_policy_rule_collection_groups" { diff --git a/networking_vpn_gateway_connection.tf b/networking_vpn_gateway_connection.tf new file mode 100644 index 0000000000..592833dbec --- /dev/null +++ b/networking_vpn_gateway_connection.tf @@ -0,0 +1,30 @@ + +# +# +# VPN Gateway Connection +# +# + +output "vpn_gateway_connections" { + value = module.vpn_gateway_connections +} + +module "vpn_gateway_connections" { + depends_on = [module.virtual_wans, module.vpn_sites, module.virtual_hubs] + source = "./modules/networking/vpn_gateway_connection" + for_each = local.networking.vpn_gateway_connections + + settings = each.value + global_settings = local.global_settings + client_config = local.client_config + vpn_sites = local.combined_objects_vpn_sites + route_tables = local.combined_objects_virtual_hub_route_tables + + vpn_gateway_id = coalesce( + try(local.combined_objects_virtual_hubs[try(each.value.virtual_hub.lz_key, local.client_config.landingzone_key)][each.value.virtual_hub.key].s2s_gateway.id, null), + try(local.combined_objects_virtual_wans[try(each.value.virtual_wan.lz_key, local.client_config.landingzone_key)][each.value.virtual_wan.key].virtual_hubs[each.value.virtual_hub.key].s2s_gateway.id, null), + try(local.combined_objects_virtual_wans[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.virtual_wan_key].virtual_hubs[each.value.virtual_hub_key].s2s_gateway.id, null), + try(local.combined_objects_virtual_wans[try(each.value.vhub.lz_key, local.client_config.landingzone_key)][each.value.vhub.virtual_wan_key].virtual_hubs[each.value.vhub.virtual_hub_key].s2s_gateway.id, null), + try(each.value.virtual_hub_gateway_id, null) + ) +} diff --git a/networking_vpn_site.tf b/networking_vpn_site.tf new file mode 100644 index 0000000000..d5e73347f8 --- /dev/null +++ b/networking_vpn_site.tf @@ -0,0 +1,42 @@ + +# +# +# VPN Sites +# +# + +output "vpn_sites" { + value = module.vpn_sites +} + +module "vpn_sites" { + depends_on = [module.virtual_wans] + source = "./modules/networking/vpn_site" + for_each = local.networking.vpn_sites + + global_settings = local.global_settings + settings = each.value + + base_tags = try(local.global_settings.inherit_tags, false) ? coalesce( + try(local.resource_groups[each.value.resource_group_key].tags, null), + try(local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][each.value.resource_group.key].tags, null), + ) : {} + + location = lookup(each.value, "region", null) == null ? coalesce( + try(local.resource_groups[each.value.resource_group_key].location, null), + try(local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][each.value.resource_group.key].location, null), + ) : local.global_settings.regions[each.value.region] + + resource_group_name = coalesce( + try(local.resource_groups[each.value.resource_group_key].name, null), + try(local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][each.value.resource_group.key].name, null), + ) + + virtual_wan_id = coalesce( + try(local.combined_objects_virtual_wans[try(each.value.virtual_wan.lz_key, local.client_config.landingzone_key)][each.value.virtual_wan.key].virtual_wan.id, null), + try(local.combined_objects_virtual_wans[try(each.value.lz_key, local.client_config.landingzone_key)][each.value.virtual_wan_key].virtual_wan.id, null), + try(each.value.virtual_wan.resource_id, null), + try(each.value.virtual_wan.id, null), + try(each.value.virtual_wan_id, null) + ) +} diff --git a/random_string.tf b/random_string.tf new file mode 100755 index 0000000000..4aff80455d --- /dev/null +++ b/random_string.tf @@ -0,0 +1,15 @@ + +module "random_strings" { + source = "./modules/random_string" + for_each = try(var.random_strings, {}) + + random_string_length = each.value.length + random_string_allow_special_characters = try(each.value.special, false) + random_string_allow_upper_case = try(each.value.upper, false) + random_string_allow_numbers = try(each.value.number, false) +} + +output "random_strings" { + value = module.random_strings + +} diff --git a/roles.tf b/roles.tf index 3336ae4392..410b5bf582 100755 --- a/roles.tf +++ b/roles.tf @@ -25,21 +25,45 @@ resource "azurerm_role_assignment" "for" { ignore_changes = [ principal_id ] + + create_before_destroy = true + } + +} + +data "azurerm_management_group" "level" { + for_each = { + for key, value in try(var.role_mapping.built_in_role_mapping.management_group, {}) : key => value } + name = lower(each.key) == "root" ? data.azurerm_client_config.current.tenant_id : each.key } locals { + + management_groups = tomap( + { + (var.current_landingzone_key) = { + for key, value in try(var.role_mapping.built_in_role_mapping.management_group, {}) : + key => { + id = data.azurerm_management_group.level[key].id + } + } + } + ) + services_roles = { aks_clusters = local.combined_objects_aks_clusters app_config = local.combined_objects_app_config - app_services = local.combined_objects_app_services - app_service_plans = local.combined_objects_app_service_plans app_service_environments = local.combined_objects_app_service_environments + app_service_plans = local.combined_objects_app_service_plans + app_services = local.combined_objects_app_services availability_sets = local.combined_objects_availability_sets azure_container_registries = local.combined_objects_azure_container_registries + azuread_applications = local.combined_objects_azuread_applications + azuread_apps = local.combined_objects_azuread_apps azuread_groups = local.combined_objects_azuread_groups - azuread_apps = local.combined_objects_azuread_applications + azuread_service_principals = local.combined_objects_azuread_service_principals azuread_users = local.combined_objects_azuread_users azurerm_firewalls = local.combined_objects_azurerm_firewalls dns_zones = local.combined_objects_dns_zones @@ -48,14 +72,15 @@ locals { logged_in = local.logged_in machine_learning_workspaces = local.combined_objects_machine_learning managed_identities = local.combined_objects_managed_identities + management_group = local.management_groups mssql_databases = local.combined_objects_mssql_databases mssql_elastic_pools = local.combined_objects_mssql_elastic_pools mssql_managed_databases = local.combined_objects_mssql_managed_databases mssql_managed_instances = local.combined_objects_mssql_managed_instances mssql_servers = local.combined_objects_mssql_servers mysql_servers = local.combined_objects_mysql_servers - networking = local.combined_objects_networking network_watchers = local.combined_objects_network_watchers + networking = local.combined_objects_networking postgresql_servers = local.combined_objects_postgresql_servers private_dns = local.combined_objects_private_dns proximity_placement_groups = local.combined_objects_proximity_placement_groups @@ -63,20 +88,23 @@ locals { recovery_vaults = local.combined_objects_recovery_vaults resource_groups = local.combined_objects_resource_groups storage_accounts = local.combined_objects_storage_accounts + subscriptions = local.combined_objects_subscriptions synapse_workspaces = local.combined_objects_synapse_workspaces - subscriptions = tomap({ (var.current_landingzone_key) = merge(try(var.subscriptions, {}), { "logged_in_subscription" = { id = data.azurerm_subscription.primary.id } }) }) } - logged_in = tomap({ - (var.current_landingzone_key) = { - user = { - rbac_id = local.client_config.logged_user_objectId - } - app = { - rbac_id = local.client_config.logged_aad_app_objectId + + logged_in = tomap( + { + (var.current_landingzone_key) = { + user = { + rbac_id = local.client_config.logged_user_objectId + } + app = { + rbac_id = local.client_config.logged_aad_app_objectId + } } } - }) + ) roles_to_process = { for mapping in @@ -103,9 +131,8 @@ locals { ] ] ] - ) : format("%s_%s_%s", mapping.scope_key_resource, replace(mapping.role_definition_name, " ", "_"), mapping.object_id_key_resource) => mapping + ) : format("%s_%s_%s_%s", mapping.object_id_resource_type, mapping.scope_key_resource, replace(mapping.role_definition_name, " ", "_"), mapping.object_id_key_resource) => mapping } - } # The code transform this input format to diff --git a/storage_account_queues.tf b/storage_account_queues.tf new file mode 100644 index 0000000000..feaebe4d67 --- /dev/null +++ b/storage_account_queues.tf @@ -0,0 +1,12 @@ +module "storage_account_queues" { + source = "./modules/storage_account/queue" + for_each = local.storage.storage_account_queues + storage_account_name = module.storage_accounts[each.value.storage_account_key].name + settings = each.value + +} + +output "storage_account_queues" { + value = module.storage_account_queues + +} \ No newline at end of file diff --git a/subscriptions.tf b/subscriptions.tf index d17b6146df..aac0ae8969 100755 --- a/subscriptions.tf +++ b/subscriptions.tf @@ -1,7 +1,6 @@ module "subscriptions" { - source = "./modules/subscriptions" - depends_on = [azurerm_role_assignment.for] + source = "./modules/subscriptions" for_each = var.subscriptions @@ -22,8 +21,9 @@ module "subscription_billing_role_assignments" { keyvaults = local.combined_objects_keyvaults settings = each.value principals = { - azuread_users = local.combined_objects_azuread_users - managed_identities = local.combined_objects_managed_identities + azuread_users = local.combined_objects_azuread_users + managed_identities = local.combined_objects_managed_identities + azuread_service_principals = local.combined_objects_azuread_service_principals } } diff --git a/variables.tf b/variables.tf index d985ff2c7e..6d8d9bed71 100755 --- a/variables.tf +++ b/variables.tf @@ -18,12 +18,47 @@ variable "client_config" { ## Cloud variables variable "cloud" { - description = "Cloud configuration objects" - default = {} + description = "Configuration object - Cloud resources defaults to Azure public, allows you to switch to other Azure endpoints." + default = { + acrLoginServerEndpoint = ".azurecr.io" + attestationEndpoint = ".attest.azure.net" + azureDatalakeAnalyticsCatalogAndJobEndpoint = "azuredatalakeanalytics.net" + azureDatalakeStoreFileSystemEndpoint = "azuredatalakestore.net" + keyvaultDns = ".vault.azure.net" + mariadbServerEndpoint = ".mariadb.database.azure.com" + mhsmDns = ".managedhsm.azure.net" + mysqlServerEndpoint = ".mysql.database.azure.com" + postgresqlServerEndpoint = ".postgres.database.azure.com" + sqlServerHostname = ".database.windows.net" + storageEndpoint = "core.windows.net" + storageSyncEndpoint = "afs.azure.net" + synapseAnalyticsEndpoint = ".dev.azuresynapse.net" + activeDirectory = "https://login.microsoftonline.com" + activeDirectoryDataLakeResourceId = "https://datalake.azure.net/" + activeDirectoryGraphResourceId = "https://graph.windows.net/" + activeDirectoryResourceId = "https://management.core.windows.net/" + appInsightsResourceId = "https://api.applicationinsights.io" + appInsightsTelemetryChannelResourceId = "https://dc.applicationinsights.azure.com/v2/track" + attestationResourceId = "https://attest.azure.net" + azmirrorStorageAccountResourceId = "null" + batchResourceId = "https://batch.core.windows.net/" + gallery = "https://gallery.azure.com/" + logAnalyticsResourceId = "https://api.loganalytics.io" + management = "https://management.core.windows.net/" + mediaResourceId = "https://rest.media.azure.net" + microsoftGraphResourceId = "https://graph.microsoft.com/" + ossrdbmsResourceId = "https://ossrdbms-aad.database.windows.net" + portal = "https://portal.azure.com" + resourceManager = "https://management.azure.com/" + sqlManagement = "https://management.core.windows.net:8443/" + synapseAnalyticsResourceId = "https://dev.azuresynapse.net" + vmImageAliasDoc = "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/arm-compute/quickstart-templates/aliases.json" + } } variable "tenant_id" { description = "Azure AD Tenant ID for the current deployment." + type = string default = null } @@ -54,10 +89,12 @@ variable "environment" { variable "logged_user_objectId" { description = "Used to set access policies based on the value 'logged_in_user'. Can only be used in interactive execution with vscode." + type = string default = null } variable "logged_aad_app_objectId" { description = "Used to set access policies based on the value 'logged_in_aad_app'" + type = string default = null } @@ -74,90 +111,85 @@ variable "tags" { } variable "resource_groups" { - description = "Resource groups configuration objects" + description = "Configuration object - Resource groups." default = {} } variable "subscriptions" { - default = {} + description = "Configuration object - Subscriptions resources." + default = {} } variable "subscription_billing_role_assignments" { - default = {} + description = "Configuration object - subscription billing roleassignments." + default = {} } variable "billing" { - description = "Billing information" + description = "Configuration object - Billing information." default = {} } variable "remote_objects" { - description = "Remote objects is used to allow the landing zone to retrieve remote tfstate objects and pass them to the caf module" + description = "Allow the landing zone to retrieve remote tfstate objects and pass them to the CAF module." default = {} } ## Diagnostics settings variable "diagnostics_definition" { default = null - description = "Shared diadgnostics settings that can be used by the services to enable diagnostics" + description = "Configuration object - Shared diadgnostics settings that can be used by the services to enable diagnostics." } variable "diagnostics_destinations" { - default = null + description = "Configuration object - Describes the destinations for the diagnostics." + default = null } variable "log_analytics" { - default = {} + description = "Configuration object - Log Analytics resources." + default = {} } variable "diagnostics" { - default = {} + description = "Configuration object - Diagnostics object." + default = {} } variable "event_hub_namespaces" { - default = {} + description = "Configuration object - Diagnostics object." + default = {} } -variable "subnet_id" { - default = {} -} +# variable "subnet_id" { +# default = {} +# } variable "user_type" { - description = "The rover set this value to user or serviceprincipal. It is used to handle Azure AD api consents." + description = "The rover set this value to user or serviceprincipal. It is used to handle Azure AD API consents." default = {} } ## Azure AD -variable "azuread_apps" { - default = {} -} - -variable "azuread_groups" { - default = {} -} - -variable "azuread_roles" { - default = {} -} - -variable "azuread_users" { - default = {} +variable "azuread" { + description = "Configuration object - Azure Active Directory resources" + default = {} } -variable "azuread_api_permissions" { - default = {} -} +# variable "azuread_api_permissions" { +# default = {} +# } ## Compute variables variable "compute" { - description = "Compute configuration objects" + description = "Configuration object - Azure compute resources" default = { virtual_machines = {} } } variable "webapp" { - description = "Web applications configuration objects" + description = "Configuration object - Web Applications" default = { # app_services = {} # app_service_environments = {} @@ -167,53 +199,60 @@ variable "webapp" { } variable "data_factory" { - default = {} + description = "Configuration object - Azure Data Factory resources" + default = {} } variable "logic_app" { - default = {} + description = "Configuration object - Azure Logic App resources" + default = {} } ## Databases variables variable "database" { - description = "Database configuration objects" + description = "Configuration object - databases resources" default = {} } ## Networking variables variable "networking" { - description = "Networking configuration objects" + description = "Configuration object - networking resources" default = {} } ## Security variables variable "security" { - default = {} + description = "Configuration object - security resources" + default = {} } variable "managed_identities" { - description = "Managed Identity configuration objects" + description = "Configuration object - Azure managed identity resources" default = {} } variable "keyvaults" { - description = "Key Vault configuration objects" + description = "Configuration object - Azure Key Vault resources" default = {} } variable "keyvault_access_policies" { - default = {} + description = "Configuration object - Azure Key Vault policies" + default = {} } variable "keyvault_access_policies_azuread_apps" { - default = {} + description = "Configuration object - Azure Key Vault policy for azure ad applications" + default = {} } variable "custom_role_definitions" { - description = "Custom role definitions configuration objects" + description = "Configuration object - Custom role definitions" default = {} } + variable "role_mapping" { + description = "Configuration object - Role mapping" default = { built_in_role_mapping = {} custom_role_mapping = {} @@ -226,19 +265,21 @@ variable "dynamic_keyvault_secrets" { ## Storage variables variable "storage_accounts" { - default = {} + description = "Configuration object - Storage account resources" + default = {} } variable "storage" { - description = "Storage configuration objects" + description = "Configuration object - Storage account resources" default = {} } variable "diagnostic_storage_accounts" { - default = {} + description = "Configuration object - Storage account for diagnostics resources" + default = {} } # Shared services variable "shared_services" { - description = "Shared services configuration objects" + description = "Configuration object - Shared services resources" default = { # automations = {} # monitoring = {} @@ -246,61 +287,70 @@ variable "shared_services" { } } -variable "virtual_network_gateways" { - default = {} -} +# variable "virtual_network_gateways" { +# default = {} +# } -variable "virtual_network_gateway_connections" { - default = {} -} +# variable "virtual_network_gateway_connections" { +# default = {} +# } -variable "shared_image_galleries" { - default = {} -} +# variable "shared_image_galleries" { +# default = {} +# } -variable "image_definitions" { - default = {} -} +# variable "image_definitions" { +# default = {} +# } -variable "packer_service_principal" { - default = {} -} +# variable "packer_service_principal" { +# default = {} +# } -variable "packer_managed_identity" { - default = {} -} +# variable "packer_managed_identity" { +# default = {} +# } variable "keyvault_certificate_issuers" { - default = {} -} -variable "cosmos_dbs" { - default = {} + description = "Configuration object - Azure Key Vault Certificate Issuers resources" + default = {} } +# variable "cosmos_dbs" { +# default = {} +# } -variable "app_config" { - default = {} -} +# variable "app_config" { +# default = {} +# } -variable "local_network_gateways" { - default = {} -} +# variable "local_network_gateways" { +# default = {} +# } -variable "application_security_groups" { - default = {} -} +# variable "application_security_groups" { +# default = {} +# } variable "event_hubs" { - default = {} + description = "Configuration object - Event Hub resources" + default = {} } variable "event_hub_auth_rules" { - default = {} + description = "Configuration object - Event Hub authentication rules" + default = {} } variable "event_hub_namespace_auth_rules" { - default = {} + description = "Configuration object - Event Hub namespaces authentication rules" + default = {} } variable "event_hub_consumer_groups" { - default = {} + description = "Configuration object - Event Hub consumer group rules" + default = {} } +variable "random_strings" { + description = "Configuration object - Random string generator resources" + default = {} +} diff --git a/virtual_machines.tf b/virtual_machines.tf index 322b71e5d7..abafcec583 100755 --- a/virtual_machines.tf +++ b/virtual_machines.tf @@ -14,7 +14,6 @@ module "virtual_machines" { application_security_groups = local.combined_objects_application_security_groups availability_sets = local.combined_objects_availability_sets - base_tags = try(local.global_settings.inherit_tags, false) ? module.resource_groups[each.value.resource_group_key].tags : {} # if boot_diagnostics_storage_account_key is points to a valid storage account, pass the endpoint # if boot_diagnostics_storage_account_key is empty string, pass empty string # if boot_diagnostics_storage_account_key not defined, pass null @@ -26,16 +25,19 @@ module "virtual_machines" { diagnostics = local.combined_diagnostics disk_encryption_sets = local.combined_objects_disk_encryption_sets global_settings = local.global_settings - keyvaults = local.combined_objects_keyvaults - location = lookup(each.value, "region", null) == null ? local.resource_groups[each.value.resource_group_key].location : local.global_settings.regions[each.value.region] + keyvaults = local.combined_objects_keyvaults managed_identities = local.combined_objects_managed_identities network_security_groups = local.combined_objects_network_security_groups proximity_placement_groups = local.combined_objects_proximity_placement_groups public_ip_addresses = local.combined_objects_public_ip_addresses recovery_vaults = local.combined_objects_recovery_vaults - resource_group_name = local.resource_groups[each.value.resource_group_key].name settings = each.value vnets = local.combined_objects_networking + dedicated_hosts = local.combined_objects_dedicated_hosts + + resource_group_name = local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].name + location = lookup(each.value, "region", null) == null ? local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].location : local.global_settings.regions[each.value.region] + base_tags = try(local.global_settings.inherit_tags, false) ? local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].tags : {} } diff --git a/virtual_machines_scale_sets.tf b/virtual_machines_scale_sets.tf index c386ff181e..5cb13d16ee 100644 --- a/virtual_machines_scale_sets.tf +++ b/virtual_machines_scale_sets.tf @@ -1,6 +1,6 @@ -module virtual_machine_scale_sets { +module "virtual_machine_scale_sets" { source = "./modules/compute/virtual_machine_scale_set" depends_on = [ module.availability_sets, @@ -37,7 +37,7 @@ module virtual_machine_scale_sets { } -output virtual_machine_scale_sets { +output "virtual_machine_scale_sets" { value = module.virtual_machine_scale_sets } diff --git a/wvd_applications.tf b/wvd_applications.tf new file mode 100644 index 0000000000..25514bbdca --- /dev/null +++ b/wvd_applications.tf @@ -0,0 +1,14 @@ +module "wvd_applications" { + source = "./modules/compute/wvd_applications" + for_each = local.compute.wvd_applications + + global_settings = local.global_settings + settings = each.value + application_group_id = try(local.combined_objects_wvd_application_groups[local.client_config.landingzone_key][each.value.application_group_key].id, local.combined_objects_wvd_application_groups[each.value.lz_key][each.value.application_group_key].id) + diagnostics = local.combined_diagnostics + diagnostic_profiles = try(each.value.diagnostic_profiles, {}) +} + +output "wvd_applications" { + value = module.wvd_applications +} \ No newline at end of file