├── .devcontainer ├── devcontainer.json └── dockerfile ├── .github ├── copilot-instructions.md ├── dependabot.yml └── workflows │ └── mega-linter.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .vscode ├── launch.json ├── settings.json └── tasks.json └── README.md /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | // "name" specifies the name of the development container, which helps in identifying it in a list of containers. 3 | "name": "Ubuntu", 4 | 5 | // "build" section is used to define how the development container is built. It can reference a Dockerfile or a Docker Compose file. 6 | "build": { 7 | "dockerfile": "dockerfile" // Specifies the Dockerfile to use for building the container. 8 | }, 9 | 10 | // "features" section allows adding and configuring predefined features or tools in the development container. 11 | "features": { 12 | // Adds and configures the Azure CLI with Bicep and Python installation options. 13 | "ghcr.io/devcontainers/features/azure-cli:latest": { 14 | "installBicep": true, // Enables Bicep installation. 15 | "installUsingPython": true, // Installs using Python. 16 | "version": "latest" // Specifies the version of the Azure CLI to install. 17 | }, 18 | // Adds PowerShell to the container. 19 | "ghcr.io/devcontainers/features/powershell:latest": { 20 | "version": "latest" // Specifies the version of PowerShell to install. 21 | }, 22 | // Adds Azure Bicep support. 23 | "ghcr.io/rchaganti/vsc-devcontainer-features/azurebicep:latest": {}, 24 | // Adds Azure Developer CLI (azd) support. 25 | "ghcr.io/azure/azure-dev/azd:latest": {}, 26 | // Adds and configures Terraform with specific version, TFLint, and Terragrunt. 27 | "ghcr.io/prulloac/devcontainer-features/pre-commit:1.0.3": {}, 28 | // Adds and configures Terraform with specific version, TFLint, and Terragrunt. 29 | "ghcr.io/devcontainers/features/terraform:1.4.0": { 30 | "version": "latest", // Specifies the version of Terraform to install. 31 | "tflint": "latest", // Specifies the version of TFLint to install. 32 | "terragrunt": "latest", // Specifies the version of Terragrunt to install. 33 | "installTerraformDocs": true 34 | }, 35 | "ghcr.io/devcontainers/features/docker-in-docker:latest": { 36 | "moby": true, 37 | "azureDnsAutoDetection": true, 38 | "installDockerBuildx": true, 39 | "installDockerComposeSwitch": true, 40 | "version": "latest", 41 | "dockerDashComposeVersion": "latest" 42 | } 43 | }, 44 | "postCreateCommand": "pre-commit install", 45 | 46 | // "customizations" section allows configuring specific aspects of the development environment, such as VS Code settings and extensions. 47 | "customizations": { 48 | "vscode": { 49 | // Defines VS Code settings to be applied within the dev container. 50 | "settings": { 51 | "editor.formatOnSaveMode": "file", // Configures format on save to be applied to the entire file. 52 | "bicep.experimental.deployPane": "true", // Enables the experimental deploy pane for Bicep. 53 | "github.copilot.chat.codeGeneration.useInstructionFiles": "true" 54 | }, 55 | // Lists VS Code extensions to be installed in the dev container environment. 56 | "extensions": [ 57 | "ms-azuretools.vscode-azurecontainerapps", 58 | "ms-azuretools.vscode-azureresourcegroups", 59 | "ms-azuretools.vscode-bicep", 60 | "editorconfig.editorconfig", 61 | "BenjaminBenais.copilot-theme", 62 | "GitHub.copilot", 63 | "GitHub.copilot-chat", 64 | "ms-vscode.azure-account", 65 | "hashicorp.terraform", 66 | "golang.Go", 67 | "ms-azuretools.vscode-docker", 68 | "formulahendry.docker-explorer", 69 | "ms-dotnettools.csdevkit", 70 | "ms-kubernetes-tools.vscode-aks-tools" 71 | ] 72 | } 73 | } 74 | 75 | // Features to add to the dev container. More info: https://containers.dev/features. 76 | // "features": {}, 77 | 78 | // Use 'forwardPorts' to make a list of ports inside the container that are available locally. 79 | // "forwardPorts": [], 80 | 81 | // Use 'postCreateCommand' to run commands after the container is created. 82 | // "postCreateCommand": "uname -a", 83 | 84 | // Configure tool-specific properties. 85 | // "customizations": {}, 86 | 87 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 88 | // "remoteUser": "root"} 89 | } 90 | -------------------------------------------------------------------------------- /.devcontainer/dockerfile: -------------------------------------------------------------------------------- 1 | # This line specifies the base image for the Docker container. 2 | # "FROM" is a Docker instruction used to set the base image from which the container is built. 3 | # "mcr.microsoft.com/devcontainers/universal:latest" is the image being used. 4 | # It is a universal image provided by Microsoft, hosted on the Microsoft Container Registry (MCR), 5 | # designed for development containers. The "latest" tag specifies the most recent version of this image. 6 | FROM mcr.microsoft.com/devcontainers/universal:latest -------------------------------------------------------------------------------- /.github/copilot-instructions.md: -------------------------------------------------------------------------------- 1 | Provide comprehensive guidance and best practices for developing reusable and reliable Infrastructure as Code using Bicep, Terraform, and PowerShell, prioritizing the Azure Well-Architected Framework pillars in this order: Security, Operational Excellence, Performance Efficiency, Reliability, and Cost Optimization. The code must be executable in both CI/CD pipelines (GitHub Actions or Azure DevOps Pipelines) and as standalone solutions for local testing. Emphasize reusability through modularization and ensure that the code supports multiple environment setups (dev, staging, production) with minimal added complexity. 2 | 3 | Incorporate preferred safe deployment practices, including effective management of feature flags, and provide recommendations for when and how to use them effectively. Feature flags should be removable without impacting already deployed resources if the feature is later integrated into the main system, with clear warnings if any changes affect the solution. Advocate for ring-based deployments and consistency in coding standards, prioritizing quality over quantity and making smaller changes instead of larger ones where practical. 4 | 5 | Follow DRY principles, include thorough comments, and structure variables in snake_case at the top of each file. Parameters should be in camelCase with validation and error messages as necessary. Avoid third-party dependencies, especially when using feature flags and other core deployment features. 6 | 7 | If asked about the location of resources to be deployed, make sure the location is either of the two below as default: 8 | 9 | * "newzealandnorth" 10 | * "australiaeast" 11 | 12 | Include recommendations for key performance indicators (KPIs) to measure the effectiveness of deployments, focusing on metrics like deployment frequency, change failure rate, mean time to recovery, and customer satisfaction. Ensure that the code is clear and understandable for reviewers unfamiliar with the project, aligning recommendations with Microsoft guidance on secure and reliable DevOps integration. If using parameters, make sure to include relevant helper functions. 13 | 14 | Highlight how GitHub Copilot can assist by providing real-time suggestions and best-practice enforcement while identifying and proposing native solutions within Bicep, Terraform, or PowerShell to replace third-party dependencies. 15 | 16 | Additionally, provide relevant guidance on: 17 | 18 | * Infrastructure testing and validation techniques. 19 | * Documentation best practices. 20 | * Error handling and logging mechanisms. 21 | * Version control strategies. 22 | * Configuration management approaches. 23 | * Security best practices tailored for Azure. 24 | * Cost management strategies for Azure resources. 25 | * Establishing a change management process for IaC updates. 26 | * Integrating monitoring and alerting for deployed resources. 27 | * Engaging with the Azure community for ongoing learning and best practices. 28 | 29 | Provide a random IT joke (that is NOT about dark mode) 30 | 31 | Review the response from the perspectives of a Site Reliability Engineer, Operations Manager, Microsoft Technical Specialist, Security Consultant, Business Analyst, and On-call Engineer, confirming factual accuracy and seeking clarification where needed, output what each persona thinks about the code. 32 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "devcontainers" 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | - package-ecosystem: github-actions 8 | directory: "/" 9 | schedule: 10 | interval: weekly 11 | open-pull-requests-limit: 10 12 | labels: 13 | - "pr: dependencies" 14 | -------------------------------------------------------------------------------- /.github/workflows/mega-linter.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # MegaLinter GitHub Action configuration file 3 | # More info at https://megalinter.io 4 | name: MegaLinter 5 | 6 | on: 7 | push: 8 | branches: 9 | - "**" 10 | 11 | env: # Comment env block if you do not want to apply fixes 12 | # Apply linter fixes configuration 13 | APPLY_FIXES: all # When active, APPLY_FIXES must also be defined as environment variable (in github/workflows/mega-linter.yml or other CI tool) 14 | APPLY_FIXES_EVENT: all # Decide which event triggers application of fixes in a commit or a PR (pull_request, push, all) 15 | APPLY_FIXES_MODE: pull_request # If APPLY_FIXES is used, defines if the fixes are directly committed (commit) or posted in a PR (pull_request) 16 | 17 | concurrency: 18 | group: ${{ github.ref }}-${{ github.workflow }} 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | build: 23 | name: MegaLinter 24 | runs-on: ubuntu-latest 25 | permissions: 26 | # Give the default GITHUB_TOKEN write permission to commit and push, comment issues & post new PR 27 | # Remove the ones you do not need 28 | contents: write 29 | issues: write 30 | pull-requests: write 31 | steps: 32 | # Git Checkout 33 | - name: Checkout Code 34 | uses: actions/checkout@v4 35 | with: 36 | token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} 37 | fetch-depth: 0 # If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to improve performances 38 | 39 | # MegaLinter 40 | - name: MegaLinter 41 | id: ml 42 | # You can override MegaLinter flavor used to have faster performances 43 | # More info at https://megalinter.io/flavors/ 44 | uses: oxsecurity/megalinter@beta 45 | env: 46 | # All available variables are described in documentation 47 | # https://megalinter.io/configuration/ 48 | VALIDATE_ALL_CODEBASE: true 49 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 50 | # ADD YOUR CUSTOM ENV VARIABLES HERE TO OVERRIDE VALUES OF .mega-linter.yml AT THE ROOT OF YOUR REPOSITORY 51 | APPLY_FIXES: all 52 | DISABLE_ERRORS: true # Uncomment if you want MegaLinter to detect errors but not block CI to pass 53 | 54 | # Upload MegaLinter artifacts 55 | - name: Archive production artifacts 56 | if: ${{ success() }} || ${{ failure() }} 57 | uses: actions/upload-artifact@v4 58 | with: 59 | name: MegaLinter reports 60 | path: | 61 | megalinter-reports 62 | mega-linter.log 63 | 64 | # Create pull request if applicable (for now works only on PR from same repository, not from forks) 65 | - name: Create Pull Request with applied fixes 66 | id: cpr 67 | if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'pull_request' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') 68 | uses: peter-evans/create-pull-request@v7 69 | with: 70 | token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} 71 | commit-message: "[MegaLinter] Apply linters automatic fixes" 72 | title: "[MegaLinter] Apply linters automatic fixes" 73 | labels: bot 74 | - name: Create PR output 75 | if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'pull_request' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') 76 | run: | 77 | echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" 78 | echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" 79 | 80 | # Push new commit if applicable (for now works only on PR from same repository, not from forks) 81 | - name: Prepare commit 82 | if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'commit' && github.ref != 'refs/heads/main' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') 83 | run: sudo chown -Rc $UID .git/ 84 | - name: Commit and push applied linter fixes 85 | if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'commit' && github.ref != 'refs/heads/main' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') 86 | uses: stefanzweifel/git-auto-commit-action@v5 87 | with: 88 | branch: ${{ github.event.pull_request.head.ref || github.head_ref || github.ref }} 89 | commit_message: "[MegaLinter] Apply linters fixes" 90 | commit_user_name: megalinter-bot 91 | commit_user_email: nicolas.vuillamy@ox.security 92 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Megalinter reports 2 | megalinter-reports/ 3 | # Local .terraform directories 4 | **/.terraform/* 5 | 6 | # .tfstate files 7 | *.tfstate 8 | *.tfstate.* 9 | 10 | # Crash log files 11 | crash.log 12 | crash.*.log 13 | 14 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 15 | # password, private keys, and other secrets. These should not be part of version 16 | # control as they are data points which are potentially sensitive and subject 17 | # to change depending on the environment. 18 | *.tfvars 19 | *.tfvars.json 20 | 21 | # Ignore override files as they are usually used to override resources locally and so 22 | # are not checked in 23 | override.tf 24 | override.tf.json 25 | *_override.tf 26 | *_override.tf.json 27 | 28 | # Include override files you do wish to add to version control using negated pattern 29 | # !example_override.tf 30 | 31 | # Ignore Terraform lock file 32 | .terraform.lock.hcl 33 | 34 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 35 | # example: *tfplan* 36 | 37 | # Ignore CLI configuration files 38 | .terraformrc 39 | terraform.rc 40 | avmmakefile 41 | README-generated.md 42 | avm.tflint.hcl 43 | avm.tflint_example.hcl 44 | avm.tflint_module.hcl 45 | avm.tflint.merged.hcl 46 | avm.tflint_example.merged.hcl 47 | avm.tflint_module.merged.hcl 48 | *tfplan* 49 | *.md.tmp 50 | # MacOS 51 | .DS_Store 52 | 53 | # C# 54 | [Bb]in/ 55 | [Oo]bj/ -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_stages: [pre-commit] 2 | repos: 3 | - repo: https://github.com/pre-commit/pre-commit-hooks 4 | rev: v5.0.0 5 | hooks: 6 | - id: trailing-whitespace 7 | - id: end-of-file-fixer 8 | - id: check-yaml 9 | - id: check-added-large-files 10 | - id: check-case-conflict 11 | - id: check-merge-conflict 12 | - repo: https://github.com/antonbabenko/pre-commit-terraform 13 | rev: v1.96.3 14 | hooks: 15 | - id: terraform_fmt 16 | args: 17 | - --args=-recursive 18 | exclude: '.*/\.terragrunt-cache' 19 | - id: terraform_validate 20 | - id: terraform_tflint 21 | - id: terraform_trivy 22 | - id: terraform_docs 23 | args: 24 | - --hook-config=--add-to-existing-file=true # Boolean. true or false 25 | - --hook-config=--create-file-if-not-exist=true # Boolean. true or false 26 | - --args=--output-mode=replace 27 | - id: tfupdate 28 | name: Autoupdate Terraform versions 29 | args: 30 | - --args=provider azurerm # Will be pined to latest version 31 | - repo: https://github.com/bridgecrewio/checkov.git 32 | rev: "3.2.346" # change to tag or sha 33 | hooks: 34 | - id: checkov 35 | verbose: true 36 | args: ["--quiet", "--compact", "--soft-fail"] 37 | - repo: https://github.com/bridgecrewio/yor 38 | rev: 0.1.199 39 | hooks: 40 | - id: yor 41 | name: yor 42 | entry: yor tag -d 43 | args: ["."] 44 | language: golang 45 | types: [terraform] 46 | pass_filenames: false 47 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": ".NET Core Launch (web)", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "preLaunchTask": "build", 9 | "program": "${workspaceFolder}/AZ2003App/bin/Debug/net8.0/AZ2003App.dll", 10 | "args": [], 11 | "cwd": "${workspaceFolder}/AZ2003App", 12 | "stopAtEntry": false, 13 | "serverReadyAction": { 14 | "action": "openExternally", 15 | "pattern": "\\bNow listening on:\\s+(https?://\\S+)" 16 | }, 17 | "env": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | }, 20 | "sourceFileMap": { 21 | "/Views": "${workspaceFolder}/Views" 22 | } 23 | }, 24 | { 25 | "name": ".NET Core Attach", 26 | "type": "coreclr", 27 | "request": "attach" 28 | }, 29 | { 30 | "name": "Docker .NET Launch", 31 | "type": "docker", 32 | "request": "launch", 33 | "preLaunchTask": "docker-run: debug", 34 | "netCore": { 35 | "appProject": "${workspaceFolder}/AZ2003App/AZ2003App.csproj" 36 | } 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "dotnet.defaultSolution": "AZ2003App.sln" 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/AZ2003App.sln", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary;ForceNoAlign" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "publish", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "publish", 22 | "${workspaceFolder}/AZ2003App.sln", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary;ForceNoAlign" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "watch", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": ["watch", "run", "--project", "${workspaceFolder}/AZ2003App.sln"], 33 | "problemMatcher": "$msCompile" 34 | }, 35 | { 36 | "type": "docker-build", 37 | "label": "docker-build: debug", 38 | "dependsOn": ["build"], 39 | "dockerBuild": { 40 | "tag": "codespaceiaccoding:dev", 41 | "target": "base", 42 | "dockerfile": "${workspaceFolder}/AZ2003App/Dockerfile", 43 | "context": "${workspaceFolder}", 44 | "pull": true 45 | }, 46 | "netCore": { 47 | "appProject": "${workspaceFolder}/AZ2003App/AZ2003App.csproj" 48 | } 49 | }, 50 | { 51 | "type": "docker-build", 52 | "label": "docker-build: release", 53 | "dependsOn": ["build"], 54 | "dockerBuild": { 55 | "tag": "codespaceiaccoding:latest", 56 | "dockerfile": "${workspaceFolder}/AZ2003App/Dockerfile", 57 | "context": "${workspaceFolder}", 58 | "platform": { 59 | "os": "linux", 60 | "architecture": "amd64" 61 | }, 62 | "pull": true 63 | }, 64 | "netCore": { 65 | "appProject": "${workspaceFolder}/AZ2003App/AZ2003App.csproj" 66 | } 67 | }, 68 | { 69 | "type": "docker-run", 70 | "label": "docker-run: debug", 71 | "dependsOn": ["docker-build: debug"], 72 | "dockerRun": {}, 73 | "netCore": { 74 | "appProject": "${workspaceFolder}/AZ2003App/AZ2003App.csproj", 75 | "enableDebugging": true 76 | } 77 | }, 78 | { 79 | "type": "docker-run", 80 | "label": "docker-run: release", 81 | "dependsOn": ["docker-build: release"], 82 | "dockerRun": {}, 83 | "netCore": { 84 | "appProject": "${workspaceFolder}/AZ2003App/AZ2003App.csproj" 85 | } 86 | } 87 | ] 88 | } 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Codespace_IaC_Coding 2 | 3 | This repository contains the code for IaC (Infrastructure as Code) coding in Codespace. 4 | 5 | Related Blog Article: [Infrastructure as Code GitHub Codespace Template](https://luke.geek.nz/azure/iac-github-codespace/). 6 | 7 | ## Development Environment 8 | 9 | This project uses a Docker container as a development environment, which includes tools like Azure CLI, PowerShell, Azure Bicep, Azure Developer CLI (azd), Terraform, TFLint, and Terragrunt. 10 | 11 | - **Azure CLI**: Used for managing Azure resources. 12 | - **PowerShell**: A cross-platform task automation solution. 13 | - **Azure Bicep**: A declarative language for deploying Azure resources. 14 | - **Azure Developer CLI (azd)**: Streamlines the process of building, deploying, and managing Azure applications. 15 | - **Terraform**: An open-source tool for building, changing, and versioning infrastructure safely and efficiently. 16 | - **TFLint**: A Terraform linter for detecting errors that cannot be detected by `terraform plan`. 17 | - **Terragrunt**: A thin wrapper for Terraform that provides extra tools for working with multiple Terraform modules. 18 | 19 | ## Code Quality and Linting 20 | 21 | This project uses [MegaLinter](https://megalinter.io/latest/) to ensure code quality and adherence to best practices. [MegaLinter](https://megalinter.io/latest/) analyzes the codebase for potential issues, coding standards violations, formatting discrepancies, and more across multiple languages and file formats. It helps maintain a high standard of code quality and consistency across the project. 22 | 23 | ## Contributing 24 | 25 | We welcome contributions to the `Codespace_IaC_Coding` project. Feel free to open a pull-request. 26 | --------------------------------------------------------------------------------