{"id":28405935,"url":"https://github.com/ansible-lockdown/github_windows_iac","last_synced_at":"2026-01-20T16:23:05.626Z","repository":{"id":185082207,"uuid":"672930819","full_name":"ansible-lockdown/github_windows_IaC","owner":"ansible-lockdown","description":":computer: Workflow Data For Github Actions \u0026 Windows Server Testing of Lockdown Enterprise Content :computer:","archived":false,"fork":false,"pushed_at":"2026-01-20T06:49:26.000Z","size":2651,"stargazers_count":2,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"self_hosted","last_synced_at":"2026-01-20T08:26:00.667Z","etag":null,"topics":["agile-workflows","approval-workflows","automation","business-processes","collaboration-tools","cross-team-collaboration","document-workflows","process-optimization","project-management","task-management","time-management","workflow-analytics","workflow-automation","workflow-design","workflow-efficiency","workflow-integration","workflow-security","workflow-streamlining","workflow-templates","workflow-tracking"],"latest_commit_sha":null,"homepage":"https://www.lockdownenterprise.com","language":"PowerShell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ansible-lockdown.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-07-31T13:40:22.000Z","updated_at":"2026-01-20T06:49:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"bea2b826-18f7-4bd7-8466-bed17e5ce34a","html_url":"https://github.com/ansible-lockdown/github_windows_IaC","commit_stats":null,"previous_names":["ansible-lockdown/github_windows_iac"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ansible-lockdown/github_windows_IaC","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ansible-lockdown%2Fgithub_windows_IaC","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ansible-lockdown%2Fgithub_windows_IaC/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ansible-lockdown%2Fgithub_windows_IaC/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ansible-lockdown%2Fgithub_windows_IaC/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ansible-lockdown","download_url":"https://codeload.github.com/ansible-lockdown/github_windows_IaC/tar.gz/refs/heads/self_hosted","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ansible-lockdown%2Fgithub_windows_IaC/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28606914,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T16:10:39.856Z","status":"ssl_error","status_checked_at":"2026-01-20T16:10:39.493Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agile-workflows","approval-workflows","automation","business-processes","collaboration-tools","cross-team-collaboration","document-workflows","process-optimization","project-management","task-management","time-management","workflow-analytics","workflow-automation","workflow-design","workflow-efficiency","workflow-integration","workflow-security","workflow-streamlining","workflow-templates","workflow-tracking"],"created_at":"2025-06-01T22:09:35.439Z","updated_at":"2026-01-20T16:23:05.619Z","avatar_url":"https://github.com/ansible-lockdown.png","language":"PowerShell","readme":"# GitHub Windows IaC\n\nInfrastructure as Code (IaC) modules and automation for use with the Lockdown Enterprise (LE) Windows-based pipelines. This central repository supports Windows benchmarking, deployment automation, and security hardening for CI workflows using Terraform (OpenTofu) and Ansible.\n\n---\n\n## 📚 Table of Contents\n\n1. [📦 Features](#1-️features)\n2. [🔐 Required Secrets](#2-️required-secrets)\n3. [📘 Repository Variables (Required)](#3-️repository-variables-required)\n4. [🏗️ IaC Modules](#4-️iac-modules)\n5. [🧪 Pipeline Validation](#5-️pipeline-validation)\n6. [🧪 Pipeline Validation Workflows](#6-️pipeline-validation-workflows)\n   - [6.1 🧼 Standard Benchmark Validation](#61-️standard-benchmark-validation)\n     - [6.1.1 Trigger Files](#611-trigger-files)\n   - [6.2 🏛 GPO Benchmark Validation](#62-️gpo-benchmark-validation)\n     - [6.2.1 Trigger Files](#621-trigger-files)\n   - [6.3 📈 Workflow Matrix](#63-️workflow-matrix)\n     - [6.3.1 🧪 Example Workflow Usage](#631-️example-workflow-usage)\n       - [6.3.1.1 🔧 main_pipeline_validation.yml](#6311--main_pipeline_validationyml)\n       - [6.3.1.2 🏛 main_pipeline_validation_gpo.yml](#6312--main_pipeline_validation_gpoyml)\n       - [6.3.1.3 🧪 devel_pipeline_validation.yml](#6313--devel_pipeline_validationyml)\n       - [6.3.1.4 🏛 devel_pipeline_validation_gpo.yml](#6314--devel_pipeline_validation_gpoyml)\n7. [🖥️ Run Locally (Test Terraform + Ansible)](#7-️run-locally-test-terraform--ansible)\n8. [🔁 Reusable GitHub Actions Workflows](#8-️reusable-github-actions-workflows)\n   - [8.1 📂 Available Shared Workflows](#81-available-shared-workflows)\n   - [8.2 🧩 Usage in Benchmark Repositories](#82-usage-in-benchmark-repositories)\n   - [8.3 🔒 Badge Secret Note](#83-badge-secret-note)\n   - [8.4 🧭 Workflow Flow](#84-workflow-flow)\n9. [🏷️ Badge Types and Their Sources](#9-️badge-types-and-their-sources)\n   - [9.1 🧷 Recommended Badge Format](#91-recommended-badge-format)\n   - [9.2 🧰 Badge Integration Guidance](#92-badge-integration-guidance)\n   - [9.3 ✅ Recommended Placement in README.md](#93-recommended-placement-in-readmemd)\n10. [📈 Benchmark Tracker \u0026 Teams/Discord Notifications](#10-️benchmark-tracker--teamsdiscord-notifications)\n    - [10.1 🧩 Workflow Files](#101-️workflow-files)\n    - [10.2 🔐 Required Secrets](#102-️required-secrets)\n    - [10.3 📝 Setup Checklist](#103-setup-checklist)\n    - [10.4 📘 Additional Notes](#104-additional-notes)\n11. [🔍 Benchmark Tracker Workflow Details](#11-️benchmark-tracker-workflow-details)\n    - [11.1 📜 benchmark-tracker Workflow](#111--benchmark-tracker-workflow)\n    - [11.2 ⏱ monitor-90day-promotions Workflow](#112--monitor-90day-promotions-workflow)\n    - [11.3 🛠️ Code Highlights](#113-️code-highlights)\n    - [11.4 🛠️ How the Tracker System Works](#114-️how-the-tracker-system-works)\n12. [💬 Notification Examples](#12-️notification-examples)\n13. [🐧 Linux Benchmark Badge Support](#13-️linux-benchmark-badge-support)\n14. [📄 GitHub Pages Deploy (~70m cadence)](#14--github-pages-deploy-70m-cadence)\n## 🔗 Shared Workflows (Windows + Linux)\n15. [📊 Export Audit Repo Badges (IaC)](#15--export-audit-repo-badges-iac)\n16. [🏷️ Create Temp Badges for README](#16--create-temp-badges-for-readme)\n\n---\n\n## 1. 📦 Features\n\n- Centralized IaC logic for all Windows benchmark pipelines (CIS/STIG)\n- Dynamic provisioning of Hyper-V Windows runners using OpenTofu\n- Self-hosted runner workflows with automatic Terraform + Ansible flow\n- GPO testing support via alternate variable files (e.g., `WIN2022GPO.tfvars`)\n- Discord onboarding notifications for first-time contributors\n- Shared GitHub Actions workflows for badge export and testing\n- Support for local testing of IaC outside GitHub Actions\n\n---\n\n## 2. 🔐 Required Secrets (Required)\n\nThese secrets must be configured under `Settings → Secrets → Actions` (repo or org level).\nThe Private repos will need to be configured in the individual repos because the org secrets\ndo not function in private on our current plan.:\n\n| Secret Name              | Description                                       |\n|--------------------------|---------------------------------------------------|\n| `AZURE_AD_CLIENT_ID`     | Azure AD app registration client ID              |\n| `AZURE_AD_CLIENT_SECRET` | Azure AD app secret                              |\n| `AZURE_AD_TENANT_ID`     | Azure AD tenant ID                               |\n| `AZURE_SUBSCRIPTION_ID`  | Azure subscription ID                            |\n| `WIN_USERNAME`           | Admin username for the Windows VM                |\n| `WIN_PASSWORD`           | Admin password for the Windows VM                |\n\n---\n\n## 3. 📘 Repository Variables (Required)\n\nThese must be added under `Settings → Actions → Variables` in benchmark repos (e.g., `Windows-2022-CIS`):\n\n| Variable Name              | Description                                                      | Example              |\n|----------------------------|------------------------------------------------------------------|----------------------|\n| `ANSIBLE_RUNNER_VERSION`   | Version of Ansible used by the CI runner                         | `2.16.2`             |\n| `BENCHMARK_TYPE`           | Benchmark under test (`CIS`, `STIG`, etc.)                       | `CIS`                |\n| `ENABLE_DEBUG`             | Enable debug output and disable auto-destroy (`true/false`)      | `false`              |\n| `IAC_BRANCH`               | GitHub branch to load IaC modules from                           | `main` or `devel`    |\n| `OSVAR`                    | OS tfvars file base name (e.g., `WIN2025`)                       | `WIN2025`            |\n| `GPO_OSVAR`                | OS tfvars for GPO variant (e.g., `WIN2025GPO`)                   | `WIN2025GPO`         |\n\n---\n\n## 4. 🏗️ IaC Modules\n\nThis repo uses [OpenTofu](https://opentofu.org/) to provision Windows test runners locally or inside GitHub Actions for compliance validation.\n\n### Terraform Files\n\n| File                | Description                                                               |\n|---------------------|---------------------------------------------------------------------------|\n| `main.tf`           | Creates Hyper-V-based Windows VMs with required networking and provisioning logic |\n| `vars.tf`           | Defines all input variables used by main Terraform plan                    |\n| `WIN2022.tfvars`    | Variable file for standard Windows Server 2022 runner setup                |\n| `WIN2022GPO.tfvars` | GPO testing variant for Windows Server 2022                               |\n\n---\n\n## 5. 🧪 Pipeline Validation Workflows\n\nThis repository supports automated validation pipelines that run on every push to `main` or `devel` branches of Windows benchmark repositories. These workflows are split by purpose:\n\n- Standard validation (`main_pipeline_validation.yml`, `devel_pipeline_validation.yml`)\n- Group Policy (GPO) validation (`main_pipeline_validation_gpo.yml`, `devel_pipeline_validation_gpo.yml`)\n\n---\n\n## 6. 🧪 Pipeline Validation Workflows\n\n### 6.1 🧼 Standard Benchmark Validation\n\nProvision → Apply → Validate → Destroy\n\nThese workflows provision a fresh Windows environment, apply the benchmark using Ansible, and validate compliance.\n\n#### 6.1.1 Trigger Files:\n- `.github/workflows/main_pipeline_validation.yml`\n- `.github/workflows/devel_pipeline_validation.yml`\n\n```mermaid\ngraph TD;\n  A[Push to Main or Devel] --\u003e B[Trigger Pipeline Workflow]\n  B --\u003e C[Load IaC repo]\n  C --\u003e D[Import Variables and Secrets]\n  D --\u003e E[Setup Environment: Terraform + Ansible]\n  E --\u003e F[Run terraform init]\n  F --\u003e G[Run terraform validate]\n  G --\u003e H[Run terraform apply → provision Windows host]\n  H --\u003e I[Wait 60s if ENABLE_DEBUG is set]\n  I --\u003e J[Run ansible-playbook → apply hardening]\n  J --\u003e K[Validate results]\n  K --\u003e L[Run terraform destroy to clean up]\n```\n\n---\n\n### 6.2 🏛 GPO Benchmark Validation\n\nThese workflows use a GPO-specific configuration to validate settings enforced through Group Policy Objects.\n\n#### 6.2.1 Trigger Files:\n- `.github/workflows/main_pipeline_validation_gpo.yml`\n- `.github/workflows/devel_pipeline_validation_gpo.yml`\n\n```mermaid\ngraph TD;\n  A[Push to Main or Devel GPO] --\u003e B[Trigger GPO Pipeline Workflow]\n  B --\u003e C[Load IaC repo for GPO testing]\n  C --\u003e D[Import GPO-specific tfvars e.g., WIN2022GPO]\n  D --\u003e E[Setup Terraform + Ansible for GPO run]\n  E --\u003e F[Run terraform init]\n  F --\u003e G[Run terraform validate]\n  G --\u003e H[terraform apply to launch GPO test VM]\n  H --\u003e I[Inject Group Policy settings via Ansible]\n  I --\u003e J[Audit or validate policy impact]\n  J --\u003e K[Run terraform destroy to clean up]\n```\n\nEach workflow is fully integrated with badge export automation and can be extended with extra validation stages (e.g., log parsing, custom output diffing) as needed.\n\n### 6.3 📈 Workflow Matrix\n\n| Workflow Filename                    | Description                                     | Trigger Branches         | OSVAR Source     |\n|-------------------------------------|-------------------------------------------------|--------------------------|------------------|\n| `main_pipeline_validation.yml`      | Validates Ansible remediation on main release   | `main`, `latest`         | `${OSVAR}`       |\n| `main_pipeline_validation_gpo.yml`  | Validates GPO settings using Ansible            | `main`, `latest`         | `${GPO_OSVAR}`   |\n| `devel_pipeline_validation.yml`     | Validates draft PRs and benchmark experiments   | `devel`, `benchmark_*`   | `${OSVAR}`       |\n| `devel_pipeline_validation_gpo.yml` | GPO validation for draft/benchmark branches     | `devel`, `benchmark_*`   | `${GPO_OSVAR}`   |\n\n---\n\n## 6.3.1 🧪 Example Workflow Usage\n\nThese workflows are automatically triggered, but you can simulate them via PRs.\n\n### 6.3.1.1 🔧 main_pipeline_validation.yml\n```bash\n# Triggers on PR to main/latest\n# Uses: ${OSVAR}.tfvars\n```\n\n### 6.3.1.2 🏛 main_pipeline_validation_gpo.yml\n```bash\n# Triggers on PR to main/latest for GPO testing\n# Uses: ${GPO_OSVAR}.tfvars\n```\n\n### 6.3.1.3 🧪 devel_pipeline_validation.yml\n```bash\n# Triggers on PR to devel or any 'benchmark_*' branch\n# Uses: ${OSVAR}.tfvars\n```\n\n### 6.3.1.4🏛 devel_pipeline_validation_gpo.yml\n```bash\n# Triggers on PR to devel or 'benchmark_*' for GPO enforcement\n# Uses: ${GPO_OSVAR}.tfvars\n```\n\n---\n\n## 7. 🖥️ Run Locally (Test Terraform + Ansible)\n\n```bash\nexport BENCHMARK_TYPE=\"CIS\"\nexport OSVAR=\"WIN2022\"\nexport TF_VAR_repository=\"${OSVAR}-${BENCHMARK_TYPE}\"\nexport TF_VAR_BENCHMARK_TYPE=\"${BENCHMARK_TYPE}\"\n\nterraform init\nterraform validate\nterraform apply -var-file=\"WIN2022.tfvars\" --auto-approve\nterraform destroy -var-file=\"WIN2022.tfvars\" --auto-approve\n```\n\n---\n\n## 8. 🔁 Reusable GitHub Actions Workflows\n\nThis repository (`github_windows_IaC`) maintains **shared GitHub Actions workflows** that are reused by Windows benchmark repos to manage badge exports and automation logic.\n\n### 8.1 📂 Available Shared Workflows\n\n| Workflow Filename                | Purpose                                       |\n|----------------------------------|-----------------------------------------------|\n| `.github/workflows/export_badges_private.yml` | Used in **private** repos for badge JSON export |\n| `.github/workflows/export_badges_public.yml`  | Used in **public** repos for shields.io badge endpoints |\n\n### 8.2 🧩 Usage in Benchmark Repositories\n\nBenchmark repos include a wrapper workflow like:\n\n```yaml\n# .github/workflows/export_badges_private.yml\nname: Export Badges to Private Repo\non:\n  push:\n    branches: [ latest ]\njobs:\n  export-badges:\n    uses: ansible-lockdown/github_windows_IaC/.github/workflows/export_badges_private.yml@main\n    secrets:\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      BADGE_PUSH_TOKEN: ${{ secrets.BADGE_PUSH_TOKEN }}\n```\n\n\u003e The reusable logic lives in the `github_windows_IaC` repo. This makes badge generation portable and consistent.\n\n---\n\n### 8.3 🔒 Badge Secret Note\n\n| Secret Name        | Where Needed   | Notes                                                              |\n|--------------------|----------------|---------------------------------------------------------------------|\n| `BADGE_PUSH_TOKEN` | 🔒 Private Repos | Must be set **manually** even if it exists at the org level         |\n| `GH_TOKEN`         | All repos       | Provided automatically by GitHub Actions                           |\n\n---\n\n### 8.4 🧭 Workflow Flow\n\n```mermaid\ngraph TD;\n  A[Push to latest or main branch] --\u003e B[Triggers local wrapper workflow]\n  B --\u003e C[Calls reusable IaC workflow using 'uses']\n  C --\u003e D[Generates JSON badge data]\n  D --\u003e E[Pushes to badge cache or GitHub Pages]\n  E --\u003e F[Badge rendered via shields.io or embedded in README]\n```\n\n---\n\n## 9. 🏷️ Badge Types and Their Sources\n\nThis repository supports a wide variety of badges across **public** and **private** benchmark repositories. These badges serve different purposes and come from different systems.\n\n| Badge Type                    | Source System                  | Example Badge | Notes |\n|------------------------------|--------------------------------|----------------|-------|\n| **GitHub Stats (Stars/Forks)** | GitHub (static links)         | ![Stars](https://img.shields.io/github/stars/ansible-lockdown/Windows-2019-CIS?style=social) | Hardcoded to specific repo/org |\n| **Twitter \u0026 Discord**        | External services              | ![Discord](https://img.shields.io/discord/925818806838919229?logo=discord) | Hardcoded link or ID |\n| **License Badge**            | GitHub                        | ![License](https://img.shields.io/github/license/ansible-lockdown/Windows-2019-CIS?label=License) | Hardcoded, dynamic on GitHub |\n| **Lint Tools (yamllint, ansible-lint)** | Hardcoded manually            | ![YamlLint](https://img.shields.io/badge/yamllint-Present-brightgreen?style=flat\u0026logo=yaml) | Always present (not dynamic) |\n| **GitHub Actions Status**    | GitHub Workflow Badge URLs     | [![Main Status](https://github.com/ansible-lockdown/Windows-2019-CIS/actions/workflows/main_pipeline_validation.yml/badge.svg)](https://github.com/ansible-lockdown/Windows-2019-CIS/actions/workflows/main_pipeline_validation.yml) | Dynamic, GitHub-managed |\n| **Commits, Issues, PRs**     | GitHub                         | ![Open Issues](https://img.shields.io/github/issues-raw/ansible-lockdown/Windows-2019-CIS) | Dynamic, GitHub-managed |\n| **Pre-Commit CI**            | IaC Badge JSON (hosted)        | [![Pre-Commit.ci](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_windows_IaC/badges/Windows-2019-CIS/pre-commit-ci.json)](https://results.pre-commit.ci/latest/github/ansible-lockdown/Windows-2019-CIS/devel) | 🔄 Updated via IaC workflow |\n| **Benchmark Version Badges** | IaC Badge JSON                 | ![Benchmark](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_windows_IaC/badges/Windows-2019-CIS/benchmark-version-main.json) | 🔄 Dynamic IaC badge |\n| **Private Repo Badges**      | IaC Badge JSON                 | ![Private Benchmark](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_windows_IaC/badges/Private-Windows-2019-CIS/benchmark-version.json) | 🔐 Internal subscribers only |\n| **Release Branch**           | Hardcoded or IaC badge         | ![Release Branch](https://img.shields.io/badge/Release%20Branch-Main-brightgreen) / IaC endpoint | Sometimes manually added |\n\n---\n\n## 9.1 🧷 Recommended Badge Format\n\n```markdown\n[![Pre-Commit](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_windows_IaC/badges/Windows-2022-CIS/pre-commit-ci.json)](https://results.pre-commit.ci/latest/github/ansible-lockdown/Windows-2022-CIS/devel)\n```\n---\n\n## 9.2 🧰 Badge Integration Guidance\n\n- **Dynamic badges** use `.json` files hosted in the `github_windows_IaC` `badges/` folder.\n- They are updated using the [`export_badges_public.yml`](https://github.com/ansible-lockdown/github_windows_IaC/blob/main/.github/workflows/export_badges_public.yml) and `export_badges_private.yml` workflows.\n- Public repos use pre-built shields.io URLs.\n- Private repos consume the same badge format but must manually set the `BADGE_PUSH_TOKEN`.\n\n---\n\n## 9.3 ✅ Recommended Placement in README.md\n\nYou can structure your badge sections like this:\n\n```markdown\n## Public Repository 📣\n\n![Org Stars](...)\n![Repo Stars](...)\n![License](...)\n[![Pre-Commit](...)](...)\n![Benchmark Version](...)\n[![Main Pipeline](...)](...)\n...\n\n## Subscriber Release Information 🔐\n\n![Private Benchmark Version](...)\n[![Private GPO Pipeline](...)](...)\n...\n```\n\n---\n\n## 10. 📈 Benchmark Tracker \u0026 Teams/Discord Notifications\n\nThe `github_windows_IaC` repository contains a shared workflow system that automates **benchmark version tracking** across private repositories. Once a benchmark reaches 90 days in a private repo, it is eligible for **auto-promotion** to its corresponding public repository. Notifications are sent via **Microsoft Teams** and **Discord**.\n\n---\n\n### 10.1 🧩 Workflow Files\n\n| Workflow File                  | Description                                                                 |\n|-------------------------------|-----------------------------------------------------------------------------|\n| `benchmark_track.yml`         | Called by private repos to initiate tracking. Determines if a benchmark version is missing from the public repo, and opens a 90-day issue if so. Sends Teams and Discord notifications. |\n| `benchmark_promote.yml`       | Called daily from a central repo. Monitors all tracking issues. If 90+ days old, closes issues (if already promoted) or auto-creates PRs. Sends milestone reminders and promotion alerts. |\n\n---\n\n### 10.2 🔐 Required Secrets\n\nThese secrets **must** be configured in the GitHub repositories involved:\n\n| Secret Name            | Scope              | Purpose                                                                 |\n|------------------------|---------------------|-------------------------------------------------------------------------|\n| `GH_TOKEN`             | All repos           | Required for GitHub CLI operations (issues, PRs, comments, etc.)        |\n| `TEAMS_WEBHOOK_URL`    | All repos           | Used to send Adaptive Card notifications to Microsoft Teams             |\n| `DISCORD_WEBHOOK_URL`  | All repos           | Sends milestone, promotion, and closure alerts to Discord channels      |\n| `BADGE_PUSH_TOKEN`     | All repos           | Grants write access to push badge files to `github_windows_IaC`        |\n\n\u003e Add these under: `Settings → Secrets → Actions` for each participating repository.\n\n---\n\n# 📝 10.3 Setup Checklist\n\nSet the required secrets in each **Private** repo:\n\n- `GH_TOKEN`\n- `TEAMS_WEBHOOK_URL`\n- `DISCORD_WEBHOOK_URL`\n- `BADGE_PUSH_TOKEN`\n\n**Private Repo:**\n- Call `benchmark_track.yml` from PR merges or scheduled runs.\n\n**IaC Repo:**\n- Schedule `benchmark_promote.yml` to run daily.\n\n**Public Repo:**\n- Ensure `devel` branch and `README.md` exist to validate versions.\n\n**Teams/Discord Webhooks:**\n- Ensure your automation supports HTTP POST with full JSON payloads.\n\n---\n\n## 📘 10.4 Additional Notes\n\n- Benchmarks must follow naming conventions (`Private-Windows-*` → `Windows-*`).\n- `README.md` format must include a recognizable version string (e.g., `vX.Y.Z` or `Version X, Rel Y`).\n- All workflows are modular and intended to be reused across repos.\n- Discord support is now included in all milestones and promotion actions.\n\n\u003e ✅ This setup ensures full traceability and timely promotion of compliance benchmarks while keeping all stakeholders informed.\n\n---\n\n## 11 🔍 Benchmark Tracker Workflow Details\n\n### 11.1 📜 `benchmark-tracker` Workflow\n\nTriggered when a pull request from a branch matching `benchmark_*` is merged into the `latest` branch of a **Private** repo.\n\n#### 🔄 What it does:\n\n1. **Extract version from PR branch name**\n   Example: `benchmark_v2.0.0` becomes `v2.0.0`\n2. **Create a GitHub issue** in the same repo with a 90-day countdown\n3. **Assign labels**, version tags, and metadata to the issue\n4. **Post a confirmation comment** in the PR for traceability\n\nThis tracks the need to promote this version publicly after 90 days.\n\n---\n\n### 11.2 ⏱ `monitor-90day-promotions` Workflow\n\nRuns daily from the **IaC repo**. Monitors issues created by the tracker workflow.\n\n#### 🔄 What it does:\n\n1. **Scan all private repos** for open issues labeled as benchmark trackers\n2. **Parse the issue body** to extract the version, repo name, and date created\n3. **Calculate the age of each issue**\n4. If the issue is **older than 90 days**:\n   - Clones the corresponding **public repo**\n   - Creates a PR to add the benchmark version to the `main` branch\n   - Uses `gh pr create` and `gh pr merge` to automate promotion\n   - Pushes new badge files to `github_windows_IaC`\n   - Sends a **Teams notification** with summary info\n   - Closes the original issue with a comment\n\n\u003e If the issue is **not** yet 90 days old, it is skipped and checked again on the next scheduled run.\n\n---\n\n### 11.3 🛠️ Code Highlights\n\nEach step is modularized inside the workflow YAML:\n\n- `benchmark-tracker.yml`\n  - `- name: Detect PR branch and extract version`\n  - `- name: Create 90-day tracking issue`\n  - `- name: Label and annotate PR`\n- `monitor-90day-promotions.yml`\n  - `- name: Search for benchmark tracker issues`\n  - `- name: Compare age against 90-day threshold`\n  - `- name: Promote version if qualified`\n  - `- name: Send Teams notification via webhook`\n  - `- name: Update badge JSON in IaC`\n\n---\n\n### 11.4 🛠️ How the Tracker System Works\n\n```mermaid\ngraph TD;\n  A[Private Repo Calls benchmark_track.yml] --\u003e B{Is Public Repo Missing Version?}\n  B -- No --\u003e C[No Action Needed]\n  B -- Yes --\u003e D[Open 90-Day Tracking Issue]\n  D --\u003e E[Send Tracking Start Notifications]\n  E --\u003e F[benchmark_promote.yml Runs Daily]\n  F --\u003e G{Is Issue 90+ Days Old?}\n  G -- No --\u003e H[Send Milestone Reminders 30/60/90 Days]\n  G -- Yes --\u003e I{Already Promoted?}\n  I -- Yes --\u003e J[Close Issue, Send Notifications]\n  I -- No --\u003e K[Create PR to Public Repo]\n  K --\u003e L[Send PR Notifications to Teams \u0026 Discord]\n```\n\n---\n\n### 12. 💬 Notification Examples\n\nThe system supports **Teams** and **Discord** alerts for all key events during benchmark tracking and promotion. These include:\n\n- ✅ Tracking Started\n- 🚨 Public Repo Missing\n- ⏰ Milestone Reminders (30, 60, 90 days)\n- ⚠️ Overdue Warnings\n- ✅ Already Promoted Notices\n- ❌ Promotion Blocked Alerts\n- 🚨 Auto-Promotion PR Created\n\nEach message is customized for Teams and Discord formatting, with links to issues and PRs where applicable.\n\n---\n\n#### ✅ Tracking Started — Teams\n```markdown\n🚀 Tracking Initiated - v2.0.0\n🔒 Subscriber Repo: ansible-lockdown/Private-Windows-2022-CIS\n📦 Subscriber Version: v2.0.0\n🌐 Community Target: ansible-lockdown/Windows-2022-CIS\n📦 Community Version: v1.9.0\n⏳ Subscriber Review Ends: Approx: 2025-09-07\n🗓️ Auto-Promotion Date To Community: Approx: 2025-09-12\n📅 Promotion In: 90 days\n```\n\n#### 🚨 Public Repo Missing — Teams\n```markdown\n🚨 Tracking Started — But There's A Problem 🚨\nBenchmark version 'v2.0.0' from **Private-Windows-2022-CIS** has entered the 90-day window.\n⚠️ However, the public repo **Windows-2022-CIS** is missing or incomplete.\n📢 Please create and prepare the community repo.\n```\n\n#### ✅ Tracking Started — Discord\n```markdown\n🚀 Benchmark Release To Community Tracking Started\n🔒 Subscriber Repo: ansible-lockdown/Private-Windows-2022-CIS\n📦 Subscriber Version: v2.0.0\n🌐 Community Repo: ansible-lockdown/Windows-2022-CIS\n📦 Community Version: v1.9.0\n⏳ Review Ends: 2025-09-07\n🗓️ Auto-Promotion Date: 2025-09-12\n```\n\n#### ⏰ 30/60/90 Day Reminder — Discord\n```markdown\n⏰ Benchmark Promotion Milestone\n📢 60-Day Reminder: Benchmark `v2.0.0` is scheduled for promotion in 30 days.\n⚠️ If not promoted manually, auto-promotion occurs on Day 95.\n🔒 Subscriber Repo: Private-Windows-2022-CIS\n📦 Version: v2.0.0\n🌐 Target: Windows-2022-CIS\n⏱️ Days Tracked: 60\n📆 Scheduled Auto-Promotion: 2025-09-12\n```\n\n#### ⚠️ Overdue Reminder — Teams\n```markdown\n⏰ Benchmark Promotion Reminder\n⚠️ Benchmark v2.0.0 from `Private-Windows-2022-CIS` is overdue by 3 days.\n⏲️ Auto-promotion will occur in 2 days.\n🔗 View Issue #43\n```\n\n#### ✅ Already Promoted — Teams\n```markdown\n✅ Benchmark Already Promoted\nBenchmark version v2.0.0 is already in Windows-2022-CIS.\n📅 Auto-closed on: 2025-09-05\n🔗 View Issue #43\n```\n\n#### ✅ Already Promoted — Discord\n```markdown\n✅ Benchmark Promoted To Community\nBenchmark v2.0.0 from `Private-Windows-2022-CIS` is already in `Windows-2022-CIS`\n🌿 Branch: devel\n📅 Auto-closed: 2025-09-05\n🔗 Issue: View Issue #43\n```\n\n#### ❌ Promotion Blocked — Teams\n```markdown\n❌ Benchmark Promotion Will Be Blocked\n🚫 The community repo **Windows-2022-CIS** does not exist or is missing `devel`.\n📢 Please resolve this to enable promotion.\n🔒 Repo: Private-Windows-2022-CIS\n📦 Version: v2.0.0\n```\n\n#### 🚨 Auto-Promotion PR Created — Teams\n```markdown\n🚨 Benchmark PR Automatically Created 🚨\nVersion v2.0.0 from Private-Windows-2022-CIS has been proposed for promotion.\n🔗 PR: https://github.com/ansible-lockdown/Windows-2022-CIS/pull/99\n📅 Days Tracked: 95\n🔄 Branch: promote_benchmark_v2_0_0\n```\n\n#### 📦 Auto-Promotion PR Created — Discord\n```markdown\n📦 Benchmark Promotion PR Created: Promote v2.0.0\n🔒 Repo: Private-Windows-2022-CIS\n🌐 Target: Windows-2022-CIS\n🌿 Branch: [promote_benchmark_v2_0_0](https://github.com/ansible-lockdown/Windows-2022-CIS/tree/promote_benchmark_v2_0_0)\n🔗 PR: https://github.com/ansible-lockdown/Windows-2022-CIS/pull/99\n📅 Days Tracked: 95\n```\n---\n\n### 13. 🐧 Linux Benchmark Badge Support\n\nThe Linux IaC repository also acts as the **central badge hub** for Linux-based benchmark pipelines.\n\n- All badge JSON files for **Linux CIS** and **Linux STIG** benchmarks are written to the `badges/` directory in this repo\n- The same export workflows (`export_badges_public.yml`, `export_badges_private.yml`) handle both **Windows** and **Linux** badge publication\n- Example: A benchmark like `UBUNTU22-CIS` will have badges stored at:\n\n```\nhttps://ansible-lockdown.github.io/github_linux_IaC/badges/UBUNTU22-CIS/pre-commit-ci.json\n```\n\n\u003e This keeps badge generation consistent and centralized across all platforms for Lockdown.\n\n---\n\n### 14. 📄 GitHub Pages Deploy (~70m cadence)\n\nThis repository includes a **scheduled GitHub Pages deployment** workflow (`.github/workflows/pages_deploy.yml`) that publishes the **entire repo root** to GitHub Pages on a ~70-minute cadence, with one intentional long gap per day.\n\n**Key Details:**\n- **Purpose:** Push updated site content (including `/badges/*.json`) to GitHub Pages.\n- **Cadence:** Runs ~every 70 minutes, except for a ~110-minute gap overnight in the Eastern Time zone.\n- **Gap Placement:** UTC schedule is arranged so the long gap (~03:10–05:00 UTC) corresponds to ~11:10 pm–1:00 am ET during Daylight Saving Time.\n- **.nojekyll:** Ensures raw JSON endpoints and other non-Jekyll assets are served correctly.\n- **Concurrency:** Deploy jobs are never canceled once started, preventing partial publishes.\n\n#### Mermaid Workflow Diagram\n\n```mermaid\nflowchart TD\n    A[Scheduled Trigger ~70m cadence \\n UTC cron times] --\u003e B[Checkout repo root self_hosted branch]\n    B --\u003e C[Create .nojekyll to preserve JSON/raw files]\n    C --\u003e D[Upload site as Pages artifact]\n    D --\u003e E[Deploy to GitHub Pages environment]\n    E --\u003e F[Public site updated \\n e.g., /badges/*.json endpoints]\n```\n\n#### Cron Schedule Overview\n\n| UTC Time(s)              | Approx. ET Time(s)*           | Notes             |\n|--------------------------|-------------------------------|-------------------|\n| `02:00, 05:00, 12:00, 19:00` | 10:00 pm, 1:00 am, 8:00 am, 3:00 pm | Major deploys     |\n| `03:10, 06:10, 13:10, 20:10` | 11:10 pm, 2:10 am, 9:10 am, 4:10 pm | Staggered deploys |\n| `07:20, 14:20, 21:20`        | 3:20 am, 10:20 am, 5:20 pm          | Staggered deploys |\n| `08:30, 15:30, 22:30`        | 4:30 am, 11:30 am, 6:30 pm          | Staggered deploys |\n| `09:40, 16:40, 23:40`        | 5:40 am, 12:40 pm, 7:40 pm          | Staggered deploys |\n| `00:50, 10:50, 17:50`        | 8:50 pm, 6:50 am, 1:50 pm           | Staggered deploys |\n\n\u003e *Times adjust by +1 hour during Eastern Standard Time (EST).\n\n---\n\n## 🧩 Contributing\n\nPull requests are welcome. When you open your first PR, a Discord invite will be sent automatically (if enabled). Ensure your repo is configured with the appropriate variables and secrets to execute workflows.\n\n---\n\n## 🔗 Shared Workflows (Windows + Linux)\n\nThe following sections (15 \u0026 16) describe workflows that are **not Windows-specific**.\nThey are shared across **both Windows and Linux IaC repos**.\n\n- To keep documentation consistent, the **Windows repo** (`github_windows_IaC`) hosts the canonical docs.\n- Linux IaC repos and the org profile `.github` page link here for reference.\n- Although examples use Windows repo names, the **same workflows run in Linux repos** as well.\n\n---\n\n## 15. 📊 Export Audit Repo Badges (IaC)\n\nThis workflow automates how we **track, display, and publish audit repository availability** across all CIS and STIG baselines. It guarantees that both CIS and STIG tables always have corresponding audit badge entries, even if one counterpart doesn’t yet exist.\n\n### Why we did this\n- **Eliminate manual badge upkeep** → no more checking if audit repos exist or contain `latest/goss.yml`.\n- **Ensure table coverage** → CIS/ STIG counterparts are always represented.\n- **Increase transparency** → consumers instantly see *Available* vs *Not Available*.\n- **Lifecycle safety** → prunes invalid/legacy badges automatically.\n- **Publish stability** → concurrency + single publisher prevents race conditions.\n\n---\n\n### Workflow Breakdown\n\n1. **Discover Repos**\n   - Lists all `*-CIS` / `*-STIG` repos in `ansible-lockdown` (non-archived, non-forked).\n   - Normalizes names, excludes `-Audit`.\n   - Adds counterparts (CIS ⇄ STIG).\n\n2. **Build Badges (Matrix)**\n   - For each base repo, check `\u003cBase\u003e-Audit`.\n   - Conditions: repo exists, `latest` branch exists, `goss.yml` present.\n   - Generates badge JSON:\n     - **Available →** brightgreen\n     - **Not Available →** lightgrey\n\n3. **Aggregate Results**\n   - Collects badge artifacts into `output/badges/audit`.\n   - Adds `.nojekyll` for GitHub Pages.\n\n4. **Publish to IaC Repo**\n   - Clones target IaC repo (default: `ansible-lockdown/github_windows_IaC@self_hosted`).\n   - Rsyncs badges → `badges/audit/`.\n   - Prunes invalid files.\n   - Commits + pushes with retry on race.\n\n---\n\n### Schedule \u0026 Inputs\n- **Runs daily** → `cron: \"15 4 * * *\"` (04:15 UTC).\n- **Manual trigger:**\n  - `repo_name` → process single CIS/STIG repo.\n  - `target_iac_repo` → override target repo.\n  - `target_branch` → override publish branch.\n\n### Required Secret\n- `BADGE_PUSH_TOKEN` → GitHub token with repo access.\n\n---\n\n### Badge Schema\n\n```yaml\n{ \"schemaVersion\": 1, \"label\": \"Repo\", \"message\": \"Available\", \"color\": \"brightgreen\" }\n\nMessage: Available / Not Available\nColor: brightgreen / lightgrey\nFile name: \u003cBase\u003e-Audit-Badge.json\n\nExample Output\nWindows-2022-CIS → badges/audit/Windows-2022-CIS-Audit-Badge.json\nWindows-2022-STIG → badges/audit/Windows-2022-STIG-Audit-Badge.json\n```\n### Workflow\n\n```mermaid\ngraph TD;\n    A[Start Workflow] --\u003e B[Discover Repos]\n    B --\u003e C[Expand CIS/STIG Counterparts]\n    C --\u003e D[Matrix Fanout: Build Badges]\n    D --\u003e|Available| E[brightgreen JSON Badge]\n    D --\u003e|Not Available| F[lightgrey JSON Badge]\n    E --\u003e G[Upload Artifacts]\n    F --\u003e G[Upload Artifacts]\n    G --\u003e H[Aggregate Results]\n    H --\u003e I[Clone Target IaC Repo]\n    I --\u003e J[Sync Badges → badges/audit/]\n    J --\u003e K[Prune Legacy Files]\n    K --\u003e L[Commit + Push]\n    L --\u003e M[Published to Pages]\n```\n---\n\n## 16. 🏷️ Create Temp Badges for README\n\nThis workflow **seeds safe placeholder badges** for repos so our README tables always render—even before real versions or releases exist. It **never overwrites real badges**, cleans up invalid legacy JSON, and fills gaps across both public and `Private-` repos.\n\n### Why we did this\n- **Continuous readability:** README tables shouldn’t break or show blanks while teams are bootstrapping repos.\n- **Safety-first:** Placeholders won’t overwrite any legit (“real”) badge files.\n- **Coverage parity:** Ensures both `-CIS` and `-STIG` families (plus `Private-` counterparts) have minimal badges from day one.\n- **Housekeeping:** Removes old/invalid JSON so future workflows don’t trip on bad files.\n\n---\n\n### What it does (step-by-step)\n\n1. **Checkout target badges branch**\n   - Checks out the `self_hosted` branch (configurable via `TARGET_BRANCH`) where badges live.\n\n2. **Install tools**\n   - Installs `jq`; verifies `gh` availability.\n\n3. **Discover CIS/STIG repos**\n   - Lists all org repos (`ansible-lockdown`), excludes audits and this repo (`github_windows_IaC`).\n   - Keeps names that end in `-CIS` or `-STIG`.\n   - Builds **four targets** per baseline:\n     - `\u003cBase\u003e-CIS`, `\u003cBase\u003e-STIG`, `Private-\u003cBase\u003e-CIS`, `Private-\u003cBase\u003e-STIG`.\n\n4. **Generate placeholders (without overwriting real badges)**\n   - **Public repos** create/maintain:\n     - `badges/\u003cRepo\u003e/benchmark-version-main.json` *(label: “Benchmark Version (main)”)*\n     - `badges/\u003cRepo\u003e/benchmark-version-devel.json` *(label: “Benchmark Version (devel)”)*\n     - `badges/\u003cRepo\u003e/lockdown-release.json` *(label: “Lockdown Release” — populated from latest GitHub release if present, else placeholder)*\n   - **Private repos** create/maintain:\n     - `badges/\u003cRepo\u003e/benchmark-version.json` *(label: “Benchmark Version”)*\n\n5. **Schema cleanup**\n   - Scans `badges/\u003cRepo\u003e/*.json` and **deletes invalid JSON** (wrong/missing keys or extra keys).\n   - Fresh placeholders are recreated automatically next run.\n\n6. **Commit \u0026 push (only when changes occur)**\n   - Fast-forwards before push; commits with a concise message.\n\n---\n\n### Schedule \u0026 Triggers\n- **Daily:** `cron: \"45 4 * * *\"` (04:45 UTC)\n- **Manual:** `workflow_dispatch` available via Actions UI\n\n### Permissions\n```yaml\npermissions:\n  contents: write\n```\n### Secrets\n- Uses the default `secrets.GITHUB_TOKEN` for discovery and pushes.\n\n---\n\n### Badge schemas (placeholders)\n\n**Generic placeholder (used for most seeded files):**\n```json\n{ \"schemaVersion\": 1, \"label\": \"\u003cvaries\u003e\", \"message\": \"Not Available\", \"color\": \"lightgrey\" }\n```\n\n**Lockdown Release (public repos):**\n- If a **latest release** exists:\n```json\n{ \"schemaVersion\": 1, \"label\": \"Lockdown Release\", \"message\": \"\u003ctag or name\u003e\", \"color\": \"blue\" }\n```\n- If **no release**:\n```json\n{ \"schemaVersion\": 1, \"label\": \"Lockdown Release\", \"message\": \"No Release\", \"color\": \"lightgrey\" }\n```\n\n\u003e 🔒 **Safety:** A file is considered a placeholder only if its `.message` is `\"Not Available\"` or `\"No Release\"`. Real badges (anything else) are **never** overwritten.\n\n---\n\n### Outputs \u0026 File Layout\n\n**Public repo example (`Windows-2022-CIS`):**\n```\nbadges/\n  Windows-2022-CIS/\n    benchmark-version-main.json\n    benchmark-version-devel.json\n    lockdown-release.json\n```\n\n**Private repo example (`Private-Windows-2022-STIG`):**\n```\nbadges/\n  Private-Windows-2022-STIG/\n    benchmark-version.json\n```\n\n---\n\n### Example README Table (consuming these endpoints)\n\n| Repo                       | Main Version                                                                 | Devel Version                                                                | Lockdown Release                                                                 |\n|----------------------------|-------------------------------------------------------------------------------|------------------------------------------------------------------------------|----------------------------------------------------------------------------------|\n| Windows-2022-CIS           | ![main](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_windows_IaC/badges/Windows-2022-CIS/benchmark-version-main.json) | ![devel](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_windows_IaC/badges/Windows-2022-CIS/benchmark-version-devel.json) | ![release](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_windows_IaC/badges/Windows-2022-CIS/lockdown-release.json) |\n| Private-Windows-2022-STIG  | ![version](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_windows_IaC/badges/Private-Windows-2022-STIG/benchmark-version.json) | —                                                                            | —                                                                                |\n\n---\n\n### Diagram\n\n```mermaid\nflowchart TD\n    A[Start 04:45 UTC / manual] --\u003e B[Checkout self_hosted branch]\n    B --\u003e C[Install jq / verify gh]\n    C --\u003e D[Discover -CIS / -STIG repos exclude -Audit, IaC]\n    D --\u003e E[Expand targets incl. Private- counterparts]\n    E --\u003e F[Clean invalid JSON schemas]\n    F --\u003e G[Seed placeholders if missing or placeholder]\n    G --\u003e H[Populate Lockdown Release from latest tag if available]\n    H --\u003e I[Commit \u0026 Push if changed]\n    I --\u003e J[Placeholders available for README tables]\n```\n\n---\n\n✅ **Result:** READMEs remain **fully populated and consistent** from day one, while real pipelines can safely replace placeholders over time without risk of being overwritten.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fansible-lockdown%2Fgithub_windows_iac","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fansible-lockdown%2Fgithub_windows_iac","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fansible-lockdown%2Fgithub_windows_iac/lists"}