diff --git a/.github/actions-config/gh-ado-sync-config.json b/.github/actions-config/gh-ado-sync-config.json new file mode 100644 index 000000000..0c3183d83 --- /dev/null +++ b/.github/actions-config/gh-ado-sync-config.json @@ -0,0 +1,18 @@ +{ + "log_level": "info", + "ado": { + "organization": "CSUSolEng", + "project": "Well-Architected Framework", + "wit": "GitHub Issue", + "states": { + "new": "New", + "closed": "Closed", + "reopened": "New", + "deleted": "Removed", + "active": "In Progress" + }, + "bypassRules": true, + "autoCreate": true, + "areaPath": "Well-Architected Framework" + } +} diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ba16fec86..25733989c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -12,3 +12,4 @@ updates: labels: - "Type: Hygiene :broom:" - "Needs: Attention from aprl-maintainers :wave:" + - "Auto-Merge :heavy_check_mark:" diff --git a/.github/workflows/ado-sync-workitems.yml b/.github/workflows/ado-sync-workitems.yml new file mode 100644 index 000000000..e6896d572 --- /dev/null +++ b/.github/workflows/ado-sync-workitems.yml @@ -0,0 +1,31 @@ +name: Sync Issues to Azure DevOps Work Items + +permissions: + contents: read + +on: + issues: + types: [opened, closed, deleted, reopened, edited, labeled, unlabeled, assigned, unassigned] + issue_comment: + types: [created] + +jobs: + alert: + runs-on: ubuntu-latest + name: Sync workflow + if: github.repository == 'Azure/Azure-Proactive-Resiliency-Library-v2' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: GitHub/ADO Sync + uses: a11smiles/GitSync@v1.2.3 + env: + ado_token: '${{ secrets.ADO_PERSONAL_ACCESS_TOKEN }}' + github_token: '${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}' + config_file: './.github/actions-config/gh-ado-sync-config.json' + with: + ado: ${{ secrets.ADO_MAPPINGS_HANDLES }} diff --git a/.github/workflows/build-recommendation-object.yml b/.github/workflows/build-recommendation-object.yml index b75448711..b4cfee1a6 100644 --- a/.github/workflows/build-recommendation-object.yml +++ b/.github/workflows/build-recommendation-object.yml @@ -3,28 +3,60 @@ name: Nightly Recommendation Object Build on: schedule: - cron: "0 0 * * *" + workflow_dispatch: {} permissions: - contents: write + contents: read jobs: build: runs-on: ubuntu-latest - + permissions: + contents: write + pull-requests: write steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: main + - name: Configure Git + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + shell: bash + + - name: Create and Switch to New Branch + run: | + git checkout -b json-object-update + shell: bash + - name: Run Recommendation Object Builder run: | pwsh .github/scripts/build-recommendation-object.ps1 - name: Commit and push changes run: | - git config --global user.name 'github-actions[bot]' - git config --global user.email 'github-actions[bot]@users.noreply.github.com' git add ./tools/data/recommendations.json git commit -m "Update recommendations.json" - git push + git push --set-upstream origin json-object-update + + - name: Create PR + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh pr create --title "chore: Update APRL JSON Object" --body "This PR updates the single JSON object for all APRL recommendations." --base main --head json-object-update + shell: bash + + - name: Merge PR + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + pr_number=$(gh pr list --state open --limit 1 --json number --jq '.[0].number') + gh pr merge $pr_number --merge + shell: bash diff --git a/.github/workflows/code-review.yml b/.github/workflows/code-review.yml index dc931b36b..30f6a8da6 100644 --- a/.github/workflows/code-review.yml +++ b/.github/workflows/code-review.yml @@ -11,22 +11,26 @@ on: permissions: contents: read packages: read - # To report GitHub Actions status checks - statuses: write jobs: lint: + permissions: + statuses: write name: Lint code base runs-on: ubuntu-latest - steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 - name: Run github/super-linter - uses: github/super-linter@v7 + uses: github/super-linter@b807e99ddd37e444d189cfd2c2ca1274d8ae8ef1 # v7 env: VALIDATE_ALL_CODEBASE: false # Need to define main branch as default is set to master in super-linter @@ -46,15 +50,19 @@ jobs: markdown_link_check: name: Markdown Link Check runs-on: ubuntu-latest - steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + - name: Checkout code - uses: actions/checkout@main + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # main with: fetch-depth: 0 - name: Check links in markdown files - uses: gaurav-nelson/github-action-markdown-link-check@1.0.15 + uses: gaurav-nelson/github-action-markdown-link-check@d53a906aa6b22b8979d33bc86170567e619495ec # 1.0.15 with: config-file: ".github/linters/mlc_config.json" use-verbose-mode: "yes" diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 000000000..2350d2aff --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,28 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, +# surfacing known-vulnerable versions of the packages declared or updated in the PR. +# Once installed, if the workflow run is marked as required, +# PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + + - name: 'Checkout Repository' + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + + - name: 'Dependency Review' + uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4 diff --git a/.github/workflows/hugo-build-pr-check.yml b/.github/workflows/hugo-build-pr-check.yml index d72f6ef81..95f266e8b 100644 --- a/.github/workflows/hugo-build-pr-check.yml +++ b/.github/workflows/hugo-build-pr-check.yml @@ -17,21 +17,25 @@ on: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read - pages: write - id-token: write - # Default to bash defaults: run: shell: bash jobs: - # Build PR job buildpr: + permissions: + pages: write + id-token: write runs-on: ubuntu-latest env: HUGO_VERSION: 0.124.1 steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + - name: Install Hugo CLI run: | wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \ @@ -41,14 +45,14 @@ jobs: run: sudo snap install dart-sass-embedded - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: submodules: recursive fetch-depth: 0 - name: Setup Pages id: pages - uses: actions/configure-pages@v5 + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 - name: Install Node.js dependencies run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true" diff --git a/.github/workflows/hugo-site-build.yml b/.github/workflows/hugo-site-build.yml index 0b8e9f88c..08fa31473 100644 --- a/.github/workflows/hugo-site-build.yml +++ b/.github/workflows/hugo-site-build.yml @@ -20,11 +20,8 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: {} -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read - pages: write - id-token: write # Allow one concurrent deployment concurrency: @@ -43,6 +40,11 @@ jobs: env: HUGO_VERSION: 0.124.1 steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + - name: Install Hugo CLI run: | wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \ @@ -52,19 +54,19 @@ jobs: run: sudo snap install dart-sass-embedded - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: submodules: recursive fetch-depth: 0 - name: Setup Python - uses: actions/setup-python@v5 + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 with: python-version: "3.12" # install the python version needed - name: Setup Pages id: pages - uses: actions/configure-pages@v5 + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 - name: Install Node.js dependencies run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true" @@ -82,12 +84,15 @@ jobs: working-directory: . - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 with: path: ./public # Deployment job deploy: + permissions: + pages: write + id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} @@ -95,6 +100,11 @@ jobs: needs: build if: github.ref == 'refs/heads/main' steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/.github/workflows/pr-title-check.yml b/.github/workflows/pr-title-check.yml index 8653fa4ef..612ab6317 100644 --- a/.github/workflows/pr-title-check.yml +++ b/.github/workflows/pr-title-check.yml @@ -7,11 +7,22 @@ on: - edited - synchronize +permissions: + contents: read + jobs: main: + permissions: + pull-requests: read # for amannn/action-semantic-pull-request to analyze PRs + statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR name: Validate PR Title runs-on: ubuntu-latest steps: - - uses: amannn/action-semantic-pull-request@v5 + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + + - uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5.5.3 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index a24f74d09..422d9e6c9 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -1,20 +1,13 @@ -# 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. - -name: Scorecard supply-chain security +name: Scorecard analysis workflow on: - # For Branch-Protection check. Only the default branch is supported. See - # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection - branch_protection_rule: - # To guarantee Maintained check is occasionally updated. See - # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained - schedule: - - cron: '20 1 * * 4' push: - branches: [ "main" ] + # Only the default branch is supported. + branches: + - main + schedule: + # Weekly on Saturdays. + - cron: '30 1 * * 6' -# Declare default permissions as read only. permissions: read-all jobs: @@ -22,17 +15,18 @@ jobs: name: Scorecard analysis runs-on: ubuntu-latest permissions: - # Needed to upload the results to code-scanning dashboard. + # Needed for Code scanning upload security-events: write - # Needed to publish results and get a badge (see publish_results below). + # Needed for GitHub OIDC token if publish_results is true id-token: write - # Uncomment the permissions below if installing in a private repository. - # contents: read - # actions: read - steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + - name: "Checkout code" - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: persist-credentials: false @@ -41,25 +35,18 @@ jobs: with: results_file: results.sarif results_format: sarif - # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: - # - you want to enable the Branch-Protection check on a *public* repository, or - # - you are installing Scorecard on a *private* repository - # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. - repo_token: ${{ secrets.SCORECARD_TOKEN }} - - # Public repositories: - # - Publish results to OpenSSF REST API for easy access by consumers - # - Allows the repository to include the Scorecard badge. - # - See https://github.com/ossf/scorecard-action#publishing-results. - # For private repositories: - # - `publish_results` will always be set to `false`, regardless - # of the value entered here. + # Scorecard team runs a weekly scan of public GitHub repos, + # see https://github.com/ossf/scorecard#public-data. + # Setting `publish_results: true` helps us scale by leveraging your workflow to + # extract the results instead of relying on our own infrastructure to run scans. + # And it's free for you! publish_results: true - # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF - # format to the repository Actions tab. + # Upload the results as artifacts (optional). Commenting out will disable + # uploads of run results in SARIF format to the repository Actions tab. + # https://docs.github.com/en/actions/advanced-guides/storing-workflow-data-as-artifacts - name: "Upload artifact" - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: SARIF file path: results.sarif @@ -68,6 +55,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@461ef6c76dfe95d5c364de2f431ddbd31a417628 # v3.26.9 + uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 with: sarif_file: results.sarif diff --git a/.github/workflows/validate-queries.yml b/.github/workflows/validate-queries.yml index 6ef7c7b5e..1280ac2b3 100644 --- a/.github/workflows/validate-queries.yml +++ b/.github/workflows/validate-queries.yml @@ -15,11 +15,12 @@ on: workflow_dispatch: {} permissions: - id-token: write # This is required for requesting the JWT contents: read # This is required for actions/checkout jobs: kql_file_check: + permissions: + id-token: write # This is required for requesting the JWT runs-on: ubuntu-latest if: | ( @@ -41,11 +42,23 @@ jobs: ) steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + with: + ref: "refs/pull/${{ github.event.number }}/merge" + fetch-depth: 2 + + - name: Sanity Check + run: | + [[ "$(git rev-parse 'HEAD^2')" == "${{ github.event.pull_request.head.sha }}" ]] - name: Azure login (OIDC) - uses: azure/login@v2 + uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 if: with: client-id: ${{ secrets.AZURE_CLIENT_ID }} diff --git a/.github/workflows/validate-recommendations.yml b/.github/workflows/validate-recommendations.yml index 40bf937a3..e5eec779a 100644 --- a/.github/workflows/validate-recommendations.yml +++ b/.github/workflows/validate-recommendations.yml @@ -9,15 +9,23 @@ on: - '**/*.yaml' workflow_dispatch: {} +permissions: + contents: read + jobs: yaml_file_check: runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - name: Set up Python 3.x - uses: actions/setup-python@v5 + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 with: python-version: 3.x diff --git a/CODEOWNERS b/CODEOWNERS index 41c83768e..53b16ad7f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,9 +1,7 @@ # The aprl-maintainers team is responsible for reviewing and merging all PRs - * @Azure/aprl-maintainers ## The aprl-networking team is partially responsible for all networking-related PRs - azure-resources/Cdn @Azure/aprl-maintainers @Azure/aprl-networking azure-resources/Network @Azure/aprl-maintainers @Azure/aprl-networking azure-resources/NetworkCloud @Azure/aprl-maintainers @Azure/aprl-networking @@ -12,19 +10,28 @@ azure-resources/Peerings @Azure/aprl-maintainers @Azure/aprl-networking azure-resources/Relay @Azure/aprl-maintainers @Azure/aprl-networking ## The aprl-sap team is partially responsible for all SAP-related PRs - azure-specialized-workloads/sap @Azure/aprl-maintainers @Azure/aprl-sap ## The aprl-hpc team is partially responsible for all HPC-related PRs - azure-resources/Batch @Azure/aprl-maintainers @Azure/aprl-hpc azure-specialized-workloads/hpc @Azure/aprl-maintainers @Azure/aprl-hpc ## The aprl-avd team is partially responsible for all AVD-related PRs - azure-resources/DesktopVirtualization @Azure/aprl-maintainers @Azure/aprl-avd azure-specialized-workloads/avd @Azure/aprl-maintainers @Azure/aprl-avd -## The aprl-wara-tools team is responsible for all WARA tools-related PRs - +## The aprl-wara-tools team is partially responsible for all WARA tools-related PRs tools @Azure/aprl-wara-tools + +## The aprl-cosmosdb team is responsible for all CosmosDB-related PRs +azure-resources/DocumentDB/databaseAccounts @Azure/aprl-maintainers @Azure/aprl-cosmosdb + +## The aprl-mysql team is responsible for all MySQL-related PRs +azure-resources/DBforMySQL @Azure/aprl-maintainers @Azure/aprl-mysql + +## The aprl-postgres team is responsible for all PostgreSQL-related PRs +azure-resources/DBforPostgreSQL @Azure/aprl-maintainers @Azure/aprl-postgres + +## The aprl-sql team is responsible for all SQL-related PRs +azure-resources/SQL @Azure/aprl-maintainers @Azure/aprl-sql +azure-resources/SQLVirtualMachines @Azure/aprl-maintainers @Azure/aprl-sql diff --git a/azure-specialized-workloads/avd/kql/4b1a45af-d35f-442d-922a-a3e7b6052de1.kql b/azure-resources/Compute/galleries/kql/b14ee8ed-7d27-447b-b6fb-6472cb5f4b75.kql similarity index 95% rename from azure-specialized-workloads/avd/kql/4b1a45af-d35f-442d-922a-a3e7b6052de1.kql rename to azure-resources/Compute/galleries/kql/b14ee8ed-7d27-447b-b6fb-6472cb5f4b75.kql index 825659376..614a7f9ca 100644 --- a/azure-specialized-workloads/avd/kql/4b1a45af-d35f-442d-922a-a3e7b6052de1.kql +++ b/azure-resources/Compute/galleries/kql/b14ee8ed-7d27-447b-b6fb-6472cb5f4b75.kql @@ -1,2 +1 @@ // under-development - diff --git a/azure-resources/Compute/galleries/kql/b3c3ba1d-7de6-442d-8c50-023330fbf765.kql b/azure-resources/Compute/galleries/kql/b3c3ba1d-7de6-442d-8c50-023330fbf765.kql new file mode 100644 index 000000000..614a7f9ca --- /dev/null +++ b/azure-resources/Compute/galleries/kql/b3c3ba1d-7de6-442d-8c50-023330fbf765.kql @@ -0,0 +1 @@ +// under-development diff --git a/azure-resources/Compute/galleries/recommendations.yaml b/azure-resources/Compute/galleries/recommendations.yaml index 156325e4f..d952a6f72 100644 --- a/azure-resources/Compute/galleries/recommendations.yaml +++ b/azure-resources/Compute/galleries/recommendations.yaml @@ -57,3 +57,39 @@ url: "https://learn.microsoft.com/en-us/windows-server/virtualization/hyper-v/plan/should-i-create-a-generation-1-or-2-virtual-machine-in-hyper-v" - name: Images in Compute gallery url: "https://learn.microsoft.com/en-us/azure/virtual-machines/shared-image-galleries?tabs=azure-cli" + +- description: Create Image Versions replicas in secondary region + aprlGuid: b14ee8ed-7d27-447b-b6fb-6472cb5f4b75 + recommendationTypeId: null + recommendationControl: Disaster Recovery + recommendationImpact: Medium + recommendationResourceType: Microsoft.Compute/galleries + recommendationMetadataState: Active + longDescription: | + On multi-region deployments, replicate Image Versions to a secondary region to ensure disaster recovery capability. This ensures that the Image Versions are available in the secondary region in case of a disaster in the primary region. + potentialBenefits: Enhances disaster recovery capability + pgVerified: true + publishedToLearn: false + automationAvailable: true + tags: null + learnMoreLink: + - name: Compute Gallery Replication + url: "https://learn.microsoft.com/azure/virtual-machines/azure-compute-gallery#replication" + +- description: Configure Image version replica count per region. + aprlGuid: b3c3ba1d-7de6-442d-8c50-023330fbf765 + recommendationTypeId: null + recommendationControl: Disaster Recovery + recommendationImpact: Medium + recommendationResourceType: Microsoft.Compute/galleries + recommendationMetadataState: Active + longDescription: | + You can set a different replica count in each target region, based on the scale needs for the region. For every 20 VMs that you create concurrently, we recommend you keep one replica. + potentialBenefits: Enhances disaster recovery capability + pgVerified: true + publishedToLearn: false + automationAvailable: true + tags: null + learnMoreLink: + - name: Compute Gallery Scaling + url: "https://learn.microsoft.com/en-us/azure/virtual-machines/azure-compute-gallery#scaling" diff --git a/azure-resources/Compute/virtualMachines/kql/587ca3e4-113b-4c4f-b4e0-92cd8d2065b6.kql b/azure-resources/Compute/virtualMachines/kql/587ca3e4-113b-4c4f-b4e0-92cd8d2065b6.kql new file mode 100644 index 000000000..62b578dfe --- /dev/null +++ b/azure-resources/Compute/virtualMachines/kql/587ca3e4-113b-4c4f-b4e0-92cd8d2065b6.kql @@ -0,0 +1,2 @@ +// cannot-be-validated-with-arg + diff --git a/azure-resources/Compute/virtualMachines/recommendations.yaml b/azure-resources/Compute/virtualMachines/recommendations.yaml index ef4b9027c..28e541fff 100644 --- a/azure-resources/Compute/virtualMachines/recommendations.yaml +++ b/azure-resources/Compute/virtualMachines/recommendations.yaml @@ -523,3 +523,21 @@ learnMoreLink: - name: How to update the Azure Linux Agent on a VM url: "https://learn.microsoft.com/en-us/azure/virtual-machines/extensions/update-linux-agent?tabs=ubuntu" + +- description: Reserve Compute Capacity in Disaster Recovery Regions + aprlGuid: 587ca3e4-113b-4c4f-b4e0-92cd8d2065b6 + recommendationTypeId: null + recommendationControl: Disaster Recovery + recommendationImpact: Medium + recommendationResourceType: Microsoft.Compute/virtualMachines + recommendationMetadataState: Active + longDescription: | + On-Demand Capacity Reservations ensure recovery of virtual machines in the event of a natural disaster by reserving compute capacity in advance within a specific region or zone. This guarantees that VMs have the necessary resources during disaster recovery failover events thus reducing downtime. + potentialBenefits: Guaranteed capacity in disaster recovery regions + pgVerified: true + publishedToLearn: false + automationAvailable: false + tags: null + learnMoreLink: + - name: On-demand Capacity Reservation + url: "https://aka.ms/on-demand-capacity-reservations-docs" diff --git a/azure-resources/ContainerService/managedClusters/kql/0611251f-e70f-4243-8ddd-cfe894bec2e7.kql b/azure-resources/ContainerService/managedClusters/kql/0611251f-e70f-4243-8ddd-cfe894bec2e7.kql index 05e2ed782..a8f51821f 100644 --- a/azure-resources/ContainerService/managedClusters/kql/0611251f-e70f-4243-8ddd-cfe894bec2e7.kql +++ b/azure-resources/ContainerService/managedClusters/kql/0611251f-e70f-4243-8ddd-cfe894bec2e7.kql @@ -1,7 +1,6 @@ // Azure Resource Graph Query -// Returns all AKS clusters not running on the Standard tier +// Returns all AKS clusters not running on the Standard tier or the Premium tier. resources -| where type == "microsoft.containerservice/managedclusters" -| where sku.tier != "Standard" -| project recommendationId="0611251f-e70f-4243-8ddd-cfe894bec2e7", id, name, tags, param1=strcat("skuName: ", sku.name), param2=strcat("skuTier: ", sku.tier) - +| where type =~ "Microsoft.ContainerService/managedClusters" +| where sku.tier !in~ ("Standard", "Premium") +| project recommendationId = "0611251f-e70f-4243-8ddd-cfe894bec2e7", id, name, tags, param1 = strcat("skuName: ", sku.name), param2 = strcat("skuTier: ", sku.tier) diff --git a/azure-resources/ContainerService/managedClusters/recommendations.yaml b/azure-resources/ContainerService/managedClusters/recommendations.yaml index 37ae3f702..1bf1e40fc 100644 --- a/azure-resources/ContainerService/managedClusters/recommendations.yaml +++ b/azure-resources/ContainerService/managedClusters/recommendations.yaml @@ -206,7 +206,7 @@ - name: Azure Container Instances url: "https://learn.microsoft.com/azure/container-instances/container-instances-overview" -- description: Update AKS tier to Standard +- description: Update AKS tier to Standard or Premium aprlGuid: 0611251f-e70f-4243-8ddd-cfe894bec2e7 recommendationTypeId: null recommendationControl: High Availability @@ -214,7 +214,7 @@ recommendationResourceType: Microsoft.ContainerService/managedClusters recommendationMetadataState: Active longDescription: | - Production AKS clusters require the Standard tier for a financially backed SLA and enhanced node scalability, as the free service lacks these features. + Production AKS clusters require the Standard or Premium tier for a financially backed SLA and enhanced node scalability, as the free service lacks these features. Use the Premium tier for mission-critical workloads. potentialBenefits: SLA guarantee and better scalability pgVerified: true publishedToLearn: false diff --git a/azure-resources/DBforPostgreSQL/flexibleServers/kql/2ab85a67-26be-4ed2-a0bb-101b2513ec63.kql b/azure-resources/DBforPostgreSQL/flexibleServers/kql/2ab85a67-26be-4ed2-a0bb-101b2513ec63.kql index 958d98acf..237d4c9fa 100644 --- a/azure-resources/DBforPostgreSQL/flexibleServers/kql/2ab85a67-26be-4ed2-a0bb-101b2513ec63.kql +++ b/azure-resources/DBforPostgreSQL/flexibleServers/kql/2ab85a67-26be-4ed2-a0bb-101b2513ec63.kql @@ -1,6 +1,8 @@ // Azure Resource Graph Query -// Find Database for PostgreSQL instances that are read replicas +// Find Database for PostgreSQL instances that do not have read replicas resources -| where type == "microsoft.dbforpostgresql/flexibleservers" -| where properties.replicationRole == "AsyncReplica" -| project recommendationId = "2ab85a67-26be-4ed2-a0bb-101b2513ec63", name, id, tags, param1 = strcat("replicationRole:", properties['replicationRole']) +| where type == "microsoft.dbforpostgresql/flexibleservers" and properties.replicationRole == "AsyncReplica" +| project replicaServerId = id, id = tostring(properties.sourceServerResourceId) +| join kind=fullouter (resources | where type == "microsoft.dbforpostgresql/flexibleservers" and properties.replicationRole != "AsyncReplica") on id +| where isempty(replicaServerId) +| project recommendationId = "2ab85a67-26be-4ed2-a0bb-101b2513ec63", name, id = id1, tags, param1 = strcat("replicationRole:", properties['replicationRole']) diff --git a/azure-resources/Dashboard/_index.md b/azure-resources/Dashboard/_index.md new file mode 100644 index 000000000..00253f673 --- /dev/null +++ b/azure-resources/Dashboard/_index.md @@ -0,0 +1,5 @@ +--- +title: Dashboard +geekdocCollapseSection: true +geekdocHidden: false +--- diff --git a/azure-resources/Dashboard/grafana/_index.md b/azure-resources/Dashboard/grafana/_index.md new file mode 100644 index 000000000..ce121b420 --- /dev/null +++ b/azure-resources/Dashboard/grafana/_index.md @@ -0,0 +1,7 @@ +--- +title: grafana +geekdocCollapseSection: true +geekdocHidden: false +--- + +{{< azure-resources-recommendationlist name="azure-resources-recommendationlist" >}} diff --git a/azure-resources/Dashboard/grafana/kql/6cd57b65-ef84-4088-9ada-c0d8de74c2f7.kql b/azure-resources/Dashboard/grafana/kql/6cd57b65-ef84-4088-9ada-c0d8de74c2f7.kql new file mode 100644 index 000000000..ceb9926cf --- /dev/null +++ b/azure-resources/Dashboard/grafana/kql/6cd57b65-ef84-4088-9ada-c0d8de74c2f7.kql @@ -0,0 +1,14 @@ +// Azure Resource Graph Query +// Provides a list of Azure Managed Grafana resources that do not zone redundancy enabled. +resources +| where type =~ "Microsoft.Dashboard/grafana" +| extend zoneRedundancy = properties.zoneRedundancy +| where zoneRedundancy !~ "Enabled" +| project + recommendationId = "6cd57b65-ef84-4088-9ada-c0d8de74c2f7", + name, + id, + tags, + param1 = strcat("location: ", location), + param2 = strcat("sku: ", sku.name), + param3 = strcat("zoneRedundancy: ", zoneRedundancy) diff --git a/azure-resources/Dashboard/grafana/recommendations.yaml b/azure-resources/Dashboard/grafana/recommendations.yaml new file mode 100644 index 000000000..be213a1a9 --- /dev/null +++ b/azure-resources/Dashboard/grafana/recommendations.yaml @@ -0,0 +1,19 @@ +- description: Enable zone redundancy in Managed Grafana + aprlGuid: 6cd57b65-ef84-4088-9ada-c0d8de74c2f7 + recommendationTypeId: null + recommendationControl: High Availability + recommendationImpact: Medium + recommendationResourceType: Microsoft.Dashboard/grafana + recommendationMetadataState: Active + longDescription: | + Managed Grafana Standard tier is hosted on a dedicated set of VMs to provide redundancy. With zone redundancy enabled, VMs are spread across availability zones (AZ). Related resources are also configured for AZ. Zone redundancy can only be enabled when creating the Azure Managed Grafana instance. + potentialBenefits: Enhanced Managed Grafana resilience to failures + pgVerified: false + publishedToLearn: false + automationAvailable: true + tags: null + learnMoreLink: + - name: Azure Managed Grafana service reliability + url: "https://learn.microsoft.com/azure/managed-grafana/high-availability" + - name: Enable zone redundancy in Azure Managed Grafana + url: "https://learn.microsoft.com/Azure/managed-grafana/how-to-enable-zone-redundancy" diff --git a/azure-resources/DesktopVirtualization/hostPools/recommendations.yaml b/azure-resources/DesktopVirtualization/hostPools/recommendations.yaml index 20066cedc..bd58c9158 100644 --- a/azure-resources/DesktopVirtualization/hostPools/recommendations.yaml +++ b/azure-resources/DesktopVirtualization/hostPools/recommendations.yaml @@ -1,4 +1,4 @@ -- description: Create a validation host pool for testing of planned updates +- description: Create a validation host pool aprlGuid: 013ac34e-7c4b-425f-9e0c-216f0cc06181 recommendationTypeId: null recommendationControl: Governance @@ -6,7 +6,7 @@ recommendationResourceType: Microsoft.DesktopVirtualization/hostPools recommendationMetadataState: Active longDescription: | - Create a Validation Pool for early issue detection with planned AVD updates. Adjust limits based on needs. Scale by adding multiple host pools for more users. Regularly test updates on host pools. Validate changes before applying to main environment to avoid downtime. + Validation host pools let you monitor service updates before the service applies them to your standard or non-validation environment. potentialBenefits: Enhanced environment stability pgVerified: true publishedToLearn: false @@ -24,7 +24,7 @@ recommendationResourceType: Microsoft.DesktopVirtualization/hostPools recommendationMetadataState: Active longDescription: | - Create maintenance schedules for AVD agent updates to avoid disruptions. Use Scheduled Agent Updates to set maintenance windows for updating Azure Virtual Desktop agent, side-by-side stack, and Geneva Monitoring agent. + Create up to two maintenance windows for the Azure Virtual Desktop agent, side-by-side stack, and Geneva Monitoring agent to get updated so that updates don't happen during peak business hours. potentialBenefits: Enhanced environment stability pgVerified: true publishedToLearn: false @@ -42,7 +42,7 @@ recommendationResourceType: Microsoft.DesktopVirtualization/hostPools recommendationMetadataState: Active longDescription: | - For optimized AVD configuration, place Hybrid VMs in unique OUs. Segregate Prod and DR units for environment-specific settings. This ensures targeted configurations for session hosts, including FSLogix, timeouts, and session controls. + Place domain joined session hosts VMs in unique OUs. Segregate Prod and DR units for environment-specific settings. This ensures targeted configurations for session hosts, including FSLogix, session controls, etc. potentialBenefits: Improved AVD hostpool config & segmentation pgVerified: true publishedToLearn: false @@ -52,7 +52,7 @@ - name: Configure the VMs and install Active Directory Domain Services url: "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/deploy/virtual-dc/adds-on-azure-vm#configure-the-vms-and-install-active-directory-domain-services" -- description: Use Azure Site Recovery or backups to protect VMs supporting personal desktops +- description: Use Azure Site Recovery to protect stateful session hosts aprlGuid: 38721758-2cc2-4d6b-b7b7-8b47dadbf7df recommendationTypeId: null recommendationControl: Disaster Recovery @@ -60,7 +60,7 @@ recommendationResourceType: Microsoft.Compute/virtualMachines recommendationMetadataState: Active longDescription: | - Implement Azure Site Recovery (ASR) or Azure Backup for personal host pools to enable seamless failover and failback. This replicates VMs supporting personal desktops to a secondary Azure region, ensuring recovery from a known state in case of a disaster or outage. + Implement Azure Site Recovery (ASR) to replicate or backup stateful session hosts. This replicates VMs to a secondary Azure region or availability zone, ensuring recovery from a known VM state in case of an outage. potentialBenefits: Ensures VM recovery & failover pgVerified: true publishedToLearn: false diff --git a/azure-resources/DesktopVirtualization/scalingPlans/recommendations.yaml b/azure-resources/DesktopVirtualization/scalingPlans/recommendations.yaml index 882a2038f..48f963ace 100644 --- a/azure-resources/DesktopVirtualization/scalingPlans/recommendations.yaml +++ b/azure-resources/DesktopVirtualization/scalingPlans/recommendations.yaml @@ -1,4 +1,4 @@ -- description: Scaling plans should be created per region and not scaled across regions +- description: Create scaling plans per region aprlGuid: 499769ae-67c9-492e-9ca5-cfd4cece5209 recommendationTypeId: null recommendationControl: Scalability @@ -6,7 +6,7 @@ recommendationResourceType: Microsoft.DesktopVirtualization/scalingPlans recommendationMetadataState: Active longDescription: | - Each region has its own scaling plans assigned to host pools within that region. However, these plans can become inaccessible if there's a regional failure. To mitigate this risk, it's advisable to create a secondary scaling plan in another region. + Scaling plans can only be assigned to host pools in the same region, on multi-region deployment scenario each region should has its own scaling plan. potentialBenefits: Enhanced scaling pgVerified: true publishedToLearn: false diff --git a/azure-resources/Network/connections/kql/f6a14b32-a727-4ace-b5fa-7b1c6bdff402.kql b/azure-resources/Network/connections/kql/f6a14b32-a727-4ace-b5fa-7b1c6bdff402.kql index 825659376..57dc44f03 100644 --- a/azure-resources/Network/connections/kql/f6a14b32-a727-4ace-b5fa-7b1c6bdff402.kql +++ b/azure-resources/Network/connections/kql/f6a14b32-a727-4ace-b5fa-7b1c6bdff402.kql @@ -1,2 +1,19 @@ -// under-development - +// Azure Resource Graph Query +// Find all ExpressRoute Connections that are connected to ErGw3AZ or UltraPerformance gateway sku that don't have +// FastPath enabled for both the Gateway Bypass or Private Endpoint/Link service. +resources +| where type == "microsoft.network/connections" +| where properties.connectionType =~ 'expressroute' +| extend gatewayId = tostring(properties.virtualNetworkGateway1.id) +| join kind=inner ( + resources + | where type =~ "Microsoft.Network/virtualNetworkGateways" + | where properties.sku.name in~ ("ErGw3AZ", "UltraPerformance") + | extend gatewayId = tostring(id) +) on gatewayId +| extend erGatewayBypass = tobool(properties.expressRouteGatewayBypass) +| extend privateLinkFastPath = tobool(properties.enablePrivateLinkFastPath) +| where not(erGatewayBypass) or not(privateLinkFastPath) +| project recommendationId = "f6a14b32-a727-4ace-b5fa-7b1c6bdff402", id, name, tags, + param1 = iff(erGatewayBypass, "Enabled: Gateway Bypass", "Disabled: Gateway Bypass"), + param2 = iff(privateLinkFastPath, "Enabled: PE FastPath", "Disabled: PE FastPath") diff --git a/azure-resources/Network/connections/recommendations.yaml b/azure-resources/Network/connections/recommendations.yaml index 200e269fd..e7cf00e00 100644 --- a/azure-resources/Network/connections/recommendations.yaml +++ b/azure-resources/Network/connections/recommendations.yaml @@ -1,4 +1,4 @@ -- description: For better data path performance enable FastPath on ExpressRoute Direct and Gateway +- description: For better data path performance enable FastPath on ExpressRoute Connections aprlGuid: f6a14b32-a727-4ace-b5fa-7b1c6bdff402 recommendationTypeId: null recommendationControl: Scalability diff --git a/azure-resources/Resources/resourceGroups/kql/98bd7098-49d6-491b-86f1-b143d6b1a0ff.kql b/azure-resources/Resources/resourceGroups/kql/98bd7098-49d6-491b-86f1-b143d6b1a0ff.kql index 0c313399e..f8cef9ca4 100644 --- a/azure-resources/Resources/resourceGroups/kql/98bd7098-49d6-491b-86f1-b143d6b1a0ff.kql +++ b/azure-resources/Resources/resourceGroups/kql/98bd7098-49d6-491b-86f1-b143d6b1a0ff.kql @@ -1,13 +1,22 @@ // Azure Resource Graph Query // Provides a list of Azure Resource Groups that have resources deployed in a region different than the Resource Group region -resources -| project id, name, tags, resourceGroup, location -| where location != "global" // exclude global resources -| where resourceGroup != "networkwatcherrg" // exclude networkwatcherrg -| where split(id, "/", 3)[0] =~ "resourceGroups" // resource is in a resource group -| extend resourceGroupId = strcat_array(array_slice(split(id, "/"),0,4), "/") // create resource group resource id -| join (resourcecontainers | project containerid=id, containerlocation=location ) on $left.resourceGroupId == $right.['containerid'] // join to resourcecontainers table -| where location != containerlocation -| project recommendationId="98bd7098-49d6-491b-86f1-b143d6b1a0ff", name, id, tags -| order by id asc - +resourcecontainers +| where type =~ "Microsoft.Resources/subscriptions/resourceGroups" +| project resourceGroupId = tolower(id), resourceGroupLocation = location +| join kind = inner ( + resources + | where location !~ "Global" and // Exclude global resources + resourceGroup !~ "NetworkWatcherRG" and // Exclude resources in the NetworkWatcherRG + id has "/resourceGroups/" // Exclude resources not in a resource group + | project id, name, tags, resourceGroup, location, resourceGroupId = tolower(strcat_array(array_slice(split(id, "/"), 0, 4), "/")) + ) + on resourceGroupId +| where resourceGroupLocation !~ location +| project + recommendationId = "98bd7098-49d6-491b-86f1-b143d6b1a0ff", + name, + id, + tags, + param1 = strcat("resourceLocation: ", location), + param2 = strcat("resourceGroupLocation: ", resourceGroupLocation), + param3 = strcat("resourceGroup: ", resourceGroup) diff --git a/azure-resources/ServiceBus/namespaces/kql/f075a1bd-de9e-4819-9a1d-1ac41037a74f.kql b/azure-resources/ServiceBus/namespaces/kql/f075a1bd-de9e-4819-9a1d-1ac41037a74f.kql new file mode 100644 index 000000000..6c18e8f15 --- /dev/null +++ b/azure-resources/ServiceBus/namespaces/kql/f075a1bd-de9e-4819-9a1d-1ac41037a74f.kql @@ -0,0 +1,11 @@ +// Azure Resource Graph Query +// Provides a list of Service Bus Namespace resources that have the lower minimum TLS version. +resources +| where type =~ "Microsoft.ServiceBus/namespaces" +| where properties.minimumTlsVersion in ("1.0", "1.1") +| project + recommendationId = "f075a1bd-de9e-4819-9a1d-1ac41037a74f", + name, + id, + tags, + param1 = strcat("minimumTlsVersion: ", properties.minimumTlsVersion) diff --git a/azure-resources/ServiceBus/namespaces/recommendations.yaml b/azure-resources/ServiceBus/namespaces/recommendations.yaml index 31f38e061..13e886adf 100644 --- a/azure-resources/ServiceBus/namespaces/recommendations.yaml +++ b/azure-resources/ServiceBus/namespaces/recommendations.yaml @@ -37,3 +37,23 @@ learnMoreLink: - name: Service Bus auto-scaling url: "https://learn.microsoft.com/azure/service-bus-messaging/automate-update-messaging-units" + +- description: Configure the minimum TLS version for Service Bus namespaces to TLS v1.2 or higher + aprlGuid: f075a1bd-de9e-4819-9a1d-1ac41037a74f + recommendationTypeId: null + recommendationControl: Service Upgrade and Retirement + recommendationImpact: High + recommendationResourceType: Microsoft.ServiceBus/namespaces + recommendationMetadataState: Active + longDescription: | + As of 31 October 2024, TLS 1.0 and TLS 1.1 will no longer be supported on Azure including Service Bus to enhance security and provide best-in-class encryption for your data. Change the minimum TLS version for your Service Bus namespace to TLS v1.2 or higher. + potentialBenefits: Avoids service disruption + pgVerified: false + publishedToLearn: false + automationAvailable: true + tags: null + learnMoreLink: + - name: Azure support for TLS 1.0 and TLS 1.1 will end by 31 October 2024 + url: "https://azure.microsoft.com/updates/azure-support-tls-will-end-by-31-october-2024-2/" + - name: Configure the minimum TLS version for a Service Bus namespace + url: "https://learn.microsoft.com/azure/service-bus-messaging/transport-layer-security-configure-minimum-version" diff --git a/azure-resources/Sql/managedInstances/kql/15e2712c-f3ea-4a8d-9081-11e822b1ccfb.kql b/azure-resources/Sql/managedInstances/kql/15e2712c-f3ea-4a8d-9081-11e822b1ccfb.kql index 825659376..c17635fde 100644 --- a/azure-resources/Sql/managedInstances/kql/15e2712c-f3ea-4a8d-9081-11e822b1ccfb.kql +++ b/azure-resources/Sql/managedInstances/kql/15e2712c-f3ea-4a8d-9081-11e822b1ccfb.kql @@ -1,2 +1,8 @@ -// under-development - +// Azure Resource Graph Query +// Managed Instance storage backup redundancy check – any server that is not configured for GZRS +resources +| where type =~ 'Microsoft.Sql/managedInstances' +| extend backupredundancy=properties.storageAccountType +| extend ServiceTier = sku.tier +| where backupredundancy != 'GeoZone' +| project recommendationId='15e2712c-f3ea-4a8d-9081-11e822b1ccfb', name, id, param1=strcat('Service Tier:', ServiceTier), param2=strcat('Backup Redundancy:', backupredundancy) diff --git a/azure-resources/Sql/managedInstances/kql/257cd903-700f-4a79-bd37-7dce2b511df4.kql b/azure-resources/Sql/managedInstances/kql/257cd903-700f-4a79-bd37-7dce2b511df4.kql index 825659376..fa5cad258 100644 --- a/azure-resources/Sql/managedInstances/kql/257cd903-700f-4a79-bd37-7dce2b511df4.kql +++ b/azure-resources/Sql/managedInstances/kql/257cd903-700f-4a79-bd37-7dce2b511df4.kql @@ -1,2 +1 @@ -// under-development - +// cannot-be-validated-with-arg diff --git a/azure-resources/Sql/managedInstances/kql/9fad5392-b852-4807-9b6d-3f700ff9771a.kql b/azure-resources/Sql/managedInstances/kql/9fad5392-b852-4807-9b6d-3f700ff9771a.kql index 825659376..fa5cad258 100644 --- a/azure-resources/Sql/managedInstances/kql/9fad5392-b852-4807-9b6d-3f700ff9771a.kql +++ b/azure-resources/Sql/managedInstances/kql/9fad5392-b852-4807-9b6d-3f700ff9771a.kql @@ -1,2 +1 @@ -// under-development - +// cannot-be-validated-with-arg diff --git a/azure-resources/Sql/managedInstances/kql/c14de326-2729-4be7-a91f-4ea185d24b10.kql b/azure-resources/Sql/managedInstances/kql/c14de326-2729-4be7-a91f-4ea185d24b10.kql index 825659376..387aab175 100644 --- a/azure-resources/Sql/managedInstances/kql/c14de326-2729-4be7-a91f-4ea185d24b10.kql +++ b/azure-resources/Sql/managedInstances/kql/c14de326-2729-4be7-a91f-4ea185d24b10.kql @@ -1,2 +1,7 @@ -// under-development - +// Azure Resource Graph Query +// Use Redirect connection type to accelerate application access +resources +| where type =~ 'Microsoft.Sql/managedInstances' +| extend connectionpolicy=properties.proxyOverride +| where connectionpolicy != 'Redirect' +| project recommendationId='c14de326-2729-4be7-a91f-4ea185d24b10', name, id, tags, param1=strcat('Connection Policy:', connectionpolicy) diff --git a/azure-resources/Sql/managedInstances/kql/c9afeb1e-e706-4809-be4e-75d9fac708f2.kql b/azure-resources/Sql/managedInstances/kql/c9afeb1e-e706-4809-be4e-75d9fac708f2.kql index 825659376..fa5cad258 100644 --- a/azure-resources/Sql/managedInstances/kql/c9afeb1e-e706-4809-be4e-75d9fac708f2.kql +++ b/azure-resources/Sql/managedInstances/kql/c9afeb1e-e706-4809-be4e-75d9fac708f2.kql @@ -1,2 +1 @@ -// under-development - +// cannot-be-validated-with-arg diff --git a/azure-resources/Sql/managedInstances/kql/f8f834a9-c761-4e84-b2cb-ac55494d0c37.kql b/azure-resources/Sql/managedInstances/kql/f8f834a9-c761-4e84-b2cb-ac55494d0c37.kql index 825659376..6b1071efd 100644 --- a/azure-resources/Sql/managedInstances/kql/f8f834a9-c761-4e84-b2cb-ac55494d0c37.kql +++ b/azure-resources/Sql/managedInstances/kql/f8f834a9-c761-4e84-b2cb-ac55494d0c37.kql @@ -1,2 +1,9 @@ -// under-development - +// Azure Resource Graph Query +// Managed Instance zone redundancy check – any server that is not configured for ZR +resources +| where type =~ 'Microsoft.Sql/managedInstances' +| extend InstanceName = properties.fullyQualifiedDomainName +| extend ServiceTier = sku.tier +| extend zoneRedundant=properties.zoneRedundant +| where zoneRedundant == 'false' +| project recommendationId='f8f834a9-c761-4e84-b2cb-ac55494d0c37', name, id, tags, param1=strcat('Service Tier:', ServiceTier), param2=strcat('Zone Redundant:', zoneRedundant) diff --git a/azure-resources/Sql/managedInstances/recommendations.yaml b/azure-resources/Sql/managedInstances/recommendations.yaml index 592b63b12..be93d21d2 100644 --- a/azure-resources/Sql/managedInstances/recommendations.yaml +++ b/azure-resources/Sql/managedInstances/recommendations.yaml @@ -1,4 +1,4 @@ -- description: Enable zone redundancy for Azure SQL Managed Instance to achieve high availability and resiliency +- description: Enable zone redundancy for Azure SQL Managed Instance to improve high availability and resiliency aprlGuid: f8f834a9-c761-4e84-b2cb-ac55494d0c37 recommendationTypeId: null recommendationControl: High Availability @@ -6,11 +6,11 @@ recommendationResourceType: Microsoft.Sql/managedInstances recommendationMetadataState: Active longDescription: | - By default, Azure SQL Database premium tier provisions multiple copies within the same region. For geo redundancy, databases can be set as Zone Redundant, distributing copies across Azure Availability Zones to maintain availability during regional outages. + Azure SQL Managed Instance offers built-in availability by deploying multiple replicas in the same zone. For higher availability, use a zone-redundant configuration that spreads replicas across three Azure availability zones, each with independent power, cooling, and networking. potentialBenefits: Enhanced availability and reliability pgVerified: false publishedToLearn: false - automationAvailable: false + automationAvailable: True tags: null learnMoreLink: - name: High availability through zone-redundancy @@ -19,16 +19,16 @@ - description: Use Zone-redundant or Geo-zone-redundant Backup storage redundancy aprlGuid: 15e2712c-f3ea-4a8d-9081-11e822b1ccfb recommendationTypeId: null - recommendationControl: High Availability + recommendationControl: Disaster Recovery recommendationImpact: High recommendationResourceType: Microsoft.Sql/managedInstances recommendationMetadataState: Active longDescription: | - This copies your backups synchronously across three Azure availability zones in the primary region, if Geo is selected it creates 3 more copies in a secondary region. + Configuring zone redundancy option for backups copies your backup file synchronously across three Azure availability zones in the primary region. If Geo is selected, then it copies your data asynchronously three times to a single physical location in the paired secondary region. potentialBenefits: Enhanced availability and reliability pgVerified: false publishedToLearn: false - automationAvailable: false + automationAvailable: True tags: null learnMoreLink: - name: Backup storage redundancy @@ -42,11 +42,11 @@ recommendationResourceType: Microsoft.Sql/managedInstances recommendationMetadataState: Active longDescription: | - Redirect mode enables direct connectivity to the instance resulting in improved latency and throughput. Redirect mode applies to the VNet-local endpoint only, while the public endpoint will always default to Proxy connection mode. + Redirect mode enables direct connectivity to the instance bypassing the local gateway component and resulting in improved latency and throughput. Redirect mode applies to the VNet-local endpoint only, while the public and private endpoint will always operate in Proxy connection mode. potentialBenefits: Improved latency and throughput pgVerified: false publishedToLearn: false - automationAvailable: false + automationAvailable: True tags: null learnMoreLink: - name: Connection types @@ -60,7 +60,7 @@ recommendationResourceType: Microsoft.Sql/managedInstances recommendationMetadataState: Active longDescription: | - If an outage impacts one or more of the databases in the managed instance, you can manually or automatically failover all the databases inside the instance to a secondary region. + During an outage on the managed instance, use the failover group to switch all databases to a secondary region, either manually or automatically. Route connections to the failover group’s listener instead of the primary instance to avoid changing the connection string after geo-failover. potentialBenefits: Ensure seamless service with cross-region failover pgVerified: false publishedToLearn: false @@ -78,7 +78,7 @@ recommendationResourceType: Microsoft.Sql/servers recommendationMetadataState: Active longDescription: | - Monitoring and alerting are an important part of database operations. When working with Azure SQL Database, make use of Azure Monitor and SQL Insights to ensure that you capture relevant database metrics. + Monitoring and alerting are an important part of database operations. When working with Azure SQL Managed Instance, make use of Azure Monitor and Database watcher to ensure that you capture relevant database metrics. potentialBenefits: Quick incident detection and response pgVerified: false publishedToLearn: false @@ -86,7 +86,7 @@ tags: null learnMoreLink: - name: Azure SQL Managed Instance monitoring options - url: "https://techcommunity.microsoft.com/t5/azure-sql/monitoring-options-available-for-azure-sql-managed-instance/ba-p/1065416" + url: "https://learn.microsoft.com/azure/azure-sql/managed-instance/monitoring-sql-managed-instance-azure-monitor?view=azuresql-mi" - description: Back Up Your Keys aprlGuid: 9fad5392-b852-4807-9b6d-3f700ff9771a diff --git a/azure-resources/Storage/storageAccounts/kql/dc55be60-6f8c-461e-a9d5-a3c7686ed94e.kql b/azure-resources/Storage/storageAccounts/kql/dc55be60-6f8c-461e-a9d5-a3c7686ed94e.kql index 0dd9340cd..d17752b32 100644 --- a/azure-resources/Storage/storageAccounts/kql/dc55be60-6f8c-461e-a9d5-a3c7686ed94e.kql +++ b/azure-resources/Storage/storageAccounts/kql/dc55be60-6f8c-461e-a9d5-a3c7686ed94e.kql @@ -3,6 +3,6 @@ resources | where type =~ "Microsoft.Storage/StorageAccounts" | where isnull(properties.privateEndpointConnections) or properties.privateEndpointConnections[0].properties.provisioningState != ("Succeeded") or (isnull(properties.networkAcls) and properties.publicNetworkAccess == 'Enabled') -| extend param1 = strcat('Private Endpoint: ', iif(isnotnull(properties.privateEndpointConnections),split(properties.privateEndpointConnections[0].properties.privateEndpoint.id,'/')[8],'No Private Endpoint')) +| extend param1 = strcat('Private Endpoint: ', iif(array_length(properties.privateEndpointConnections) != 0,split(properties.privateEndpointConnections[0].properties.privateEndpoint.id,'/')[8],'No Private Endpoint')) | extend param2 = strcat('Access: ', iif(properties.publicNetworkAccess == 'Disabled', 'Public Access Disabled', iif(isnotnull(properties.networkAcls), 'NetworkACLs in place','Public Access Enabled'))) | project recommendationId = "dc55be60-6f8c-461e-a9d5-a3c7686ed94e", name, id, tags, param1, param2 diff --git a/azure-resources/VirtualMachineImages/imageTemplates/recommendations.yaml b/azure-resources/VirtualMachineImages/imageTemplates/recommendations.yaml index d9d89d8e6..619071f11 100644 --- a/azure-resources/VirtualMachineImages/imageTemplates/recommendations.yaml +++ b/azure-resources/VirtualMachineImages/imageTemplates/recommendations.yaml @@ -24,7 +24,7 @@ recommendationResourceType: Microsoft.VirtualMachineImages/imageTemplates recommendationMetadataState: Active longDescription: | - The Azure Image Builder service, used for deploying Image Templates, lacks availability zones support. By replicating Image Templates to a secondary, preferably paired, region, quick recovery from a region failure is enabled, ensuring continuous virtual machine deployment from these templates. + The Azure Image Builder service lacks availability zones support. Replicating Image Templates to a secondary region will enable the build of new images in secondary region. potentialBenefits: Enhances disaster recovery capability pgVerified: true publishedToLearn: false @@ -32,6 +32,6 @@ tags: null learnMoreLink: - name: Image Template resiliency - url: "https://learn.microsoft.com/en-us/azure/reliability/reliability-image-builder?toc=%2Fazure%2Fvirtual-machines%2Ftoc.json&bc=%2Fazure%2Fvirtual-machines%2Fbreadcrumb%2Ftoc.json#capacity-and-proactive-disaster-recovery-resiliency" + url: "https://learn.microsoft.com/en-us/azure/reliability/reliability-image-builder?toc=%2Fazure%2Fvirtual-machines%2Ftoc.json&bc=%2Fazure%2Fvirtual-machines%2Fbreadcrumb%2Ftoc.json&tabs=graph#disaster-recovery" - name: Azure Image Builder Supported Regions url: "https://learn.microsoft.com/en-us/azure/virtual-machines/image-builder-overview?tabs=azure-powershell#regions" diff --git a/azure-resources/Web/serverFarms/recommendations.yaml b/azure-resources/Web/serverFarms/recommendations.yaml index 26750673d..5bbb32913 100644 --- a/azure-resources/Web/serverFarms/recommendations.yaml +++ b/azure-resources/Web/serverFarms/recommendations.yaml @@ -46,7 +46,7 @@ longDescription: | Avoid frequent scaling up/down of Azure App Service instances to prevent service disruptions. Choose the right tier and size for the workload and scale out for traffic changes, as scaling adjustments can trigger application restarts. potentialBenefits: Minimizes restarts, enhances stability - pgVerified: false + pgVerified: true publishedToLearn: false automationAvailable: true tags: null @@ -82,7 +82,7 @@ longDescription: | Enabling Autoscale/Automatic Scaling for your Azure App Service ensures sufficient resources for incoming requests. Autoscaling is rule-based, whereas Automatic Scaling, a newer feature, automatically adjusts resources based on HTTP traffic. potentialBenefits: Optimizes resources for traffic - pgVerified: false + pgVerified: true publishedToLearn: false automationAvailable: false tags: null diff --git a/azure-resources/Web/sites/recommendations.yaml b/azure-resources/Web/sites/recommendations.yaml index 9dcdbc108..9261bbd34 100644 --- a/azure-resources/Web/sites/recommendations.yaml +++ b/azure-resources/Web/sites/recommendations.yaml @@ -20,13 +20,13 @@ aprlGuid: a7e8bb3d-8ceb-442d-b26f-007cd63f9ffc recommendationTypeId: null recommendationControl: Monitoring and Alerting - recommendationImpact: Medium + recommendationImpact: High recommendationResourceType: Microsoft.Web/sites recommendationMetadataState: Active longDescription: | Use Application Insights to monitor app performance and load behavior, offering real-time insights, issue diagnosis, and root-cause analysis. It supports ASP.NET, ASP.NET Core, Java, and Node.js on Azure App Service, now with built-in monitoring. potentialBenefits: Real-time insights and issue diagnosis - pgVerified: false + pgVerified: true publishedToLearn: false automationAvailable: false tags: null @@ -64,7 +64,7 @@ longDescription: | Creating a separate storage account for logs and not using the same one for application data prevents logging activities from reducing application performance by ensuring that the resources dedicated to handling application data are not burdened by logging processes. potentialBenefits: Improves app performance - pgVerified: false + pgVerified: true publishedToLearn: false automationAvailable: false tags: null @@ -100,7 +100,7 @@ longDescription: | Use app settings for configuration and define them in Resource Manager templates or via PowerShell to facilitate part of an automated deployment/update process for improved reliability. potentialBenefits: Enhanced reliability via automation - pgVerified: false + pgVerified: true publishedToLearn: false automationAvailable: true tags: null @@ -112,13 +112,13 @@ aprlGuid: fd049c28-ae6d-48f0-a641-cc3ba1a3fe1d recommendationTypeId: null recommendationControl: Other Best Practices - recommendationImpact: Medium + recommendationImpact: High recommendationResourceType: Microsoft.Web/sites recommendationMetadataState: Active longDescription: | Use Health Check for production workloads. Health check increases your application's availability by rerouting requests away from unhealthy instances, and replacing instances if they remain unhealthy. The Health check path should check critical components of your application. potentialBenefits: Enhanced reliability via automation - pgVerified: false + pgVerified: true publishedToLearn: false automationAvailable: true tags: null @@ -136,7 +136,7 @@ longDescription: | Use network access restrictions to define a priority-ordered allow/deny list that controls network access to your app. Web application firewalls, such as the one available in Application Gateway, are recommended for protection of public-facing web applications. potentialBenefits: Enhanced security - pgVerified: false + pgVerified: true publishedToLearn: false automationAvailable: true tags: null @@ -148,13 +148,13 @@ aprlGuid: 9e6682ac-31bc-4635-9959-ab74b52454e6 recommendationTypeId: null recommendationControl: Scalability - recommendationImpact: Medium + recommendationImpact: High recommendationResourceType: Microsoft.Web/sites recommendationMetadataState: Active longDescription: | App Service should be configured with a minimum of two instances for production workloads. If apps have a longer warmup time a minimum of three instances should be used. potentialBenefits: Improves app performace - pgVerified: false + pgVerified: true publishedToLearn: false automationAvailable: true tags: null diff --git a/azure-specialized-workloads/avd/_index.md b/azure-specialized-workloads/avd/_index.md index dc01c6c0b..d4324854e 100644 --- a/azure-specialized-workloads/avd/_index.md +++ b/azure-specialized-workloads/avd/_index.md @@ -8,12 +8,14 @@ geekdocHidden: false | Recommendation | Provider Namespace | Resource Type | |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------:|:----------------------:| -| [Create a validation host pool for testing of planned updates](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/DesktopVirtualization/hostPools/#Create-a-validation-host-pool-for-testing-of-planned-updates) | DesktopVirtualization | hostPools | +| [Create a validation host pool](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/DesktopVirtualization/hostPools/#Create-a-validation-host-pool) | DesktopVirtualization | hostPools | | [Configure host pool scheduled agent updates](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/DesktopVirtualization/hostPools/#configure-host-pool-scheduled-agent-updates) | DesktopVirtualization | hostPools | | [Ensure a unique OU is used when deploying host pools with domain joined session hosts](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/DesktopVirtualization/hostPools/#ensure-a-unique-ou-is-used-when-deploying-host-pools-with-domain-joined-session-hosts) | DesktopVirtualization | hostPools | -| [Use Azure Site Recovery or backups to protect VMs supporting personal desktops](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/DesktopVirtualization/hostPools/#use-azure-site-recovery-or-backups-to-protect-vms-supporting-personal-desktops) | DesktopVirtualization | hostPools | -| [Scaling plans should be created per region and not scaled across regions](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/DesktopVirtualization/scalingPlans/#scaling-plans-should-be-created-per-region-and-not-scaled-across-regions) | DesktopVirtualization | scalingPlans | -| [Replicate your Image Templates to a secondary region](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/VirtualMachineImages/imageTemplates/#replicate-your-image-templates-to-a-secondary-region) | Compute | galleries | +| [Use Azure Site Recovery to protect stateful session hosts](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/DesktopVirtualization/hostPools/#use-azure-site-recovery-to-protect-stateful-session hosts) | DesktopVirtualization | hostPools | +| [Create scaling plans per region](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/DesktopVirtualization/scalingPlans/#create-scaling-plans-per-region) | DesktopVirtualization | scalingPlans | +| [Replicate your image templates to a secondary region](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/VirtualMachineImages/imageTemplates/#replicate-your-image-templates-to-a-secondary-region) | Compute | virtualMachineImages | +| [Create image Versions replicas in secondary region](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/compute/galleries/#create-image-versions-replicas-in-secondary-region) | Compute | galleries | +| [Configure image version replica count per region](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/compute/galleries/#configure-image-version-replica-count-per-region) | Compute | galleries | | [A minimum of three replicas should be kept for production image versions](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/Compute/galleries/#a-minimum-of-three-replicas-should-be-kept-for-production-image-versions) | Compute | galleries | | [Zone redundant storage should be used for image versions](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/Compute/galleries/#zone-redundant-storage-should-be-used-for-image-versions) | Compute | galleries | | [Deploy VMs across Availability Zones](../../../Azure-Proactive-Resiliency-Library-v2/azure-resources/Compute/virtualMachines/#deploy-vms-across-availability-zones) | Compute | virtualMachines | diff --git a/azure-specialized-workloads/avd/recommendations.yaml b/azure-specialized-workloads/avd/recommendations.yaml index b900a31c8..ef2ef7c49 100644 --- a/azure-specialized-workloads/avd/recommendations.yaml +++ b/azure-specialized-workloads/avd/recommendations.yaml @@ -279,25 +279,6 @@ - name: Learn More url: "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing" -- description: Ensure route tables accommodate failover - aprlGuid: 4b1a45af-d35f-442d-922a-a3e7b6052de1 - recommendationTypeId: null - recommendationControl: Disaster Recovery - recommendationImpact: High - recommendationResourceType: Specialized.Workload/AVD - recommendationMetadataState: Active - longDescription: | - Ensure Route Tables that force tunnel traffic to FW/NVA have failover considerations evaluated and won't fail or trigger next-gen FW protections. - AVD workload teams should collaborate with centralized teams that manage the shared infrastructure, like networking, to ensure that both Production and DR workloads have the appropriate route tables in place for failover of routing to perform as expected. - potentialBenefits: Enhanced failover reliability - pgVerified: true - publishedToLearn: false - automationAvailable: false - tags: - learnMoreLink: - - name: Learn More - url: "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-business-continuity-disaster-recovery" - - description: Configure static routes for session hosts to directly access the AVD control plane subnet aprlGuid: 1c6c97d7-4d03-4f53-985d-fa239f715173 recommendationTypeId: null diff --git a/docs/content/contributing/create-content/create-recommendations/_index.md b/docs/content/contributing/create-content/create-recommendations/_index.md index 3e382d923..295931234 100644 --- a/docs/content/contributing/create-content/create-recommendations/_index.md +++ b/docs/content/contributing/create-content/create-recommendations/_index.md @@ -72,7 +72,7 @@ The YAML structure for adding new recommendations consists of several key-value | recommendationTypeId | 3464854d-6f75-4922-95e4-a2a308b53ce6 | String | `null` until updated by the Azure Advisor team | The unique identifier for the recommendation in the context of Advisor. | | recommendationControl | Monitoring and Alerting | String | [High Availability, Business Continuity, Disaster Recovery, Scalability, Monitoring and Alerting, Service Upgrade and Retirement, Other Best Practices, Personalized, Governance, Security](#recommendation-categories) | Resiliency category associated with the recommendation | | recommendationImpact | Medium | String | Low, Medium, High | Importance of adopting the recommendation and/or the risk of choosing not to adopt | -| recommendationResourceType | Storage Account | String | Align with the resource type | Friendly name to identity resource type | +| recommendationResourceType | Microsoft.Storage/storageAccounts | String | Align with the resource type | Friendly name to identity resource type | | recommendationMetadataState | Active | String | Active, Disabled | Indicates whether the recommendation is visible | | longDescription | To enable Cross-region disaster recovery and business continuity, ensure that the appropriate quotas are set for all user subscription Batch accounts. | String | The length should be less than 300 characters | Detailed description of the recommendation and its implications | | potentialBenefits | Enhanced data redundancy and boosts availability | String | The length should be less than 60 characters | The potential benefits of implementing the recommendation | diff --git a/docs/layouts/shortcodes/azure-resources-recommendationlist.html b/docs/layouts/shortcodes/azure-resources-recommendationlist.html index 8f4c1f71f..c959a7d94 100644 --- a/docs/layouts/shortcodes/azure-resources-recommendationlist.html +++ b/docs/layouts/shortcodes/azure-resources-recommendationlist.html @@ -15,7 +15,6 @@

