Infrastructure 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.
- π¦ Features
- π Required Secrets
- π Repository Variables (Required)
- ποΈ IaC Modules
- π§ͺ Pipeline Validation Workflows
- π§ͺ Pipeline Validation Workflows
- π₯οΈ Run Locally (Test Terraform + Ansible)
- π Reusable GitHub Actions Workflows
- π·οΈ Badge Types and Their Sources
- π Benchmark Tracker & Teams/Discord Notifications
- π Benchmark Tracker Workflow Details
- π¬ Notification Examples
- π§ Linux Benchmark Badge Support
- Centralized IaC logic for all Windows benchmark pipelines (CIS/STIG)
- Dynamic provisioning of Hyper-V Windows runners using OpenTofu
- Self-hosted runner workflows with automatic Terraform + Ansible flow
- GPO testing support via alternate variable files (e.g.,
WIN2022GPO.tfvars
) - Discord onboarding notifications for first-time contributors
- Shared GitHub Actions workflows for badge export and testing
- Support for local testing of IaC outside GitHub Actions
These secrets must be configured under Settings β Secrets β Actions
(repo or org level).
The Private repos will need to be configured in the individual repos because the org secrets
do not funtion in private on our current plan.:
Secret Name | Description |
---|---|
AZURE_AD_CLIENT_ID |
Azure AD app registration client ID |
AZURE_AD_CLIENT_SECRET |
Azure AD app secret |
AZURE_AD_TENANT_ID |
Azure AD tenant ID |
AZURE_SUBSCRIPTION_ID |
Azure subscription ID |
WIN_USERNAME |
Admin username for the Windows VM |
WIN_PASSWORD |
Admin password for the Windows VM |
These must be added under Settings β Actions β Variables
in benchmark repos (e.g., Windows-2022-CIS
):
Variable Name | Description | Example |
---|---|---|
ANSIBLE_RUNNER_VERSION |
Version of Ansible used by the CI runner | 2.16.2 |
BENCHMARK_TYPE |
Benchmark under test (CIS , STIG , etc.) |
CIS |
ENABLE_DEBUG |
Enable debug output and disable auto-destroy (true/false ) |
false |
IAC_BRANCH |
GitHub branch to load IaC modules from | main or devel |
OSVAR |
OS tfvars file base name (e.g., WIN2025 ) |
WIN2025 |
GPO_OSVAR |
OS tfvars for GPO variant (e.g., WIN2025GPO ) |
WIN2025GPO |
This repo uses OpenTofu to provision Windows test runners locally or inside GitHub Actions for compliance validation.
File | Description |
---|---|
main.tf |
Creates Hyper-V-based Windows VMs with required networking and provisioning logic |
vars.tf |
Defines all input variables used by main Terraform plan |
WIN2022.tfvars |
Variable file for standard Windows Server 2022 runner setup |
WIN2022GPO.tfvars |
GPO testing variant for Windows Server 2022 |
This 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:
- Standard validation (
main_pipeline_validation.yml
,devel_pipeline_validation.yml
) - Group Policy (GPO) validation (
main_pipeline_validation_gpo.yml
,devel_pipeline_validation_gpo.yml
)
Provision β Apply β Validate β Destroy
These workflows provision a fresh Windows environment, apply the benchmark using Ansible, and validate compliance.
.github/workflows/main_pipeline_validation.yml
.github/workflows/devel_pipeline_validation.yml
graph TD;
A[Push to Main or Devel] --> B[Trigger Pipeline Workflow]
B --> C[Load IaC repo]
C --> D[Import Variables and Secrets]
D --> E[Setup Environment: Terraform + Ansible]
E --> F[Run terraform init]
F --> G[Run terraform validate]
G --> H[Run terraform apply β provision Windows host]
H --> I[Wait 60s if ENABLE_DEBUG is set]
I --> J[Run ansible-playbook β apply hardening]
J --> K[Validate results]
K --> L[Run terraform destroy to clean up]
These workflows use a GPO-specific configuration to validate settings enforced through Group Policy Objects.
.github/workflows/main_pipeline_validation_gpo.yml
.github/workflows/devel_pipeline_validation_gpo.yml
graph TD;
A[Push to Main or Devel GPO] --> B[Trigger GPO Pipeline Workflow]
B --> C[Load IaC repo for GPO testing]
C --> D[Import GPO-specific tfvars e.g., WIN2022GPO]
D --> E[Setup Terraform + Ansible for GPO run]
E --> F[Run terraform init]
F --> G[Run terraform validate]
G --> H[terraform apply to launch GPO test VM]
H --> I[Inject Group Policy settings via Ansible]
I --> J[Audit or validate policy impact]
J --> K[Run terraform destroy to clean up]
Each 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.
Workflow Filename | Description | Trigger Branches | OSVAR Source |
---|---|---|---|
main_pipeline_validation.yml |
Validates Ansible remediation on main release | main , latest |
${OSVAR} |
main_pipeline_validation_gpo.yml |
Validates GPO settings using Ansible | main , latest |
${GPO_OSVAR} |
devel_pipeline_validation.yml |
Validates draft PRs and benchmark experiments | devel , benchmark_* |
${OSVAR} |
devel_pipeline_validation_gpo.yml |
GPO validation for draft/benchmark branches | devel , benchmark_* |
${GPO_OSVAR} |
These workflows are automatically triggered, but you can simulate them via PRs.
# Triggers on PR to main/latest
# Uses: ${OSVAR}.tfvars
# Triggers on PR to main/latest for GPO testing
# Uses: ${GPO_OSVAR}.tfvars
# Triggers on PR to devel or any 'benchmark_*' branch
# Uses: ${OSVAR}.tfvars
# Triggers on PR to devel or 'benchmark_*' for GPO enforcement
# Uses: ${GPO_OSVAR}.tfvars
export BENCHMARK_TYPE="CIS"
export OSVAR="WIN2022"
export TF_VAR_repository="${OSVAR}-${BENCHMARK_TYPE}"
export TF_VAR_BENCHMARK_TYPE="${BENCHMARK_TYPE}"
terraform init
terraform validate
terraform apply -var-file="WIN2022.tfvars" --auto-approve
terraform destroy -var-file="WIN2022.tfvars" --auto-approve
This repository (github_windows_IaC
) maintains shared GitHub Actions workflows that are reused by Windows benchmark repos to manage badge exports and automation logic.
Workflow Filename | Purpose |
---|---|
.github/workflows/export_badges_private.yml |
Used in private repos for badge JSON export |
.github/workflows/export_badges_public.yml |
Used in public repos for shields.io badge endpoints |
Benchmark repos include a wrapper workflow like:
# .github/workflows/export_badges_private.yml
name: Export Badges to Private Repo
on:
push:
branches: [ latest ]
jobs:
export-badges:
uses: ansible-lockdown/github_windows_IaC/.github/workflows/export_badges_private.yml@main
secrets:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BADGE_PUSH_TOKEN: ${{ secrets.BADGE_PUSH_TOKEN }}
The reusable logic lives in the
github_windows_IaC
repo. This makes badge generation portable and consistent.
Secret Name | Where Needed | Notes |
---|---|---|
BADGE_PUSH_TOKEN |
π Private Repos | Must be set manually even if it exists at the org level |
GH_TOKEN |
All repos | Provided automatically by GitHub Actions |
graph TD;
A[Push to latest or main branch] --> B[Triggers local wrapper workflow]
B --> C[Calls reusable IaC workflow using 'uses']
C --> D[Generates JSON badge data]
D --> E[Pushes to badge cache or GitHub Pages]
E --> F[Badge rendered via shields.io or embedded in README]
This repository supports a wide variety of badges across public and private benchmark repositories. These badges serve different purposes and come from different systems.
[](https://results.pre-commit.ci/latest/github/ansible-lockdown/Windows-2022-CIS/devel)
- Dynamic badges use
.json
files hosted in thegithub_windows_IaC
badges/
folder. - They are updated using the
export_badges_public.yml
andexport_badges_private.yml
workflows. - Public repos use pre-built shields.io URLs.
- Private repos consume the same badge format but must manually set the
BADGE_PUSH_TOKEN
.
You can structure your badge sections like this:
## Public Repository π£



[](...)

[](...)
...
## Subscriber Release Information π

[](...)
...
The 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.
Workflow File | Description |
---|---|
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. |
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. |
These secrets must be configured in the GitHub repositories involved:
Secret Name | Scope | Purpose |
---|---|---|
GH_TOKEN |
All repos | Required for GitHub CLI operations (issues, PRs, comments, etc.) |
TEAMS_WEBHOOK_URL |
All repos | Used to send Adaptive Card notifications to Microsoft Teams |
DISCORD_WEBHOOK_URL |
All repos | Sends milestone, promotion, and closure alerts to Discord channels |
BADGE_PUSH_TOKEN |
All repos | Grants write access to push badge files to github_windows_IaC |
Add these under:
Settings β Secrets β Actions
for each participating repository.
Set the required secrets in each Private repo:
GH_TOKEN
TEAMS_WEBHOOK_URL
DISCORD_WEBHOOK_URL
BADGE_PUSH_TOKEN
Private Repo:
- Call
benchmark_track.yml
from PR merges or scheduled runs.
IaC Repo:
- Schedule
benchmark_promote.yml
to run daily.
Public Repo:
- Ensure
devel
branch andREADME.md
exist to validate versions.
Teams/Discord Webhooks:
- Ensure your automation supports HTTP POST with full JSON payloads.
- Benchmarks must follow naming conventions (
Private-Windows-*
βWindows-*
). README.md
format must include a recognizable version string (e.g.,vX.Y.Z
orVersion X, Rel Y
).- All workflows are modular and intended to be reused across repos.
- Discord support is now included in all milestones and promotion actions.
β This setup ensures full traceability and timely promotion of compliance benchmarks while keeping all stakeholders informed.
Triggered when a pull request from a branch matching benchmark_*
is merged into the latest
branch of a Private repo.
- Extract version from PR branch name
Example:
benchmark_v2.0.0
becomesv2.0.0
- Create a GitHub issue in the same repo with a 90-day countdown
- Assign labels, version tags, and metadata to the issue
- Post a confirmation comment in the PR for traceability
This tracks the need to promote this version publicly after 90 days.
Runs daily from the IaC repo. Monitors issues created by the tracker workflow.
- Scan all private repos for open issues labeled as benchmark trackers
- Parse the issue body to extract the version, repo name, and date created
- Calculate the age of each issue
- If the issue is older than 90 days:
- Clones the corresponding public repo
- Creates a PR to add the benchmark version to the
main
branch - Uses
gh pr create
andgh pr merge
to automate promotion - Pushes new badge files to
github_windows_IaC
- Sends a Teams notification with summary info
- Closes the original issue with a comment
If the issue is not yet 90 days old, it is skipped and checked again on the next scheduled run.
Each step is modularized inside the workflow YAML:
benchmark-tracker.yml
- name: Detect PR branch and extract version
- name: Create 90-day tracking issue
- name: Label and annotate PR
monitor-90day-promotions.yml
- name: Search for benchmark tracker issues
- name: Compare age against 90-day threshold
- name: Promote version if qualified
- name: Send Teams notification via webhook
- name: Update badge JSON in IaC
graph TD;
A[Private Repo Calls benchmark_track.yml] --> B{Is Public Repo Missing Version?}
B -- No --> C[No Action Needed]
B -- Yes --> D[Open 90-Day Tracking Issue]
D --> E[Send Tracking Start Notifications]
E --> F[benchmark_promote.yml Runs Daily]
F --> G{Is Issue 90+ Days Old?}
G -- No --> H[Send Milestone Reminders (30/60/90 Days)]
G -- Yes --> I{Already Promoted?}
I -- Yes --> J[Close Issue, Send Notifications]
I -- No --> K[Create PR to Public Repo]
K --> L[Send PR Notifications to Teams & Discord]
The system supports Teams and Discord alerts for all key events during benchmark tracking and promotion. These include:
- β Tracking Started
- π¨ Public Repo Missing
- β° Milestone Reminders (30, 60, 90 days)
β οΈ Overdue Warnings- β Already Promoted Notices
- β Promotion Blocked Alerts
- π¨ Auto-Promotion PR Created
Each message is customized for Teams and Discord formatting, with links to issues and PRs where applicable.
π Tracking Initiated - v2.0.0
π Subscriber Repo: ansible-lockdown/Private-Windows-2022-CIS
π¦ Subscriber Version: v2.0.0
π Community Target: ansible-lockdown/Windows-2022-CIS
π¦ Community Version: v1.9.0
β³ Subscriber Review Ends: Approx: 2025-09-07
ποΈ Auto-Promotion Date To Community: Approx: 2025-09-12
π
Promotion In: 90 days
π¨ Tracking Started β But There's A Problem π¨
Benchmark version 'v2.0.0' from **Private-Windows-2022-CIS** has entered the 90-day window.
β οΈ However, the public repo **Windows-2022-CIS** is missing or incomplete.
π’ Please create and prepare the community repo.
π Benchmark Release To Community Tracking Started
π Subscriber Repo: ansible-lockdown/Private-Windows-2022-CIS
π¦ Subscriber Version: v2.0.0
π Community Repo: ansible-lockdown/Windows-2022-CIS
π¦ Community Version: v1.9.0
β³ Review Ends: 2025-09-07
ποΈ Auto-Promotion Date: 2025-09-12
β° Benchmark Promotion Milestone
π’ 60-Day Reminder: Benchmark `v2.0.0` is scheduled for promotion in 30 days.
β οΈ If not promoted manually, auto-promotion occurs on Day 95.
π Subscriber Repo: Private-Windows-2022-CIS
π¦ Version: v2.0.0
π Target: Windows-2022-CIS
β±οΈ Days Tracked: 60
π Scheduled Auto-Promotion: 2025-09-12
β° Benchmark Promotion Reminder
β οΈ Benchmark v2.0.0 from `Private-Windows-2022-CIS` is overdue by 3 days.
β²οΈ Auto-promotion will occur in 2 days.
π View Issue #43
β
Benchmark Already Promoted
Benchmark version v2.0.0 is already in Windows-2022-CIS.
π
Auto-closed on: 2025-09-05
π View Issue #43
β
Benchmark Promoted To Community
Benchmark v2.0.0 from `Private-Windows-2022-CIS` is already in `Windows-2022-CIS`
πΏ Branch: devel
π
Auto-closed: 2025-09-05
π Issue: View Issue #43
β Benchmark Promotion Will Be Blocked
π« The community repo **Windows-2022-CIS** does not exist or is missing `devel`.
π’ Please resolve this to enable promotion.
π Repo: Private-Windows-2022-CIS
π¦ Version: v2.0.0
π¨ Benchmark PR Automatically Created π¨
Version v2.0.0 from Private-Windows-2022-CIS has been proposed for promotion.
π PR: https://github.com/ansible-lockdown/Windows-2022-CIS/pull/99
π
Days Tracked: 95
π Branch: promote_benchmark_v2_0_0
π¦ Benchmark Promotion PR Created: Promote v2.0.0
π Repo: Private-Windows-2022-CIS
π Target: Windows-2022-CIS
πΏ Branch: [promote_benchmark_v2_0_0](https://github.com/ansible-lockdown/Windows-2022-CIS/tree/promote_benchmark_v2_0_0)
π PR: https://github.com/ansible-lockdown/Windows-2022-CIS/pull/99
π
Days Tracked: 95
This repository also acts as the central badge hub for Linux-based benchmark pipelines in addition to Windows.
- All badge JSON files for Linux CIS and Linux STIG benchmarks are written to the
badges/
directory in this repo - The same export workflows (
export_badges_public.yml
,export_badges_private.yml
) handle both Windows and Linux badge publication - Example: A benchmark like
Ubuntu-22.04-CIS
will have badges stored at:
https://ansible-lockdown.github.io/github_windows_IaC/badges/Ubuntu-22.04-CIS/pre-commit-ci.json
This keeps badge generation consistent and centralized across all platforms for Lockdown.
Pull 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.