diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 57b9f71..19b443c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,3 +1,4 @@ +--- # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: @@ -5,7 +6,7 @@ version: 2 updates: - - package-ecosystem: "nuget" # See documentation for possible values - directory: "/src/ALZ" # Location of package manifests + - package-ecosystem: "nuget" # See documentation for possible values + directory: "/src/ALZ" # Location of package manifests schedule: interval: "daily" diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml new file mode 100644 index 0000000..49fb796 --- /dev/null +++ b/.github/linters/.markdown-lint.yml @@ -0,0 +1,36 @@ +--- +########################### +########################### +## Markdown Linter rules ## +########################### +########################### + +# Linter rules doc: +# - https://github.com/DavidAnson/markdownlint +# +# Note: +# To comment out a single error: +# +# any violations you want +# +# + +############### +# Rules by id # +############### +MD004: false # ul-style - Unordered list style +MD007: + indent: 2 # ul-indent - Unordered list indentation +MD013: + line_length: 500 # line-length - Line length +MD026: + punctuation: ".,;:!。,;:" # no-trailing-punctuation - Trailing punctuation in heading +MD029: false # ol-prefix - Ordered list item prefix +MD033: false # no-inline-html - Inline HTML +MD036: false # no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading +MD041: false # first-line-heading/first-line-h1 - First line in a file should be a top-level heading + +################# +# Rules by tags # +################# +blank_lines: false # MD012, MD022, MD031, MD032, MD047 diff --git a/.github/linters/.yaml-lint.yml b/.github/linters/.yaml-lint.yml new file mode 100644 index 0000000..96fe9da --- /dev/null +++ b/.github/linters/.yaml-lint.yml @@ -0,0 +1,11 @@ +--- +extends: default + +rules: + # 500 chars should be enough, but don't fail if a line is longer + line-length: + max: 500 + level: warning + truthy: + check-keys: false + level: warning diff --git a/.github/prerelease-drafter.yml b/.github/prerelease-drafter.yml index 5d94abf..3adbc4f 100644 --- a/.github/prerelease-drafter.yml +++ b/.github/prerelease-drafter.yml @@ -1,3 +1,4 @@ +--- name-template: '$RESOLVED_VERSION-alpha' tag-template: '$RESOLVED_VERSION-alpha' prerelease: true @@ -14,7 +15,7 @@ categories: - title: '🧰 Maintenance' label: 'chore' change-template: '- $TITLE @$AUTHOR (#$NUMBER)' -change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. +change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. version-resolver: major: labels: @@ -29,4 +30,4 @@ version-resolver: template: | ## Changes - $CHANGES \ No newline at end of file + $CHANGES diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index f21d1ff..a06dd54 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,3 +1,4 @@ +--- name-template: '$RESOLVED_VERSION' tag-template: '$RESOLVED_VERSION' categories: @@ -13,7 +14,7 @@ categories: - title: '🧰 Maintenance' label: 'chore' change-template: '- $TITLE @$AUTHOR (#$NUMBER)' -change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. +change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. version-resolver: major: labels: @@ -28,4 +29,4 @@ version-resolver: template: | ## Changes - $CHANGES \ No newline at end of file + $CHANGES diff --git a/.github/workflows/Prerelease.yml b/.github/workflows/Prerelease.yml index 8d97b68..87fa3bb 100644 --- a/.github/workflows/Prerelease.yml +++ b/.github/workflows/Prerelease.yml @@ -1,3 +1,4 @@ +--- name: Prerelease Build on: @@ -20,62 +21,62 @@ jobs: runs-on: ubuntu-latest steps: # Drafts your next Release notes as Pull Requests are merged into "master" - - name: Check out repository - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Display the path - shell: pwsh - run: echo ${env:PATH} - - name: Version Display - shell: pwsh - run: $PSVersionTable - - name: Bootstrap - shell: pwsh - run: ./actions_bootstrap.ps1 - - name: Test and Build - shell: pwsh - run: Invoke-Build -File .\src\ALZ.build.ps1 - - name: Upload pester results - uses: actions/upload-artifact@v3 - with: - name: pester-results - path: .\src\Artifacts\testOutput - if-no-files-found: warn - - name: Upload zip module archive build - uses: actions/upload-artifact@v3 - with: - name: zip-archive - path: .\src\Archive - if-no-files-found: warn - - uses: release-drafter/release-drafter@v5 - id: create_release - with: - config-name: prerelease-drafter.yml - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Package ALZ Module - shell: pwsh - run: | - $tag_version = "${{ steps.create_release.outputs.tag_name }}".Replace("-alpha", "") - ./package_ALZ.ps1 -version $tag_version -prerelease alpha - - uses: montudor/action-zip@v1 - with: + - name: Check out repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Display the path + shell: pwsh + run: echo ${env:PATH} + - name: Version Display + shell: pwsh + run: $PSVersionTable + - name: Bootstrap + shell: pwsh + run: ./actions_bootstrap.ps1 + - name: Test and Build + shell: pwsh + run: Invoke-Build -File .\src\ALZ.build.ps1 + - name: Upload pester results + uses: actions/upload-artifact@v3 + with: + name: pester-results + path: .\src\Artifacts\testOutput + if-no-files-found: warn + - name: Upload zip module archive build + uses: actions/upload-artifact@v3 + with: + name: zip-archive + path: .\src\Archive + if-no-files-found: warn + - uses: release-drafter/release-drafter@v5 + id: create_release + with: + config-name: prerelease-drafter.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Package ALZ Module + shell: pwsh + run: | + $tag_version = "${{ steps.create_release.outputs.tag_name }}".Replace("-alpha", "") + ./package_ALZ.ps1 -version $tag_version -prerelease alpha + - uses: montudor/action-zip@v1 + with: args: zip -qq -r ALZ.zip ALZ - - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./ALZ.zip - asset_name: ALZ.zip - asset_content_type: application/zip - - uses: eregon/publish-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - release_id: ${{ steps.create_release.outputs.id }} - - name: Publish ALZ Module - shell: pwsh - run: | - Publish-Module -Path "./ALZ" -NuGetApiKey ${{ secrets.POWERSHELL_GALLERY_KEY }} -ReleaseNotes "${{ steps.create_release.outputs.body }}" -Force \ No newline at end of file + - uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./ALZ.zip + asset_name: ALZ.zip + asset_content_type: application/zip + - uses: eregon/publish-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + release_id: ${{ steps.create_release.outputs.id }} + - name: Publish ALZ Module + shell: pwsh + run: | + Publish-Module -Path "./ALZ" -NuGetApiKey ${{ secrets.POWERSHELL_GALLERY_KEY }} -ReleaseNotes "${{ steps.create_release.outputs.body }}" -Force diff --git a/.github/workflows/PullRequest.yml b/.github/workflows/PullRequest.yml index fbcb2f0..28e0ddd 100644 --- a/.github/workflows/PullRequest.yml +++ b/.github/workflows/PullRequest.yml @@ -1,3 +1,4 @@ +--- name: Pull Request Validator on: pull_request: @@ -12,27 +13,27 @@ jobs: strategy: fail-fast: false matrix: - pwsh: [ '7.1.3' ] + pwsh: ['7.1.3'] steps: - - name: Check out repository - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Display the path - shell: pwsh - run: echo ${env:PATH} - - name: Version Display - shell: pwsh - run: $PSVersionTable - - name: Bootstrap - shell: pwsh - run: ./actions_bootstrap.ps1 - - name: Test and Build - shell: pwsh - run: Invoke-Build -File .\src\ALZ.build.ps1 - - name: Upload pester results - uses: actions/upload-artifact@v3 - with: - name: pester-results - path: .\src\Artifacts\testOutput - if-no-files-found: warn \ No newline at end of file + - name: Check out repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Display the path + shell: pwsh + run: echo ${env:PATH} + - name: Version Display + shell: pwsh + run: $PSVersionTable + - name: Bootstrap + shell: pwsh + run: ./actions_bootstrap.ps1 + - name: Test and Build + shell: pwsh + run: Invoke-Build -File .\src\ALZ.build.ps1 + - name: Upload pester results + uses: actions/upload-artifact@v3 + with: + name: pester-results + path: .\src\Artifacts\testOutput + if-no-files-found: warn diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index cdb0149..dfa35e1 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -1,3 +1,4 @@ +--- name: Release Build on: @@ -17,61 +18,61 @@ jobs: runs-on: ubuntu-latest steps: # Drafts your next Release notes as Pull Requests are merged into "master" - - name: Check out repository - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Display the path - shell: pwsh - run: echo ${env:PATH} - - name: Version Display - shell: pwsh - run: $PSVersionTable - - name: Bootstrap - shell: pwsh - run: ./actions_bootstrap.ps1 - - name: Test and Build - shell: pwsh - run: Invoke-Build -File .\src\ALZ.build.ps1 - - name: Upload pester results - uses: actions/upload-artifact@v3 - with: - name: pester-results - path: .\src\Artifacts\testOutput - if-no-files-found: warn - - name: Upload zip module archive build - uses: actions/upload-artifact@v3 - with: - name: zip-archive - path: .\src\Archive - if-no-files-found: warn - - uses: release-drafter/release-drafter@v5 - id: create_release - with: - config-name: release-drafter.yml - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Package ALZ Module - shell: pwsh - run: | - ./package_ALZ.ps1 -version ${{ steps.create_release.outputs.tag_name }} - - uses: montudor/action-zip@v1 - with: + - name: Check out repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Display the path + shell: pwsh + run: echo ${env:PATH} + - name: Version Display + shell: pwsh + run: $PSVersionTable + - name: Bootstrap + shell: pwsh + run: ./actions_bootstrap.ps1 + - name: Test and Build + shell: pwsh + run: Invoke-Build -File .\src\ALZ.build.ps1 + - name: Upload pester results + uses: actions/upload-artifact@v3 + with: + name: pester-results + path: .\src\Artifacts\testOutput + if-no-files-found: warn + - name: Upload zip module archive build + uses: actions/upload-artifact@v3 + with: + name: zip-archive + path: .\src\Archive + if-no-files-found: warn + - uses: release-drafter/release-drafter@v5 + id: create_release + with: + config-name: release-drafter.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Package ALZ Module + shell: pwsh + run: | + ./package_ALZ.ps1 -version ${{ steps.create_release.outputs.tag_name }} + - uses: montudor/action-zip@v1 + with: args: zip -qq -r ALZ.zip ALZ - - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./ALZ.zip - asset_name: ALZ.zip - asset_content_type: application/zip - - uses: eregon/publish-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - release_id: ${{ steps.create_release.outputs.id }} - - name: Publish ALZ Module - shell: pwsh - run: | - Publish-Module -Path "./ALZ" -NuGetApiKey ${{ secrets.POWERSHELL_GALLERY_KEY }} -ReleaseNotes "${{ steps.create_release.outputs.body }}" -Force \ No newline at end of file + - uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./ALZ.zip + asset_name: ALZ.zip + asset_content_type: application/zip + - uses: eregon/publish-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + release_id: ${{ steps.create_release.outputs.id }} + - name: Publish ALZ Module + shell: pwsh + run: | + Publish-Module -Path "./ALZ" -NuGetApiKey ${{ secrets.POWERSHELL_GALLERY_KEY }} -ReleaseNotes "${{ steps.create_release.outputs.body }}" -Force diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 269986b..ebe13ff 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -1,3 +1,4 @@ +--- # This workflow uses actions that are not certified by GitHub. They are provided # by a third-party and are governed by separate terms of service, privacy # policy, and support documentation. @@ -12,7 +13,7 @@ on: schedule: - cron: '16 23 * * 2' push: - branches: [ "main" ] + branches: ["main"] # Declare default permissions as read only. permissions: read-all @@ -32,12 +33,12 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 with: results_file: results.sarif results_format: sarif @@ -59,7 +60,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20 + uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20 with: name: SARIF file path: results.sarif @@ -68,6 +69,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 with: sarif_file: results.sarif diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 7380068..eaf9e1c 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,9 +1,7 @@ { - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format "recommendations": [ "ms-vscode.PowerShell", "ryanluker.vscode-coverage-gutters", "DavidAnson.vscode-markdownlint" ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index b6d2d10..5a5a570 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,5 @@ { - // When enabled, will trim trailing whitespace when you save a file. "files.trimTrailingWhitespace": true, - // specifies the location of the explicitly ScriptAnalyzer settings file "powershell.scriptAnalysis.settingsPath": "PSScriptAnalyzerSettings.psd1", - // specifies the PowerShell coding style used in this project (https://github.com/PoshCode/PowerShellPracticeAndStyle/issues/81) "powershell.codeFormatting.preset":"OTBS" } - diff --git a/.vscode/tasks.json b/.vscode/tasks.json index c4678f4..edd53b7 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,30 +1,8 @@ -// Portions of this file were generated using New-VSCodeTask.ps1 -// Modify the build script or tasks-merge.json and recreate. -// https://code.visualstudio.com/docs/editor/tasks -// Available variables which can be used inside of strings. -// https://code.visualstudio.com/docs/editor/variables-reference#_predefined-variables -// ${workspaceFolder}: path of the folder opened in VS Code -// ${workspaceFolderBasename} - name of the folder opened in VS Code without any slashes (/) -// ${file}: current opened file -// ${fileWorkspaceFolder} - current opened file's workspace folder -// ${relativeFile}: the current opened file relative to workspaceFolder -// ${relativeFileDirname}: current opened file's dirname relative to workspaceFolder -// ${fileBasename}: current opened file's basename -// ${fileBasenameNoExtension} - current opened file's basename with no file extension -// ${fileDirname}: current opened file's dirname -// ${fileExtname}: current opened file's extension -// ${cwd}: the current working directory of the spawned process -// ${lineNumber} - current selected line number in the active file -// ${selectedText} - current selected text in the active file -// ${execPath} - path to the running VS Code executable -// ${defaultBuildTask} - name of the default build task -// ${pathSeparator} - character used by the operating system to separate components in file paths { "version": "2.0.0", "windows": { "options": { "shell": { - // "executable": "powershell.exe", "executable": "pwsh.exe", "args": [ "-NoProfile", @@ -264,4 +242,3 @@ } ] } - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..79c137d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Development + +## Development Prerequisites + +In order to develop this module you will need PowerShell 7.1 or later. + +## Pre-requisites + +```powershell +# Required to run Invoke-Build +Install-Module -F PSScriptAnalyzer +Install-Module -F InvokeBuild +Install-Module -F Pester +``` + +## Commands to build locally + +```powershell +# Build and test locally +Remove-Module "ALZ" -Force +Invoke-Build -File .\src\ALZ.build.ps1 +``` + +## Commands to import a build locally + +```powershell +# Install the module locally +Invoke-Build -File .\src\ALZ.build.ps1 +Import-Module .\src\Artifacts\ALZ.psd1 -Force +``` diff --git a/README.md b/README.md index fa4ad8d..8f81dcd 100644 --- a/README.md +++ b/README.md @@ -1,166 +1,78 @@ -# ALZ / Accelerator PowerShell Module +# Azure Landing Zones Accelerators for Bicep and Terraform [![license](https://img.shields.io/badge/License-MIT-purple.svg)](LICENSE) [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/Azure/ALZ-PowerShell-Module/badge)](https://scorecard.dev/viewer/?uri=github.com/Azure/ALZ-PowerShell-Module) +![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Azure/ALZ-PowerShell-Module?style=flat&logo=github) +![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed/Azure/ALZ-PowerShell-Module) +![GitHub contributors](https://img.shields.io/github/contributors/Azure/ALZ-PowerShell-Module) -![Logo](./docs/ALZLogo.png) +![Logo](./docs/wiki/media/Logo.png) -## Synopsis +## Introduction -This is a PowerShell module that provides a set of cmdlets to create and manage Accelerators for Azure Landing Zones and other workloads. +TLDR: Head straight over to our [Quick Start](https://github.com/Azure/ALZ-PowerShell-Module/wiki/%5BUser-Guide%5D-Quick-Start) to get going now. -## Description +This repository contains the PowerShell module and documentation for the Azure landing zones Accelerators for Bicep and Terraform. The accelerators are an opinionated implementation of the Azure Landing Zones Terraform modules, with Azure DevOps or GitHub bootstrapping. -This module provides a set of cmdlets to create and manage Accelerators for Azure Landing Zones and other workloads. +It is designed to be used as a template to enable you to get started quickly deploying ALZ with Bicep or Terraform. -## Why +Please refer to our [Wiki](https://github.com/Azure/ALZ-PowerShell-Module/wiki) for detailed features and usage instructions. -The goal of this project it is to make easy to get started with Azure Landing Zones and other workloads. It is designed to speed up some basic tasks that you would need to perform whilst managing your Azure Landing Zones. +## Quick Start -For usage of the Azure Landing Zoners Accelerators, please refer to the detailed documentation: +To get going right now, run these PowerShell steps: -- [Bicep](https://github.com/Azure/ALZ-Bicep/wiki/Accelerator) -- [Terraform](https://github.com/Azure/alz-terraform-accelerator/wiki) - -## Getting Started - -### Prerequisites - -In order to use this module you will need PowerShell 7.1 or higher. -Download and install the latest version from the official PowerShell GitHub releases page: [PowerShell Releases](https://github.com/PowerShell/PowerShell/releases) - -To make PowerShell 7 your default instead of version 5, consider setting an alias. - -Open a PowerShell session and run the following command: - - ```powershell - $PSVersionTable.PSVersion - Set-Alias powershell pwsh - ``` - -### Installation - -You can install this module using PowerShellGet. - -```powershell +```pwsh Install-Module -Name ALZ +Deploy-Accelerator ``` -### Update - -Whenever a new release from the module has been released, you can update it easily. The changelog can be found [here](/docs/CHANGELOG.md). - -```powershell -# find out which version you have installed -PS C:\Users\you> Get-InstalledModule -Name ALZ - -Version Name Repository Description -------- ---- ---------- ----------- -0.2.6 ALZ PSGallery Azure Landing Zones Powershell Module - -# update to the latest version -Update-Module -Name ALZ -``` - -### Quick start - -Before you start you can utilize the functionality of the module to verify if you have all the prerequisites installed with the built in command. - -#### Bicep - -```powershell -Test-ALZRequirement -i "bicep" -``` - -Currently this tests for: +## More Examples -* Supported minimum PowerShell version (7.1) -* Supported minimum Az PowerShell module version (10.0.0) -* Git -* Azure CLI -* Bicep -* Visual Studio Code +Here are more examples with different options: -#### Terraform - -```powershell -Test-ALZRequirement -i "terraform" -``` - -This currently tests for: - -* Supported minimum PowerShell version (7.1) -* Azure CLI - -> NOTE: Terraform CLI is downloaded as part of the module if you don't already have the latest version. - -#### Azure Landing Zone Environment with Bicep and GitHub Actions Workflows +### Azure Landing Zone Environment with Bicep and GitHub Actions Workflows ```powershell Deploy-Accelerator -o -i "bicep" -b "alz_github" ``` -#### Azure Landing Zone Environment with Bicep and Azure DevOps Pipelines +### Azure Landing Zone Environment with Bicep and Azure DevOps Pipelines ```powershell Deploy-Accelerator -o -i "bicep" -b "alz_azuredevops" ``` -#### Azure Landing Zone Environment with Terraform and GitHub Pipelines +### Azure Landing Zone Environment with Terraform and GitHub Pipelines ```powershell Deploy-Accelerator -o -i "terraform" -b "alz_github" ``` -#### Azure Landing Zone Environment with Terraform and Azure DevOps Pipelines +### Azure Landing Zone Environment with Terraform and Azure DevOps Pipelines ```powershell Deploy-Accelerator -o -i "terraform" -b "alz_azuredevops" ``` -## Development - -### Development Prerequisites - -In order to develop this module you will need PowerShell 7.1 or later. - -### Pre-requisites - -```powershell -# Required to run Invoke-Build -Install-Module -F PSScriptAnalyzer -Install-Module -F InvokeBuild -Install-Module -F Pester -``` - -### Commands to build locally - -```powershell -# Build and test locally -Remove-Module "ALZ" -Force -Invoke-Build -File .\src\ALZ.build.ps1 -``` - -### Commands to import a build locally - -```powershell -# Install the module locally -Invoke-Build -File .\src\ALZ.build.ps1 -Import-Module .\src\Artifacts\ALZ.psd1 -Force -``` - ## Contributing -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 . +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](https://cla.opensource.microsoft.com). -When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. +When you submit a pull request, a CLA bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. ## Trademarks -This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). +This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft +trademarks or logos is subject to and must follow +[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/legal/intellectualproperty/trademarks/usage/general). Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies. diff --git a/SECURITY.md b/SECURITY.md index e138ec5..9380866 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,6 +1,6 @@ -## Security +# Security Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). @@ -14,17 +14,17 @@ Instead, please report them to the Microsoft Security Response Center (MSRC) at If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue +* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. diff --git a/SUPPORT.md b/SUPPORT.md index 291d4d4..3e7d07e 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -1,25 +1,13 @@ -# TODO: The maintainer of this repo has not yet edited this file - -**REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project? - -- **No CSS support:** Fill out this template with information about how to file issues and get help. -- **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps. -- **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide. - -*Then remove this first heading from this SUPPORT.MD file before publishing your repo.* - # Support -## How to file issues and get help +## How to file issues and get help -This project uses GitHub Issues to track bugs and feature requests. Please search the existing -issues before filing new issues to avoid duplicates. For new issues, file your bug or +This project uses GitHub Issues to track bugs and feature requests. Please search the existing +issues before filing new issues to avoid duplicates. For new issues, file your bug or feature request as a new Issue. -For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE -FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER -CHANNEL. WHERE WILL YOU HELP PEOPLE?**. +For help and questions about using this project, please raise an issue. -## Microsoft Support Policy +## Microsoft Support Policy Support for this **PROJECT or PRODUCT** is limited to the resources listed above. diff --git a/docs/wiki/Contributing-to-Code.md b/docs/wiki/Contributing-to-Code.md new file mode 100644 index 0000000..fecea92 --- /dev/null +++ b/docs/wiki/Contributing-to-Code.md @@ -0,0 +1,15 @@ + +Please ensure you have read our [Contributing](Contributing) page before going any further. + +## Checklist + +- Fixes a bug or feature reported and accepted in our [Issues][Issues] log +- New features should be relevant to, and improve upon, existing core functionality +- PR contains documentation update +- PR is rebased against the latest `main` branch +- PR is squashed into one commit per logical change +- PR commit message should be concise but descriptive (will be used to generate release notes) + + + +[Issues]: https://github.com/Azure/alz-terraform-accelerator/issues "Our issues log" diff --git a/docs/wiki/Contributing-to-Documentation.md b/docs/wiki/Contributing-to-Documentation.md new file mode 100644 index 0000000..540a54e --- /dev/null +++ b/docs/wiki/Contributing-to-Documentation.md @@ -0,0 +1,14 @@ + +Please ensure you have read our [Contributing](Contributing) page before going any further. + +## Checklist + +- Fixes a documentation bug or feature reported and accepted in our [Issues][Issues] log +- New features should be relevant to, and improve upon, existing core documentation +- PR is rebased against the latest `main` branch +- PR is squashed into one commit per logical change +- PR commit message should be concise but descriptive (will be used to generate release notes) + + + +[Issues]: https://github.com/Azure/alz-terraform-accelerator/issues "Our issues log" diff --git a/docs/wiki/Contributing.md b/docs/wiki/Contributing.md new file mode 100644 index 0000000..b41cbbc --- /dev/null +++ b/docs/wiki/Contributing.md @@ -0,0 +1,20 @@ + +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](https://cla.opensource.microsoft.com). + +When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact with any additional questions or comments. + +Please familiarize yourself with our [Code of Conduct][Code-of-Conduct] and the [MIT License][License] associated with this repository to ensure all code contributions are submitted in accordance with these terms. + +## Next steps + +- [Raising an Issue](Raising-an-Issue) +- [Feature Requests](Feature-Requests) +- [Contributing to Code](Contributing-to-Code) +- [Contributing to Documentation](Contributing-to-Documentation) + + + +[Code-of-Conduct]: https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/blob/main/CODE_OF_CONDUCT.md "Our Code-of-Conduct" +[License]: https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/blob/main/LICENSE "Our license" diff --git a/docs/wiki/Feature-Requests.md b/docs/wiki/Feature-Requests.md new file mode 100644 index 0000000..d5729d4 --- /dev/null +++ b/docs/wiki/Feature-Requests.md @@ -0,0 +1,3 @@ + + +Please raise a feature request as an [issue](https://github.com/Azure/ALZ-PowerShell-Module/issues) diff --git a/docs/wiki/Frequently-Asked-Questions.md b/docs/wiki/Frequently-Asked-Questions.md new file mode 100644 index 0000000..f10992a --- /dev/null +++ b/docs/wiki/Frequently-Asked-Questions.md @@ -0,0 +1,157 @@ + +## Azure landing zones Terraform accelerator FAQ + +This article answers frequently asked questions relating to the Azure landing zones Terraform accelerator. + +> If you have a question not listed here, please raise an [issue](https://github.com/Azure/alz-terraform-accelerator/issues) and we'll do our best to help. + +## Questions about customisation + +### How do I use my own naming convention for the resources that are deployed? + +Follow these steps to customise the resource names: + +1. At step 2.2 of the quickstart, you will run the `Deploy-Accelerator` command to start the user input process. +1. Once the prompt appears for the first question open the relevant bootstrap `terraform.tfvars` file: + 1. Azure DevOps: `./bootstrap/v#.#.#/alz/azuredevops/terraform.tfvars` + 1. GitHub: `./bootstrap/v#.#.#/alz/github/terraform.tfvars` +1. Look for the variable called `resource_names`. +1. Update this map to have the names you desire and save it. +1. Continue with the user input as normal. + +You'll now get the names you specified instead of the default ones. + +## Questions about bootstrap clean up + +### I was just testing or I made a mistake, how do I remove the bootstrap environment and start again? + +After the Terraform apply has been completed there is an opportunity to remove the environment it just created. Follow these steps to run a `terraform destroy`. + +1. If you already ran the CD pipeline / action in phase 3 to deploy the ALZ, then you will need to run the pipeline / action again, but this time select the `destroy` option. This will delete the landing zone resources. If you don't do this, those resource will be left orphaned and you will have to clean them up manually. +1. Wait for the destroy run to complete before moving to the next step, you will need to approve it if you configured approvals. +1. Now run `Deploy-Accelerator` with the `-destroy` flag. E.g. `Deploy-Accelerator -i "terraform" -b "alz_azuredevops" -o "./my-folder" -destroy`. +1. The module will run and ask if you want to use the existing variables, enter `use` to use them. +1. You can confirm the destroy by typing `yes` when prompted. +1. To fully clean up, you should now delete the folder that was created for the accelerator. E.g. `./my-folder`. +1. You'll now be able to run the `Deploy-Accelerator` command again to start fresh. + +## Questions about changing variables + +### I made a mistake in the variables I entered, do I need to re-enter them all? + +When you run the PowerShell module, it caches the responses you supply. If you make a mistake, you can re-run the `Deploy-Accelerator` command and it will ask you if you want to use the cached variables. If you hit enter here, then you will be able to skip through each variable in turn, check the set value and alter it if desired. + +### I want to update a variable after the bootstrap has been completed, how do I do that? + +When you run the PowerShell module, it caches the responses you supply. If you want to update a variable, you can re-run the `Deploy-Accelerator` command and it will ask you if you want to use the cached variables. If you hit enter here, then you will be able to skip through each variable in turn, check the set value and alter it if desired. + +> NOTE: In some cases changing a variable may result in a change to a starter module or CI / CD file. In this scenario you may see an error on Terraform Apply due to branch protection. You can disable branch protection and re-run the `Deploy-Accelerator` command to resolve this. + +## Questions about Upgrading to a newer version of the accelerator + +### How do I upgrade to a newer version of the accelerator? + +Follow the steps in the [Upgrade Guide][wiki_upgrade_process] to upgrade to a newer version of the accelerator. + +## Questions about Multiple landing zone deployments + +### I want to deploy multiple landing zones, but the PowerShell command keeps trying to overrwrite my existing environment + +After bootstrapping, the PowerShell leaves the folder structure intact, including the Terraform state file. This is by design, so you have an opportunity to amend or destroy the environment. + +If you want to deploy to a separate environment, the simplest approach is to specify a separate folder for each deployment using the `-Output` parameter. For example: + +- Deployment 1: `Deploy-Accelerator -i "terraform" -b "alz_azuredevops" -Output "./deployment1"` +- Deployment 2: `Deploy-Accelerator -i "terraform" -b "alz_azuredevops" -Output "./deployment2"` + +You can then deploy as many times as you like without interferring with a previous deployment. + +## Questions about Automating the PowerShell Module + +### I want to automate the PowerShell module, but it keeps prompting me for input, can I supply the answers? + +>NOTE: We now recommend this as the preferred approach and our documentation has been updated to reflect this. + +Yes, you can supply the variables to the PowerShell module by using the `-inputs` parameter. You just need to supply a single file that includes the variables for the bootstrap and the starter module. The ordering of the variables in the file is not important. + +The module will accept inputs as in json or yaml format. `.json,`, `.yaml` or `.yml` file extensions are supported. Examples of both are shown below. + +To call the module, you then specify the `-inputs` parameter with the path to the file containing the inputs. For example: + +```powershell +Deploy-Accelerator -i "terraform" -b "alz_azuredevops" -Inputs "~/config/inputs.json" +``` + +yaml example: + +```yaml +starter: "basic" +azure_location: "uksouth" +``` + +json example: + +```json +{ + "starter": "basic", + "azure_location": "uksouth" +} +``` + +> NOTE: These examples show a partial set of variables. In this scenario, the module will prompt for the remaining variables. You can find the full list of variables in the quick start phase 2 and starter module documentation. + +Full yaml examples can be found under the `Input Files` section of the right-hand menu. + +### I get prompted to approve the Terraform plan, can I skip that? + +Yes, you can skip the approval of the Terraform plan by using the `-autoApprove` parameter. + +For example: + +```powershell +Deploy-Accelerator -i "terraform" -b "alz_azuredevops" -Inputs "~/config/inputs.json" -autoApprove +``` + +## Questions about adding more subscriptions post initial deployment + +### I used a single subscription for the initial deployment, how do I split my landing zone to the recommended 3 subscriptions? + +There are some steps you need to take: + +1. Create a new subscription and take a note of the subscriptions ID. +1. Find the names of the user assigned managed identities that were created in the initial boostrap. There should be one for `plan` and one for `apply`. +1. Go to the `Access control (IAM)` section pf the subscription. Add the following permissions for each user assigned managed identity: + 1. `Reader` to the `plan` identity + 1. `Owner` to the `apply` identity +1. Go to your Terraform code in source control and update the `terraform.tfvars` file, specifying the new subscription id in the relevant variable. You will need to create a branch and raise a PR to do this. +1. You can now plan and apply from pipelines to update the subscriptions. + +## Questions about using custom starter modules + +### I want to use my own custom bootstrap module(s), how do I do that? + +Follow the structure and json schema in the [Azure/accelerator-bootstrap-modules](https://github.com/Azure/accelerator-bootstrap-modules). You can then target your custom bootstrap module by using the `bootstrapModuleUrl` or `bootstrapModuleOverrideFolderPath` parameters in the PowerShell module. For example: + +```powershell +Deploy-Accelerator -i "terraform" -b "alz_azuredevops" -bootstrapModuleUrl "https://github.com/my-org/my-boostrap-modules" +``` + +```powershell +Deploy-Accelerator -i "terraform" -b "alz_azuredevops" -bootstrapModuleOverrideFolderPath "./my-bootstrap-modules" +``` + +### I want to use my own custom starter modules, how do I do that? + +Follow the folder structure in this repository and create your own custom starter module(s). You can then target your custom starter module by using the `starterModuleOverrideFolderPath` parameters in the PowerShell module. For example: + +```powershell +Deploy-Accelerator -i "terraform" -b "alz_azuredevops" -starterModuleOverrideFolderPath "~/my-custom-starter-modules" +``` + +Alternatively, if you are also supplying a custom bootstrap module, you can specify the starter module repo url in the `json` config file in the bootstrap module. + +[//]: # "************************" +[//]: # "INSERT LINK LABELS BELOW" +[//]: # "************************" + +[wiki_upgrade_process]: Upgrade-Process "Wiki - Upgrade Process" diff --git a/docs/wiki/Home.md b/docs/wiki/Home.md new file mode 100644 index 0000000..3a9de63 --- /dev/null +++ b/docs/wiki/Home.md @@ -0,0 +1,125 @@ + +Welcome to the Azure Landing Zones Accelerators for Bicep and Terraform! + +The Azure landing zones [Terraform][alz_tf_module] and [Bicep][alz_bc_module] modules provide an opinionated approach for deploying and managing the core platform capabilities of [Azure landing zones architecture][alz_architecture] using Bicep or Terraform. + +This accelerator provides an opinionated approach for configuring and securing those modules in a continuous delivery environment. It has end to end automation for bootstrapping the modules. + +## Supported Version Control Systems (VCS) + +The accelerator supports both Azure DevOps and GitHub. We are only able to support the hosted versions of these services. + +If you are using self-hosted versions of these services or another VCS, you can still use the accelerator to produce the landing zone code by using the `alz_local` bootstrap module, but you will need to configure the VCS manually or with your own automation. + +## Accelerator features + +The accelerator bootstraps a continuous delivery environment for you. It supports both the Azure DevOps and GitHub version control system (VCS). It uses the [ALZ](https://www.powershellgallery.com/packages/ALZ) PowerShell module to gather required user input and apply a Terraform module to configure the bootstrap environment. + +> NOTE: For Bicep users, the accelerator uses Terraform to bootstrap the environment only. Bicep is used to deploy and update the Azure landing zone. + +The accelerator follows a 3 phase approach: + +1. Pre-requisites: Instructions to configure credentials and subscriptions. +2. Bootstrap: Run the PowerShell module to generate the continuous delivery environment. +3. Run: Update the module (if needed) to suit the needs of your organisation and deploy via continuous delivery. + +![Azure landing zone accelerator process][alz_accelerator_overview] + +The components of the environment are similar, but differ depending on your choice of VCS: + +![Components][components] + +### GitHub + +- Azure: + - Resource Group for State (Terraform only) + - Storage Account and Container for State (Terraform only) + - Resource Group for Identity + - User Assigned Managed Identities (UAMI) with Federated Credentials for Plan and Apply + - Permissions for the UAMI on state storage container, subscriptions and management groups + - [Optional] Container Registry for GitHub Runner image + - [Optional] Container Instances hosting GitHub Runners + - [Optional] Virtual network, subnets, private DNS zone and private endpoint. + +- GitHub + - Repository for the Module + - Repository for the Action Templates + - Starter Terraform module with tfvars + - Branch policy + - Action for Continuous Integration + - Action for Continuous Delivery + - Environment for Plan + - Environment for Apply + - Action Variables for Backend and Plan / Apply + - Team and Members for Apply Approval + - Customised OIDC Token Subject for governed Actions + - [Optional] Runner Group + +### Azure DevOps + +- Azure: + - Resource Group for State (Terraform only) + - Storage Account and Container for State (Terraform only) + - Resource Group for Identity + - User Assigned Managed Identities (UAMI) with Federated Credentials for Plan and Apply + - Permissions for the UAMI on state storage container, subscriptions and management groups + - [Optional] Container Registry for Azure DevOps Agent image + - [Optional] Container Instances hosting Azure DevOps Agents + - [Optional] Virtual network, subnets, private DNS zone and private endpoint. + +- Azure DevOps + - Project (can be supplied or created) + - Repository for the Module + - Repository for the Pipeline Templates + - Starter Terraform module with tfvars + - Branch policy + - Pipeline for Continuous Integration + - Pipeline for Continuous Delivery + - Environment for Plan + - Environment for Apply + - Variable Group for Backend + - Service Connections with Workload identity federation for Plan and Apply + - Service Connection Approvals, Template Validation and Concurrency Control + - Group and Members for Apply Approval + - [Optional] Agent Pool + +### Local File System + +This outputs the ALZ module files to the file system, so you can apply them manually or with your own VCS / automation. + +- Azure: + - Resource Group for State (Terraform only) + - Storage Account and Container for State (Terraform only) + - Resource Group for Identity + - User Assigned Managed Identities (UAMI) for Plan and Apply + - Permissions for the UAMI on state storage container, subscriptions and management groups + +- Local File System + - Starter module with variables + +## Next steps + +Check out the [User Guide](User-Guide). + +## Azure landing zones + +The following diagram and links detail the Azure landing zone, but you can learn a lot more about Azure landing zones [here](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/). + +![Azure landing zone conceptual architecture][alz_tf_overview] + + [//]: # (*****************************) + [//]: # (INSERT IMAGE REFERENCES BELOW) + [//]: # (*****************************) + +[alz_accelerator_overview]: media/alz-terraform-acclerator.png "A process flow showing the areas covered by the Azure landing zones Terraform accelerator." +[components]: media/components.png "The components deployed by the accelerator." + +[alz_tf_overview]: https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/enterprise-scale/media/ns-arch-cust-expanded.svg "A conceptual architecture diagram highlighting the design areas covered by the Azure landing zones Terraform module." + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[alz_tf_module]: https://registry.terraform.io/modules/Azure/caf-enterprise-scale/azurerm/latest "Terraform: Azure landing zones module" +[alz_bc_module]: https://github.com/Azure/ALZ-Bicep "Bicep: Azure landing zones module" +[alz_architecture]: https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone#azure-landing-zone-conceptual-architecture diff --git a/docs/wiki/Raising-an-Issue.md b/docs/wiki/Raising-an-Issue.md new file mode 100644 index 0000000..ed57bf8 --- /dev/null +++ b/docs/wiki/Raising-an-Issue.md @@ -0,0 +1,9 @@ + + +To raise an issue, please go to our [Issues][Issues] log and raise a new issue. + +Fill out the Bug or Feature template in full and submit the issue for triage. + + + +[Issues]: https://github.com/Azure/alz-terraform-accelerator/issues "Our issues log" diff --git a/docs/wiki/Troubleshooting.md b/docs/wiki/Troubleshooting.md new file mode 100644 index 0000000..670aa0c --- /dev/null +++ b/docs/wiki/Troubleshooting.md @@ -0,0 +1,43 @@ + +Having trouble using the module and unable to find a solution in the Wiki? + +If it isn't listed below, let us know about it in our [Issues][Issues] log. We'll do our best to help and you may find your issue documented here. + +## PowerShell ALZ Module Failing for non-obvious reasons + +For example, when running `Deploy-Accelerator` you may see an error like: + +- `Parameter cannot be processed because the parameter name 'i' is ambiguous. Possible matches include: -InformationAction -InformationVariable -alzIacProvider -userInputOverridePath.` + +This is most likely because you are not using the most recent release of the PowerShell module. Update the module and try again. If that doesn't work, follow on below. + +We have noted that some users have issues when they install the module in PowerShell 5.X instead of PowerShell 7.X. When you install a module in PowerShell 5.X (PS) it appears to override any modules installed with PowerShell 7.X (pwsh). In this scenario you need to uninstall the module from PS in order to be able to install it in pwsh. + +Follow these steps to ensure you have a working environment: + +1. Update the latest PowerShell Core / 7.X (pwsh) version. +2. Open a PS (PowerShell 5.1) terminal. You may need to be an administrator to do this. +3. Run `Uninstall-Module -Name ALZ`, then run `Get-InstalledModule -Name ALZ` +4. If the previous command shows a version of the module is still installed, then repeat the previous step until you no longer see an installed version. +5. Open a pwsh (PowerShell 7.X) terminal. +6. Run `Uninstall-Module -Name ALZ`, then run `Get-InstalledModule -Name ALZ` +7. If the previous command shows a version of the module is still installed, then repeat the previous step until you no longer see an installed version. +8. Run `Install-Module -Name ALZ` + +You should now be able to successfully run the `Deploy-Accelerator` command and continue. + +## 422 Error when deleting Runner Group + +When trying to destroy a GitHub environment with a runner group you may see an error like: + +`Error: DELETE https://api.github.com/orgs//actions/runner-groups/3: 422 This group cannot be deleted because it contains runners. Please remove or move them to another group before proceeding. []` + +Unfortunately, this requires manual intervantion at the moment. The runners do not delete themselves when the container instance is delete, so they will show in the offline state for 14 days prior to being deleted. + +To resolve this, you can manually delete the runners from Runner Group in the GitHub UI. You can then re-run the destroy to complete the clean up. + +This only affects you if you have Enterprise licensing and have chosen to use a Runner Group. More details can be found here: + + + +[Issues]: https://github.com/Azure/alz-terraform-accelerator/issues "Our issues log" diff --git a/docs/wiki/Upgrade-Guide.md b/docs/wiki/Upgrade-Guide.md new file mode 100644 index 0000000..d376da3 --- /dev/null +++ b/docs/wiki/Upgrade-Guide.md @@ -0,0 +1,43 @@ + + +Although the accelerator is designed to be a one-time run, we have some rudimentary support for automatically upgrading to newer versions of the accelerator. + +This upgrade path is specifically for customers using the accelerator who haven't updated the repositories it deploys. If you have updated the repositories post initial bootstrap, you will need to take an alternative approach to upgrading. + +## Important Notes + +- The upgrade process does not support the scenario where you have made any changes to the deployed bootstrap or starter modules via git or the VCS system. If you run the upgrade it will overwrite your changes or fail. +- The upgrade process does not support breaking changes to major version of bootstrap or starter modules. If there is a breaking change, it will likely result in a destroy and re-create as part of the Terraform plan for the deployment. In most cases this may not be a problem, but you should validate prior to accepting the plan. +- If changes are made to the starter module as part of the upgrade, you will have to disable brach protection rules in the VCS system in order the update to succeed. To do this, you will need to navigate to the branmc protection rules in the VCS system and disable them. The apply will see that they have been disabled and re-apply them for you automatically. + +## Upgrade Process + +If you want to upgrade to a newer version of the accelerator bootstrap and / or starter, you can follow the steps below. + +> NOTE: Behind the scenes the upgrade process copies the Terraform state file and the last set of cacched variables you entered, it is not any more intelligent than that. + +1. Run `Deploy-Accelerator`, targetting the same output folder you did for the previous version and optionally specifiy the version you wish to upgrade to. + - For example if you want to upgrade to specific versions of the starter and bootstrap module, you could run: + + ```powershell + Deploy-Accelerator -i "terraform" -b "alz_azuredevops" -o "./my-folder" -starterRelease "2.0.1" -bootstrapRelease "2.0.2" + ``` + + - If you want to upgrade to the latest versions of both, you would run: + + ```powershell + Deploy-Accelerator -i "terraform" -b "alz_azuredevops" -o "./my-folder" + ``` + +2. You will see a message that starts with `AUTOMATIC UPGRADE:`. This will explain which version you will be upgrading from and to. E.g. `AUTOMATIC UPGRADE: We found version v2.0.0 of the bootstrap module that has been previously run. You can upgrade from this version to the new version v2.0.2` +3. You will then be prompted to confirm the upgrade. Type `upgrade` and hit enter. +4. The module will then run the upgrade process and you will see a success message once it completes. +5. The module will now follow the standard process and will pick up on the cached variables or input files and prompt you to use them. Type `use` to use the cached inputs or hit enter to update them or use input files. +6. If the new version of the accelerator has any new variables, you will be prompted to enter those manually if you haven't supplied them in an input file. +7. The module will then run the Terraform `init` and `apply` and you will see a success message once it completes. + +> NOTE: As per the important notes above. If the new version of the accelerator starter module has any changes to the files it creates, it may fail due to branch protection rules. If this happens, you will need to manually disable the branch protection rules and then re-run the `Deploy-Accelerator` command. + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) diff --git a/docs/wiki/User-Guide.md b/docs/wiki/User-Guide.md new file mode 100644 index 0000000..214782c --- /dev/null +++ b/docs/wiki/User-Guide.md @@ -0,0 +1,20 @@ + +## Table of Contents + +Please refer to the following to learn about the accelerator: + +- [Getting Started][wiki_getting_started] +- [Quick Start][wiki_quick_start] + - [Quick Start Phase 1][wiki_quick_start_phase_1] + - [Quick Start Phase 2][wiki_quick_start_phase_2] + - [Quick Start Phase 3][wiki_quick_start_phase_3] + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_getting_started]: %5BUser-Guide%5D-Getting-Started "Wiki - Getting Started" +[wiki_quick_start]: %5BUser-Guide%5D-Quick-Start "Wiki - Quick Start" +[wiki_quick_start_phase_1]: %5BUser-Guide%5D-Quick-Start-Phase-1 "Wiki - Quick Start - Phase 1" +[wiki_quick_start_phase_2]: %5BUser-Guide%5D-Quick-Start-Phase-2 "Wiki - Quick Start - Phase 2" +[wiki_quick_start_phase_3]: %5BUser-Guide%5D-Quick-Start-Phase-3 "Wiki - Quick Start - Phase 3" diff --git a/docs/wiki/[User-Guide]-Advanced-Scenarios.md b/docs/wiki/[User-Guide]-Advanced-Scenarios.md new file mode 100644 index 0000000..2c267d1 --- /dev/null +++ b/docs/wiki/[User-Guide]-Advanced-Scenarios.md @@ -0,0 +1,77 @@ + + +## Scenario 1 - Secure island for bootstrap resources + +Depending on your security needs, you may wish to store the Azure resources deployed by the bootstrap in separate subscription and optionally a separate management group hierarchy to the Azure Landing Zone. This could be the case when you need to separate the concerns of deploying and maintaining the Azure Landing Zone from the day to day access of the Azure Landing Zone. + +The resources deployed by the bootstrap vary depending on the options you choose, but they may include the following: + +- Storage account for state file +- User assigned managed identities +- [Optional] Self hosted agents +- [Optional] Networking, DNS and Private End Point for storage account + +In order to use the secure island approach, you can follow these steps: + +### Option 1 - Separate subscription under separate management group hierarchy + +1. Create a new management group under `Tenant Root Group`. +1. Apply your desired policies and permissions to the new management group. +1. Create a new subscription for the bootstrap resources and place it in the new management group. Take note of the subscription id. +1. Grant owner rights to the account you are using to deploy the accelerator on the new subscription. +1. Run the bootstrap as normal, following the instructions in the [Quick Start][wiki_quick_start] guide. +1. When you get to step 2.2.1 (GitHub), 2.2.2 (Azure DevOps) or 2.2.3 (Local), enter the subscription id of the new subscription you created into the `azure_subscription_id` field. +1. Continue with the rest of the steps in the [Quick Start][wiki_quick_start] guide. + +This will result in the bootstrap resources being deployed in the new subscription and management group hierarchy, while the Azure Landing Zone is deployed into the defined management group hierarchy. + +### Option 2 - Separate subscription under Azure Landing Zones management group hierarchy + +1. Create a new subscription for the bootstrap resources. Take note of the subscription id. +2. Grant owner rights to the account you are using to deploy the accelerator on the new subscription. +3. Use the `complete` starter module to deploy the Azure Landing Zone. +4. Update the `config.yaml` file to include subscription placement for the new subscription using the `subscription-id-overrides` setting. For example: + +```yaml +archetypes: # `caf-enterprise-scale` module, add inputs as listed on the module registry where necessary. + root_name: es + root_id: Enterprise-Scale + deploy_corp_landing_zones: true + deploy_online_landing_zones: true + default_location: uksouth + disable_telemetry: true + deploy_management_resources: true + configure_management_resources: + location: uksouth + settings: + security_center: + config: + email_security_contact: "security_contact@replace_me" + advanced: + asc_export_resource_group_name: rg-asc-export + custom_settings_by_resource_type: + azurerm_resource_group: + management: + name: rg-management + azurerm_log_analytics_workspace: + management: + name: log-management + azurerm_automation_account: + management: + name: aa-management + subscription-id-overrides: + management: + - "00000000-0000-0000-0000-000000000000" # Your new subscription id +``` + +5. Run the bootstrap as normal, following the instructions in the [Quick Start][wiki_quick_start] guide. +6. When you get to step 2.2.1 (GitHub), 2.2.2 (Azure DevOps) or 2.2.3 (Local), enter the subscription id of the new subscription you created into the `azure_subscription_id` field. +7. Continue with the rest of the steps in the [Quick Start][wiki_quick_start] guide. + +This will result in the bootstrap resources being deployed in the new subscription. When you then deploy the Azure Landing Zone your subscription will be moved under the `management` management group. + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_quick_start]: %5BUser-Guide%5D-Quick-Start "Wiki - Quick start" diff --git a/docs/wiki/[User-Guide]-Getting-Started.md b/docs/wiki/[User-Guide]-Getting-Started.md new file mode 100644 index 0000000..efe4d06 --- /dev/null +++ b/docs/wiki/[User-Guide]-Getting-Started.md @@ -0,0 +1,20 @@ + +## Quick Start + +For the majority of users, this is the place to start. The quick start is a step by step guide to get your Azure Landing Zone environment up and running. + +Now follow the [Quick Start][wiki_quick_start] guide. + +## Advanced Users + +For those users with very specific requirements we provide some advanced capabilities that allow you to override some of the defaults. + +See our [FAQ][wiki_frequently_asked_questions] and [Advanced Scenarios][wiki_advanced_scenarios] for more info. + +[//]: # "************************" +[//]: # "INSERT LINK LABELS BELOW" +[//]: # "************************" + +[wiki_quick_start]: %5BUser-Guide%5D-Quick-Start "Wiki - Quick start" +[wiki_advanced_scenarios]: %5BUser-Guide%5D-Advanced-Scenarios "Wiki - Advanced Scenarios" +[wiki_frequently_asked_questions]: %5BUser-Guide%5D-FAQ "Wiki - FAQ" diff --git a/docs/wiki/[User-Guide]-Quick-Start-Phase-1-Service-Principal.md b/docs/wiki/[User-Guide]-Quick-Start-Phase-1-Service-Principal.md new file mode 100644 index 0000000..6cc0509 --- /dev/null +++ b/docs/wiki/[User-Guide]-Quick-Start-Phase-1-Service-Principal.md @@ -0,0 +1,77 @@ + +### 1.3.2 Authenticate via Service Principal (Skip this if using a User account) + +#### 1.3.2.1 Create Service Principal + +1. Navigate to the [Azure Portal](https://portal.azure.com) and sign in to your tenant. +1. Search for `Azure Active Directory` and open it. +1. Copy the `Tenant ID` field and save it somewhere safe, making a note it is the `ARM_TENANT_ID`. +1. Click `App registrations` in the left navigation. +1. Click `+ New registration`. +1. Choose a name (SPN) that you will remember and make a note of it, we recommend using `sp-alz-bootstrap`. +1. Type the chosen name into the `Name` field. +1. Leave the other settings as default and click `Register`. +1. Wait for it to be created. +1. Copy the `Application (client) ID` field and save it somewhere safe, making a note it is the `ARM_CLIENT_ID`. +1. Click `Certificates & secrets` in the left navigation. +1. Ensure the `Client secrets` tab is selected and click `+ New client secret`. +1. Enter `ALZ Bootstrap` in the `Description` field. +1. Change the `Expires` field, choose `Custom`. +1. Set the `Start` field to todays date. +1. Set the `End` field to tomorrows date. +1. Click `Add`. +1. Copy the `Value` field save it somewhere safe, making a note that it is the `ARM_CLIENT_SECRET`. + +#### 1.3.2.2 Create Permissions + +1. The service principal name (SPN) is the username of the User account or the name of the app registration you created. +1. Search for `Subscriptions` and click to navigate to the subscription view. +1. For each of the subscriptions you created in the previous step: + 1. Navigate to the subscription. + 1. Click `Access control (IAM)` in the left navigation. + 1. Click `+ Add` and choose `Add role assignment`. + 1. Choose the `Privileged administrator roles` tab. + 1. Click `Owner` to highlight the row and then click `Next`. + 1. Leave the `User, group or service principal` option checked. + 1. Click `+ Select Members` and search for your SPN in the search box on the right. + 1. Click on your User to highlight it and then click `Select` and then click `Next`. + 1. Click the `Allow user to assign all roles (highly privileged)` option. + 1. Click `Review + assign`, then click `Review + assign` again when the warning appears. + 1. Wait for the role to be assigned and move onto the next subscription. +1. Search for `Management Groups` and click to navigate to the management groups view. +1. Click the parent management group you plan to deploy the Landing Zone into (this could be `Tenant Root Group` or a new management group you created). +1. Click `Access control (IAM)` in the left navigation. +1. Click `+ Add` and choose `Add role assignment`. +1. Choose the `Privileged administrator roles` tab. +1. Click `Owner` to highlight the row and then click `Next`. +1. Click `Next`. +1. Leave the `User, group or service principal` option checked. +1. Click `+ Select Members` and search for your SPN in the search box on the right. +1. Click on your User to highlight it and then click `Select`. +1. Click `Review + assign`, then click `Review + assign` again when the warning appears. +1. Wait for the role to be assigned and you are done with this part. + +#### 1.3.2.3 Set Service Principal Credentials in Terminal + +1. Open a new PowerShell Core (pwsh) terminal. +1. Find the `ARM_TENANT_ID` you made a note of earlier. +1. Type `$env:ARM_TENANT_ID=""` and hit enter. +1. Find the `ARM_CLIENT_ID` you made a note of earlier. +1. Type `$env:ARM_CLIENT_ID=""` and hit enter. +1. Find the `ARM_CLIENT_SECRET` you made a note of earlier. +1. Type `$env:ARM_CLIENT_SECRET=""` and hit enter. +1. Find the subscription id of the management subscription you made a note of earlier. +1. Type `$env:ARM_SUBSCRIPTION_ID=""` and hit enter. + +[!NOTE] +If you close your PowerShell prompt prior to running the bootstrap, you need to re-enter these environment variables. + +## Next Steps + +Return to [Phase 1][wiki_quick_start_phase_1] step 1.4. + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_quick_start_phase_1]: %5BUser-Guide%5D-Quick-Start-Phase-1 "Wiki - Quick Start - Phase 1" diff --git a/docs/wiki/[User-Guide]-Quick-Start-Phase-1.md b/docs/wiki/[User-Guide]-Quick-Start-Phase-1.md new file mode 100644 index 0000000..d545859 --- /dev/null +++ b/docs/wiki/[User-Guide]-Quick-Start-Phase-1.md @@ -0,0 +1,156 @@ + +Phase 1 of the accelerator is to setup your pre-requisites. Follow the steps below to do that. + +## 1.1 Tools + +You'll need to install the following tools before getting started. + +- PowerShell 7.4 (or newer): [Follow the instructions for your operating system](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) +- Azure CLI 2.55.0 (or newer): [Follow the instructions for your operating system](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) + +> NOTE: In all cases, ensure that the tools are available from a PowerShell core (pwsh) terminal. You may need to add them to your environment path if they are not. + +## 1.2 Azure Subscriptions + +We recommend setting up 3 subscriptions for Azure landing zones. These are management, identity and connectivity. See our [advanced scenarios][wiki_advanced_scenarios] section for alternatives. + +- Management: This is used to deploy the bootstrap and management resources, such as log analytics and automation accounts. +- Identity: This is used to deploy the identity resources, such as Azure AD and Azure AD Domain Services. +- Connectivity: This is used to deploy the hub networking resources, such as virtual networks and firewalls. + +You can read more about the management, identity and connectivity subscriptions in the [Landing Zone docs](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/deploy-landing-zones-with-terraform). + +To create the subscriptions you will need access to a billing agreement. The following links detail the permissions required for each type of agreement: + +- [Enterprise Agreement (EA)](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/create-enterprise-subscription) +- [Microsoft Customer Agreement (MCA)](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/create-subscription) + +Once you have the access required, create the three subscriptions following your desired naming convention. + +Take note of the subscription id of each subscription as we will need them later. + +## 1.3 Azure Authentication and Permissions + +You need either an Azure User Account or Service Principal with the following permissions to run the bootstrap: + +- `Owner` on your chosen parent management group for the Azure landing zone. This could be `Tenant Root Group` or a new management group you create under there if preferred. + - Owner is required as this account will be granting permissions for the identities that run the management group deployment. Those identities will be granted least privilege permissions. +- `Owner` on each of your 3 Azure landing zone subscriptions. + +For simplicity we recommend using a User account since this is a one off process that you are unlikely to repeat. + +### 1.3.1 Authenticate via User Account + +1. Open a new PowerShell Core (pwsh) terminal. +1. Run `az login`. +1. You'll be redirected to a browser to login, perform MFA, etc. +1. Find the subscription id of the management subscription you made a note of earlier. +1. Type `az account set --subscription ""` and hit enter. +1. Type `az account show` and verify that you are connected to the management subscription. + +### 1.3.2 Authenticate via Service Principal (Skip this if using a User account) + +Follow the instructions in the [Service Principal][wiki_quick_start_phase_1_service_principal] section. + +## 1.4 Version Control Systems + +You'll need to decide if you are using GitHub, Azure DevOps or the Local File System and follow these steps: + +### 1.4.1 Azure DevOps + +#### 1.4.1.1 Azure DevOps Pre-Requisites + +When you first create an Azure DevOps organization, it will not have any Microsoft-hosted agents available. If you intend to use Microsoft-hosted agents, you must either license your org or request a free pipeline. + +1. Setup billing for your organization: [Set up billing for your organization](https://learn.microsoft.com/en-us/azure/devops/organizations/billing/set-up-billing-for-your-organization-vs?view=azure-devops) +2. Check for and request a free pipeline via the form here: [Configure and pay for parallel jobs](https://learn.microsoft.com/en-us/azure/devops/pipelines/licensing/concurrent-jobs?view=azure-devops&tabs=ms-hosted#how-much-do-parallel-jobs-cost) + +If you choose the billing option, you'll then need to purchase at least one parallel pipeline. You can do this by following the instructions here: [Configure and pay for parallel jobs](https://learn.microsoft.com/en-us/azure/devops/pipelines/licensing/concurrent-jobs?view=azure-devops&tabs=ms-hosted#how-do-i-buy-more-parallel-jobs). + +#### 1.4.1.2 Azure DevOps Personal Access Token (PAT) + +This first PAT is referred to as `token-1`. + +1. Navigate to [dev.azure.com](https://dev.azure.com) and sign in to your organization. +1. Ensure you navigate to the organization you want to deploy to. +1. Click the `User settings` icon in the top right and select `Personal access tokens`. +1. Click `+ New Token`. +1. Enter `Azure Landing Zone Terraform Accelerator` in the `Name` field. +1. Alter the `Expiration` drop down and select `Custom defined`. +1. Choose tomorrows date in the date picker. +1. Click the `Show all scopes` link at the bottom. +1. Check the following scopes: + 1. `Agent Pools`: `Read & manage` + 1. `Build`: `Read & execute` + 1. `Code`: `Full` + 1. `Environment`: `Read & manage` + 1. `Graph`: `Read & manage` + 1. `Pipeline Resources`: `Use & manage` + 1. `Project and Team`: `Read, write & manage` + 1. `Service Connections`: `Read, query & manage` + 1. `Variable Groups`: `Read, create & manage` +1. Click `Create`. +1. Copy the token and save it somewhere safe. +1. Click `Close`. + +If you are using self-hosted runners, you will need to create a second PAT that we'll refer to as `token-2` for them. You can do this by following the steps above with the following differences: + +1. Select the maximum value for the `Expiration` field (this allows up to 1 year). NOTE: You may want to set a shorter expiration date for security reasons. In either case, you will need to have a process in place to extend expiration the token before it expires. +1. Select only the `Agent Pools`: `Read & manage` scope. + +### 1.4.2 GitHub + +#### 1.4.2.1 GitHub Pre-Requisites + +The accelerator does not support GitHub personal accounts, since they don't support all the features required for security. You must have a GitHub organization account or the accelerator will fail on apply. You can create a free organization [here](https://github.com/organizations/plan). Learn more about account types [here](https://docs.github.com/en/get-started/learning-about-github/types-of-github-accounts). + +> NOTE: If you choose to use a `free` organization account the accelerator bootstrap will make your repositories public. It must do this to support the functionality required by the accelerator. This is not recommended for production environments. + +#### 1.4.2.2 GitHub Personal Access Token (PAT) + +> NOTE: The following instructions refer to `classic` personal access tokens. You can also use `fine-grained` access tokens which are still in beta to provide more granular permissions. These docs will be updated to reflect this in the future. + +This first PAT is referred to as `token-1`. + +1. Navigate to [github.com](https://github.com). +1. Click on your user icon in the top right and select `Settings`. +1. Scroll down and click on `Developer Settings` in the left navigation. +1. Click `Personal access tokens` in the left navigation and select `Tokens (classic)`. +1. Click `Generate new token` at the top and select `Generate new token (classic)`. +1. Enter `Azure Landing Zone Terraform Accelerator` in the `Note` field. +1. Alter the `Expiration` drop down and select `Custom`. +1. Choose tomorrows date in the date picker. +1. Check the following scopes: + 1. `repo` + 1. `workflow` + 1. `admin:org` + 1. `user`: `read:user` + 1. `user`: `user:email` + 1. `delete_repo` +1. Click `Generate token`. +1. Copy the token and save it somewhere safe. +1. If your organization uses single sign on, then click the `Configure SSO` link next to your new PAT. +1. Select your organization and click `Authorize`, then follow the prompts to allow SSO. + +If you are using self-hosted runners, you will need to create a second PAT that we'll refer to as `token-2` for them. You can do this by following the steps above with the following differences: + +1. Select `No expiration` for the `Expiration` field. NOTE: You may want to set an expiration date for security reasons, but you will need to have a process in place to regenerate the token in that scenario. +1. The scope required depends on the type of organization you are using: + 1. If you are using a Free organization or an Enterprise orgnization without a runner group, select only the `repo` scope. + 1. If you are using an Enterprise organization and a runner group, select the `admin:org` scope for classic tokens (or `organization_self_hosted_runners:write` for fine-grained tokens). + +### 1.4.3 Local File System + +You just need to ensure that you have a folder on your local file system that you can use to store the files, which your current session has access to. + +## Next Steps + +Now head to [Phase 2][wiki_quick_start_phase_2]. + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_quick_start_phase_2]: %5BUser-Guide%5D-Quick-Start-Phase-2 "Wiki - Quick Start - Phase 2" +[wiki_quick_start_phase_1_service_principal]: %5BUser-Guide%5D-Quick-Start-Phase-1-Service-Principal "Wiki - Quick Start - Phase 1 - Service Principal" +[wiki_advanced_scenarios]: %5BUser-Guide%5D-Advanced-Scenarios "Wiki - Advanced Scenarios" diff --git a/docs/wiki/[User-Guide]-Quick-Start-Phase-2-Azure-DevOps.md b/docs/wiki/[User-Guide]-Quick-Start-Phase-2-Azure-DevOps.md new file mode 100644 index 0000000..cd5bc57 --- /dev/null +++ b/docs/wiki/[User-Guide]-Quick-Start-Phase-2-Azure-DevOps.md @@ -0,0 +1,176 @@ + +## 2.2.1 Azure DevOps + +You can choose to bootstrap with `bicep` or `terraform` skip to the relevant section below to do that. + +Although you can just run `Deploy-Accelerator` and fill out the prompted inputs, we recommend creating an inputs file. This will make it easier to run the accelerator more than once in order to refine your preferred configuration. In the following docs, we'll show that approach, but if you want to be prompted for inputs, just go ahead and run `Deploy-Accelerator` now. + +### 2.2.1.1 Azure DevOps with Bicep + +1. Create a new folder on you local drive called `accelerator`. +1. Inside the accelerator create two folders called `config` and `output`. You'll store you input file inside config and the output folder will be the place that the accelerator stores files while it works. +1. Inside the `config` folder create a new file called `inputs.yaml`. You can use `json` if you prefer, but our examples here are `yaml`. + + ```pwsh + # Windows + New-Item c:\accelerator\config\inputs.yaml -Force + New-Item c:\accelerator\output + ``` + + ```pwsh + # Linux/Mac + New-Item ~/accelerator/config/inputs.yaml -Force + New-Item ~/accelerator/output + ``` + + ```plaintext + 📂accelerator + ┣ 📂config + ┃ ┗ 📜inputs.yaml + ┗ 📂output + ``` + +1. Open your `inputs.yaml` file in Visual Studio Code (or your preferred editor) and copy the content from [inputs-azure-devops-bicep.yaml][example_powershell_inputs_azure_devops_bicep] into that file. +1. Check through the file and update each input as required. It is mandatory to update items with placeholders surrounded by angle brackets `<>`: + + | Input | Placeholder | Description | + | - | -- | --- | + | `iac` | `bicep` | This is the choice of `bicep` or `terraform`. Keep this as `bicep` for this example. | + | `bootstrap` | `alz_azuredevops` | This is the choice of Version Control System. Keep this as `alz_azuredevops` for this example. | + | `starter` | `complete` | This is the choice of [Starter Modules][wiki_starter_modules], which is the baseline configuration you want for your Azure landing zone. Keep this as `complete` for this example. This also determines the second set of inputs you'll be prompted for. | + | `bootstrap_location` | `` | Replace `` with the Azure region where you would like to deploy the bootstrap resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `starter_location` | `` | Replace `` with the Azure region where you would like to deploy the starter module resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `root_parent_management_group_id` | `""` | This is the id of the management group that will be the parent of the management group structure created by the accelerator. If you are using the `Tenant Root Group` management group, you leave this as an empty string `""` or supply the tenant id. | + | `subscription_id_management` | `` | Replace `` with the id of the management subscription you created in the previous phase. | + | `subscription_id_identity` | `` | Replace `` with the id of the identity subscription you created in the previous phase. | + | `subscription_id_connectivity` | `` | Replace `` with the id of the connectivity subscription you created in the previous phase. | + | `azure_devops_personal_access_token` | `` | Replace `` with the `token-1` Azure DevOps PAT you generated in a previous step. | + | `azure_devops_agents_personal_access_token` | `` | Replace `` with the `token-2` Azure DevOps PAT you generated in the previous step specifically for the self-hosted agents. This only applies if you have `use_self_hosted_agents` set to `true`. You can set this to an empty string `""` if you are not using self-hosted agents. | + | `azure_devops_organization_name` | `` | Replace `` with the name of your Azure DevOps organization. This is the section of the url after `dev.azure.com` or before `.visualstudio.com`. E.g. enter `my-org` for `https://dev.azure.com/my-org`. | + | `use_separate_repository_for_templates` | `true` | Determine whether to create a separate repository to store pipeline templates as an extra layer of security. Set to `false` if you don't wish to secure your pipeline templates by using a separate repository. This will default to `true`. | + | `bootstrap_location` | `` | Replace `` with the Azure region where you would like to deploy the bootstrap resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `bootstrap_subscription_id` | `` | Replace `` with the id of the subscription in which you would like to deploy the bootstrap resources in Azure. If left blank, the subscription you are connected to via `az login` will be used. In most cases this is the management subscription, but you can specifiy a separate subscription if you prefer. | + | `service_name` | `alz` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg--mgmt-uksouth-001`. We recommend using `alz` for this. | + | `environment_name` | `mgmt` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz--uksouth-001`. We recommend using `mgmt` for this. | + | `postfix_number` | `1` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz-mgmt-uksouth-`. We recommend using `1` for this. | + | `azure_devops_use_organisation_legacy_url` | `false` | If you have not migrated to the modern url (still using `https://.visualstudio.com`) for your Azure DevOps organisation, then set this to `true`. | + | `azure_devops_create_project` | `true` | If you have an existing project you want to use rather than creating a new one, select `true`. We recommend creating a new project to ensure it is isolated by a strong security boundary. | + | `azure_devops_project_name` | `` | Replace `` with the name of the Azure DevOps project to create or the name of an existing project if you set `azure_devops_create_project` to `false`. | + | `use_self_hosted_agents` | `true` | This controls if you want to deploy self-hosted agents. This will default to `true`. | + | `use_private_networking` | `true` | This controls whether private networking is deployed for your self-hosted agents and storage account. This only applies if you have `use_self_hosted_agents` set to `true`. This defaults to `true`. | + | `allow_storage_access_from_my_ip` | `false` | This is not relecant to Bicep and we'll remove the need to specify it later, leave it set to `false`. | + | `apply_approvers` | `` | This is a list of service principal names (SPN) of people you wish to be in the group that approves apply of the Azure landing zone module. This is a comma-separated list like `abc@xyz.com,def@xyz.com,ghi@xyz.com`. You may need to check what the SPN is prior to filling this out as it can vary based on identity provider. Use empty string `""` to disable approvals. | + | `create_branch_policies` | `true` | This controls whether to create branch policies for the repository. This defaults to `true`. | + +1. Now head over to your chosen starter module documentation to get the specific inputs for that module. Come back here when you are done. + - [Bicep Complete Starter Module][wiki_starter_module_bicep_complete] +1. In your PowerShell Core (pwsh) terminal run the module: + + ```pwsh + # Windows (adjust the paths to match your setup) + Deploy-Accelerator -inputs "c:\accelerator\config\inputs.yaml" -output "c:\accelerator\output" + ``` + + ```pwsh + # Linux/Mac (adjust the paths to match your setup) + Deploy-Accelerator -inputs "~/accelerator/config/inputs.yaml" -output "~/accelerator/output" + ``` + +1. You will see a Terraform `init` and `apply` happen. +1. There will be a pause after the `plan` phase you allow you to validate what is going to be deployed. +1. If you are happy with the plan, then type `yes` and hit enter. +1. The Terraform will `apply` and your environment will be bootstrapped. + +### 2.2.1.2 Azure DevOps with Terraform + +1. Create a new folder on you local drive called `accelerator`. +1. Inside the accelerator create two folders called `config` and `output`. You'll store you input file inside config and the output folder will be the place that the accelerator stores files while it works. +1. Inside the `config` folder create a new file called `inputs.yaml`. You can use `json` if you prefer, but our examples here are `yaml`. + + ```pwsh + # Windows + New-Item c:\accelerator\config\inputs.yaml -Force + New-Item c:\accelerator\output + ``` + + ```pwsh + # Linux/Mac + New-Item ~/accelerator/config/inputs.yaml -Force + New-Item ~/accelerator/output + ``` + + ```plaintext + 📂accelerator + ┣ 📂config + ┃ ┗ 📜inputs.yaml + ┗ 📂output + ``` + +1. Open your `inputs.yaml` file in Visual Studio Code (or your preferred editor) and copy the content from [inputs-azure-devops-terraform.yaml][example_powershell_inputs_azure_devops_terraform] into that file. +1. Check through the file and update each input as required. It is mandatory to update items with placeholders surrounded by angle brackets `<>`: + + | Input | Placeholder | Description | + | - | -- | --- | + | `iac` | `terraform` | This is the choice of `bicep` or `terraform`. Keep this as `terraform` for this example. | + | `bootstrap` | `alz_azuredevops` | This is the choice of Version Control System. Keep this as `alz_azuredevops` for this example. | + | `starter` | `complete` | This is the choice of [Starter Modules][wiki_starter_modules], which is the baseline configuration you want for your Azure landing zone. Choose `complete`, `hubnetworking` or `basic` for this example. This also determines the second set of inputs you'll be prompted for. | + | `bootstrap_location` | `` | Replace `` with the Azure region where you would like to deploy the bootstrap resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `starter_location` | `` | Replace `` with the Azure region where you would like to deploy the starter module resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `root_parent_management_group_id` | `""` | This is the id of the management group that will be the parent of the management group structure created by the accelerator. If you are using the `Tenant Root Group` management group, you leave this as an empty string `""` or supply the tenant id. | + | `subscription_id_management` | `` | Replace `` with the id of the management subscription you created in the previous phase. | + | `subscription_id_identity` | `` | Replace `` with the id of the identity subscription you created in the previous phase. | + | `subscription_id_connectivity` | `` | Replace `` with the id of the connectivity subscription you created in the previous phase. | + | `azure_devops_personal_access_token` | `` | Replace `` with the `token-1` Azure DevOps PAT you generated in a previous step. | + | `azure_devops_agents_personal_access_token` | `` | Replace `` with the `token-2` Azure DevOps PAT you generated in the previous step specifically for the self-hosted agents. This only applies if you have `use_self_hosted_agents` set to `true`. You can set this to an empty string `""` if you are not using self-hosted agents. | + | `azure_devops_organization_name` | `` | Replace `` with the name of your Azure DevOps organization. This is the section of the url after `dev.azure.com` or before `.visualstudio.com`. E.g. enter `my-org` for `https://dev.azure.com/my-org`. | + | `use_separate_repository_for_templates` | `true` | Determine whether to create a separate repository to store pipeline templates as an extra layer of security. Set to `false` if you don't wish to secure your pipeline templates by using a separate repository. This will default to `true`. | + | `bootstrap_subscription_id` | `` | Replace `` with the id of the subscription in which you would like to deploy the bootstrap resources in Azure. If left blank, the subscription you are connected to via `az login` will be used. In most cases this is the management subscription, but you can specifiy a separate subscription if you prefer. | + | `service_name` | `alz` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg--mgmt-uksouth-001`. We recommend using `alz` for this. | + | `environment_name` | `mgmt` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz--uksouth-001`. We recommend using `mgmt` for this. | + | `postfix_number` | `1` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz-mgmt-uksouth-`. We recommend using `1` for this. | + | `azure_devops_use_organisation_legacy_url` | `false` | If you have not migrated to the modern url (still using `https://.visualstudio.com`) for your Azure DevOps organisation, then set this to `true`. | + | `azure_devops_create_project` | `true` | If you have an existing project you want to use rather than creating a new one, select `true`. We recommend creating a new project to ensure it is isolated by a strong security boundary. | + | `azure_devops_project_name` | `` | Replace `` with the name of the Azure DevOps project to create or the name of an existing project if you set `azure_devops_create_project` to `false`. | + | `use_self_hosted_agents` | `true` | This controls if you want to deploy self-hosted agents. This will default to `true`. | + | `use_private_networking` | `true` | This controls whether private networking is deployed for your self-hosted agents and storage account. This only applies if you have `use_self_hosted_agents` set to `true`. This defaults to `true`. | + | `allow_storage_access_from_my_ip` | `false` | This controls whether to allow access to the storage account from your IP address. This is only needed for trouble shooting. This only applies if you have `use_private_networking` set to `true`. This defaults to `false`. | + | `apply_approvers` | `` | This is a list of service principal names (SPN) of people you wish to be in the group that approves apply of the Azure landing zone module. This is a comma-separated list like `abc@xyz.com,def@xyz.com,ghi@xyz.com`. You may need to check what the SPN is prior to filling this out as it can vary based on identity provider. Use empty string `""` to disable approvals. | + | `create_branch_policies` | `true` | This controls whether to create branch policies for the repository. This defaults to `true`. | + +1. Now head over to your chosen starter module documentation to get the specific inputs for that module. Come back here when you are done. + - [Terraform Basic Starter Module][wiki_starter_module_terraform_basic]: Management groups and policies. + - [Terraform Hub Networking Starter Module][wiki_starter_module_terraform_hubnetworking]: Management groups, policies and hub networking. + - [Terraform Complete Starter Module][wiki_starter_module_terraform_complete]: Management groups, policies, hub networking with fully custom configuration. +1. In your PowerShell Core (pwsh) terminal run the module: + + ```pwsh + # Windows (adjust the paths to match your setup) + Deploy-Accelerator -inputs "c:\accelerator\config\inputs.yaml" -output "c:\accelerator\output" + ``` + + ```pwsh + # Linux/Mac (adjust the paths to match your setup) + Deploy-Accelerator -inputs "~/accelerator/config/inputs.yaml" -output "~/accelerator/output" + ``` + +1. You will see a Terraform `init` and `apply` happen. +1. There will be a pause after the `plan` phase you allow you to validate what is going to be deployed. +1. If you are happy with the plan, then type `yes` and hit enter. +1. The Terraform will `apply` and your environment will be bootstrapped. + +## Next Steps + +Now head to [Phase 3][wiki_quick_start_phase_3]. + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_starter_modules]: %5BUser-Guide%5D-Starter-Modules "Wiki - Starter Modules" +[wiki_starter_module_bicep_complete]: %5BUser-Guide%5D-Starter-Module-Bicep-Complete "Wiki - Starter Modules - Bicep Complete" +[wiki_starter_module_terraform_basic]: %5BUser-Guide%5D-Starter-Module-Terraform-Basic "Wiki - Starter Modules - Terraform Basic" +[wiki_starter_module_terraform_hubnetworking]: %5BUser-Guide%5D-Starter-Module-Terraform-HubNetworking "Wiki - Start Modules - Terraform Hub Networking" +[wiki_starter_module_terraform_complete]: %5BUser-Guide%5D-Starter-Module-Terraform-Complete "Wiki - Starter Modules - Terraform Complete" +[wiki_quick_start_phase_3]: %5BUser-Guide%5D-Quick-Start-Phase-3 "Wiki - Quick Start - Phase 3" +[example_powershell_inputs_azure_devops_bicep]: examples/powershell-inputs/inputs-azure-devops-bicep.yaml "Example - PowerShell Inputs - Azure DevOps - Bicep" +[example_powershell_inputs_azure_devops_terraform]: examples/powershell-inputs/inputs-azure-devops-terraform.yaml "Example - PowerShell Inputs - Azure DevOps - Terraform" diff --git a/docs/wiki/[User-Guide]-Quick-Start-Phase-2-GitHub.md b/docs/wiki/[User-Guide]-Quick-Start-Phase-2-GitHub.md new file mode 100644 index 0000000..eb8936f --- /dev/null +++ b/docs/wiki/[User-Guide]-Quick-Start-Phase-2-GitHub.md @@ -0,0 +1,161 @@ + +## 2.2.2 GitHub + +You can choose to bootstrap with `bicep` or `terraform` skip to the relevant section below to do that. + +Although you can just run `Deploy-Accelerator` and fill out the prompted inputs, we recommend creating an inputs file. This will make it easier to run the accelerator more than once in order to refine your preferred configuration. In the following docs, we'll show that approach, but if you want to be prompted for inputs, just go ahead and run `Deploy-Accelerator` now. + +### 2.2.2.1 GitHub with Bicep + +1. Create a new folder on you local drive called `accelerator`. +1. Inside the accelerator create two folders called `config` and `output`. You'll store you input file inside config and the output folder will be the place that the accelerator stores files while it works. +1. Inside the `config` folder create a new file called `inputs.yaml`. You can use `json` if you prefer, but our examples here are `yaml`. + + ```pwsh + # Windows + New-Item c:\accelerator\config\inputs.yaml -Force + New-Item c:\accelerator\output + + # Linux/Mac + New-Item ~/accelerator/config/inputs.yaml -Force + New-Item ~/accelerator/output + ``` + + ```plaintext + 📂accelerator + ┣ 📂config + ┃ ┗ 📜inputs.yaml + ┗ 📂output + ``` + +1. Open your `inputs.yaml` file in Visual Studio Code (or your preferred editor) and copy the content from [inputs-github-bicep.yaml][example_powershell_inputs_github_bicep] into that file. +1. Check through the file and update each input as required. It is mandatory to update items with placeholders surrounded by angle brackets `<>`: + + | Input | Placeholder | Description | + | - | -- | --- | + | `iac` | `bicep` | This is the choice of `bicep` or `terraform`. Keep this as `bicep` for this example. | + | `bootstrap` | `alz_github` | This is the choice of Version Control System. Keep this as `alz_github` for this example. | + | `starter` | `complete` | This is the choice of [Starter Modules][wiki_starter_modules], which is the baseline configuration you want for your Azure landing zone. Keep this as `complete` for this example. This also determines the second set of inputs you'll be prompted for. | + | `bootstrap_location` | `` | Replace `` with the Azure region where you would like to deploy the bootstrap resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `starter_location` | `` | Replace `` with the Azure region where you would like to deploy the starter module resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `root_parent_management_group_id` | `""` | This is the id of the management group that will be the parent of the management group structure created by the accelerator. If you are using the `Tenant Root Group` management group, you leave this as an empty string `""` or supply the tenant id. | + | `subscription_id_management` | `` | Replace `` with the id of the management subscription you created in the previous phase. | + | `subscription_id_identity` | `` | Replace `` with the id of the identity subscription you created in the previous phase. | + | `subscription_id_connectivity` | `` | Replace `` with the id of the connectivity subscription you created in the previous phase. | + | `github_personal_access_token` | `` | Replace `` with the `token-1` GitHub PAT you generated in a previous step. | + | `github_runners_personal_access_token` | `` | Replace `` with the `token-2` GitHub PAT you generated in the previous step specifically for the self-hosted runners. This only applies if you have `use_self_hosted_agents` set to `true`. You can set this to an empty string `""` if you are not using self-hosted runners. | + | `github_organization_name` | `` | Replace `` with the name of your Azure DevOps organization. This is the section of the url after `github.com`. E.g. enter `my-org` for `https://github.com/my-org`. | + | `use_separate_repository_for_templates` | `true` | Determine whether to create a separate repository to store workflow templates as an extra layer of security. Set to `false` if you don't wish to secure your workflow templates by using a separate repository. This will default to `true`. | + | `bootstrap_subscription_id` | `` | Replace `` with the id of the subscription in which you would like to deploy the bootstrap resources in Azure. If left blank, the subscription you are connected to via `az login` will be used. In most cases this is the management subscription, but you can specifiy a separate subscription if you prefer. | + | `service_name` | `alz` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg--mgmt-uksouth-001`. We recommend using `alz` for this. | + | `environment_name` | `mgmt` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz--uksouth-001`. We recommend using `mgmt` for this. | + | `postfix_number` | `1` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz-mgmt-uksouth-`. We recommend using `1` for this. | + | `use_self_hosted_agents` | `true` | This controls if you want to deploy self-hosted agents. This will default to `true`. | + | `use_private_networking` | `true` | This controls whether private networking is deployed for your self-hosted agents and storage account. This only applies if you have `use_self_hosted_agents` set to `true`. This defaults to `true`. | + | `allow_storage_access_from_my_ip` | `false` | This is not relevant to Bicep and we'll remove the need to specify it later, leave it set to `false`. | + | `apply_approvers` | `` | This is a list of service principal names (SPN) of people you wish to be in the group that approves apply of the Azure landing zone module. This is a comma-separated list like `abc@xyz.com,def@xyz.com,ghi@xyz.com`. You may need to check what the SPN is prior to filling this out as it can vary based on identity provider. Use empty string `""` to disable approvals. | + | `create_branch_policies` | `true` | This controls whether to create branch policies for the repository. This defaults to `true`. | + +1. Now head over to your chosen starter module documentation to get the specific inputs for that module. Come back here when you are done. + - [Bicep Complete Starter Module][wiki_starter_module_bicep_complete] +1. In your PowerShell Core (pwsh) terminal run the module: + + ```pwsh + # Windows (adjust the paths to match your setup) + Deploy-Accelerator -inputs "c:\accelerator\config\inputs.yaml" -output "c:\accelerator\output" + + # Linux/Mac (adjust the paths to match your setup) + Deploy-Accelerator -inputs "~/accelerator/config/inputs.yaml" -output "~/accelerator/output" + ``` + +1. You will see a Terraform `init` and `apply` happen. +1. There will be a pause after the `plan` phase you allow you to validate what is going to be deployed. +1. If you are happy with the plan, then type `yes` and hit enter. +1. The Terraform will `apply` and your environment will be bootstrapped. + +### 2.2.2.2 GitHub with Terraform + +1. Create a new folder on you local drive called `accelerator`. +1. Inside the accelerator create two folders called `config` and `output`. You'll store you input file inside config and the output folder will be the place that the accelerator stores files while it works. +1. Inside the `config` folder create a new file called `inputs.yaml`. You can use `json` if you prefer, but our examples here are `yaml`. + + ```pwsh + # Windows + New-Item c:\accelerator\config\inputs.yaml -Force + New-Item c:\accelerator\output + + # Linux/Mac + New-Item ~/accelerator/config/inputs.yaml -Force + New-Item ~/accelerator/output + ``` + + ```plaintext + 📂accelerator + ┣ 📂config + ┃ ┗ 📜inputs.yaml + ┗ 📂output + ``` + +1. Open your `inputs.yaml` file in Visual Studio Code (or your preferred editor) and copy the content from [inputs-github-terraform.yaml][example_powershell_inputs_github_terraform] into that file. +1. Check through the file and update each input as required. It is mandatory to update items with placeholders surrounded by angle brackets `<>`: + + | Input | Placeholder | Description | + | - | -- | --- | + | `iac` | `terraform` | This is the choice of `bicep` or `terraform`. Keep this as `terraform` for this example. | + | `bootstrap` | `alz_github` | This is the choice of Version Control System. Keep this as `alz_github` for this example. | + | `starter` | `complete` | This is the choice of [Starter Modules][wiki_starter_modules], which is the baseline configuration you want for your Azure landing zone. Choose `complete`, `hubnetworking` or `basic` for this example. This also determines the second set of inputs you'll be prompted for. | + | `bootstrap_location` | `` | Replace `` with the Azure region where you would like to deploy the bootstrap resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `starter_location` | `` | Replace `` with the Azure region where you would like to deploy the starter module resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `root_parent_management_group_id` | `""` | This is the id of the management group that will be the parent of the management group structure created by the accelerator. If you are using the `Tenant Root Group` management group, you leave this as an empty string `""` or supply the tenant id. | + | `subscription_id_management` | `` | Replace `` with the id of the management subscription you created in the previous phase. | + | `subscription_id_identity` | `` | Replace `` with the id of the identity subscription you created in the previous phase. | + | `subscription_id_connectivity` | `` | Replace `` with the id of the connectivity subscription you created in the previous phase. | + | `github_personal_access_token` | `` | Replace `` with the `token-1` GitHub PAT you generated in a previous step. | + | `github_runners_personal_access_token` | `` | Replace `` with the `token-2` GitHub PAT you generated in the previous step specifically for the self-hosted runners. This only applies if you have `use_self_hosted_agents` set to `true`. You can set this to an empty string `""` if you are not using self-hosted runners. | + | `github_organization_name` | `` | Replace `` with the name of your Azure DevOps organization. This is the section of the url after `github.com`. E.g. enter `my-org` for `https://github.com/my-org`. | + | `use_separate_repository_for_templates` | `true` | Determine whether to create a separate repository to store workflow templates as an extra layer of security. Set to `false` if you don't wish to secure your workflow templates by using a separate repository. This will default to `true`. | + | `bootstrap_subscription_id` | `` | Replace `` with the id of the subscription in which you would like to deploy the bootstrap resources in Azure. If left blank, the subscription you are connected to via `az login` will be used. In most cases this is the management subscription, but you can specifiy a separate subscription if you prefer. | + | `service_name` | `alz` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg--mgmt-uksouth-001`. We recommend using `alz` for this. | + | `environment_name` | `mgmt` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz--uksouth-001`. We recommend using `mgmt` for this. | + | `postfix_number` | `1` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz-mgmt-uksouth-`. We recommend using `1` for this. | + | `use_self_hosted_agents` | `true` | This controls if you want to deploy self-hosted agents. This will default to `true`. | + | `use_private_networking` | `true` | This controls whether private networking is deployed for your self-hosted agents and storage account. This only applies if you have `use_self_hosted_agents` set to `true`. This defaults to `true`. | + | `allow_storage_access_from_my_ip` | `false` | This controls whether to allow access to the storage account from your IP address. This is only needed for trouble shooting. This only applies if you have `use_private_networking` set to `true`. This defaults to `false`. | + | `apply_approvers` | `` | This is a list of service principal names (SPN) of people you wish to be in the group that approves apply of the Azure landing zone module. This is a comma-separated list like `abc@xyz.com,def@xyz.com,ghi@xyz.com`. You may need to check what the SPN is prior to filling this out as it can vary based on identity provider. Use empty string `""` to disable approvals. | + | `create_branch_policies` | `true` | This controls whether to create branch policies for the repository. This defaults to `true`. | + +1. Now head over to your chosen starter module documentation to get the specific inputs for that module. Come back here when you are done. + - [Terraform Basic Starter Module][wiki_starter_module_terraform_basic]: Management groups and policies. + - [Terraform Hub Networking Starter Module][wiki_starter_module_terraform_hubnetworking]: Management groups, policies and hub networking. + - [Terraform Complete Starter Module][wiki_starter_module_terraform_complete]: Management groups, policies, hub networking with fully custom configuration. +1. In your PowerShell Core (pwsh) terminal run the module: + + ```pwsh + # Windows (adjust the paths to match your setup) + Deploy-Accelerator -inputs "c:\accelerator\config\inputs.yaml" -output "c:\accelerator\output" + + # Linux/Mac (adjust the paths to match your setup) + Deploy-Accelerator -inputs "~/accelerator/config/inputs.yaml" -output "~/accelerator/output" + ``` + +1. You will see a Terraform `init` and `apply` happen. +1. There will be a pause after the `plan` phase you allow you to validate what is going to be deployed. +1. If you are happy with the plan, then type `yes` and hit enter. +1. The Terraform will `apply` and your environment will be bootstrapped. + +## Next Steps + +Now head to [Phase 3][wiki_quick_start_phase_3]. + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_starter_modules]: %5BUser-Guide%5D-Starter-Modules "Wiki - Starter Modules" +[wiki_starter_module_bicep_complete]: %5BUser-Guide%5D-Starter-Module-Bicep-Complete "Wiki - Starter Modules - Bicep Complete" +[wiki_starter_module_terraform_basic]: %5BUser-Guide%5D-Starter-Module-Terraform-Basic "Wiki - Starter Modules - Terraform Basic" +[wiki_starter_module_terraform_hubnetworking]: %5BUser-Guide%5D-Starter-Module-Terraform-HubNetworking "Wiki - Start Modules - Terraform Hub Networking" +[wiki_starter_module_terraform_complete]: %5BUser-Guide%5D-Starter-Module-Terraform-Complete "Wiki - Starter Modules - Terraform Complete" +[wiki_quick_start_phase_3]: %5BUser-Guide%5D-Quick-Start-Phase-3 "Wiki - Quick Start - Phase 3" +[example_powershell_inputs_github_bicep]: examples/powershell-inputs/inputs-github-bicep.yaml "Example - PowerShell Inputs - GitHub - Bicep" +[example_powershell_inputs_github_terraform]: examples/powershell-inputs/inputs-github-terraform.yaml "Example - PowerShell Inputs - GitHub - Terraform" diff --git a/docs/wiki/[User-Guide]-Quick-Start-Phase-2-Local.md b/docs/wiki/[User-Guide]-Quick-Start-Phase-2-Local.md new file mode 100644 index 0000000..8f1a40b --- /dev/null +++ b/docs/wiki/[User-Guide]-Quick-Start-Phase-2-Local.md @@ -0,0 +1,151 @@ + +## 2.2.3 Local File System + +You can choose to bootstrap with `bicep` or `terraform` skip to the relevant section below to do that. + +Although you can just run `Deploy-Accelerator` and fill out the prompted inputs, we recommend creating an inputs file. This will make it easier to run the accelerator more than once in order to refine your preferred configuration. In the following docs, we'll show that approach, but if you want to be prompted for inputs, just go ahead and run `Deploy-Accelerator` now. + +### 2.2.3.1 Local File System with Bicep + +1. Create a new folder on you local drive called `accelerator`. +1. Inside the accelerator create two folders called `config` and `output`. You'll store you input file inside config and the output folder will be the place that the accelerator stores files while it works. +1. Inside the `config` folder create a new file called `inputs.yaml`. You can use `json` if you prefer, but our examples here are `yaml`. + + ```pwsh + # Windows + New-Item c:\accelerator\config\inputs.yaml -Force + New-Item c:\accelerator\output + + # Linux/Mac + New-Item ~/accelerator/config/inputs.yaml -Force + New-Item ~/accelerator/output + ``` + + ```plaintext + 📂accelerator + ┣ 📂config + ┃ ┗ 📜inputs.yaml + ┗ 📂output + ``` + +1. Open your `inputs.yaml` file in Visual Studio Code (or your preferred editor) and copy the content from [inputs-github-local.yaml][example_powershell_inputs_local_bicep] into that file. +1. Check through the file and update each input as required. It is mandatory to update items with placeholders surrounded by angle brackets `<>`: + + | Input | Placeholder | Description | + | - | -- | --- | + | `iac` | `bicep` | This is the choice of `bicep` or `terraform`. Keep this as `bicep` for this example. | + | `bootstrap` | `alz_local` | This is the choice of Version Control System. Keep this as `alz_local` for this example. | + | `starter` | `complete` | This is the choice of [Starter Modules][wiki_starter_modules], which is the baseline configuration you want for your Azure landing zone. Keep this as `complete` for this example. This also determines the second set of inputs you'll be prompted for. | + | `bootstrap_location` | `` | Replace `` with the Azure region where you would like to deploy the bootstrap resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `starter_location` | `` | Replace `` with the Azure region where you would like to deploy the starter module resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `root_parent_management_group_id` | `""` | This is the id of the management group that will be the parent of the management group structure created by the accelerator. If you are using the `Tenant Root Group` management group, you leave this as an empty string `""` or supply the tenant id. | + | `subscription_id_management` | `` | Replace `` with the id of the management subscription you created in the previous phase. | + | `subscription_id_identity` | `` | Replace `` with the id of the identity subscription you created in the previous phase. | + | `subscription_id_connectivity` | `` | Replace `` with the id of the connectivity subscription you created in the previous phase. | + | `target_directory` | `` | This is the directory where the ALZ module code will be created. This defaults a directory called `local` in the root of the accelerator directory if not supplied. | + | `create_bootstrap_resources_in_azure` | `true` | This determines whether the bootstrap will create the bootstrap resources in Azure. This defaults to `true`. | + | `bootstrap_subscription_id` | `` | Replace `` with the id of the subscription in which you would like to deploy the bootstrap resources in Azure. If left blank, the subscription you are connected to via `az login` will be used. In most cases this is the management subscription, but you can specifiy a separate subscription if you prefer. | + | `service_name` | `alz` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg--mgmt-uksouth-001`. We recommend using `alz` for this. | + | `environment_name` | `mgmt` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz--uksouth-001`. We recommend using `mgmt` for this. | + | `postfix_number` | `1` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz-mgmt-uksouth-`. We recommend using `1` for this. | + +1. Now head over to your chosen starter module documentation to get the specific inputs for that module. Come back here when you are done. + - [Bicep Complete Starter Module][wiki_starter_module_bicep_complete] +1. In your PowerShell Core (pwsh) terminal run the module: + + ```pwsh + # Windows (adjust the paths to match your setup) + Deploy-Accelerator -inputs "c:\accelerator\config\inputs.yaml" -output "c:\accelerator\output" + + # Linux/Mac (adjust the paths to match your setup) + Deploy-Accelerator -inputs "~/accelerator/config/inputs.yaml" -output "~/accelerator/output" + ``` + +1. You will see a Terraform `init` and `apply` happen. +1. There will be a pause after the `plan` phase you allow you to validate what is going to be deployed. +1. If you are happy with the plan, then type `yes` and hit enter. +1. The Terraform will `apply` and your environment will be bootstrapped. + +### 2.2.3.2 Local File System with Terraform + +1. Create a new folder on you local drive called `accelerator`. +1. Inside the accelerator create two folders called `config` and `output`. You'll store you input file inside config and the output folder will be the place that the accelerator stores files while it works. +1. Inside the `config` folder create a new file called `inputs.yaml`. You can use `json` if you prefer, but our examples here are `yaml`. + + ```pwsh + # Windows + New-Item c:\accelerator\config\inputs.yaml -Force + New-Item c:\accelerator\output + ``` + + ```pwsh + # Linux/Mac + New-Item ~/accelerator/config/inputs.yaml -Force + New-Item ~/accelerator/output + ``` + + ```plaintext + 📂accelerator + ┣ 📂config + ┃ ┗ 📜inputs.yaml + ┗ 📂output + ``` + +1. Open your `inputs.yaml` file in Visual Studio Code (or your preferred editor) and copy the content from [inputs-local-terraform.yaml][example_powershell_inputs_local_terraform] into that file. +1. Check through the file and update each input as required. It is mandatory to update items with placeholders surrounded by angle brackets `<>`: + + | Input | Placeholder | Description | + | - | -- | --- | + | `iac` | `terraform` | This is the choice of `bicep` or `terraform`. Keep this as `terraform` for this example. | + | `bootstrap` | `alz_local` | This is the choice of Version Control System. Keep this as `alz_local` for this example. | + | `starter` | `complete` | This is the choice of [Starter Modules][wiki_starter_modules], which is the baseline configuration you want for your Azure landing zone. Choose `complete`, `hubnetworking` or `basic` for this example. This also determines the second set of inputs you'll be prompted for. | + | `bootstrap_location` | `` | Replace `` with the Azure region where you would like to deploy the bootstrap resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `starter_location` | `` | Replace `` with the Azure region where you would like to deploy the starter module resources in Azure. This field expects the `name` of the region, such as `uksouth`. You can find a full list of names by running `az account list-locations -o table`. | + | `root_parent_management_group_id` | `""` | This is the id of the management group that will be the parent of the management group structure created by the accelerator. If you are using the `Tenant Root Group` management group, you leave this as an empty string `""` or supply the tenant id. | + | `subscription_id_management` | `` | Replace `` with the id of the management subscription you created in the previous phase. | + | `subscription_id_identity` | `` | Replace `` with the id of the identity subscription you created in the previous phase. | + | `subscription_id_connectivity` | `` | Replace `` with the id of the connectivity subscription you created in the previous phase. | + | `target_directory` | `` | This is the directory where the ALZ module code will be created. This defaults a directory called `local` in the root of the accelerator directory if not supplied. | + | `create_bootstrap_resources_in_azure` | `true` | This determines whether the bootstrap will create the bootstrap resources in Azure. This defaults to `true`. | + | `bootstrap_subscription_id` | `` | Replace `` with the id of the subscription in which you would like to deploy the bootstrap resources in Azure. If left blank, the subscription you are connected to via `az login` will be used. In most cases this is the management subscription, but you can specifiy a separate subscription if you prefer. | + | `service_name` | `alz` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg--mgmt-uksouth-001`. We recommend using `alz` for this. | + | `environment_name` | `mgmt` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz--uksouth-001`. We recommend using `mgmt` for this. | + | `postfix_number` | `1` | This is used to build up the names of your Azure and Azure DevOps resources, for example `rg-alz-mgmt-uksouth-`. We recommend using `1` for this. | + +1. Now head over to your chosen starter module documentation to get the specific inputs for that module. Come back here when you are done. + - [Terraform Basic Starter Module][wiki_starter_module_terraform_basic]: Management groups and policies. + - [Terraform Hub Networking Starter Module][wiki_starter_module_terraform_hubnetworking]: Management groups, policies and hub networking. + - [Terraform Complete Starter Module][wiki_starter_module_terraform_complete]: Management groups, policies, hub networking with fully custom configuration. +1. In your PowerShell Core (pwsh) terminal run the module: + + ```pwsh + # Windows (adjust the paths to match your setup) + Deploy-Accelerator -inputs "c:\accelerator\config\inputs.yaml" -output "c:\accelerator\output" + ``` + + ```pwsh + # Linux/Mac (adjust the paths to match your setup) + Deploy-Accelerator -inputs "~/accelerator/config/inputs.yaml" -output "~/accelerator/output" + ``` + +1. You will see a Terraform `init` and `apply` happen. +1. There will be a pause after the `plan` phase you allow you to validate what is going to be deployed. +1. If you are happy with the plan, then type `yes` and hit enter. +1. The Terraform will `apply` and your environment will be bootstrapped. + +## Next Steps + +Now head to [Phase 3][wiki_quick_start_phase_3]. + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_starter_modules]: %5BUser-Guide%5D-Starter-Modules "Wiki - Starter Modules" +[wiki_starter_module_bicep_complete]: %5BUser-Guide%5D-Starter-Module-Bicep-Complete "Wiki - Starter Modules - Bicep Complete" +[wiki_starter_module_terraform_basic]: %5BUser-Guide%5D-Starter-Module-Terraform-Basic "Wiki - Starter Modules - Terraform Basic" +[wiki_starter_module_terraform_hubnetworking]: %5BUser-Guide%5D-Starter-Module-Terraform-HubNetworking "Wiki - Start Modules - Terraform Hub Networking" +[wiki_starter_module_terraform_complete]: %5BUser-Guide%5D-Starter-Module-Terraform-Complete "Wiki - Starter Modules - Terraform Complete" +[wiki_quick_start_phase_3]: %5BUser-Guide%5D-Quick-Start-Phase-3 "Wiki - Quick Start - Phase 3" +[example_powershell_inputs_local_bicep]: examples/powershell-inputs/inputs-local-bicep.yaml "Example - PowerShell Inputs - Local - Bicep" +[example_powershell_inputs_local_terraform]: examples/powershell-inputs/inputs-local-terraform.yaml "Example - PowerShell Inputs - Local - Terraform" diff --git a/docs/wiki/[User-Guide]-Quick-Start-Phase-2.md b/docs/wiki/[User-Guide]-Quick-Start-Phase-2.md new file mode 100644 index 0000000..c76e793 --- /dev/null +++ b/docs/wiki/[User-Guide]-Quick-Start-Phase-2.md @@ -0,0 +1,41 @@ + +Phase 2 of the accelerator is to run the bootstrap. Follow the steps below to do that. + +## 2.1 Install the ALZ PowerShell module + +The ALZ PowerShell module is used to run the bootstrap phase. It is available on the [PowerShell Gallery](https://www.powershellgallery.com/packages/ALZ/). You can install it using the following steps: + +1. Open a PowerShell Core (pwsh) terminal. +2. Check if you already have the ALZ module installed by runnung `Get-InstalledModule -Name ALZ`. You'll see something like this if it is already installed: + +```powershell +Version Name Repository Description +------- ---- ---------- ----------- +1.0.0 ALZ PSGallery Azure Landing Zones Powershell Module +``` + +3. If the module is already installed, run `Update-Module -Name ALZ` to ensure you have the latest version. +4. If the module is not installed, run `Install-Module -Name ALZ`. + +## 2.2 Run the Bootstrap + +You are now ready to run the bootstrap and setup your environment. If you want to use custom names for your resources or automate the bootstrap, please refer to our [FAQs](https://github.com/Azure/alz-terraform-accelerator/wiki/Frequently-Asked-Questions) section. + +The inputs differ depending on the version control system and infrastructure as code tooling you have chosen. Click through to the relevant page for detailed instructions: + +- [Azure DevOps][wiki_quick_start_phase_2_azure_devops] +- [GitHub][wiki_quick_start_phase_2_github] +- [Local file system][wiki_quick_start_phase_2_local] + +## Next Steps + +Once the steps in the VCS specific section are completed, head to [Phase 3][wiki_quick_start_phase_3]. + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_quick_start_phase_2_azure_devops]: %5BUser-Guide%5D-Quick-Start-Phase-2-Azure-DevOps "Wiki - Quick Start - Phase 2 - Azure DevOps" +[wiki_quick_start_phase_2_github]: %5BUser-Guide%5D-Quick-Start-Phase-2-GitHub "Wiki - Quick Start - Phase 2 - GitHub" +[wiki_quick_start_phase_2_local]: %5BUser-Guide%5D-Quick-Start-Phase-2-Local "Wiki - Quick Start - Phase 2 - Local" +[wiki_quick_start_phase_3]: %5BUser-Guide%5D-Quick-Start-Phase-3 "Wiki - Quick Start - Phase 3" diff --git a/docs/wiki/[User-Guide]-Quick-Start-Phase-3.md b/docs/wiki/[User-Guide]-Quick-Start-Phase-3.md new file mode 100644 index 0000000..a203689 --- /dev/null +++ b/docs/wiki/[User-Guide]-Quick-Start-Phase-3.md @@ -0,0 +1,42 @@ + +Phase 3 of the accelerator is to run pipeline. Follow the steps below to do that. + +## 3.1 Deploy the Landing Zone + +Now you have created your bootstrapped environment you can deploy you Azure landing zone by triggering the continuous delivery pipeline in your version control system. + +### 3.1.1 Azure DevOps + +1. Navigate to [dev.azure.com](https://dev.azure.com) and sign in to your organization. +1. Navigate to your project. +1. Click `Pipelines` in the left navigation. +1. Click the `02 Azure Landing Zones Continuous Delivery` pipeline. +1. Click `Run pipeline` in the top right. +1. Take the defaults and click `Run`. +1. Your pipeline will run a `plan`. +1. If you provided `apply_approvers` to the bootstrap, it will prompt you to approve the `apply` stage. +1. Your pipeline will run an `apply` and deploy an Azure landing zone based on the starter module you choose. + +### 3.1.2 GitHub + +1. Navigate to [github.com](https://github.com). +1. Navigate to your repository. +1. Click `Actions` in the top navigation. +1. Click the `02 Azure Landing Zones Continuous Delivery` pipeline in the left navigation. +1. Click `Run workflow` in the top right, then keep the default branch and click `Run workflow`. +1. Your pipeline will run a `plan`. +1. If you provided `apply_approvers` to the bootstrap, it will prompt you to approve the `apply` job. +1. Your pipeline will run an `apply` and deploy an Azure landing zone based on the starter module you choose. + +### 3.1.3 Local file system + +1. Open a new PowerShell Core (pwsh) terminal or use the one you already have open. +1. Navigate to the directory shown in the `module_output_directory_path` output from the bootstrap. +1. If you choose to deploy the bootstrap resources in Azure, then you will need to navigate to the Azure Portal and find you storage account. +1. Make note of the `Resource Group Name`, `Storage account name`and `Container Name` from the storage account. +1. If you did not choose to deploy the bootstrap resources in Azure, type `terraform init` and hit enter. +1. If you choose to deploy the bootstrap resources in Azure, type `terraform init -backend-config="resource_group_name=" -backend-config="storage_account_name=" -backend-config="container_name=" -backend-config="key=terraform.tfstate"` , replacing the items in angle brackets and hit enter. +1. Type `terraform plan` and hit enter. +1. Review the plan. +1. If you are happy with the plan, then type `terraform apply` and hit enter. +1. The ALZ will now be deployed, this may take some time. diff --git a/docs/wiki/[User-Guide]-Quick-Start.md b/docs/wiki/[User-Guide]-Quick-Start.md new file mode 100644 index 0000000..a20c98f --- /dev/null +++ b/docs/wiki/[User-Guide]-Quick-Start.md @@ -0,0 +1,28 @@ + +## Introduction + +The quick start guide takes you through the steps to prepare your pre-requisites and then run the PowerShell module. + +The accelerator bootstraps a continuous delivery environment for you. It supports both the Azure DevOps and GitHub version control system (VCS). It uses the [ALZ](https://www.powershellgallery.com/packages/ALZ) PowerShell module to gather required user input and apply a Terraform module to configure the bootstrap environment. + +The accelerator follows a 3 phase approach: + +- [Quick Start Phase 1][wiki_quick_start_phase_1]: Instructions to configure credentials and subscriptions. +- [Quick Start Phase 2][wiki_quick_start_phase_2]: Run the PowerShell script to generate the continuous delivery environment. +- [Quick Start Phase 3][wiki_quick_start_phase_3]: Update the module (if needed) to suit the needs of your organisation and deploy via continuous delivery. + +![Azure landing zone accelerator process][alz_accelerator_overview] + + [//]: # (*****************************) + [//]: # (INSERT IMAGE REFERENCES BELOW) + [//]: # (*****************************) + +[alz_accelerator_overview]: media/alz-terraform-acclerator.png "A process flow showing the areas covered by the Azure landing zones Terraform accelerator." + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_quick_start_phase_1]: %5BUser-Guide%5D-Quick-Start-Phase-1 "Wiki - Quick Start - Phase 1" +[wiki_quick_start_phase_2]: %5BUser-Guide%5D-Quick-Start-Phase-2 "Wiki - Quick Start - Phase 2" +[wiki_quick_start_phase_3]: %5BUser-Guide%5D-Quick-Start-Phase-3 "Wiki - Quick Start - Phase 3" diff --git a/docs/wiki/[User-Guide]-Starter-Module-Bicep-Complete.md b/docs/wiki/[User-Guide]-Starter-Module-Bicep-Complete.md new file mode 100644 index 0000000..8efef8a --- /dev/null +++ b/docs/wiki/[User-Guide]-Starter-Module-Bicep-Complete.md @@ -0,0 +1,23 @@ + +The `complete` starter module is currently the only option available for Bicep. + +Example input files can be found here: + +- [inputs-azure-devops-bicep.yaml][example_powershell_inputs_azure_devops_bicep] +- [inputs-github-bicep.yaml][example_powershell_inputs_github_bicep] + +The following table describes the inputs required for the `complete` starter module. + +| Input | Placeholder | Description | +| - | -- | --- | +| `Prefix` | `landing-zone` | This is the defaut prefix for names of resources and management groups. | +| `Environment` | `live` | The environment name for the landing zone. This can be any lower case string. (e.g. `live` or `canary`) | +| `networkType` | `hubNetworking` | The type of network configuration to deploy. Currently only `hubNetworking`, `vwanConnectivity` or `none` are supported. | +| `SecurityContact` | `` | The email address of the security contact for the landing zone. | + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[example_powershell_inputs_azure_devops_bicep]: examples/powershell-inputs/inputs-azure-devops-bicep.yaml "Example - PowerShell Inputs - Azure DevOps - Bicep" +[example_powershell_inputs_github_bicep]: examples/powershell-inputs/inputs-github-bicep.yaml "Example - PowerShell Inputs - GitHub - Bicep" diff --git a/docs/wiki/[User-Guide]-Starter-Module-Terraform-Basic.md b/docs/wiki/[User-Guide]-Starter-Module-Terraform-Basic.md new file mode 100644 index 0000000..022e520 --- /dev/null +++ b/docs/wiki/[User-Guide]-Starter-Module-Terraform-Basic.md @@ -0,0 +1,17 @@ + +The `basic` starter module creates a management group hierarchy with policy assignments, and deploys management resources such as the Log Analytics Workspace and Automation Account. + +## High Level Design + +![Alt text](./media/starter-module-basic.png) + +## Terraform Modules + +### `caf-enterprise-scale` + +The `caf-enterprise-scale` module is solely used for this basic starter module, and has only been populated with its most basic of inputs. It is worth noting that the module itself can be extended to deploy, connectivity resources, custom polices and more. For more information on the module itself see [here](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale). + +## Inputs + +- `root_id`: The root id is the identity for the root management group and a prefix applied to all management group identities. +- `root_name`: The display name for the root management group. diff --git a/docs/wiki/[User-Guide]-Starter-Module-Terraform-Complete.md b/docs/wiki/[User-Guide]-Starter-Module-Terraform-Complete.md new file mode 100644 index 0000000..d9134e1 --- /dev/null +++ b/docs/wiki/[User-Guide]-Starter-Module-Terraform-Complete.md @@ -0,0 +1,183 @@ + +The `complete` starter module provides full customization of the Azure Landing Zone using the `config.yaml` file. The `config.yaml` file provides the ability to enable and disable modules, configure module inputs and outputs, and configure module resources. +A custom `config.yaml` file can be passed to the `additional_files` argument of the ALZ PowerShell Module. This allows you to firstly design your Azure Landing Zone, and then deploy it. +If not specified, the default `config.yaml` file will be used, which is as follows: + +```yaml +# This file contains templated variables to avoid repeating the same hard-coded values. +# Templated variables are denoted by the dollar curly braces token. The following details each templated variable that you can use: +# `default_location`: This is an Azure location sourced from the `default_location` variable. This can be used to set the location of resources. +# `default_postfix`: This is a string sourced from the variable `default_postfix`. This can be used to append to resource names for consistency. +# `root_parent_management_group_id`: This is the id of the management group that the ALZ hierarchy will be nested under. +# `subscription_id_identity`: The subscription ID of the subscription to deploy the identity resources to, sourced from the variable `subscription_id_identity`. +# `subscription_id_connectivity`: The subscription ID of the subscription to deploy the connectivity resources to, sourced from the variable `subscription_id_connectivity`. +# `subscription_id_management`: The subscription ID of the subscription to deploy the management resources to, sourced from the variable `subscription_id_management`. +--- +archetypes: # `caf-enterprise-scale` module, add inputs as listed on the module registry where necessary. + root_name: es + root_id: Enterprise-Scale + subscription_id_connectivity: ${subscription_id_connectivity} + subscription_id_identity: ${subscription_id_identity} + subscription_id_management: ${subscription_id_management} + root_parent_id: ${root_parent_management_group_id} + deploy_corp_landing_zones: true + deploy_online_landing_zones: true + default_location: ${default_location} + disable_telemetry: true + deploy_management_resources: true + configure_management_resources: + location: ${default_location} + settings: + security_center: + config: + email_security_contact: "security_contact@replace_me" + advanced: + asc_export_resource_group_name: rg-asc-export + custom_settings_by_resource_type: + azurerm_resource_group: + management: + name: rg-management + azurerm_log_analytics_workspace: + management: + name: log-management + azurerm_automation_account: + management: + name: aa-management +connectivity: + hubnetworking: # `hubnetworking` module, add inputs as listed on the module registry where necessary. + hub_virtual_networks: + primary: + name: vnet-hub + resource_group_name: rg-connectivity + location: ${default_location} + address_space: + - 10.0.0.0/16 + firewall: + name: fw-hub + sku_name: AZFW_VNet + sku_tier: Standard + subnet_address_prefix: 10.0.1.0/24 + zones: ["1", "2", "3"] + default_ip_configuration: + public_ip_config: + zones: ["1", "2", "3"] + name: "pip-hub" + virtual_network_gateway: # `avm-ptn-vnetgateway` module, add inputs as listed on the module registry where necessary. + name: vgw-hub + subnet_address_prefix: 10.0.2.0/24 + vwan: # `avm-ptn-vwan` module, add inputs as listed on the module registry where necessary. + +``` + +The `config.yaml` file also comes with helpful templated variables such as `default_location` and `root_parent_management_group_id` which get prompted for during the ALZ PowerShell Module run. Alternatively, you can opt to not use the templated variables and hard-code the values in the `config.yaml` file. + +> **Note:** We recommend that you use the `caf-enterprise-scale` module for management groups and policies, and the `hubnetworking` module for connectivity resources. However, connectivity resources can be deployed using the `caf-enterprise-scale` module if you desire. + +The schema for the `config.yaml` is documented here - [Configuration YAML Schema][wiki_yaml_schema_reference]. + +## High Level Design + +![Alt text](./media/starter-module-hubnetworking.png) + +## Terraform Modules + +### `caf-enterprise-scale` + +The `caf-enterprise-scale` module is used to deploy the management group hierarchy, policy assignments and management resources. For more information on the module itself see [here](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale). + +### `hubnetworking` + +The `hubnetworking` module is used to deploy connectivity resources such as Virtual Networks and Firewalls. +This module can be extended to deploy multiple Virtual Networks at scale, Route Tables, and Resource Locks. For more information on the module itself see [here](https://github.com/Azure/terraform-azurerm-hubnetworking). + +### `avm-ptn-vnetgateway` + +The `avm-ptn-vnetgateway` module is used to deploy a Virtual Network Gateway inside your Virtual Network. Further configuration can be added (depending on requirements) to deploy Local Network Gateways, configure Virtual Network Gateway Connections, deploy ExpressRoute Gateways, and more. Additional information on the module can be found [here](https://github.com/Azure/terraform-azurerm-avm-ptn-vnetgateway). + +### `avm-ptn-vwan` + +The `avm-ptn-vwan` module is used to deploy a Virtual WAN. Further configuration can be added (depending on requirements) to deploy VPN Sites, configure VPN Connections, and more. Additional information on the module can be found [here](https://github.com/Azure/terraform-azurerm-avm-ptn-vwan). + +## Inputs + +- `configuration_file_path`: This is the path to your custom config file if you wish to supply one. Leaving this empty will use the default `config.yaml` file. This must be specified as an absolute file paths (e.g. c:\\my-config\\my-config.yaml or /home/user/my-config/my-config.yaml). If you don't supply an absolute path, it will fail. + +## Example + +### Design your Azure Landing Zone through a custom config file + +Create a custom yaml config to tailor to your needs, for example an Azure Landing Zone with a three-region mesh: + +- Example config file for hub and spoke: [config-hub-spoke.yaml][example_starter_module_complete_config_hub_spoke] +- Example config file for Virtual WAN: [config-vwan.yaml][example_starter_module_complete_config_vwan] + +```yaml + +# Path of file: C:\users\johndoe\my-config.yaml + +archetypes: # `caf-enterprise-scale` module, add inputs as listed on the module registry where necessary. + root_name: es + root_id: Enterprise-Scale + deploy_corp_landing_zones: true + deploy_online_landing_zones: true + default_location: uksouth + disable_telemetry: true + deploy_management_resources: true +connectivity: + hubnetworking: # `hubnetworking` module, add inputs as listed on the module registry where necessary. + hub_virtual_networks: + primary: + name: vnet-hub-uks + resource_group_name: rg-connectivity-uks + location: uksouth + mesh_peering_enabled: true + address_space: + - 10.0.0.0/16 + secondary: + name: vnet-hub-ukw + resource_group_name: rg-connectivity-ukw + location: ukwest + mesh_peering_enabled: true + address_space: + - 10.1.0.0/16 + tertiary: + name: vnet-hub-ne + resource_group_name: rg-connectivity-ne + location: northeurope + mesh_peering_enabled: true + address_space: + - 10.2.0.0/16 + +``` + +### Use the ALZ PowerShell Module to prepare your Azure Landing Zone for deployment + +Set your inputs.yaml file (See [Frequently Asked Questions][wiki_frequently_asked_questions] for more information on the `inputs.yaml` file.) for the `Deploy-Accelerator` command as follows: + +> **Note:** This is an alternative way of supplying the input arguments to the ALZ PowerShell Module, you can still run it as documented in the Quick Start guide and be prompted for inputs. + +GitHub Example: + +- Example input file: [inputs-github-terraform.yaml][example_powershell_inputs_github_terraform] + +Azure DevOps Example: + +- Example input file: [inputs-azure-devops-terraform.yaml][example_powershell_inputs_azure_devops_terraform] + +Run the accelerator: + +```powershell +# Working Directory: C:\users\johndoe +Deploy-Accelerator -Inputs "inputs.yaml" -autoApprove +``` + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_yaml_schema_reference]: %5BUser-Guide%5D-YAML-Schema-Reference "Wiki - YAML Schema Reference" +[wiki_frequently_asked_questions]: Frequently-Asked-Questions "Wiki - Frequently Asked Questions" +[example_powershell_inputs_azure_devops_terraform]: examples/powershell-inputs/inputs-azure-devops-terraform.yaml "Example - PowerShell Inputs - Azure DevOps - Terraform" +[example_powershell_inputs_github_terraform]: examples/powershell-inputs/inputs-github-terraform.yaml "Example - PowerShell Inputs - GitHub - Terraform" +[example_starter_module_complete_config_hub_spoke]: examples/starter-module-config/complete/config-hub-spoke.yaml "Example - Starter Module Config - Complete - Hub and Spoke" +[example_starter_module_complete_config_vwan]: examples/starter-module-config/complete/config-vwan.yaml "Example - Starter Module Config - Complete - Virtual WAN" diff --git a/docs/wiki/[User-Guide]-Starter-Module-Terraform-HubNetworking.md b/docs/wiki/[User-Guide]-Starter-Module-Terraform-HubNetworking.md new file mode 100644 index 0000000..737b964 --- /dev/null +++ b/docs/wiki/[User-Guide]-Starter-Module-Terraform-HubNetworking.md @@ -0,0 +1,37 @@ + +The `hubnetworking` starter module builds off the `basic` starter module ([Basic Starter Module][wiki_starter_module_basic]) and additionally configures hub networking resources such as the Virtual Network, Firewall and Virtual Network Gateway. + +## High Level Design + +![Alt text](./media/starter-module-hubnetworking.png) + +## Terraform Modules + +### `caf-enterprise-scale` + +The `caf-enterprise-scale` has been used to deploy the management group hierarchy, policy assignments and management resources. For more information on the module itself see [here](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale). + +### `hubnetworking` + +The `hubnetworking` module is used to deploy connectivity resources such as Virtual Networks and Firewalls. By default, the module will deploy a Virtual Network with a Firewall in your `default_location`. + This module can be extended however to deploy multiple Virtual Networks at scale, Route Tables, and Resource Locks. For more information on the module itself see [here](https://github.com/Azure/terraform-azurerm-hubnetworking). + +### `avm-ptn-vnetgateway` + +The `avm-ptn-vnetgateway` module is used to deploy a Virtual Network Gateway inside your Virtual Network. By default, the resources of the module will not be deployed unless `virtual_network_gateway_creation_enabled` is set to true, if so, the module will deploy a ExpressRoute Gateway with SKU ErGw1AZ. + Further configuration can be added depending on requirements to deploy Local Network Gateways, configure Virtual Network Gateway Connections, deploy ExpressRoute Gateways and more. Additional information on the module can be found [here](https://github.com/Azure/terraform-azurerm-avm-ptn-vnetgateway). + +## Inputs + +- `root_id`: The root id is the identity for the root management group and a prefix applied to all management group identities. +- `root_name`: The display name for the root management group. +- `hub_virtual_network_address_prefix`: The IP address range for the hub network in CIDR format (e.g 10.0.0.0/16). +- `firewall_subnet_address_prefix`: The IP address range for the firewall subnet in CIDR format (e.g. 10.0.0.0/24). +- `gateway_subnet_address_prefix`: The IP address range for the gateway subnet in CIDR format (e.g. 10.0.1.0/24). +- `virtual_network_gateway_creation_enabled`: Whether the virtual network gateway is created. + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_starter_module_basic]: %5BUser-Guide%5D-Starter-Module-Basic "Wiki - Starter Modules - Basic" diff --git a/docs/wiki/[User-Guide]-Starter-Modules.md b/docs/wiki/[User-Guide]-Starter-Modules.md new file mode 100644 index 0000000..991cb40 --- /dev/null +++ b/docs/wiki/[User-Guide]-Starter-Modules.md @@ -0,0 +1,21 @@ + + +The Azure landing zones accelerator includes a number of starter modules that provide opinionated implementations of the Bicep or Terraform Azure landing zones modules. + +These are called starter modules because the expectation is you'll update these modules as the needs of your organization evolves and you want to add or remove features to your landing zone. + +Each starter module expects different inputs and the following pages detail those inputs. You'll be prompted for these inputs when you run the Accelerator PowerShell module. + +- [Bicep Complete Starter Module][wiki_starter_module_bicep_complete]: Management groups, policies and hub networking. +- [Terraform Basic Starter Module][wiki_starter_module_terraform_basic]: Management groups and policies. +- [Terraform Hub Networking Starter Module][wiki_starter_module_terraform_hubnetworking]: Management groups, policies and hub networking. +- [Terraform Complete Starter Module][wiki_starter_module_terraform_complete]: Management groups, policies, hub networking with fully custom configuration. + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) + +[wiki_starter_module_bicep_complete]: %5BUser-Guide%5D-Starter-Module-Bicep-Complete "Wiki - Starter Modules - Bicep Complete" +[wiki_starter_module_terraform_basic]: %5BUser-Guide%5D-Starter-Module-Terraform-Basic "Wiki - Starter Modules - Terraform Basic" +[wiki_starter_module_terraform_hubnetworking]: %5BUser-Guide%5D-Starter-Module-Terraform-HubNetworking "Wiki - Start Modules - Terraform Hub Networking" +[wiki_starter_module_terraform_complete]: %5BUser-Guide%5D-Starter-Module-Terraform-Complete "Wiki - Starter Modules - Terraform Complete" diff --git a/docs/wiki/[User-Guide]-YAML-Schema-Reference.md b/docs/wiki/[User-Guide]-YAML-Schema-Reference.md new file mode 100644 index 0000000..3766741 --- /dev/null +++ b/docs/wiki/[User-Guide]-YAML-Schema-Reference.md @@ -0,0 +1,222 @@ + + +## `archetypes` + +Specifies the archetypes to be used through the `caf-enterprise-scale` module. + +```yaml + +archetypes: # Arguments from https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/blob/v4.2.0/variables.tf converted to YAML. + disable_telemetry: # boolean + default_location: # string + root_parent_id: # string + archetype_config_overrides: # object + configure_connectivity_resources: # object + configure_identity_resources: # object + configure_management_resources: # object + create_duration_delay: # object + custom_landing_zones: # object + custom_policy_roles: # object + default_tags: # object + deploy_connectivity_resources: # boolean + deploy_corp_landing_zones: # boolean + deploy_core_landing_zones: # boolean + deploy_demo_landing_zones: # boolean + deploy_diagnostics_for_mg: # boolean + deploy_identity_resources: # boolean + deploy_management_resources: # boolean + deploy_online_landing_zones: # boolean + deploy_sap_landing_zones: # boolean + destroy_duration_delay: # object + disable_base_module_tags: # boolean + library_path: # string + policy_non_compliance_message_default: # string + policy_non_compliance_message_default_enabled: # boolean + policy_non_compliance_message_enabled: # boolean + policy_non_compliance_message_enforced_replacement: # string + policy_non_compliance_message_enforcement_placeholder: # string + policy_non_compliance_message_not_enforced_replacement: # string + policy_non_compliance_message_not_supported_definitions: # list + resource_custom_timeouts: # object + root_id: # string + root_name: # string + strict_subscription_association: # boolean + subscription_id_connectivity: # string + subscription_id_identity: # string + subscription_id_management: # string + subscription_id_overrides: # object + template_file_variables: # string + +``` + +### `archetypes` Example + +```yaml + +archetypes: # `caf-enterprise-scale` module, add inputs as listed on the module registry where necessary. + root_name: es + root_id: Enterprise-Scale + deploy_corp_landing_zones: true + deploy_online_landing_zones: true + default_location: uksouth + disable_telemetry: true + deploy_management_resources: true + default_tags: + environment: dev + costcenter: 12345 + configure_management_resources: + location: uksouth + settings: + security_center: + config: + email_security_contact: "security_contact@replace_me" + custom_landing_zones: + eucustomers: + display_name: EU Customers + parent_management_group_id: es-landing-zones + +``` + +## `connectivity` + +Specifies the connectivity configuration to be used. + +```yaml + +connectivity: [ hubnetworking ] # Type of connectivity to be deployed (e.g. hubnetworking or virtual wan.) + +``` + +## `connectivity.hubnetworking` + +Specifies the hub networking configuration to be used from the `terraform-azurerm-hubnetworking` module. + +```yaml + +connectivity: + hubnetworking: # # Arguments from https://github.com/Azure/terraform-azurerm-hubnetworking/blob/v1.1.1/variables.tf converted to YAML. + hub_virtual_networks: # object + +``` + +### `connectivity.hubnetworking` Example + +```yaml +connectivity: + hubnetworking: + hub_virtual_networks: + hub-one: + name: vnet-hub + resource_group_name: rg-connectivity + location: uksouth + address_space: + - 10.0.0.0/16 + firewall: + name: fw-hub + sku_name: AZFW_VNet + sku_tier: Standard + subnet_address_prefix: 10.0.1.0/24 + +``` + +## `connectivity.hubnetworking.hub_virtual_networks..virtual_network_gateway` + +Specifies the virtual network gateway configuration to be used from the `terraform-azurerm-avm-ptn-vnetgateway` module. + +```yaml + +connectivity: + hubnetworking: + hub_virtual_networks: + : + name: # string + resource_group_name: # string + location: # string + address_space: # list + virtual_network_gateway: # Arguments from https://github.com/Azure/terraform-azurerm-avm-ptn-vnetgateway/blob/v0.3.0/variables.tf converted to YAML. + name: # string + sku: # string + subnet_address_prefix: # string + subnet_creation_enabled: # boolean + type: # string + default_tags: # object + edge_zone: # string + express_route_circuits: # object + ip_configurations: # object + local_network_gateways: # object + tags: # object + vpn_active_active_enabled: # boolean + vpn_bgp_enabled: # boolean + vpn_bgp_settings: # object + vpn_generation: # string + vpn_point_to_site: # object + vpn_type: # string + vpn_private_ip_address_enabled: # boolean + route_table_bgp_route_propagation_enabled: # boolean + route_table_creation_enabled: # boolean + route_table_name: # string + route_table_tags: # object + +``` + +### `connectivity.hubnetworking.hub_virtual_networks..virtual_network_gateway` Example + +```yaml +connectivity: + hubnetworking: + hub_virtual_networks: + hub-one: + name: vnet-hub + resource_group_name: rg-connectivity + location: uksouth + address_space: + - 10.0.0.0/16 + firewall: + name: fw-hub + sku_name: AZFW_VNet + sku_tier: Standard + subnet_address_prefix: 10.0.1.0/24 + virtual_network_gateway: + name: vgw-hub + sku: VpnGw1 + type: Vpn + subnet_address_prefix: 10.0.2.0/24 +``` + +## `connectivity.vwan` + +Specifies the hub networking configuration to be used from the `terraform-azurerm-avm-ptn-virtualwan` module. + +```yaml + +connectivity: + vwan: # Arguments from https://github.com/Azure/terraform-azurerm-avm-ptn-virtualwan/blob/v0.4.0/variables.tf converted to YAML. + allow_branch_to_branch_traffic: # boolean + create_resource_group: # boolean + disable_vpn_encryption: # boolean + enable_telemetry: # boolean + er_circuit_connections: # object + expressroute_gateways: # object + firewalls: # object + location: # string + office365_local_breakout_category + p2s_gateway_vpn_server_configurations: # object + p2s_gateways: # object + resource_group_name: # string + resource_group_tags: # object + routing_intents: # object + telemetry_resource_group_name: # string + type: # string + virtual_hubs: # object + virtual_network_connections: # object + virtual_wan_name: # string + virtual_wan_tags: # object + vpn_gateways: # object + vpn_site_connections: # object + vpn_sites: # object + tags: # object +``` + + [//]: # (************************) + [//]: # (INSERT LINK LABELS BELOW) + [//]: # (************************) diff --git a/docs/wiki/_Footer.md b/docs/wiki/_Footer.md new file mode 100644 index 0000000..d54dfe7 --- /dev/null +++ b/docs/wiki/_Footer.md @@ -0,0 +1,4 @@ + +**This wiki is being actively developed** + +If you discover any documentation bugs or would like to request new content, please raise them as an [issue](https://github.com/Azure/ALZ-PowerShell-Module/issues) or feel free to contribute to the wiki via a [pull request](https://github.com/Azure/ALZ-PowerShell-Module/pulls). The wiki docs are located in the repository in the `docs/wiki/` folder. diff --git a/docs/wiki/_Sidebar.md b/docs/wiki/_Sidebar.md new file mode 100644 index 0000000..a4e6cb1 --- /dev/null +++ b/docs/wiki/_Sidebar.md @@ -0,0 +1,79 @@ + +![Azure logo](media/Logo-Small.png) + +## Azure landing zones accelerators + +- [Home][wiki_home] +- [User guide][wiki_user_guide] + - [Getting started][wiki_getting_started] + - [Quick Start][wiki_quick_start] + - [Phase 1 - Pre-requisites][wiki_quick_start_phase_1] + - [Service Principal][wiki_quick_start_phase_1_service_principal] + - [Phase 2 - Bootstrap][wiki_quick_start_phase_2] + - [Azure DevOps][wiki_quick_start_phase_2_azure_devops] + - [GitHub][wiki_quick_start_phase_2_github] + - [Local][wiki_quick_start_phase_2_local] + - [Phase 3 - Run][wiki_quick_start_phase_3] + - [Starter Modules][wiki_starter_modules] + - [Bicep - Complete][wiki_starter_module_bicep_complete] + - [Terraform - Basic][wiki_starter_module_terraform_basic] + - [Terraform - Hub Networking][wiki_starter_module_terraform_hubnetworking] + - [Terraform - Complete][wiki_starter_module_terraform_complete] + - [Configuration YAML Schema][wiki_yaml_schema_reference] + - [Example Hub and Spoke config][example_starter_module_complete_config_hub_spoke] + - [Example Virtual WAN config][example_starter_module_complete_config_vwan] + - Input Files + - [Azure DevOps Bicep Inputs][example_powershell_inputs_azure_devops_bicep] + - [Azure DevOps Terraform Inputs][example_powershell_inputs_azure_devops_terraform] + - [GitHub Bicep Inputs][example_powershell_inputs_github_bicep] + - [GitHub Terraform Inputs][example_powershell_inputs_github_terraform] + - [Local Bicep Inputs][example_powershell_inputs_local_bicep] + - [Local Terraform Inputs][example_powershell_inputs_local_terraform] +- [Frequently Asked Questions][wiki_frequently_asked_questions] +- [Upgrade Guide][wiki_upgrade_guide] +- [Advanced Scenarios][wiki_advanced_scenarios] +- [Troubleshooting][wiki_troubleshooting] +- [Contributing][wiki_contributing] + - [Raising an issue][wiki_raising_an_issue] + - [Feature requests][wiki_feature_requests] + - [Contributing to code][wiki_contributing_to_code] + - [Contributing to documentation][wiki_contributing_to_documentation] + +[//]: # "************************" +[//]: # "INSERT LINK LABELS BELOW" +[//]: # "************************" + +[wiki_home]: Home "Wiki - Home" +[wiki_user_guide]: User-Guide "Wiki - User guide" +[wiki_getting_started]: %5BUser-Guide%5D-Getting-Started "Wiki - Getting started" +[wiki_quick_start]: %5BUser-Guide%5D-Quick-Start "Wiki - Quick start" +[wiki_quick_start_phase_1]: %5BUser-Guide%5D-Quick-Start-Phase-1 "Wiki - Quick Start - Phase 1" +[wiki_quick_start_phase_1_service_principal]: %5BUser-Guide%5D-Quick-Start-Phase-1-Service-Principal "Wiki - Quick Start - Phase 1 - Service Principal" +[wiki_quick_start_phase_2]: %5BUser-Guide%5D-Quick-Start-Phase-2 "Wiki - Quick Start - Phase 2" +[wiki_quick_start_phase_2_azure_devops]: %5BUser-Guide%5D-Quick-Start-Phase-2-Azure-DevOps "Wiki - Quick Start - Phase 2 - Azure DevOps" +[wiki_quick_start_phase_2_github]: %5BUser-Guide%5D-Quick-Start-Phase-2-GitHub "Wiki - Quick Start - Phase 2 - GitHub" +[wiki_quick_start_phase_2_local]: %5BUser-Guide%5D-Quick-Start-Phase-2-Local "Wiki - Quick Start - Phase 2 - Local" +[wiki_quick_start_phase_3]: %5BUser-Guide%5D-Quick-Start-Phase-3 "Wiki - Quick Start - Phase 3" +[wiki_starter_modules]: %5BUser-Guide%5D-Starter-Modules "Wiki - Starter Modules" +[wiki_starter_module_bicep_complete]: %5BUser-Guide%5D-Starter-Module-Bicep-Complete "Wiki - Starter Modules - Bicep Complete" +[wiki_starter_module_terraform_basic]: %5BUser-Guide%5D-Starter-Module-Terraform-Basic "Wiki - Starter Modules - Terraform Basic" +[wiki_starter_module_terraform_hubnetworking]: %5BUser-Guide%5D-Starter-Module-Terraform-HubNetworking "Wiki - Start Modules - Terraform Hub Networking" +[wiki_starter_module_terraform_complete]: %5BUser-Guide%5D-Starter-Module-Terraform-Complete "Wiki - Starter Modules - Terraform Complete" +[wiki_yaml_schema_reference]: %5BUser-Guide%5D-YAML-Schema-Reference "Wiki - YAML Schema Reference" +[wiki_frequently_asked_questions]: Frequently-Asked-Questions "Wiki - Frequently Asked Questions" +[wiki_troubleshooting]: Troubleshooting "Wiki - Troubleshooting" +[wiki_contributing]: Contributing "Wiki - Contributing" +[wiki_raising_an_issue]: Raising-an-Issue "Wiki - Raising an issue" +[wiki_feature_requests]: Feature-Requests "Wiki - Feature requests" +[wiki_contributing_to_code]: Contributing-to-Code "Wiki - Contributing to code" +[wiki_contributing_to_documentation]: Contributing-to-Documentation "Wiki - Contributing to documentation" +[wiki_upgrade_guide]: Upgrade-Guide "Wiki - Upgrade Guide" +[wiki_advanced_scenarios]: %5BUser-Guide%5D-Advanced-Scenarios "Wiki - Advanced Scenarios" +[example_powershell_inputs_azure_devops_bicep]: examples/powershell-inputs/inputs-azure-devops-bicep.yaml "Example - PowerShell Inputs - Azure DevOps - Bicep" +[example_powershell_inputs_azure_devops_terraform]: examples/powershell-inputs/inputs-azure-devops-terraform.yaml "Example - PowerShell Inputs - Azure DevOps - Terraform" +[example_powershell_inputs_github_bicep]: examples/powershell-inputs/inputs-github-bicep.yaml "Example - PowerShell Inputs - GitHub - Bicep" +[example_powershell_inputs_github_terraform]: examples/powershell-inputs/inputs-github-terraform.yaml "Example - PowerShell Inputs - GitHub - Terraform" +[example_powershell_inputs_local_bicep]: examples/powershell-inputs/inputs-local-bicep.yaml "Example - PowerShell Inputs - Local - Bicep" +[example_powershell_inputs_local_terraform]: examples/powershell-inputs/inputs-local-terraform.yaml "Example - PowerShell Inputs - Local - Terraform" +[example_starter_module_complete_config_hub_spoke]: examples/starter-module-config/complete/config-hub-spoke.yaml "Example - Starter Module Config - Complete - Hub and Spoke" +[example_starter_module_complete_config_vwan]: examples/starter-module-config/complete/config-vwan.yaml "Example - Starter Module Config - Complete - Virtual WAN" diff --git a/docs/wiki/examples/powershell-inputs/inputs-azure-devops-bicep.yaml b/docs/wiki/examples/powershell-inputs/inputs-azure-devops-bicep.yaml new file mode 100644 index 0000000..4721966 --- /dev/null +++ b/docs/wiki/examples/powershell-inputs/inputs-azure-devops-bicep.yaml @@ -0,0 +1,41 @@ +--- +# For detailed instructions on using this file, visit: +# https://github.com/Azure/ALZ-PowerShell-Module/wiki/%5BUser-Guide%5D-Quick-Start-Phase-2-Azure-DevOps#2211-azure-devops-with-bicep + +# Basic Inputs +iac: "bicep" +bootstrap: "alz_azuredevops" +starter: "complete" + +# Shared Interface Inputs +bootstrap_location: "" +starter_location: "" +root_parent_management_group_id: "" +subscription_id_management: "" +subscription_id_identity: "" +subscription_id_connectivity: "" + +# Bootstrap Inputs +azure_devops_personal_access_token: "" +azure_devops_agents_personal_access_token: "" +azure_devops_organization_name: "" +use_separate_repository_for_templates: "true" +bootstrap_subscription_id: "" +service_name: "alz" +environment_name: "mgmt" +postfix_number: "1" +azure_devops_use_organisation_legacy_url: "false" +azure_devops_create_project: "true" +azure_devops_project_name: "" +use_self_hosted_agents: "true" +use_private_networking: "true" +allow_storage_access_from_my_ip: "false" +apply_approvers: "" +create_branch_policies: "true" + +# Starter Module Specific Variables +Prefix: "landing-zone" +Location: "" +Environment: "live" +networkType: "hubNetworking" +SecurityContact: "" diff --git a/docs/wiki/examples/powershell-inputs/inputs-azure-devops-terraform.yaml b/docs/wiki/examples/powershell-inputs/inputs-azure-devops-terraform.yaml new file mode 100644 index 0000000..8e5b9e3 --- /dev/null +++ b/docs/wiki/examples/powershell-inputs/inputs-azure-devops-terraform.yaml @@ -0,0 +1,39 @@ +--- +# For detailed instructions on using this file, visit: +# https://github.com/Azure/ALZ-PowerShell-Module/wiki/%5BUser-Guide%5D-Quick-Start-Phase-2-Azure-DevOps#2212-azure-devops-with-terraform + +# Basic Inputs +iac: "terraform" +bootstrap: "alz_azuredevops" +starter: "complete" + +# Shared Interface Inputs +bootstrap_location: "" +starter_location: "" +root_parent_management_group_id: "" +subscription_id_management: "" +subscription_id_identity: "" +subscription_id_connectivity: "" + +# Bootstrap Inputs +azure_devops_personal_access_token: "" +azure_devops_agents_personal_access_token: "" +azure_devops_organization_name: "" +use_separate_repository_for_templates: "true" +bootstrap_subscription_id: "" +service_name: "alz" +environment_name: "mgmt" +postfix_number: "1" +azure_devops_use_organisation_legacy_url: "false" +azure_devops_create_project: "true" +azure_devops_project_name: "" +use_self_hosted_agents: "true" +use_private_networking: "true" +allow_storage_access_from_my_ip: "false" +apply_approvers: "" +create_branch_policies: "true" + +# Starter Module Specific Variables +default_location: "" +default_postfix: "landing-zone" +configuration_file_path: "" # Only required for the `complete` starter module diff --git a/docs/wiki/examples/powershell-inputs/inputs-github-bicep.yaml b/docs/wiki/examples/powershell-inputs/inputs-github-bicep.yaml new file mode 100644 index 0000000..c604e71 --- /dev/null +++ b/docs/wiki/examples/powershell-inputs/inputs-github-bicep.yaml @@ -0,0 +1,38 @@ +--- +# For detailed instructions on using this file, visit: +# https://github.com/Azure/ALZ-PowerShell-Module/wiki/%5BUser-Guide%5D-Quick-Start-Phase-2-GitHub#2221-github-with-bicep + +# Basic Inputs +iac: "bicep" +bootstrap: "alz_github" +starter: "complete" + +# Shared Interface Inputs +bootstrap_location: "" +starter_location: "" +root_parent_management_group_id: "" +subscription_id_management: "" +subscription_id_identity: "" +subscription_id_connectivity: "" + +# Bootstrap Inputs +github_personal_access_token: "" +github_runners_personal_access_token: "" +github_organization_name: "" +use_separate_repository_for_templates: "true" +bootstrap_subscription_id: "" +service_name: "alz" +environment_name: "mgmt" +postfix_number: "1" +use_self_hosted_runners: "true" +use_private_networking: "true" +allow_storage_access_from_my_ip: "false" +apply_approvers: "" +create_branch_policies: "true" + +# Starter Module Specific Variables +Prefix: "landing-zone" +Location: "" +Environment: "live" +networkType: "hubNetworking" +SecurityContact: "" diff --git a/docs/wiki/examples/powershell-inputs/inputs-github-terraform.yaml b/docs/wiki/examples/powershell-inputs/inputs-github-terraform.yaml new file mode 100644 index 0000000..d1be4eb --- /dev/null +++ b/docs/wiki/examples/powershell-inputs/inputs-github-terraform.yaml @@ -0,0 +1,36 @@ +--- +# For detailed instructions on using this file, visit: +# https://github.com/Azure/ALZ-PowerShell-Module/wiki/%5BUser-Guide%5D-Quick-Start-Phase-2-GitHub#2222-github-with-terraform + +# Basic Inputs +iac: "terraform" +bootstrap: "alz_github" +starter: "complete" + +# Shared Interface Inputs +bootstrap_location: "" +starter_location: "" +root_parent_management_group_id: "" +subscription_id_management: "" +subscription_id_identity: "" +subscription_id_connectivity: "" + +# Bootstrap Inputs +github_personal_access_token: "" +github_runners_personal_access_token: "" +github_organization_name: "" +use_separate_repository_for_templates: "true" +bootstrap_subscription_id: "" +service_name: "alz" +environment_name: "mgmt" +postfix_number: "1" +use_self_hosted_runners: "true" +use_private_networking: "true" +allow_storage_access_from_my_ip: "false" +apply_approvers: "" +create_branch_policies: "true" + +# Starter Module Specific Variables +default_location: "" +default_postfix: "landing-zone" +configuration_file_path: "" # Only required for the `complete` starter module diff --git a/docs/wiki/examples/powershell-inputs/inputs-local-bicep.yaml b/docs/wiki/examples/powershell-inputs/inputs-local-bicep.yaml new file mode 100644 index 0000000..e92d88d --- /dev/null +++ b/docs/wiki/examples/powershell-inputs/inputs-local-bicep.yaml @@ -0,0 +1,31 @@ +--- +# For detailed instructions on using this file, visit: +# https://github.com/Azure/ALZ-PowerShell-Module/wiki/%5BUser-Guide%5D-Quick-Start-Phase-2-Azure-DevOps#2211-azure-devops-with-bicep + +# Basic Inputs +iac: "bicep" +bootstrap: "alz_local" +starter: "complete" + +# Shared Interface Inputs +bootstrap_location: "" +starter_location: "" +root_parent_management_group_id: "" +subscription_id_management: "" +subscription_id_identity: "" +subscription_id_connectivity: "" + +# Bootstrap Inputs +target_directory: "" +create_bootstrap_resources_in_azure: "true" +bootstrap_subscription_id: "" +service_name: "alz" +environment_name: "mgmt" +postfix_number: "1" + +# Starter Module Specific Variables +Prefix: "landing-zone" +Location: "" +Environment: "live" +networkType: "hubNetworking" +SecurityContact: "" diff --git a/docs/wiki/examples/powershell-inputs/inputs-local-terraform.yaml b/docs/wiki/examples/powershell-inputs/inputs-local-terraform.yaml new file mode 100644 index 0000000..0e79764 --- /dev/null +++ b/docs/wiki/examples/powershell-inputs/inputs-local-terraform.yaml @@ -0,0 +1,29 @@ +--- +# For detailed instructions on using this file, visit: +# https://github.com/Azure/ALZ-PowerShell-Module/wiki/%5BUser-Guide%5D-Quick-Start-Phase-2-Azure-DevOps#2211-azure-devops-with-bicep + +# Basic Inputs +iac: "bicep" +bootstrap: "alz_local" +starter: "complete" + +# Shared Interface Inputs +bootstrap_location: "" +starter_location: "" +root_parent_management_group_id: "" +subscription_id_management: "" +subscription_id_identity: "" +subscription_id_connectivity: "" + +# Bootstrap Inputs +target_directory: "" +create_bootstrap_resources_in_azure: "true" +bootstrap_subscription_id: "" +service_name: "alz" +environment_name: "mgmt" +postfix_number: "1" + +# Starter Module Specific Variables +default_location: "" +default_postfix: "landing-zone" +configuration_file_path: "" # Only required for the `complete` starter module diff --git a/docs/wiki/examples/starter-module-config/complete/config-hub-spoke.yaml b/docs/wiki/examples/starter-module-config/complete/config-hub-spoke.yaml new file mode 100644 index 0000000..4be01ae --- /dev/null +++ b/docs/wiki/examples/starter-module-config/complete/config-hub-spoke.yaml @@ -0,0 +1,235 @@ +# This file contains templated variables to avoid repeating the same hard-coded values. +# Templated variables are denoted by the dollar curly braces token. The following details each templated variable that you can use: +# `default_location`: This is an Azure location sourced from the `default_location` variable. This can be used to set the location of resources. +# `default_postfix`: This is a string sourced from the variable `default_postfix`. This can be used to append to resource names for consistency. +# `root_parent_management_group_id`: This is the id of the management group that the ALZ hierarchy will be nested under. +# `subscription_id_identity`: The subscription ID of the subscription to deploy the identity resources to, sourced from the variable `subscription_id_identity`. +# `subscription_id_connectivity`: The subscription ID of the subscription to deploy the connectivity resources to, sourced from the variable `subscription_id_connectivity`. +# `subscription_id_management`: The subscription ID of the subscription to deploy the management resources to, sourced from the variable `subscription_id_management`. +--- +archetypes: # `caf-enterprise-scale` module, add inputs as listed on the module registry where necessary. + # Base variables + root_name: Contoso + root_id: contoso + subscription_id_connectivity: ${subscription_id_connectivity} + subscription_id_identity: ${subscription_id_identity} + subscription_id_management: ${subscription_id_management} + root_parent_id: ${root_parent_management_group_id} + deploy_core_landing_zones: true + deploy_corp_landing_zones: true + deploy_online_landing_zones: true + default_location: ${default_location} + deploy_management_resources: true + deploy_connectivity_resources: true + deploy_identity_resources: true + disable_telemetry: true + + # Management + configure_management_resources: + location: ${default_location} + settings: + log_analytics: + enabled: true + config: + retention_in_days: 50 + enable_monitoring_for_vm: true + enable_monitoring_for_vmss: true + enable_solution_for_agent_health_assessment: true + enable_solution_for_anti_malware: true + enable_solution_for_change_tracking: true + enable_solution_for_service_map: true + enable_solution_for_sql_assessment: true + enable_solution_for_sql_vulnerability_assessment: true + enable_solution_for_sql_advanced_threat_detection: true + enable_solution_for_updates: true + enable_solution_for_vm_insights: true + enable_solution_for_container_insights: true + enable_sentinel: true + security_center: + enabled: true + config: + email_security_contact: "user@contoso.com" + enable_defender_for_apis: true + enable_defender_for_app_services: true + enable_defender_for_arm: true + enable_defender_for_containers: true + enable_defender_for_cosmosdbs: true + enable_defender_for_cspm: true + enable_defender_for_dns: true + enable_defender_for_key_vault: true + enable_defender_for_oss_databases: true + enable_defender_for_servers: true + enable_defender_for_servers_vulnerability_assessments: true + enable_defender_for_sql_servers: true + enable_defender_for_sql_server_vms: true + enable_defender_for_storage: true + location: ${default_location} + tags: null + advanced: + asc_export_resource_group_name: rg-asc-export + custom_settings_by_resource_type: + azurerm_resource_group: + management: + name: rg-management + azurerm_log_analytics_workspace: + management: + name: log-management + azurerm_automation_account: + management: + name: aa-management + + # Networking + configure_connectivity_resources: + settings: + hub_networks: + - config: + address_space: + - 10.100.0.0/16 + location: ${default_location} + link_to_ddos_protection_plan: false + dns_servers: [] + bgp_community: "" + subnets: [] + virtual_network_gateway: + enabled: true + config: + address_prefix: 10.100.1.0/24 + gateway_sku_expressroute: ErGw2AZ + gateway_sku_vpn: null + advanced_vpn_settings: + enable_bgp: null + active_active: null + private_ip_address_allocation: "" + default_local_network_gateway_id: "" + vpn_client_configuration: [] + bgp_settings: [] + custom_route: [] + azure_firewall: + enabled: false + config: + address_prefix: 10.100.0.0/24 + enable_dns_proxy: true + sku_tier: "" + base_policy_id: "" + private_ip_ranges: [] + threat_intelligence_mode: "" + threat_intelligence_allowlist: {} + availability_zones: + zone_1: true + zone_2: true + zone_3: true + spoke_virtual_network_resource_ids: [] + enable_outbound_virtual_network_peering: true + enable_hub_network_mesh_peering: false + vwan_hub_networks: [] + ddos_protection_plan: + enabled: false + config: + location: ${default_location} + dns: + enabled: true + config: + location: null + enable_private_link_by_service: + azure_api_management: true + azure_app_configuration_stores: true + azure_arc: true + azure_automation_dscandhybridworker: true + azure_automation_webhook: true + azure_backup: true + azure_batch_account: true + azure_bot_service_bot: true + azure_bot_service_token: true + azure_cache_for_redis: true + azure_cache_for_redis_enterprise: true + azure_container_registry: true + azure_cosmos_db_cassandra: true + azure_cosmos_db_gremlin: true + azure_cosmos_db_mongodb: true + azure_cosmos_db_sql: true + azure_cosmos_db_table: true + azure_data_explorer: true + azure_data_factory: true + azure_data_factory_portal: true + azure_data_health_data_services: true + azure_data_lake_file_system_gen2: true + azure_database_for_mariadb_server: true + azure_database_for_mysql_server: true + azure_database_for_postgresql_server: true + azure_digital_twins: true + azure_event_grid_domain: true + azure_event_grid_topic: true + azure_event_hubs_namespace: true + azure_file_sync: true + azure_hdinsights: true + azure_iot_dps: true + azure_iot_hub: true + azure_key_vault: true + azure_key_vault_managed_hsm: true + azure_kubernetes_service_management: true + azure_machine_learning_workspace: true + azure_managed_disks: true + azure_media_services: true + azure_migrate: true + azure_monitor: true + azure_purview_account: true + azure_purview_studio: true + azure_relay_namespace: true + azure_search_service: true + azure_service_bus_namespace: true + azure_site_recovery: true + azure_sql_database_sqlserver: true + azure_synapse_analytics_dev: true + azure_synapse_analytics_sql: true + azure_synapse_studio: true + azure_web_apps_sites: true + azure_web_apps_static_sites: true + cognitive_services_account: true + microsoft_power_bi: true + signalr: true + signalr_webpubsub: true + storage_account_blob: true + private_link_locations: + - ${default_location} + public_dns_zones: [] + private_dns_zones: [] + enable_private_dns_zone_virtual_network_link_on_hubs: true + enable_private_dns_zone_virtual_network_link_on_spokes: true + virtual_network_resource_ids_to_link: [] + location: ${default_location} + tags: null + advanced: null + + # Identity + configure_identity_resources: + settings: + identity: + enabled: true + config: + enable_deny_public_ip: true + enable_deny_rdp_from_internet: true + enable_deny_subnet_without_nsg: true + enable_deploy_azure_backup_on_vms: true + +# ** vNext ** +# vNext is currently under development and will contain the next version of Terraform providers for CAF ALZ deployment. + +# connectivity: +# hubnetworking: # `hubnetworking` module, add inputs as listed on the module registry where necessary. +# hub_virtual_networks: +# primary: +# name: vnet-hub +# resource_group_name: rg-connectivity +# location: ${default_location} +# address_space: +# - 10.0.0.0/16 +# firewall: +# name: fw-hub +# sku_name: AZFW_VNet +# sku_tier: Standard +# subnet_address_prefix: 10.0.1.0/24 +# virtual_network_gateway: # `vnet-gateway` module, add inputs as listed on the module registry where necessary. +# name: vgw-hub +# sku: VpnGw1 +# type: Vpn +# subnet_address_prefix: 10.0.2.0/24 diff --git a/docs/wiki/examples/starter-module-config/complete/config-vwan.yaml b/docs/wiki/examples/starter-module-config/complete/config-vwan.yaml new file mode 100644 index 0000000..1652712 --- /dev/null +++ b/docs/wiki/examples/starter-module-config/complete/config-vwan.yaml @@ -0,0 +1,229 @@ +# This file contains templated variables to avoid repeating the same hard-coded values. +# Templated variables are denoted by the dollar curly braces token. The following details each templated variable that you can use: +# `default_location`: This is an Azure location sourced from the `default_location` variable. This can be used to set the location of resources. +# `default_postfix`: This is a string sourced from the variable `default_postfix`. This can be used to append to resource names for consistency. +# `root_parent_management_group_id`: This is the id of the management group that the ALZ hierarchy will be nested under. +# `subscription_id_identity`: The subscription ID of the subscription to deploy the identity resources to, sourced from the variable `subscription_id_identity`. +# `subscription_id_connectivity`: The subscription ID of the subscription to deploy the connectivity resources to, sourced from the variable `subscription_id_connectivity`. +# `subscription_id_management`: The subscription ID of the subscription to deploy the management resources to, sourced from the variable `subscription_id_management`. +--- +archetypes: # `caf-enterprise-scale` module, add inputs as listed on the module registry where necessary. + # Base variables + root_name: Contoso + root_id: contoso + subscription_id_connectivity: ${subscription_id_connectivity} + subscription_id_identity: ${subscription_id_identity} + subscription_id_management: ${subscription_id_management} + root_parent_id: ${root_parent_management_group_id} + deploy_core_landing_zones: true + deploy_corp_landing_zones: true + deploy_online_landing_zones: true + default_location: ${default_location} + deploy_management_resources: true + deploy_connectivity_resources: true + deploy_identity_resources: true + disable_telemetry: true + + # Management + configure_management_resources: + location: ${default_location} + settings: + log_analytics: + enabled: true + config: + retention_in_days: 50 + enable_monitoring_for_vm: true + enable_monitoring_for_vmss: true + enable_solution_for_agent_health_assessment: true + enable_solution_for_anti_malware: true + enable_solution_for_change_tracking: true + enable_solution_for_service_map: true + enable_solution_for_sql_assessment: true + enable_solution_for_sql_vulnerability_assessment: true + enable_solution_for_sql_advanced_threat_detection: true + enable_solution_for_updates: true + enable_solution_for_vm_insights: true + enable_solution_for_container_insights: true + enable_sentinel: true + security_center: + enabled: true + config: + email_security_contact: "user@contoso.com" + enable_defender_for_apis: true + enable_defender_for_app_services: true + enable_defender_for_arm: true + enable_defender_for_containers: true + enable_defender_for_cosmosdbs: true + enable_defender_for_cspm: true + enable_defender_for_dns: true + enable_defender_for_key_vault: true + enable_defender_for_oss_databases: true + enable_defender_for_servers: true + enable_defender_for_servers_vulnerability_assessments: true + enable_defender_for_sql_servers: true + enable_defender_for_sql_server_vms: true + enable_defender_for_storage: true + location: ${default_location} + tags: null + advanced: + asc_export_resource_group_name: rg-asc-export + custom_settings_by_resource_type: + azurerm_resource_group: + management: + name: rg-management + azurerm_log_analytics_workspace: + management: + name: log-management + azurerm_automation_account: + management: + name: aa-management + + # Networking + configure_connectivity_resources: + settings: + hub_networks: [] + vwan_hub_networks: + - enabled: true + config: + address_prefix: 10.200.0.0/22 + location: ${default_location} + sku: "" + routes: [] + expressroute_gateway: + enabled: true + config: + scale_unit: 1 + vpn_gateway: + enabled: true + config: + bgp_settings: [] + routing_preference: "" + scale_unit: 1 + azure_firewall: + enabled: false + config: + enable_dns_proxy: true + dns_servers: [] + sku_tier: "Standard" + base_policy_id: "" + private_ip_ranges: [] + threat_intelligence_mode: "" + threat_intelligence_allowlist: {} + availability_zones: + zone_1: true + zone_2: true + zone_3: true + spoke_virtual_network_resource_ids: [] + enable_outbound_virtual_network_peering: true + enable_hub_network_mesh_peering: false + ddos_protection_plan: + enabled: false + config: + location: ${default_location} + dns: + enabled: true + config: + location: null + enable_private_link_by_service: + azure_api_management: true + azure_app_configuration_stores: true + azure_arc: true + azure_automation_dscandhybridworker: true + azure_automation_webhook: true + azure_backup: true + azure_batch_account: true + azure_bot_service_bot: true + azure_bot_service_token: true + azure_cache_for_redis: true + azure_cache_for_redis_enterprise: true + azure_container_registry: true + azure_cosmos_db_cassandra: true + azure_cosmos_db_gremlin: true + azure_cosmos_db_mongodb: true + azure_cosmos_db_sql: true + azure_cosmos_db_table: true + azure_data_explorer: true + azure_data_factory: true + azure_data_factory_portal: true + azure_data_health_data_services: true + azure_data_lake_file_system_gen2: true + azure_database_for_mariadb_server: true + azure_database_for_mysql_server: true + azure_database_for_postgresql_server: true + azure_digital_twins: true + azure_event_grid_domain: true + azure_event_grid_topic: true + azure_event_hubs_namespace: true + azure_file_sync: true + azure_hdinsights: true + azure_iot_dps: true + azure_iot_hub: true + azure_key_vault: true + azure_key_vault_managed_hsm: true + azure_kubernetes_service_management: true + azure_machine_learning_workspace: true + azure_managed_disks: true + azure_media_services: true + azure_migrate: true + azure_monitor: true + azure_purview_account: true + azure_purview_studio: true + azure_relay_namespace: true + azure_search_service: true + azure_service_bus_namespace: true + azure_site_recovery: true + azure_sql_database_sqlserver: true + azure_synapse_analytics_dev: true + azure_synapse_analytics_sql: true + azure_synapse_studio: true + azure_web_apps_sites: true + azure_web_apps_static_sites: true + cognitive_services_account: true + microsoft_power_bi: true + signalr: true + signalr_webpubsub: true + storage_account_blob: true + private_link_locations: + - ${default_location} + public_dns_zones: [] + private_dns_zones: [] + enable_private_dns_zone_virtual_network_link_on_hubs: true + enable_private_dns_zone_virtual_network_link_on_spokes: true + virtual_network_resource_ids_to_link: [] + location: ${default_location} + tags: null + advanced: null + + # Identity + configure_identity_resources: + settings: + identity: + enabled: true + config: + enable_deny_public_ip: true + enable_deny_rdp_from_internet: true + enable_deny_subnet_without_nsg: true + enable_deploy_azure_backup_on_vms: true + +# ** vNext ** +# vNext is currently under development and will contain the next version of Terraform providers for CAF ALZ deployment. + +# connectivity: +# hubnetworking: # `hubnetworking` module, add inputs as listed on the module registry where necessary. +# hub_virtual_networks: +# primary: +# name: vnet-hub +# resource_group_name: rg-connectivity +# location: ${default_location} +# address_space: +# - 10.0.0.0/16 +# firewall: +# name: fw-hub +# sku_name: AZFW_VNet +# sku_tier: Standard +# subnet_address_prefix: 10.0.1.0/24 +# virtual_network_gateway: # `vnet-gateway` module, add inputs as listed on the module registry where necessary. +# name: vgw-hub +# sku: VpnGw1 +# type: Vpn +# subnet_address_prefix: 10.0.2.0/24 diff --git a/docs/wiki/media/ALZ Accelerator Drawings.pptx b/docs/wiki/media/ALZ Accelerator Drawings.pptx new file mode 100644 index 0000000..42a1f1f Binary files /dev/null and b/docs/wiki/media/ALZ Accelerator Drawings.pptx differ diff --git a/docs/wiki/media/ALZLogo.png b/docs/wiki/media/ALZLogo.png new file mode 100644 index 0000000..f831c04 Binary files /dev/null and b/docs/wiki/media/ALZLogo.png differ diff --git a/docs/wiki/media/Logo-Small.png b/docs/wiki/media/Logo-Small.png new file mode 100644 index 0000000..4a641a3 Binary files /dev/null and b/docs/wiki/media/Logo-Small.png differ diff --git a/docs/wiki/media/Logo.png b/docs/wiki/media/Logo.png new file mode 100644 index 0000000..e4e5f66 Binary files /dev/null and b/docs/wiki/media/Logo.png differ diff --git a/docs/wiki/media/MS-Azure_logo_horiz_c-gray_rgb.png b/docs/wiki/media/MS-Azure_logo_horiz_c-gray_rgb.png new file mode 100644 index 0000000..4b1879e Binary files /dev/null and b/docs/wiki/media/MS-Azure_logo_horiz_c-gray_rgb.png differ diff --git a/docs/wiki/media/MS-Azure_logo_horiz_c-white_rgb.png b/docs/wiki/media/MS-Azure_logo_horiz_c-white_rgb.png new file mode 100644 index 0000000..e1204c5 Binary files /dev/null and b/docs/wiki/media/MS-Azure_logo_horiz_c-white_rgb.png differ diff --git a/docs/wiki/media/MS-Azure_logo_horiz_white_rgb.png b/docs/wiki/media/MS-Azure_logo_horiz_white_rgb.png new file mode 100644 index 0000000..a06f050 Binary files /dev/null and b/docs/wiki/media/MS-Azure_logo_horiz_white_rgb.png differ diff --git a/docs/wiki/media/Terraform_PrimaryLogo_ColorWhite_RGB.png b/docs/wiki/media/Terraform_PrimaryLogo_ColorWhite_RGB.png new file mode 100644 index 0000000..b9959ce Binary files /dev/null and b/docs/wiki/media/Terraform_PrimaryLogo_ColorWhite_RGB.png differ diff --git a/docs/wiki/media/Terraform_PrimaryLogo_Color_RGB.png b/docs/wiki/media/Terraform_PrimaryLogo_Color_RGB.png new file mode 100644 index 0000000..2bd59f4 Binary files /dev/null and b/docs/wiki/media/Terraform_PrimaryLogo_Color_RGB.png differ diff --git a/docs/wiki/media/Terraform_PrimaryLogo_White_RGB.png b/docs/wiki/media/Terraform_PrimaryLogo_White_RGB.png new file mode 100644 index 0000000..32f16b6 Binary files /dev/null and b/docs/wiki/media/Terraform_PrimaryLogo_White_RGB.png differ diff --git a/docs/wiki/media/alz-terraform-acclerator.png b/docs/wiki/media/alz-terraform-acclerator.png new file mode 100644 index 0000000..4837c1e Binary files /dev/null and b/docs/wiki/media/alz-terraform-acclerator.png differ diff --git a/docs/wiki/media/azure.svg b/docs/wiki/media/azure.svg new file mode 100644 index 0000000..45e44a9 --- /dev/null +++ b/docs/wiki/media/azure.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/wiki/media/components.png b/docs/wiki/media/components.png new file mode 100644 index 0000000..36fc27d Binary files /dev/null and b/docs/wiki/media/components.png differ diff --git a/docs/wiki/media/ps_black_64.svg b/docs/wiki/media/ps_black_64.svg new file mode 100644 index 0000000..a238b21 --- /dev/null +++ b/docs/wiki/media/ps_black_64.svg @@ -0,0 +1,120 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/docs/wiki/media/starter-module-basic.png b/docs/wiki/media/starter-module-basic.png new file mode 100644 index 0000000..1ada24f Binary files /dev/null and b/docs/wiki/media/starter-module-basic.png differ diff --git a/docs/wiki/media/starter-module-hubnetworking.png b/docs/wiki/media/starter-module-hubnetworking.png new file mode 100644 index 0000000..a772597 Binary files /dev/null and b/docs/wiki/media/starter-module-hubnetworking.png differ diff --git a/docs/wiki/media/variables-archetype_config_overrides-mapping.png b/docs/wiki/media/variables-archetype_config_overrides-mapping.png new file mode 100644 index 0000000..c051d7c Binary files /dev/null and b/docs/wiki/media/variables-archetype_config_overrides-mapping.png differ diff --git a/src/ALZ/Private/Config-Helpers/Add-AvailabilityZonesBicepParameters.ps1 b/src/ALZ/Private/Config-Helpers/Add-AvailabilityZonesBicepParameters.ps1 deleted file mode 100644 index 38a4c60..0000000 --- a/src/ALZ/Private/Config-Helpers/Add-AvailabilityZonesBicepParameters.ps1 +++ /dev/null @@ -1,51 +0,0 @@ -function Add-AvailabilityZonesBicepParameter { - [CmdletBinding(SupportsShouldProcess = $true)] - param ( - [Parameter(Mandatory = $true)] - [Alias("Output")] - [Alias("OutputDirectory")] - [Alias("O")] - [string] $alzEnvironmentDestination, - - [Parameter(Mandatory = $true)] - [PSCustomObject]$configFile - ) - - $parametersConfig = @( - [pscustomobject]@{ - source = "hubNetworking.parameters.all.json"; - parameters = "parAzErGatewayAvailabilityZones,parAzVpnGatewayAvailabilityZones,parAzFirewallAvailabilityZones" - } - [pscustomobject]@{ - source = "vwanConnectivity.parameters.all.json"; - parameters = "parAzFirewallAvailabilityZones" - } - ) - - foreach ($parametersFile in $parametersConfig) { - $parametersFilePath = Join-Path -Path $alzEnvironmentDestination "config\custom-parameters\$($parametersFile.source)" - $region = (Get-Content $parametersFilePath | ConvertFrom-Json).parameters.parLocation.Value - $zones = ($configFile.PsObject.Properties["zonesSupport"].Value | Where-Object { $_.region -eq $region }).zones - $parametersFileJsonContent = Get-Content -Path $parametersFilePath -Raw - $jsonObject = $parametersFileJsonContent | ConvertFrom-Json - $parametersFile.parameters.Split(",") | ForEach-Object { - $parameter = $_ - try { - if ($null -eq $jsonObject.parameters.$parameter.value) { - $jsonObject.parameters.$parameter.value = @($zones) - } - - else { - $jsonObject.parameters.$parameter.value = $zones - } - - } - - catch { - Write-Error -Message "The parameter $parameter does not exist in the file $parametersFilePath" - } - } - $parametersFileJsonContent = $jsonObject | ConvertTo-Json -Depth 10 - Set-Content -Path $parametersFilePath -Value $parametersFileJsonContent - } -} \ No newline at end of file diff --git a/src/ALZ/Private/Config-Helpers/Convert-InterfaceInputToUserInputConfig.ps1 b/src/ALZ/Private/Config-Helpers/Convert-InterfaceInputToUserInputConfig.ps1 index 6a1d2d4..abc5c06 100644 --- a/src/ALZ/Private/Config-Helpers/Convert-InterfaceInputToUserInputConfig.ps1 +++ b/src/ALZ/Private/Config-Helpers/Convert-InterfaceInputToUserInputConfig.ps1 @@ -40,10 +40,15 @@ function Convert-InterfaceInputToUserInputConfig { $starterModuleConfigurationInstance = [PSCustomObject]@{} $starterModuleConfigurationInstance | Add-Member -NotePropertyName "Order" -NotePropertyValue $order $starterModuleConfigurationInstance | Add-Member -NotePropertyName "Type" -NotePropertyValue $inputType - $starterModuleConfigurationInstance | Add-Member -NotePropertyName "Value" -NotePropertyValue "" $starterModuleConfigurationInstance | Add-Member -NotePropertyName "DataType" -NotePropertyValue $dataType $starterModuleConfigurationInstance | Add-Member -NotePropertyName "Sensitive" -NotePropertyValue $sensitive + if($variable.Value.PSObject.Properties.Name -contains "Value") { + $starterModuleConfigurationInstance | Add-Member -NotePropertyName "Value" -NotePropertyValue $variable.Value.Value + } else { + $starterModuleConfigurationInstance | Add-Member -NotePropertyName "Value" -NotePropertyValue "" + } + if($variable.Value.PSObject.Properties.Name -contains "default") { $defaultValue = $variable.Value.default $starterModuleConfigurationInstance | Add-Member -NotePropertyName "DefaultValue" -NotePropertyValue $defaultValue @@ -63,6 +68,10 @@ function Convert-InterfaceInputToUserInputConfig { $starterModuleConfigurationInstance | Add-Member -NotePropertyName "Validator" -NotePropertyValue $validationType } + if($variable.Value.PSObject.Properties.Name -contains "Targets") { + $starterModuleConfigurationInstance | Add-Member -NotePropertyName "Targets" -NotePropertyValue $variable.Value.Targets + } + $starterModuleConfigurationInstance | Add-Member -NotePropertyName "Description" -NotePropertyValue $description $starterModuleConfiguration | Add-Member -NotePropertyName $variable.Name -NotePropertyValue $starterModuleConfigurationInstance } diff --git a/src/ALZ/Private/Legacy-Bicep/Edit-ALZConfigurationFilesInPlace.ps1 b/src/ALZ/Private/Config-Helpers/Edit-ALZConfigurationFilesInPlace.ps1 similarity index 79% rename from src/ALZ/Private/Legacy-Bicep/Edit-ALZConfigurationFilesInPlace.ps1 rename to src/ALZ/Private/Config-Helpers/Edit-ALZConfigurationFilesInPlace.ps1 index 800f022..45c9fec 100644 --- a/src/ALZ/Private/Legacy-Bicep/Edit-ALZConfigurationFilesInPlace.ps1 +++ b/src/ALZ/Private/Config-Helpers/Edit-ALZConfigurationFilesInPlace.ps1 @@ -1,6 +1,5 @@ function Edit-ALZConfigurationFilesInPlace { param( - [Parameter(Mandatory = $false)] [Alias("Output")] [Alias("OutputDirectory")] @@ -20,20 +19,23 @@ function Edit-ALZConfigurationFilesInPlace { } foreach ($file in $files) { + Write-Verbose "Checking Bicep parameter file: $($file.Name)" $bicepConfiguration = Get-Content $file.FullName | ConvertFrom-Json -AsHashtable $modified = $false foreach ($configKey in $configuration.PsObject.Properties) { foreach ($target in $configKey.Value.Targets) { # Is this configuration value for this file? - $targetedAtThisFile = $null -eq $target.File -or $target.File -eq $file.Name + $targetedAtThisFile = $target.Destination -eq "Parameters" -and ($null -eq $target.File -or $target.File -eq $file.Name) if ($targetedAtThisFile -eq $false) { continue } + Write-Verbose "Attempting to update $($target.Name) in $($file.Name) with '$($configKey.Value.Value)' from $($configKey.Name)" + # Find the appropriate item which will be changed in the Bicep file. # Remove array '[' ']' characters so we can use the index value direct. - $propertyNames = $target.Name -replace "\[|\]","" -split "\." + $propertyNames = $target.Name.Replace("[", ".").Replace("]", "").Replace("..", ".") -split "\." $bicepConfigNode = $bicepConfiguration.parameters $index = 0 @@ -64,6 +66,7 @@ function Edit-ALZConfigurationFilesInPlace { # If we're here, we can modify this file and we've got an actual object specified by the Name path value - and we can modify values on it. if ($target.Destination -eq "Parameters" -and $null -ne $bicepConfigNode) { $leafPropertyName = $propertyNames[-1] + Write-Verbose "Updating $($target.Name) in $($file.Name) with '$($configKey.Value.Value)' from $($configKey.Name)" $bicepConfigNode[$leafPropertyName] = $configKey.Value.Value $modified = $true } @@ -71,8 +74,8 @@ function Edit-ALZConfigurationFilesInPlace { } if ($true -eq $modified) { - Write-Verbose $file.FullName - $bicepConfiguration | ConvertTo-Json -Depth 10 | Out-File $file.FullName + Write-Verbose "Updating Bicep parameter file: $($file.Name)" + ConvertTo-Json $bicepConfiguration -Depth 10 | Out-File $file.FullName } } } diff --git a/src/ALZ/Private/Legacy-Bicep/Format-TokenizedConfigurationString.ps1 b/src/ALZ/Private/Config-Helpers/Format-TokenizedConfigurationString.ps1 similarity index 100% rename from src/ALZ/Private/Legacy-Bicep/Format-TokenizedConfigurationString.ps1 rename to src/ALZ/Private/Config-Helpers/Format-TokenizedConfigurationString.ps1 diff --git a/src/ALZ/Private/Config-Helpers/Get-AvailabilityZonesSupport.ps1 b/src/ALZ/Private/Config-Helpers/Get-AvailabilityZonesSupport.ps1 new file mode 100644 index 0000000..4095ff0 --- /dev/null +++ b/src/ALZ/Private/Config-Helpers/Get-AvailabilityZonesSupport.ps1 @@ -0,0 +1,15 @@ +function Get-AvailabilityZonesSupport { + [OutputType([string[]])] + param ( + [Parameter(Mandatory = $true)] + [string] $region, + + [Parameter(Mandatory = $true)] + [PSCustomObject]$zonesSupport + ) + + $zone = $zonesSupport | Where-Object { $_.region -eq $region } + $jsonZones = ConvertTo-Json $zone.zones -Depth 10 + Write-Verbose "Zones for $region are $jsonZones" + return $zone.zones +} \ No newline at end of file diff --git a/src/ALZ/Private/Config-Helpers/Remove-UnrequiredFileSet.ps1 b/src/ALZ/Private/Config-Helpers/Remove-UnrequiredFileSet.ps1 new file mode 100644 index 0000000..ebb72a5 --- /dev/null +++ b/src/ALZ/Private/Config-Helpers/Remove-UnrequiredFileSet.ps1 @@ -0,0 +1,77 @@ +function Remove-UnrequiredFileSet { + [CmdletBinding(SupportsShouldProcess = $true)] + param ( + [Parameter(Mandatory = $false)] + [string]$path, + [Parameter(Mandatory = $false)] + [array]$foldersOrFilesToRetain = @(), + [Parameter(Mandatory = $false)] + [array]$subFoldersOrFilesToRemove = @(), + [Parameter(Mandatory = $false)] + [switch]$writeVerboseLogs + ) + + if($PSCmdlet.ShouldProcess("Remove files", "modify")) { + if($foldersOrFilesToRetain.Length -eq 0 -and $subFoldersOrFilesToRemove.Length -eq 0) { + Write-Verbose "No folders or files to retain specified, so not removing aything from $path" + return + } + + $files = Get-ChildItem -Path $path -File -Recurse -Force + $filesToRetain = @() + + foreach ($file in $files) { + $fileRelativePath = $file.FullName.Replace($path, "").Replace("\", "/").TrimStart("/") + $folderRelativePath = $file.Directory.FullName.Replace($path, "").Replace("\", "/").TrimStart("/") + foreach ($folderOrFileToRetain in $foldersOrFilesToRetain) { + # If we have an exact match of the file name and path, always retain it. + if($folderOrFileToRetain.TrimStart("./") -eq $fileRelativePath) { + if($writeVerboseLogs) { + Write-Verbose "Exact Match - Retaining: $fileRelativePath at $($file.FullName)" + } + $filesToRetain += $file.FullName + continue + } + + # If we match on a pattern, take into account the subfolders or files to remove. + if ($fileRelativePath -like "$folderOrFileToRetain*") { + $skipFile = $false + foreach($subfolderOrFileToRemove in $subFoldersOrFilesToRemove) { + if ($file.Name -eq $subfolderOrFileToRemove -or $file.Directory.Name -eq $subfolderOrFileToRemove -or $fileRelativePath.EndsWith("/$subfolderOrFileToRemove") -or $folderRelativePath.EndsWith("/$subfolderOrFileToRemove")) { + $skipFile = $true + } + } + + if(!$skipFile) { + if($writeVerboseLogs) { + Write-Verbose "Pattern Match - Retaining: $fileRelativePath at $($file.FullName)" + } + $filesToRetain += $file.FullName + } + } + } + } + + foreach($file in $files) { + if($filesToRetain -notcontains $file.FullName) { + if($writeVerboseLogs) { + Write-Verbose "Removing: $($file.FullName)" + } + Remove-Item -Path $file.FullName -Force | Out-Null + } + } + + $folders = Get-ChildItem -Path $path -Directory -Recurse -Force + foreach($folder in $folders) { + if(Test-Path $folder.FullName) { + $folderItems = Get-ChildItem -Path $folder.FullName -Recurse -File -Force + if($folderItems.Count -eq 0) { + if($writeVerboseLogs) { + Write-Verbose "Removing empty folder: $($folder.FullName)" + } + Remove-Item -Path $folder.FullName -Force -Recurse | Out-Null + } + } + } + } +} \ No newline at end of file diff --git a/src/ALZ/Private/Config-Helpers/Request-ALZEnvironmentConfig.ps1 b/src/ALZ/Private/Config-Helpers/Request-ALZEnvironmentConfig.ps1 index 621843d..936c92b 100644 --- a/src/ALZ/Private/Config-Helpers/Request-ALZEnvironmentConfig.ps1 +++ b/src/ALZ/Private/Config-Helpers/Request-ALZEnvironmentConfig.ps1 @@ -39,17 +39,7 @@ function Request-ALZEnvironmentConfig { if($userInputDefaultOverrides -ne $null) { $hasDefaultOverrides = $true $useDefaults = "" - if($hasInputOverrides) { - Write-InformationColored "We found you have cached values from a previous run, but have also supplied inputs." -ForegroundColor Yellow -InformationAction Continue - if($autoApprove) { - $useDefaults = "skip" - } else { - $useDefaults = Read-Host "Would you like to use the cached values or use the inputs you have supplied intead? Enter 'use' to use the cached value or just hit 'enter' to use your inputs. (use/skip)" - } - if($useDefaults.ToLower() -eq "use") { - $userInputOverrides = $userInputDefaultOverrides - } - } else { + if(!$hasInputOverrides) { Write-InformationColored "We found you have cached values from a previous run." -ForegroundColor Yellow -InformationAction Continue if($autoApprove) { $useDefaults = "use" @@ -83,7 +73,7 @@ function Request-ALZEnvironmentConfig { if ($configurationValue.Value.Type -eq "UserInput") { # Check for and add cached as default - if($hasDefaultOverrides) { + if(!$hasInputOverrides -and $hasDefaultOverrides) { $defaultOverride = $userInputDefaultOverrides.PsObject.Properties | Where-Object { $_.Name -eq $configurationValue.Name } if($null -ne $defaultOverride) { if(!($configurationValue.Value.PSObject.Properties.Name -match "DefaultValue")) { @@ -100,7 +90,13 @@ function Request-ALZEnvironmentConfig { if($null -ne $userInputOverride) { $configurationValue.Value.Value = $userInputOverride.Value } else { - Request-ConfigurationValue -configName $configurationValue.Name -configValue $configurationValue.Value -treatEmptyDefaultAsValid $treatEmptyDefaultAsValid + if($configurationValue.Value.PSObject.Properties.Name -match "DefaultValue") { + Write-Verbose "Input not supplied, so using default value of $($configurationValue.Value.DefaultValue) for $($configurationValue.Name)" + $configurationValue.Value.Value = $configurationValue.Value.DefaultValue + } else { + Write-Verbose "Input not supplied, and no default for $($configurationValue.Name), so prompting for input..." + Request-ConfigurationValue -configName $configurationValue.Name -configValue $configurationValue.Value -treatEmptyDefaultAsValid $treatEmptyDefaultAsValid + } } } else { Request-ConfigurationValue -configName $configurationValue.Name -configValue $configurationValue.Value -treatEmptyDefaultAsValid $treatEmptyDefaultAsValid diff --git a/src/ALZ/Private/Config-Helpers/Request-ConfigurationValue.ps1 b/src/ALZ/Private/Config-Helpers/Request-ConfigurationValue.ps1 index f8b6615..12eedb0 100644 --- a/src/ALZ/Private/Config-Helpers/Request-ConfigurationValue.ps1 +++ b/src/ALZ/Private/Config-Helpers/Request-ConfigurationValue.ps1 @@ -33,6 +33,9 @@ function Request-ConfigurationValue { Write-InformationColored "[allowed: $allowedValues] " -ForegroundColor Yellow -InformationAction Continue } + $attempt = 0 + $maxAttempts = 10 + do { Write-InformationColored "$($configName) " -ForegroundColor Yellow -NoNewline -InformationAction Continue if ($hasDefaultValue) { @@ -71,6 +74,7 @@ function Request-ConfigurationValue { if($skipValidationForEmptyDefault) { $isNotValid = $false } else { + Write-Verbose "Checking '$($configValue.Value)' against '$($configValue.Valid)'" $isNotValid = $hasValidator -and $configValue.Value -match $configValue.Valid -eq $false } @@ -81,10 +85,13 @@ function Request-ConfigurationValue { } $shouldRetry = $validationError -and $withRetries - } - while ( - ($hasNotSpecifiedValue -or $isDisallowedValue -or $isNotValid) -and $shouldRetry) + $attempt += 1 + } + while (($hasNotSpecifiedValue -or $isDisallowedValue -or $isNotValid) -and $shouldRetry -and $attempt -lt $maxAttempts) - Write-InformationColored "" -InformationAction Continue + if($attempt -eq $maxAttempts) { + Write-InformationColored "Max attempts reached for getting input value. Exiting..." -ForegroundColor Red -InformationAction Continue + throw "Max attempts reached for getting input value. Exiting..." + } } diff --git a/src/ALZ/Private/Legacy-Bicep/Set-ComputedConfiguration.ps1 b/src/ALZ/Private/Config-Helpers/Set-ComputedConfiguration.ps1 similarity index 95% rename from src/ALZ/Private/Legacy-Bicep/Set-ComputedConfiguration.ps1 rename to src/ALZ/Private/Config-Helpers/Set-ComputedConfiguration.ps1 index 1dbadf9..75b8fb0 100644 --- a/src/ALZ/Private/Legacy-Bicep/Set-ComputedConfiguration.ps1 +++ b/src/ALZ/Private/Config-Helpers/Set-ComputedConfiguration.ps1 @@ -8,7 +8,7 @@ function Set-ComputedConfiguration { if ($PSCmdlet.ShouldProcess("ALZ-Bicep computed configuration.", "calculate computed values")) { foreach ($configKey in $configuration.PsObject.Properties) { - if ($configKey.Value.Type -ne "Computed") { + if (@("ComputedInput", "Computed") -notcontains $configKey.Value.Type) { continue; } diff --git a/src/ALZ/Private/Config-Helpers/Write-JsonFile.ps1 b/src/ALZ/Private/Config-Helpers/Write-JsonFile.ps1 new file mode 100644 index 0000000..572687f --- /dev/null +++ b/src/ALZ/Private/Config-Helpers/Write-JsonFile.ps1 @@ -0,0 +1,30 @@ +function Write-JsonFile { + [CmdletBinding(SupportsShouldProcess = $true)] + param ( + [Parameter(Mandatory = $false)] + [string] $jsonFilePath, + + [Parameter(Mandatory = $false)] + [PSObject] $configuration + ) + + if ($PSCmdlet.ShouldProcess("Download Terraform Tools", "modify")) { + + if(Test-Path $jsonFilePath) { + Remove-Item -Path $jsonFilePath + } + + $environmentVariables = @{} + + foreach ($configKey in $configuration.PsObject.Properties) { + foreach ($target in $configKey.Value.Targets) { + if($target.Destination -eq "Environment") { + $environmentVariables.$($target.Name) = $configKey.Value.Value + } + } + } + + $json = ConvertTo-Json -InputObject $environmentVariables -Depth 10 + $json | Out-File -FilePath $jsonFilePath + } +} \ No newline at end of file diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/Copy-ParameterFileCollection.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/Copy-ParameterFileCollection.ps1 new file mode 100644 index 0000000..f730dc0 --- /dev/null +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/Copy-ParameterFileCollection.ps1 @@ -0,0 +1,26 @@ +function Copy-ParametersFileCollection { + [CmdletBinding(SupportsShouldProcess = $true)] + param ( + [Parameter(Mandatory = $true)] + [string] $starterPath, + + [Parameter(Mandatory = $true)] + [array]$configFiles + ) + foreach ($configFile in $configFiles) { + $sourcePath = Join-Path $starterPath $configFile.templateParametersSourceFilePath + $destinationPath = Join-Path $starterPath $configFile.templateParametersFilePath + if (Test-Path $sourcePath) { + if ($PSCmdlet.ShouldProcess($sourcePath, "Copy")) { + # create destination folder if it does not exists + $destinationFolder = Split-Path -Path $destinationPath -Parent + if (-not (Test-Path $destinationFolder)) { + New-Item -ItemType Directory -Path $destinationFolder -Force | Out-String | Write-Verbose + } + Copy-Item -Path $sourcePath -Destination $destinationPath -Recurse -Force | Out-String | Write-Verbose + } + } else { + Write-Warning "The file $sourcePath does not exist." + } + } +} \ No newline at end of file diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 index 163f7ac..e2046cc 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 @@ -18,12 +18,12 @@ function Get-BootstrapAndStarterConfig { $hasStarterModule = $false $starterModuleUrl = "" $starterModuleSourceFolder = "" - $starterReleaseTag = "" $starterReleaseArtifactName = "" $starterConfigFilePath = "" $bootstrapDetails = $null $validationConfig = $null + $zonesSupport = $null $inputConfig = $null # Get the bootstap configuration @@ -31,6 +31,7 @@ function Get-BootstrapAndStarterConfig { Write-Verbose "Bootstrap config path $bootstrapConfigFullPath" $bootstrapConfig = Get-ALZConfig -configFilePath $bootstrapConfigFullPath $validationConfig = $bootstrapConfig.validators + $zonesSupport = $bootstrapConfig.zonesSupport # Get the available bootstrap modules $bootstrapModules = $bootstrapConfig.bootstrap_modules @@ -77,10 +78,10 @@ function Get-BootstrapAndStarterConfig { hasStarterModule = $hasStarterModule starterModuleUrl = $starterModuleUrl starterModuleSourceFolder = $starterModuleSourceFolder - starterReleaseTag = $starterReleaseTag starterReleaseArtifactName = $starterReleaseArtifactName starterConfigFilePath = $starterConfigFilePath validationConfig = $validationConfig + zonesSupport = $zonesSupport inputConfig = $inputConfig } } diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/Invoke-Terraform.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/Invoke-Terraform.ps1 index b067e71..8b6bc3d 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/Invoke-Terraform.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/Invoke-Terraform.ps1 @@ -21,20 +21,100 @@ function Invoke-Terraform { $action = "destroy" } - Write-InformationColored "Terraform init has completed, now running the $action..." -ForegroundColor Green -InformationAction Continue + Write-InformationColored "Terraform init has completed, now running the $action..." -ForegroundColor Green -NewLineBefore -InformationAction Continue - if($destroy) { - if($autoApprove) { - terraform -chdir="$moduleFolderPath" destroy -var-file="$tfvarsFileName" -auto-approve - } else { - terraform -chdir="$moduleFolderPath" destroy -var-file="$tfvarsFileName" + $planFileName = "tfplan" + + # Start timer + $StopWatch = New-Object -TypeName System.Diagnostics.Stopwatch + $StopWatch.Start() + + $command = "terraform" + $arguments = @() + $arguments += "-chdir=$moduleFolderPath" + $arguments += "plan" + $arguments += "-out=$planFileName" + $arguments += "-input=false" + $arguments += "-var-file=$tfvarsFileName" + + if ($destroy) { + $arguments += "-destroy" + } + + Write-InformationColored "Running Plan Command for $action : $command $arguments" -ForegroundColor Green -NewLineBefore -InformationAction Continue + & $command $arguments + + $exitCode = $LASTEXITCODE + + # Stop and display timer + $StopWatch.Stop() + Write-InformationColored "Time taken to complete Terraform plan:" -ForegroundColor Green -NewLineBefore -InformationAction Continue + $StopWatch.Elapsed | Format-Table + + if($exitCode -ne 0) { + Write-InformationColored "Terraform plan for $action failed with exit code $exitCode. Please review the error and try again or raise an issue." -ForegroundColor Red -NewLineBefore -InformationAction Continue + throw "Terraform plan failed with exit code $exitCode. Please review the error and try again or raise an issue." + } + + if(!$autoApprove) { + Write-InformationColored "Terraform plan has completed, please review the plan and confirm you wish to continue." -ForegroundColor Yellow -NewLineBefore -InformationAction Continue + $choices = [System.Management.Automation.Host.ChoiceDescription[]] @("&Yes", "&No") + $message = "Please confirm you wish to apply the plan." + $title = "Confirm Terraform plan" + $resultIndex = $host.ui.PromptForChoice($title, $message, $choices, 0) + if($resultIndex -eq 1) { + Write-InformationColored "You have chosen not to apply the plan. Exiting..." -ForegroundColor Red -NewLineBefore -InformationAction Continue + return } - } else { - if($autoApprove) { - terraform -chdir="$moduleFolderPath" apply -var-file="$tfvarsFileName" -auto-approve - } else { - terraform -chdir="$moduleFolderPath" apply -var-file="$tfvarsFileName" + } + + # Start timer + $StopWatch = New-Object -TypeName System.Diagnostics.Stopwatch + $StopWatch.Start() + + $command = "terraform" + $arguments = @() + $arguments += "-chdir=$moduleFolderPath" + $arguments += "apply" + $arguments += "-auto-approve" + $arguments += "-input=false" + $arguments += "$planFileName" + + Write-InformationColored "Running Apply Command for $action : $command $arguments" -ForegroundColor Green -NewLineBefore -InformationAction Continue + & $command $arguments + + $exitCode = $LASTEXITCODE + + $currentAttempt = 0 + $maxAttempts = 5 + + while($exitCode -ne 0 -and $currentAttempt -lt $maxAttempts) { + Write-InformationColored "Terraform $action failed with exit code $exitCode. This is likely a transient issue, so we are retrying..." -ForegroundColor Yellow -NewLineBefore -InformationAction Continue + $currentAttempt++ + $command = "terraform" + $arguments = @() + $arguments += "-chdir=$moduleFolderPath" + $arguments += "apply" + $arguments += "-auto-approve" + $arguments += "-input=false" + $arguments += "-var-file=$tfvarsFileName" + if ($destroy) { + $arguments += "-destroy" } + + Write-InformationColored "Running Apply Command for $action : $command $arguments" -ForegroundColor Green -NewLineBefore -InformationAction Continue + & $command $arguments + $exitCode = $LASTEXITCODE + } + + # Stop and display timer + $StopWatch.Stop() + Write-InformationColored "Time taken to complete Terraform apply:" -ForegroundColor Green -NewLineBefore -InformationAction Continue + $StopWatch.Elapsed | Format-Table + + if($exitCode -ne 0) { + Write-InformationColored "Terraform $action failed with exit code $exitCode after $maxAttempts attempts. Please review the error and try again or raise an issue." -ForegroundColor Red -NewLineBefore -InformationAction Continue + throw "Terraform $action failed with exit code $exitCode after $maxAttempts attempts. Please review the error and try again or raise an issue." } } } \ No newline at end of file diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/Invoke-Upgrade.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/Invoke-Upgrade.ps1 index 4c30ed9..164f660 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/Invoke-Upgrade.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/Invoke-Upgrade.ps1 @@ -53,15 +53,23 @@ function Invoke-Upgrade { } if($foundPreviousRelease) { - $upgrade = "" + $upgrade = $true if($autoApprove) { - $upgrade = "upgrade" + $upgrade = $true } else { - Write-InformationColored "AUTOMATIC UPGRADE: We found version $previousVersion of the $moduleType module that has been previously run. You can upgrade from this version to the new version $currentVersion" -NewLineBefore -ForegroundColor Yellow -InformationAction Continue - $upgrade = Read-Host "If you would like to upgrade, enter 'upgrade' or just hit 'enter' to continue with a new environment. (upgrade/exit)" + Write-InformationColored "AUTOMATIC UPGRADE: We found version $previousVersion of the $moduleType module that has been previously run. You can migrate your settings and state from this version to the new version $currentVersion" -NewLineBefore -ForegroundColor Yellow -InformationAction Continue + $choices = [System.Management.Automation.Host.ChoiceDescription[]] @("&Yes", "&No") + $message = "Please confirm you wish to migrate your previous settings and state to the new version." + $title = "Confirm migrate settings and state" + $resultIndex = $host.ui.PromptForChoice($title, $message, $choices, 0) + + if($resultIndex -eq 1) { + Write-InformationColored "You have chosen not to migrate your settings and state. Please note that your state file is still in the folder for the previous version if this was a mistake." -ForegroundColor Yellow -NewLineBefore -InformationAction Continue + $upgrade = $false + } } - if($upgrade.ToLower() -eq "upgrade") { + if($upgrade) { $currentPath = Join-Path $targetDirectory $release $currentCachedValuesPath = Join-Path $currentPath $targetFolder $cacheFileName diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 index 55b1e0a..0b29ddd 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 @@ -38,7 +38,20 @@ function New-Bootstrap { [switch] $autoApprove, [Parameter(Mandatory = $false)] - [switch] $destroy + [switch] $destroy, + + [Parameter(Mandatory = $false)] + [string] $starter = "", + + [Parameter(Mandatory = $false)] + [PSCustomObject] $zonesSupport = $null, + + [Parameter(Mandatory = $false)] + [hashtable] $computedInputs, + + [Parameter(Mandatory = $false, HelpMessage = "An extra level of logging that is turned off by default for easier debugging.")] + [switch] + $writeVerboseLogs ) if ($PSCmdlet.ShouldProcess("ALZ-Terraform module configuration", "modify")) { @@ -78,11 +91,12 @@ function New-Bootstrap { $starterCachedConfig = Get-ALZConfig -configFilePath $starterCachePath # Get starter module - $starter = "" $starterModulePath = "" if($hasStarter) { - $starter = Request-SpecialInput -type "starter" -starterConfig $starterConfig -userInputOverrides $userInputOverrides + if($starter -eq "") { + $starter = Request-SpecialInput -type "starter" -starterConfig $starterConfig -userInputOverrides $userInputOverrides + } Write-Verbose "Selected Starter: $starter" @@ -113,8 +127,14 @@ function New-Bootstrap { $starterParameters = [PSCustomObject]@{} if($hasStarter) { - $targetVariableFilePath = Join-Path -Path $starterModulePath -ChildPath "variables.tf" - $starterParameters = Convert-HCLVariablesToUserInputConfig -targetVariableFile $targetVariableFilePath -hclParserToolPath $hclParserToolPath -validators $validationConfig + if($iac -eq "terraform") { + $targetVariableFilePath = Join-Path -Path $starterModulePath -ChildPath "variables.tf" + $starterParameters = Convert-HCLVariablesToUserInputConfig -targetVariableFile $targetVariableFilePath -hclParserToolPath $hclParserToolPath -validators $validationConfig + } + + if($iac -eq "bicep") { + $starterParameters = Convert-InterfaceInputToUserInputConfig -inputConfig $starterConfig.starter_modules.$starter -validators $validationConfig + } } # Filter interface inputs if not in bootstrap or starter @@ -167,17 +187,21 @@ function New-Bootstrap { -autoApprove:$autoApprove.IsPresent # Set computed interface inputs - $computedInputMapping = @{ - "iac_type" = $iac - "module_folder_path" = $starterModulePath - } + $computedInputs["starter_module_name"] = $starter + $computedInputs["module_folder_path"] = $starterModulePath + $computedInputs["availability_zones_bootstrap"] = @(Get-AvailabilityZonesSupport -region $interfaceConfiguration.bootstrap_location.Value -zonesSupport $zonesSupport) + $computedInputs["availability_zones_starter"] = @(Get-AvailabilityZonesSupport -region $interfaceConfiguration.starter_location.Value -zonesSupport $zonesSupport) foreach($inputConfigItem in $inputConfig.inputs.PSObject.Properties) { if($inputConfigItem.Value.source -eq "powershell") { - $inputVariable = $interfaceConfiguration.PSObject.Properties | Where-Object { $_.Name -eq $inputConfigItem.Name } - $inputValue = $computedInputMapping[$inputConfigItem.Name] - Write-Verbose "Setting $($inputConfigItem.Name) to $inputValue" + $inputValue = $computedInputs[$inputConfigItem.Name] + if($inputValue -is [array]) { + $jsonInputValue = ConvertTo-Json $inputValue -Depth 10 + Write-Verbose "Setting computed interface input array $($inputConfigItem.Name) to $jsonInputValue" + } else { + Write-Verbose "Setting computed interface input string $($inputConfigItem.Name) to $inputValue" + } $inputVariable.Value.Value = $inputValue } } @@ -191,8 +215,20 @@ function New-Bootstrap { if("bootstrap" -in $inputConfigItem.Value.maps_to) { $bootstrapComputed | Add-Member -NotePropertyName $inputVariable.Name -NotePropertyValue $inputVariable.Value } + if("starter" -in $inputConfigItem.Value.maps_to) { - $starterComputed | Add-Member -NotePropertyName $inputVariable.Name -NotePropertyValue $inputVariable.Value + if($iac -eq "terraform") { + $starterComputed | Add-Member -NotePropertyName $inputVariable.Name -NotePropertyValue $inputVariable.Value + } + + if($iac -eq "bicep") { + if($inputConfigItem.Value.PSObject.Properties.Name -contains "bicep_alias") { + Write-Verbose "Setting computed bicep alias $($inputConfigItem.Value.bicep_alias)" + $starterComputed | Add-Member -NotePropertyName $inputConfigItem.Value.bicep_alias -NotePropertyValue $inputVariable.Value + } else { + $starterComputed | Add-Member -NotePropertyName $inputVariable.Name -NotePropertyValue $inputVariable.Value + } + } } } @@ -221,8 +257,33 @@ function New-Bootstrap { # Creating the tfvars files for the bootstrap and starter module $bootstrapTfvarsPath = Join-Path -Path $bootstrapModulePath -ChildPath "override.tfvars" $starterTfvarsPath = Join-Path -Path $starterModulePath -ChildPath "terraform.tfvars" + $starterBicepVarsPath = Join-Path -Path $starterModulePath -ChildPath "parameters.json" Write-TfvarsFile -tfvarsFilePath $bootstrapTfvarsPath -configuration $bootstrapConfiguration - Write-TfvarsFile -tfvarsFilePath $starterTfvarsPath -configuration $starterConfiguration + + if($iac -eq "terraform") { + Write-TfvarsFile -tfvarsFilePath $starterTfvarsPath -configuration $starterConfiguration + } + + if($iac -eq "bicep") { + Copy-ParametersFileCollection -starterPath $starterModulePath -configFiles $starterConfig.starter_modules.$starter.deployment_files + Set-ComputedConfiguration -configuration $starterConfiguration + Edit-ALZConfigurationFilesInPlace -alzEnvironmentDestination $starterModulePath -configuration $starterConfiguration + Write-JsonFile -jsonFilePath $starterBicepVarsPath -configuration $starterConfiguration + + # Remove unrequired files + $foldersOrFilesToRetain = $starterConfig.starter_modules.$starter.folders_or_files_to_retain + $foldersOrFilesToRetain += "parameters.json" + $foldersOrFilesToRetain += "config" + $foldersOrFilesToRetain += "starter-cache.json" + + foreach($deployment_file in $starterConfig.starter_modules.$starter.deployment_files) { + $foldersOrFilesToRetain += $deployment_file.templateParametersSourceFilePath + } + + $subFoldersOrFilesToRemove = $starterConfig.starter_modules.$starter.subfolders_or_files_to_remove + + Remove-UnrequiredFileSet -path $starterModulePath -foldersOrFilesToRetain $foldersOrFilesToRetain -subFoldersOrFilesToRemove $subFoldersOrFilesToRemove -writeVerboseLogs:$writeVerboseLogs.IsPresent + } # Caching the bootstrap and starter module values paths for retry / upgrade scenarios Write-ConfigurationCache -filePath $interfaceCachePath -configuration $interfaceConfiguration @@ -235,8 +296,10 @@ function New-Bootstrap { if($autoApprove) { Invoke-Terraform -moduleFolderPath $bootstrapModulePath -tfvarsFileName "override.tfvars" -autoApprove -destroy:$destroy.IsPresent } else { - Write-InformationColored "Once the plan is complete you will be prompted to confirm the apply. You must enter 'yes' to apply." -ForegroundColor Green -NewLineBefore -InformationAction Continue + Write-InformationColored "Once the plan is complete you will be prompted to confirm the apply." -ForegroundColor Green -NewLineBefore -InformationAction Continue Invoke-Terraform -moduleFolderPath $bootstrapModulePath -tfvarsFileName "override.tfvars" -destroy:$destroy.IsPresent } + + Write-InformationColored "Bootstrap has completed successfully! Thanks for using our tool. Head over to Phase 3 in the documentation to continue..." -ForegroundColor Green -NewLineBefore -InformationAction Continue } } \ No newline at end of file diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-FolderStructure.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-FolderStructure.ps1 index d0cc631..a3eedc4 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-FolderStructure.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-FolderStructure.ps1 @@ -20,7 +20,10 @@ function New-FolderStructure { [string] $sourceFolder, [Parameter(Mandatory = $false)] - [string] $overrideSourceDirectoryPath = "" + [string] $overrideSourceDirectoryPath = "", + + [Parameter(Mandatory = $false)] + [switch] $replaceFiles ) if ($PSCmdlet.ShouldProcess("ALZ-Terraform module configuration", "modify")) { @@ -37,11 +40,13 @@ function New-FolderStructure { $releaseTag = "local" $path = Join-Path $targetDirectory $targetFolder $releaseTag - if(Test-Path $path) { + if((Test-Path $path) -and !$replaceFiles) { Write-Verbose "Folder $path already exists, so not copying files." } else { Write-InformationColored "Copying files from $overrideSourceDirectoryPath to $path" -ForegroundColor Green -InformationAction Continue - New-Item -Path $path -ItemType "Directory" + if(!(Test-Path $path)) { + New-Item -Path $path -ItemType "Directory" + } Copy-Item -Path "$overrideSourceDirectoryPath/$sourceFolder/*" -Destination "$path" -Recurse -Force | Out-String | Write-Verbose } diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-ModuleSetup.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-ModuleSetup.ps1 index c04b3b0..cd59b4d 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-ModuleSetup.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-ModuleSetup.ps1 @@ -17,7 +17,9 @@ function New-ModuleSetup { [Parameter(Mandatory = $false)] [string]$moduleOverrideFolderPath, [Parameter(Mandatory = $false)] - [bool]$skipInternetChecks + [bool]$skipInternetChecks, + [Parameter(Mandatory = $false)] + [switch]$replaceFiles ) if ($PSCmdlet.ShouldProcess("Check and get module", "modify")) { @@ -33,7 +35,8 @@ function New-ModuleSetup { -releaseArtifactName $releaseArtifactName ` -targetFolder $targetFolder ` -sourceFolder $sourceFolder ` - -overrideSourceDirectoryPath $moduleOverrideFolderPath + -overrideSourceDirectoryPath $moduleOverrideFolderPath ` + -replaceFiles:$replaceFiles.IsPresent } return $versionAndPath } diff --git a/src/ALZ/Private/Legacy-Bicep/Add-AvailabilityZonesBicepParameters.ps1 b/src/ALZ/Private/Legacy-Bicep/Add-AvailabilityZonesBicepParameters.ps1 new file mode 100644 index 0000000..503959a --- /dev/null +++ b/src/ALZ/Private/Legacy-Bicep/Add-AvailabilityZonesBicepParameters.ps1 @@ -0,0 +1,88 @@ +function Add-AvailabilityZonesBicepParameter { + [CmdletBinding(SupportsShouldProcess = $true)] + param ( + [Parameter(Mandatory = $true)] + [Alias("Output")] + [Alias("OutputDirectory")] + [Alias("O")] + [string] $alzEnvironmentDestination, + + [Parameter(Mandatory = $true)] + [PSCustomObject]$zonesSupport + ) + + $parametersConfig = @( + [pscustomobject]@{ + source = "hubNetworking.parameters.all.json"; + parameters = @( + "parAzErGatewayAvailabilityZones.value", + "parAzVpnGatewayAvailabilityZones.value", + "parAzFirewallAvailabilityZones.value" + ) + } + [pscustomobject]@{ + source = "vwanConnectivity.parameters.all.json"; + parameters = @("parVirtualWanHubs.value[0].parAzFirewallAvailabilityZones") + } + ) + + foreach ($parametersFile in $parametersConfig) { + $parametersFilePath = Join-Path -Path $alzEnvironmentDestination "config\custom-parameters\$($parametersFile.source)" + if(!(Test-Path -Path $parametersFilePath)) { + Write-Verbose -Message "The file $parametersFilePath does not exist, so skipping it..." + continue + } + + $parametersFileJsonContent = Get-Content -Path $parametersFilePath -Raw + $bicepConfiguration = $parametersFileJsonContent | ConvertFrom-Json -AsHashtable + + $region = $bicepConfiguration.parameters.parLocation.value + $zones = ($zonesSupport | Where-Object { $_.region -eq $region }).zones + + $parametersFile.parameters | ForEach-Object { + $target = $_ + + Write-Verbose "Attempting to update $($target) in $($parametersFile.source) with '$($zones)'" + + # Find the appropriate item which will be changed in the Bicep file. + # Remove array '[' ']' characters so we can use the index value direct. + $propertyNames = $target.Replace("[", ".").Replace("]", "").Replace("..", ".") -split "\." + $bicepConfigNode = $bicepConfiguration.parameters + $index = 0 + + # Keep navigating into properties which the configuration specifies until we reach the bottom most object, + # e.g. not a value type - but the object reference so the value is persisted. + do { + if ($bicepConfigNode -is [array]) { + # If this is an array - use the property as an array index... + if ($propertyNames[$index] -match "[0-9]+" -eq $false) { + throw "Configuration specifies an array, but the index value '${$propertyNames[$index]}' is not a number" + } + + $bicepConfigNode = $bicepConfigNode[$propertyNames[$index]] + + } elseif ($bicepConfigNode.ContainsKey($propertyNames[$index]) -eq $true) { + # We found the item, keep indexing into the object. + $bicepConfigNode = $bicepConfigNode[$propertyNames[$index]] + } else { + # This property doesn't exist at this level in the hierarchy, + # this isn't the property we're looking for, stop looking. + $bicepConfigNode = $null + } + + ++$index + + } while (($null -ne $bicepConfigNode) -and ($index -lt $propertyNames.Length - 1)) + + # If we're here, we can modify this file and we've got an actual object specified by the Name path value - and we can modify values on it. + if ($null -ne $bicepConfigNode) { + $leafPropertyName = $propertyNames[-1] + Write-Verbose "Attempting to update $($target) in $($parametersFile.source) with '$($zones)'" + $bicepConfigNode[$leafPropertyName] = $zones + } + } + + Write-Verbose "Updating Bicep parameter file: $parametersFilePath" + ConvertTo-Json $bicepConfiguration -Depth 10 | Out-File $parametersFilePath + } +} \ No newline at end of file diff --git a/src/ALZ/Private/Legacy-Bicep/New-ALZEnvironmentBicep.ps1 b/src/ALZ/Private/Legacy-Bicep/New-ALZEnvironmentBicep.ps1 index 2fc6082..8cb8718 100644 --- a/src/ALZ/Private/Legacy-Bicep/New-ALZEnvironmentBicep.ps1 +++ b/src/ALZ/Private/Legacy-Bicep/New-ALZEnvironmentBicep.ps1 @@ -42,7 +42,7 @@ function New-ALZEnvironmentBicep { Set-ComputedConfiguration -configuration $configuration | Out-String | Write-Verbose Edit-ALZConfigurationFilesInPlace -alzEnvironmentDestination $targetDirectory -configuration $configuration | Out-String | Write-Verbose Build-ALZDeploymentEnvFile -configuration $configuration -Destination $targetDirectory -version $upstreamReleaseVersion | Out-String | Write-Verbose - Add-AvailabilityZonesBicepParameter -alzEnvironmentDestination $targetDirectory -configFile $bicepConfig | Out-String | Write-Verbose + Add-AvailabilityZonesBicepParameter -alzEnvironmentDestination $targetDirectory -zonesSupport $bicepConfig.zonesSupport | Out-String | Write-Verbose if($local) { $isGitRepo = Test-ALZGitRepository -alzEnvironmentDestination $targetDirectory -autoApprove:$autoApprove.IsPresent diff --git a/src/ALZ/Private/Shared/Get-OsArchitecture.ps1 b/src/ALZ/Private/Shared/Get-OsArchitecture.ps1 index 969d6f9..733187d 100644 --- a/src/ALZ/Private/Shared/Get-OsArchitecture.ps1 +++ b/src/ALZ/Private/Shared/Get-OsArchitecture.ps1 @@ -35,7 +35,7 @@ function Get-OSArchitecture { if($supportedOsAndArchitectures -notcontains $osAndArchitecture) { Write-Error "Unsupported OS and architecture combination: $osAndArchitecture" - exit 1 + return } if($osAndArchitecture -eq "windows_arm64") { diff --git a/src/ALZ/Public/New-ALZEnvironment.ps1 b/src/ALZ/Public/New-ALZEnvironment.ps1 index b9841ec..52283f0 100644 --- a/src/ALZ/Public/New-ALZEnvironment.ps1 +++ b/src/ALZ/Public/New-ALZEnvironment.ps1 @@ -57,6 +57,10 @@ function New-ALZEnvironment { [Alias("b")] [string] $bootstrap = "", + + [Parameter(Mandatory = $false, HelpMessage = "The starter module to deploy. You will be prompted to enter this if not supplied.")] + [string] $starter = "", + [Parameter(Mandatory = $false, HelpMessage = "The inputs in json or yaml format. This is optional and used to automate or pre-prepare the accelerator inputs.")] [Alias("inputs")] [string] $userInputOverridePath = "", @@ -101,7 +105,15 @@ function New-ALZEnvironment { [Parameter(Mandatory = $false, HelpMessage = "Whether to use legacy local mode for Bicep.")] [bool] - $bicepLegacyMode = $true # Note this is set to true to act as a feature flag while the Bicep bootstrap is developed. It will be switched to false once it is all working. + $bicepLegacyMode = $false, + + [Parameter(Mandatory = $false, HelpMessage = "Whether to overwrite bootstrap and starter modules if they already exist. Warning, this may result in unexpected behaviour and should only be used for local development purposes.")] + [switch] + $replaceFiles, + + [Parameter(Mandatory = $false, HelpMessage = "An extra level of logging that is turned off by default for easier debugging.")] + [switch] + $writeVerboseLogs ) $ProgressPreference = "SilentlyContinue" @@ -140,6 +152,9 @@ function New-ALZEnvironment { Write-InformationColored "Skipping Terraform tool check as you used the skipInternetCheck parameter. Please ensure you have the most recent version of Terraform installed" -ForegroundColor Yellow -InformationAction Continue } else { Write-InformationColored "Checking you have the latest version of Terraform installed..." -ForegroundColor Green -NewLineBefore -InformationAction Continue + if($iac -eq "bicep") { + Write-InformationColored "Although you have selected Bicep, the Accelerator leverages the Terraform tool to bootstrap your Version Control System and Azure. This is will not impact your choice of Bicep post this initial bootstrap. Please refer to our documentation for further details..." -ForegroundColor Yellow -InformationAction Continue + } $toolsPath = Join-Path -Path $targetDirectory -ChildPath ".tools" Get-TerraformTool -version "latest" -toolsPath $toolsPath } @@ -161,7 +176,8 @@ function New-ALZEnvironment { -release $bootstrapRelease ` -releaseArtifactName $bootstrapModuleReleaseArtifactName ` -moduleOverrideFolderPath $bootstrapModuleOverrideFolderPath ` - -skipInternetChecks $skipInternetChecks + -skipInternetChecks $skipInternetChecks ` + -replaceFile:$replaceFiles.IsPresent $bootstrapReleaseTag = $versionAndPath.releaseTag $bootstrapPath = $versionAndPath.path @@ -171,24 +187,21 @@ function New-ALZEnvironment { $starterFolder = "starter" $starterModuleTargetFolder = $starterFolder - if($iac -eq "bicep") { - if($isLegacyBicep) { - $starterFolder = "." - } - $starterModuleTargetFolder = "$starterFolder/upstream-releases" + if($isLegacyBicep) { + $starterModuleTargetFolder = "./upstream-releases" } # Setup the variables for bootstrap and starter modules $hasStarterModule = $false $starterModuleUrl = $bicepLegacyUrl $starterModuleSourceFolder = "." - $starterReleaseTag = "local" $starterReleaseArtifactName = "" $starterConfigFilePath = "" $bootstrapDetails = $null $validationConfig = $null $inputConfig = $null + $zonesSupport = $null if(!$isLegacyBicep) { $bootstrapAndStarterConfig = Get-BootstrapAndStarterConfig ` @@ -202,11 +215,11 @@ function New-ALZEnvironment { $hasStarterModule = $bootstrapAndStarterConfig.hasStarterModule $starterModuleUrl = $bootstrapAndStarterConfig.starterModuleUrl $starterModuleSourceFolder = $bootstrapAndStarterConfig.starterModuleSourceFolder - $starterReleaseTag = $bootstrapAndStarterConfig.starterReleaseTag $starterReleaseArtifactName = $bootstrapAndStarterConfig.starterReleaseArtifactName $starterConfigFilePath = $bootstrapAndStarterConfig.starterConfigFilePath $validationConfig = $bootstrapAndStarterConfig.validationConfig $inputConfig = $bootstrapAndStarterConfig.inputConfig + $zonesSupport = $bootstrapAndStarterConfig.zonesSupport } else { if($bootstrap -eq "") { $bootstrap = Request-SpecialInput -type "bootstrap" -bootstrapModules $bootstrapModules -userInputOverrides $userInputOverrides @@ -229,7 +242,8 @@ function New-ALZEnvironment { -release $starterRelease ` -releaseArtifactName $starterReleaseArtifactName ` -moduleOverrideFolderPath $starterModuleOverrideFolderPath ` - -skipInternetChecks $skipInternetChecks + -skipInternetChecks $skipInternetChecks ` + -replaceFile:$replaceFiles.IsPresent $starterReleaseTag = $versionAndPath.releaseTag $starterPath = $versionAndPath.path @@ -239,7 +253,7 @@ function New-ALZEnvironment { } # Run the bicep parameter setup if the iac is Bicep - if ($iac -eq "bicep") { + if ($isLegacyBicep) { Write-Verbose "Starting the Bicep specific environment setup..." $bootstrapLegacy = $bootstrap.ToLower().Replace("alz_", "") @@ -260,6 +274,15 @@ function New-ALZEnvironment { # Run the bootstrap if(!$isLegacyBicep) { + + # Set computed interface inputs + $computedInputs = @{ + "iac_type" = $iac + "on_demand_folder_repository" = $starterModuleUrl + "on_demand_folder_artifact_name" = $starterReleaseArtifactName + "release_version" = $starterReleaseTag -eq "local" ? $starterRelease : $starterReleaseTag + } + $bootstrapTargetPath = Join-Path $targetDirectory $bootstrapTargetFolder $starterTargetPath = Join-Path $targetDirectory $starterFolder @@ -276,7 +299,11 @@ function New-ALZEnvironment { -starterConfig $starterConfig ` -userInputOverrides $userInputOverrides ` -autoApprove:$autoApprove.IsPresent ` - -destroy:$destroy.IsPresent + -destroy:$destroy.IsPresent ` + -starter $starter ` + -zonesSupport $zonesSupport ` + -computedInputs $computedInputs ` + -writeVerboseLogs:$writeVerboseLogs.IsPresent } } diff --git a/src/Tests/Unit/Private/Add-AvailabilityZonesBicepParameters.Tests.ps1 b/src/Tests/Unit/Private/Add-AvailabilityZonesBicepParameters.Tests.ps1 index ae75d99..603bacf 100644 --- a/src/Tests/Unit/Private/Add-AvailabilityZonesBicepParameters.Tests.ps1 +++ b/src/Tests/Unit/Private/Add-AvailabilityZonesBicepParameters.Tests.ps1 @@ -12,61 +12,54 @@ Import-Module $PathToManifest -Force #------------------------------------------------------------------------- InModuleScope 'ALZ' { + $VerbosePreference = "Continue" Describe "Add-AvailabilityZonesBicepParameter" { BeforeAll { $alzEnvironmentDestination = "TestDrive:\" $hubParametersPath = "https://raw.githubusercontent.com/Azure/ALZ-Bicep/main/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json" - Invoke-WebRequest -Uri $hubParametersPath -OutFile "$alzEnvironmentDestination\hubNetworking.parameters.all.json" + New-Item -Path "$alzEnvironmentDestination\config\custom-parameters" -Force -ItemType Directory + Invoke-WebRequest -Uri $hubParametersPath -OutFile "$alzEnvironmentDestination\config\custom-parameters\hubNetworking.parameters.all.json" } Context "Hub networking parameters availability zones check" { - BeforeAll { - Mock -CommandName Join-Path -MockWith { - $alzEnvironmentDestination + "\hubNetworking.parameters.all.json" - } - Mock -CommandName Get-Content -ParameterFilter { $Path -contains 'parametersFilePath' } -MockWith { - Get-Content -Path "TestDrive:\hubNetworking.parameters.all.json" - } - } It "Should add 3 availability zones for hub networking parameters" { - Add-AvailabilityZonesBicepParameter -alzEnvironmentDestination $alzEnvironmentDestination -configFile ([PSCustomObject]@{ - zonesSupport = @( + Add-AvailabilityZonesBicepParameter -alzEnvironmentDestination $alzEnvironmentDestination -zonesSupport (@( [PSCustomObject]@{ region = "eastus" zones = @("1", "2", "3") } ) - }) - $parametersFileJsonContent = Get-Content -Path "TestDrive:\hubNetworking.parameters.all.json" -Raw + ) + $parametersFileJsonContent = Get-Content -Path "TestDrive:\config\custom-parameters\hubNetworking.parameters.all.json" -Raw + Write-Verbose (Test-Path -Path "TestDrive:\config\custom-parameters\hubNetworking.parameters.all.json") + #Write-Verbose $parametersFileJsonContent $jsonObject = $parametersFileJsonContent | ConvertFrom-Json $jsonObject.parameters.parAzErGatewayAvailabilityZones.value | Should -Be @("1", "2", "3") $jsonObject.parameters.parAzVpnGatewayAvailabilityZones.value | Should -Be @("1", "2", "3") $jsonObject.parameters.parAzFirewallAvailabilityZones.value | Should -Be @("1", "2", "3") } It "Should add 2 availability zones for hub networking parameters" { - Add-AvailabilityZonesBicepParameter -alzEnvironmentDestination $alzEnvironmentDestination -configFile ([PSCustomObject]@{ - zonesSupport = @( + Add-AvailabilityZonesBicepParameter -alzEnvironmentDestination $alzEnvironmentDestination -zonesSupport (@( [PSCustomObject]@{ region = "eastus" zones = @("1", "2") } ) - }) - $parametersFileJsonContent = Get-Content -Path "TestDrive:\hubNetworking.parameters.all.json" -Raw + ) + $parametersFileJsonContent = Get-Content -Path "TestDrive:\config\custom-parameters\hubNetworking.parameters.all.json" -Raw $jsonObject = $parametersFileJsonContent | ConvertFrom-Json $jsonObject.parameters.parAzErGatewayAvailabilityZones.value | Should -Be @("1", "2") $jsonObject.parameters.parAzVpnGatewayAvailabilityZones.value | Should -Be @("1", "2") $jsonObject.parameters.parAzFirewallAvailabilityZones.value | Should -Be @("1", "2") } It "Should add 0 availability zones for hub networking parameters" { - Add-AvailabilityZonesBicepParameter -alzEnvironmentDestination $alzEnvironmentDestination -configFile ([PSCustomObject]@{ - zonesSupport = @( + Add-AvailabilityZonesBicepParameter -alzEnvironmentDestination $alzEnvironmentDestination -zonesSupport (@( [PSCustomObject]@{ region = "eastus" zones = @() } ) - }) - $parametersFileJsonContent = Get-Content -Path "TestDrive:\hubNetworking.parameters.all.json" -Raw + ) + $parametersFileJsonContent = Get-Content -Path "TestDrive:\config\custom-parameters\hubNetworking.parameters.all.json" -Raw $jsonObject = $parametersFileJsonContent | ConvertFrom-Json $jsonObject.parameters.parAzErGatewayAvailabilityZones.value | Should -Be @() $jsonObject.parameters.parAzVpnGatewayAvailabilityZones.value | Should -Be @() diff --git a/src/Tests/Unit/Private/Request-ConfigurationValue.Tests.ps1 b/src/Tests/Unit/Private/Request-ConfigurationValue.Tests.ps1 index 6ff57c7..8e34201 100644 --- a/src/Tests/Unit/Private/Request-ConfigurationValue.Tests.ps1 +++ b/src/Tests/Unit/Private/Request-ConfigurationValue.Tests.ps1 @@ -37,7 +37,7 @@ InModuleScope 'ALZ' { Request-ConfigurationValue -configName "prefix" -configValue $configValue - Should -Invoke -CommandName Write-InformationColored -Times 4 -Exactly + Should -Invoke -CommandName Write-InformationColored -Times 3 -Exactly $configValue.Value | Should -BeExactly "user input value" } @@ -56,7 +56,7 @@ InModuleScope 'ALZ' { Request-ConfigurationValue -configName "prefix" -configValue $configValue - Should -Invoke -CommandName Write-InformationColored -Times 4 -Exactly + Should -Invoke -CommandName Write-InformationColored -Times 3 -Exactly $configValue.Value | Should -BeExactly "alz" } @@ -132,7 +132,7 @@ InModuleScope 'ALZ' { } Request-ConfigurationValue -configName "calculated" -configValue $configValue -withRetries $false - Should -Invoke -CommandName Write-InformationColored -Times 6 -Exactly + Should -Invoke -CommandName Write-InformationColored -Times 5 -Exactly $configValue.Value | Should -BeExactly "l" } @@ -155,7 +155,7 @@ InModuleScope 'ALZ' { } Request-ConfigurationValue -configName "calculated" -configValue $configValue -withRetries $false - Should -Invoke -CommandName Write-InformationColored -Times 5 -Exactly + Should -Invoke -CommandName Write-InformationColored -Times 4 -Exactly $configValue.Value | Should -BeExactly "l" } } diff --git a/src/Tests/Unit/Public/New-ALZEnvironment.Tests.ps1 b/src/Tests/Unit/Public/New-ALZEnvironment.Tests.ps1 index 6c0c5df..1fc2ce1 100644 --- a/src/Tests/Unit/Public/New-ALZEnvironment.Tests.ps1 +++ b/src/Tests/Unit/Public/New-ALZEnvironment.Tests.ps1 @@ -49,6 +49,15 @@ InModuleScope 'ALZ' { @{ "module_url" = "test" "version" = "v1.0.0" + "deployment_files" = @( + @{ + "displayName" = "Management Groups Deployment" + "templateFilePath" = "./infra-as-code/bicep/modules/managementGroups/managementGroupsScopeEscape.bicep" + "templateParametersFilePath" = "./config/custom-parameters/managementGroups.parameters.all.json" + "templateParametersSourceFilePath" = "./infra-as-code/bicep/modules/managementGroups/parameters/managementGroups.parameters.all.json" + "deploymentType" = "managementGroup" + } + ) "config_files" = @( @{ "source" = "a" @@ -139,7 +148,7 @@ InModuleScope 'ALZ' { } It 'should call the correct functions for bicep legacy module configuration' { - New-ALZEnvironment -i "bicep" -c "github" + New-ALZEnvironment -i "bicep" -c "github" -bicepLegacyMode $true Assert-MockCalled -CommandName New-ALZEnvironmentBicep -Exactly 1 Assert-MockCalled -CommandName New-ModuleSetup -Exactly 1 }