Summary

Impact Category Automation Available - PG Verified {{ range sort .recommendations "recommendation" "asc" }} @@ -27,7 +26,6 @@

Summary

{{ .recommendationImpact }} {{ .recommendationControl }} {{ if eq .automationAvailable true }}Yes{{ else }}No{{ end }} - {{ if eq .pgVerified true }}Verified{{ else }}Preview{{ end }} {{ end }} {{ end }} @@ -62,9 +60,6 @@

Category:  {{ .recommendationControl }} - PG Verified:  - {{ if eq .pgVerified true }}Verified{{ else }}Preview{{ end }} -

diff --git a/docs/layouts/shortcodes/azure-specialized-workloads-recommendationlist.html b/docs/layouts/shortcodes/azure-specialized-workloads-recommendationlist.html index e418e9f2f..c73ae6fbb 100644 --- a/docs/layouts/shortcodes/azure-specialized-workloads-recommendationlist.html +++ b/docs/layouts/shortcodes/azure-specialized-workloads-recommendationlist.html @@ -15,7 +15,6 @@

Summary

Impact Category Automation Available - PG Verified {{ range sort .recommendations "recommendation" "asc" }} @@ -27,7 +26,6 @@

Summary

{{ .recommendationImpact }} {{ .recommendationControl }} {{ if eq .automationAvailable true }}Yes{{ else }}No{{ end }} - {{ if eq .pgVerified true }}Verified{{ else }}Preview{{ end }} {{ end }} {{ end }} @@ -62,9 +60,6 @@

Category:  {{ .recommendationControl }} - PG Verified:  - {{ if eq .pgVerified true }}Verified{{ else }}Preview{{ end }} -

diff --git a/docs/layouts/shortcodes/azure-waf-recommendationlist.html b/docs/layouts/shortcodes/azure-waf-recommendationlist.html index 562609400..463ca33ca 100644 --- a/docs/layouts/shortcodes/azure-waf-recommendationlist.html +++ b/docs/layouts/shortcodes/azure-waf-recommendationlist.html @@ -14,7 +14,6 @@

Summary

Recommendation Impact Category - PG Verified {{ range sort .recommendations "recommendation" "asc" }} @@ -25,7 +24,6 @@

Summary

{{ .recommendationImpact }} {{ .recommendationControl }} - {{ if eq .pgVerified true }}Verified{{ else }}Preview{{ end }} {{ end }} {{ end }} @@ -60,9 +58,6 @@

Category:  {{ .recommendationControl }} - PG Verified:  - {{ if eq .pgVerified true }}Verified{{ else }}Preview{{ end }} -