ansible-lockdown/Windows-2019-STIG
ansible-lockdown/Windows-2019-STIG has 41 GitHub stars and 22 forks. GitHot measured 0 stars in 24 hours. Last checked 2026-11-15 05:36 UTC. Last push 2026-09-24.
Measured star growth
- in 24h
- 0
- in 7 days
- Collecting history
- in 15 days
- Collecting history
- in 1 month
- Collecting history
Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.
About
Automated STIG Benchmark Compliance Remediation for Windows Server 2019 with Ansible
ProductivityREADME.md
OriginalWindows 2019 DISA STIG
Configure a Windows 2019 system to be DISA STIG Compliant
Based on Windows DISA STIG Version 3, Rel 9 released on July 1st, 2026
Looking For Support?
Community
Join us on our Discord Server to ask questions, discuss features, or just chat with other Ansible-Lockdown users.
Contributing
Bug reports and feature requests are welcome from everyone, please raise an issue.
Pull requests are accepted from approved contributors only. To be onboarded, join the Discord Server and request contributor access. See CONTRIBUTING.md for the full process.
Caution(s)
This role will make changes to the system which may have unintended consequences. This is not an auditing tool but a remediation tool to be used after an audit.
Check Mode is not supported! The role will be completed in check mode without errors, but it is not supported and should be used with caution.
This role was developed against a clean install of the Windows 2019 operating system. If you are implementing an existing system please review this role for any site-specific changes that are needed.
To use the release version please point to the main branch and relevant release for the STIG benchmark you wish to work with.
Domain Members
Account policy is domain scoped. On a domain joined host the Default Domain Policy owns
[System Access], so the 13 secedit backed controls in this role cannot hold there. prelim.yml
detects domain membership, skips those controls and warns once, rather than writing settings the
domain will not keep. Set them in the Default Domain Policy instead.
Everything outside [System Access] applies normally on a domain member.
This behavior was verified on a domain joined workstation during Windows Fleet testing, where a
complete hardening run left all [System Access] values byte-identical to the pre-run baseline. It
has not been separately measured on Windows Server 2019.
Matching A Security Level For STIG
It is possible to only run controls that are based on a particular security level for STIG. This is managed using tags:
- CAT1
- CAT2
- CAT3
The control found in defaults/main/main.yml also needs to reflect true as this will allow the controls to run when the playbook is launched.
Coming From A Previous Release
STIG releases always include changes, so it is highly recommended to review the new references and available variables. This process has evolved significantly since the initial release of Ansible-Lockdown.
The solution is now compatible with Python3, provided it is set as the default interpreter. However, this compatibility requires certain prerequisites to ensure the system is configured appropriately.
Further details can be seen in the Changelog
Auditing (new)
Currently, this release does not have an auditing tool.
Compliance facts
With create_benchmark_facts enabled (the default), the role writes a record of what it applied to:
C:\ProgramData\ansible\facts.d\compliance_facts.json
It captures the benchmark release, the run date and which CAT levels were enabled.
Windows has no default local-facts directory, so unlike the Linux roles this file is not collected automatically. Ask for it explicitly:
- name: Read the compliance facts
ansible.windows.setup:
fact_path: 'C:\ProgramData\ansible\facts.d'
It then appears as ansible_compliance_facts - not under ansible_local, which is the Linux
convention. Set ansible_facts_path to relocate the directory, or create_benchmark_facts: false
to skip writing it.
Documentation
- Read The Docs
- Getting Started
- Customizing Roles
- Per-Host Configuration
- Getting the Most Out of the Role
Requirements
General:
Basic knowledge of Ansible, below are some links to the Ansible documentation to help get started if you are unfamiliar with Ansible
Functioning Ansible and/or Tower Installed, configured, and running. This includes all of the base Ansible/Tower configurations, needed packages installed, and infrastructure setup.
Please read through the tasks in this role to gain an understanding of what each control is doing. Some of the tasks are disruptive and can have unintended consequences in a live production system. Also, familiarize yourself with the variables in the defaults/main/main.yml file.
Technical Dependencies:
- Windows 2019 - Other versions are not supported
- Running Ansible/Tower setup. This role requires ansible-core 2.16.1 or newer; the role asserts this at run time.
- Python3 Ansible run environment
- pywinrm
pywinrm is required on the controller host that executes Ansible; it is the connection library Ansible uses to reach a Windows target.
Role Variables
Breaking change in this release
Role behavior variables and security tunables now share the win19stig_ prefix. If you override any of the security
tunables in inventory, group_vars or extra vars, rename them - the old names are no longer read
and your setting will be silently ignored.
wn19stig_<name>becomeswin19stig_<name>(for examplewn19stig_minimumpasswordlengthbecomeswin19stig_minimumpasswordlength)win2019stig_<name>becomeswin19stig_<name>(for examplewin2019stig_disruption_highbecomeswin19stig_disruption_high)- the three category switches change suffix as well as prefix:
win2019stig_cat1_patch,cat2_patchandcat3_patchbecomewin19stig_cat1_controls,cat2_controlsandcat3_controls wn19stig_machineaccountpsswd_max_agebecomeswin19stig_machineaccountpassword_max_age
Four variables are removed rather than renamed: win19stig_cloud_based_system with the cloud
detection it gated, win2019stig_min_ansible_version which is now min_ansible_version in
meta/main.yml, and the rule toggles wn19_00_000290 and wn19_cc_000451 for controls DISA has
retired.
Rule toggles are unchanged. They keep the wn19_<control id> form, for example
wn19_au_000010.
This role is designed so that the end user should not have to edit the tasks themselves. All customizing should be done via the defaults/main/main.yml file or with extra vars within the project, job, workflow, etc. Non-disruptive CAT I, CAT II, and CAT III findings will be corrected by default. Disruptive finding remediation can be enabled by setting win19stig_disruption_high to true.
Tags
There are many tags available for added control precision. Each control may have its own set of tags noting what category, what OS element it relates to if it's a patch or audit, and the rule number.
Conversion Format for NIST References:
- Standard Prefix:
- All references are prefixed with "NIST".
- Standard Types:
- "800-53" references are formatted as NIST800-53.
- "800-53r5" references are formatted as NIST800-53R5 (with 'R' capitalized).
- "800-171" references are formatted as NIST800-171.
- Details:
- Section and subsection numbers use periods (.) for numeric separators.
- Parenthetical elements are separated by underscores (_), e.g., IA-5(1)(d) becomes IA-5_1_d.
- Subsection letters (e.g., "b") are appended with an underscore.
Example of Tag Usage:
Below is an example of the tag section from a control within this role. Using this example if you set your run to skip all controls with the tag CCI-000185, this task will be skipped. The opposite can also happen where you run only controls tagged with CCI-000185.
tags:
- WN19-00-000130
- CAT1
- CCI-000213
- SRG-OS-000080-GPOS-00048
- SV-205663r958472_rule
- V-205663
- NIST800-53R4_AC-3
Conversion Examples in Use:
- 800-53r4 IA-5(1)(d) -> NIST800-53R4_IA-5_1_d
- 800-171 3.5.2 -> NIST800-171_3.5.2
- 800-53 AC-17(2) -> NIST800-53_AC-17_2
- 800-53 CM-6b. -> NIST800-53_CM-6b.
By maintaining this consistent tagging structure, it becomes easier to filter and manage tasks based on specific controls and compliance requirements.
Community Contribution
Pull requests are accepted from approved contributors only, and issues are welcome from everyone. See CONTRIBUTING.md for the onboarding process, the rules, and the commit signing requirements (GPG signature and Signed-off-by on every commit).
Pipeline Testing
uses:
- ansible-core 2.16.1 or newer, from the pinned virtualenv on the runner
- runs the role against a Windows target provisioned on Azure with OpenTofu, which is torn down when the run ends
- self-hosted runners
- pull requests into
develor abenchmark*branch run the devel pipeline; pull requests intomainorlatestrun the main pipeline - the job runs only for pull requests raised from a branch in this repository, because it carries the cloud credentials
Local Testing
- Ansible
- ansible-core 2.16.1 or newer, with Python 3
pywinrmon the controller, which is the connection library Ansible uses to reach a Windows target
Credits and Thanks
Massive thanks to the fantastic community and all its members.
This includes a huge thanks and credit to the original authors and maintainers.