Enforce a suite of Installs, OS Settings, and Trusted Root Certificates with an output file sent to email when any issues or warnings are detected.
Private Repo Version: enforcement-script-windows
The NAS will host the enforcer and suite of files that manage the certificates and install packages. Email alerts are sent using attachments to Postfix. Crontab performs hourly reruns. The hosted files are accessible by clients on Z:\<NAS HOST>\<PARENT DIRECTORY>
.
Local hosts are first bootstrapped, which executes a series of tasks: creating the automated scheduled tasks in the Task Scheduler, checking for the NAS device availability then syncing the data from the device, instantiating script tamper protections, desired Windows OS Settings, and performing initial package and certificate installs. The local enforcer script runs based on pre-defined parameters including every logon. Local install persists to the C:\Tools
directory except for Winget-based packages. Certificates are placed within the NAS` trusted-root-certificates
folder. Installations and certificates may therefore be managed centrally and enforced including uninstalls and certificated renewal and revocations, without requiring a PKI setup.
An enforcement cron job runs on the NAS which performs the management of certificates, checking of valid packages for install management options, and certificate renewal and revocation for certificate management files. An email alert is sent when issues are discovered with any of the install and/or certificate management files including certificate revocation notices.
Replace the following when following for this readme to apply to your internal network in addition to the Scheduled Tasks XML files:
<DOMAIN>
: When referring to a folder path, user_
instead of.
characters. i.e.,Google_com
instead ofGoogle.com
. Non folder paths should retain the original.
character such as when pinging a device.- This does not apply to the XML files for Scheduled Tasks except where script calls via folder paths are defined.
<ROUTER IP>
: Internal IP of your router. Must respond to ping internally.<ROUTER HOSTNAME>
: Internal hostname of your router. Must be pingable and resolvable vianslookup
- Winget and OpenSSL are installed
- robocopy is also required but should be already included in Windows 10 or higher by default
- Ensure the following does not exist for each new target host being bootstrapped:
- Drive mapping letter
Z
- Directory path
C:\Tools
- Directory path
C:\<DOMAIN>
- Drive mapping letter
- Administrator permissions to bootstrap using an elevated command prompt.
- Ensure the client is connected to the workgroup,
- Copy the file
<DOMAIN>\windows_enforcer\batch\first_run_enforcement_checks.bat
, locally to the the 'C' drive from the NAS server, ensuring the client is on an<DOMAIN>
network. - Ensure the NAS is mapped as drive 'Z', if not, ensure you can ping
<ROUTER IP>
, the NAS server. (Note: If any other drive is mapped to 'Z', the script will fail) - Start an elevated command prompt, then execute the locally copied file.
- Check the
C:\<DOMAIN>\windows_enforcer\batch
folder, ensuring the filesC:\<DOMAIN>\windows_enforcer\batch\first_run_enforcement_checks.bat
andFirst Run Enforcement Checks.xml
exist. - Delete the manually executed
first_run_enforcement_checks.bat
file (which should not be theC:\<DOMAIN>\windows_enforcer\batch\first_run_enforcement_checks.bat
copy).
- Ensure
xmllint
is installed by running the following command"if ! command -v xmllint; then sudo apt install libxml2-utils; fi
. - Place a copy of the entire enforcement-script-windows folder somewhere within the directory structure of the NAS and create a Shared Folder with read-only permissions.
- Update the
first_run_enforcement_checks.bat
andjumpstart.bat
scripts to robocopy from the Shared Folder root recursively via the full path from the client's 'Z' drive mapping, per the snippet: -
:: check if drive is mapped, if not, ping NAS, if fails, skip, otherwise, re-map if not exist Z:\ ( echo mapped drive not found, pinging NAS >> %LOGFILE% :: use IP of NAS device ping -n 1 <ROUTER IP> | find "TTL" if not errorlevel 1 ( echo re-mapping NAS, ping responded >> %LOGFILE% goto resync ) else ( echo cannot ping NAS, either down or off the network >> %LOGFILE% echo will attempt remaining enforcement tasks, which will fail if at least one sync has not occurred >> %LOGFILE% ) ) else ( if exist Z:\<DOMAIN>\windows_enforcer\batch\first_run_enforcement_checks.bat ( goto resync ) else ( *** echo Z drive mapping is incorrect. Un-map existing Z drive, then try again *** >> %LOGFILE% ) )
- Create a cronjob that runs once per day and executes the
enforce-checker.sh
script from the NAS device. The cronjob should use an entrypoint to ensure proper carriage returns-
#!/bin/bash # entrypoint to execute windows enforcer enforce-checker.sh via crontab fullfilepath=$1 sed -i -e 's/\r$//' $fullfilepath /bin/bash $fullfilepath
- Give execute permissions to the entrypoint file:
chmod +x /path/to/entrypoint/file
- Refer to the example entrypoint file
example-crontab-enforcer_entrypoint.sh
in thewindows_enforcer/bash directory
. If the example file does not run, perform the following to correct the carriage returns and move the file outside of thewindows_enforcer
folder into/opt/<DOMAIN>/windows-enforcer
:sed -i -e 's/\r$//' /path/to/example-crontab-enforcer_entrypoint.sh
. -
# example crontab entries MAILTO=<EMAIL ADDRESS> 0 0 * * * /opt/<DOMAIN>/windows-enforcer/example-crontab-enforcer_entrypoint.sh /nas_path/<DOMAIN>/windows-enforcer/bash/enforce-checker.sh
-
- The NAS' IP must be
<ROUTER IP>0
- Additional home networks may be added by following instructions within the
first_run_enforcement_checks.bat
andjumpstart.bat
scripts, assuming NAS replication exists and the drive letter persists, per the snippet:-
:: copy and paste the below 2 lines for each network, updating the FQDN of the router hostname and IP and updating the integer value for neterror array ping -n 1 <ROUTER IP> | find "TTL" && ping -n 1 -a <ROUTER IP> | find "<ROUTER HOSTNAME>" && ipconfig | find "<DOMAIN>" set neterror[0]=%errorlevel%
-
- Create a folder on the NAS` parent
Z
drive,<DOMAIN>_last-runs
, with read, write, and delete access for all users. This is where theenforce-checker.sh
script can iterate and parse each text file created for every run by each local host to ensure each client completed afirst_run_enforcement_check
within the last 21 days from the day the enforcement checker is executed.
- Read access should be the default permission for the parent and subdirectories of the Shared Folder to allow for local Windows robocopy to copy the data.
- Write access should only be granted to admins designated to determine host enforcement.
From the NAS drive's enforcement folder, make changes to any file and it will sync and either execute or install.
IMPORTANT Never change the name of the file, C:\<DOMAIN>\windows_enforcer\batch\first_run_enforcement_checks.bat
, either within the NAS directory or locally on any client. If the 'First Run Enforcement Checks' scheduled task is ever deleted or modified, the above steps should be followed.
Each client runtime will ensure the following OS Settings and Windows Filesystem Permissions
- Enable Audit logging for logon and logoff events -both success and failures
- Enable Audit logging for all objects within the
C:\<DOMAIN>
directory for both success and failures. - Lock down the directory,
C:\<DOMAIN>
with only read and list access by non-Admins within theUsers
group. - Scheduled tasks are only viewable/modifiable by Admins.
- The First Run Enforcement Checks scheduled task is recreated when deleted by the The First Run Enforcement Checks Jumpstart scheduled task, which performs a check every user logon.
- Separate log files are created for the program which executes under the Jumpstarter. Log files are located in the same folder as the First Run Enforcement tasks prepended with
jumpstart-
. Refer to the Logging section for more info.
- Separate log files are created for the program which executes under the Jumpstarter. Log files are located in the same folder as the First Run Enforcement tasks prepended with
- The Jumpstart process runs every logon and every 3 days, checking scheduled tasks, scripts files, and last runs. Any errors will trigger re-syncing of the enforcement folder and re-creation of the scheduled tasks.
The First Run Enforcement Script contains a feature flag folder, editable on the NAS enforcement folder, \windows_enforcer\batch\featureFlags-first-run_enforcement_checks
Each file may be set to ON by updating the appended name accordingly.
certificate-refresh-renameMe-ON.txt
--> This file is managed by the program and should not be modified; used to track which certs are slated for refresh based on their expiry. certs expiring within 15 days are added to this list. new certs should be replaced using the same values and cert file name.certificate-refresh_FORCE_renameMe-OFF.txt
--> Rename with OFF set to ON and add hostnames for hosts that require a full cert refresh. only used for hosts that have been offline long enough to miss certificate replacements. set back to OFF when not in use.windows_os-malware-privacy_renameMe-ON.txt
--> A future feature flag, ensuring all privacy and malware-based Windows OS settings are hardened. Based on Chris Wellons' hardening. The code was taken from 0mid. Default:OFF
Use extreme caution in editing the Task Scheduler files which determine the scheduled tasks configurations. Only users with write permissions to the NAS enforcement folder may edit these files.
First Run Enforcement Checks.xml
: Manage the triggers and cadence of thefirst_run_enforcement_checks.bat
executions.Jumpstarter.xml
: Manage the triggers and cadence of theJumpstarter.bat
executions.Network Adapters - All - Reset.xml
: Manage the triggers and cadence of theNetwork_Adapters-All-Reset-Default.ps1
executions.
A Powershell facility exists in order to add customizations to the enforcement process. Add customizations with extreme caution ensuring the script has be thoroughly tested, ideally in a separate test.ps1
file. Edit the following file to add custom scripting: \windows_enforcer\powershell\first_run_enforcement-powershell.ps1
. This file may only be edited from the NAS device with proper write permissions. Be sure not to edit
Scripts executed manually will output logging data to the logged-in user's temp directory --> %temp%\<DOMAIN>\logs
(C:\Users\<user>\AppData\Local\Temp\<DOMAIN>
)
Scripts executed via task scheduler, even if executed manually, will output logging data from the system's specified log directory --> %temp%\<DOMAIN>\logs
(C:\Windows\temp
)
A new log is generated with the execution's point-in-time date and time stamp appended.
If the client is off the network, the script will attempt to execute enforcement tasks, which are expected to fail if at least one sync has not occurred or if the files were deleted within the local scripts folder. The next successful re-sync will re-create any missing files.
For every client run, last_run.txt
is overwritten with the timestamp of the most recent execution. The file is located in windows_enforcer\batch\last_run.tx
. This file is created on each local host in addition to a remote copy with the filename being the hostname. These remote files are used be Enforcement Checker to alert on last runs which did not occur for at least 28 days.
Every Jumpstart run also created an overwritten file, last_run-jumpstart.txt
, with the most recent timestamp of execution.
Log files are created in %TEMP%
(system level) as follows:
first-run-enforcement-<timestamp>.log
: contains details about thefirst_run_enforcement.bat
executions.first-run-enforcement-powershell-<timestamp>.log
: contains details about thefirst_run_enforcement-powershell.ps1
executions.jumpstart-<timestamp>.log
: contains details about thejumpstarter.bat
executions.
Downloads packages to the C:\Tools
folder, except for those that are obtained via the Winget package manager, in which case are installed according to the Winget process. Note, that only the data is downloaded to the C:\Tools
folder. Subsequent installs must occur manually post the data retrieval if required. Use this feature for pulling down simple packages. Subsequent download attempts are ignored for each install in which its corresponding directory gets created. For Winget, the script first checks the Winget list command for existing installs. Upgrades are not attempted once the installation is completed. Use Winget update --all
instead.
There are four files within the scripts\batch folder which reference the following install methods:
winget-install.txt
- Specify the official widget package names you would like installed. (Recommended). Values are case-sensitive. Usehttps://winstall.app
to check the package name spelling.winget-uninstall.txt
- Specify the official widget package names you would like uninstalled. (Recommended). Values are case-sensitive. Usehttps://winstall.app
to check the package name spelling. If the same value exists inwinget-install.txt
, the package will be skipped.github-release-installs.txt
- specify a list of downloadable repo packages against repos that utilize the GitHub package release feature. Use OWNER/REPO format.github-raw-installs.txt
- specify the full URLs against a raw GitHub downloadable, pointing to theraw.githubusercontent.com
domain.- i.e.,
https://raw.githubusercontent.com/AndyFul/ConfigureDefender/master/ConfigureDefender.exe
- i.e.,
Except for 'widget-install.txt', items removed from the text files will result in their respective directory removal from C:\Tools
only. You must still uninstall packages installed via an installer, hence, these methods, except for Winget, should only be used for simple executables. Winget uninstalls can be enforced by the aforementioned winget-uninstall.txt
install management input file.
Trusted Root Certificates may be added for home network devices that contain a web interface for TLS, such as a router's admin UI. This feature can be used to ensure all hosts receive the Trusted Root Certificate applied to the Computer setting of the Certificate Manager
trusted-root-certificates
folder is where the trusted root certificate should be placed. Once copied locally by the enforcement script, the certificate will be installed on the local host.- Certs within a 45-day or less certificate expiry will trigger an email alert via the Enforcement Checker hook.
- Email alerts will trigger and apply to the attached report until the cert is renewed. Ensure the same cert options are specified such as the CN, Subject, and SAN.
- Within 14 days are less of the cert expiry, the certificate will be placed on the refresh list,
certificate-refresh_renameMe-ON.txt
, located within thebatch\featureFlags-first-run_enforcement_checks
directory, which instructs all hosts to first remove the cert from the local Certificate Manager before installing the newly added cert dropped into thetrusted-root-certificates
directory.- After the 14-day window, any offline hosts will require a forced refresh. Rename
certificate-refresh_FORCE_renameMe-OFF.txt
within thebatch\featureFlags-first-run_enforcement_checks
directory, changing the textOFF
toON
. Then add the hosts that missed the 14-day window or were off the home network.- Hostnames that are not resolvable will trigger an error during an Enforcement Checker email.
- Upon the next enforcement run, only those hosts listed within the
certificate-refresh_FORCE_renameMe-ON.txt
will first remove the certificate from the local Certificate Manager, then install the non-expiring replacement.
- After the 14-day window, any offline hosts will require a forced refresh. Rename
- Certificates removed from the
trusted-root-certificates
folder are automatically placed on a revocation list,cert-revoked.txt
- Certificates present within the
cert-revoked.txt
are automatically removed from the local Certificate Manager. - Certificates with the same CN added back to the
trusted-root-certificates
folder are removed from the revocation list. - The text files used to track the presence and revocation of certificates are automatically backed up for redundancy. Restoration occurs when the original cert revocation files are missing or corrupted.
- Certificates present within the
- Ensure openssl is installed on the Windows host where the cert is to be generated
- Execute the following openssl command:
-
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 3650 -nodes -subj "/C=US/ST=NY/L=NY/O=<DOMAIN>/OU=Network/CN=<CERT NAME>" -addext "subjectAltName=DNS:<DNS ADDRESS 1>,DNS:<DNS ADDRESS 2>,DNS:<DNS ADDRESS 3>,DNS:<DNS ADDRESS 4..>,DNS:<IP ADDRESS>,IP:<IP ADDRESS>"
<CERT NAME>
=router-14brp.<DOMAIN>
as an example. This is the part used by the cert manager process above. - Convert Trusted Root Cert to Windows CRT file
openssl x509 -outform der -in cert.pem -out your-cert.crt
- Upload the private key to the device that will be used with the corresponding public key. Copy the key to a secure location then remove the local copy.
- Place the newly created CRT file inside the
trusted-root-certificates
folder on the NAS device.
-
The following Windows 10/11 Operating System settings are enforced. Explorer.exe will not be rebooted in favor of an uninterrupted end-user experience. Instead, settings will take effect on the next reboot.
- Audit logging enabled for the following
Success
andFailure
events:logon
andlogoff
events (including account events)Account management
Object access
(file and folder access; only those then enabled inside advanced ACLs)Privilege use
- The following files/folders are enabled recursively for audit logging upon
Success
andFailure
events for all usersC:\<DOMAIN>\*
- Windows File Explorer - Enable viewable file extensions
A files placed within the directory on the NAS enforcement side, ``C:<DOMAIN>`, will be replicated to all bootstrapped hosts. By default, a scripts
folder is created and enforced to ensure a predicable folder structure across all hosts for future automation and the enforcement of local scripts within the network.
Enforcement checker runs via cron to check for proper file and folder hygiene. It ensure the requisite certificate and installer management files are present and formatted correctly. Email alerts are sent out if any issues are detected including certain informational and warning types.
Email alerts will be generated with an attached log file if any of the following issues are detected by the enforce-checker.sh
cron job:
- Installer management files are missing such as 'winget-install.txt' or the 'install-removal' directory is missing
- Files and directories will be re-created without input or data
- Check installer management files for non-existent packages are executables
- Check if the Winget installer and uninstaller input files contain the same package
- Certificate management files are missing such as 'certificate-refresh-FORCE_renameMe-OFF.txt' or the 'trusted-root-certificates' directory is missing.
- Files and directories will be re-created with default settings
- Certificate validity is checked and invalid certs are placed in a newly created folder,
trusted-root-certificates-INVALID
. Certs already processed with this file name are placed on the revocation list. - Certificate has been added to the revocation list and will be removed from all clients on their next enforcement run
- Missing or corrupt certificate revocation management files and corrective actions.
- Ensure input files are properly formatted by replacing correct POSIX carriage returns and removes empty lines
- Any certs expiring within 45 days or less
- Will continue to alert until replaced with a non-expiring cert. All cert options should be identical, such as Subject, CN, and SAN.
- Once the expiry is 14 days or less automatic replacements will occur. These expiring certs will be removed and then added during the 14-day window.
- Last runs for any host is not reported back for more than 21 days. Last runs may be monitored by checking the parent NAS drive
Z
, checking the filename of the hostname corresponding to the last run check. Simply open the file to check the last date and time of the most recent enforcement run. - The
enforce-checker.sh
produces a log file inwindows_enforcer\last_run_enforce-checker.txt
. The log file is overwritten by every run of the process.
The Last Run Checker is presents a list of all hosts with their last First Run Enforcement Check runs. The same files parsed by the tools are also used by the Enforcement Checker to produce email alerts for each host that did not incur a run in 21 days or more. These emails are sent with a unified attachment of all other issues detected by the Enforcement Checker; for hosts which meet this criteria, an indicator will be presented within the output. The Last Run Checker tool may only be executed on the NAS device and not on the clients-side and are excluded from the enforcement's copy process.
- To use the tool, execute the following command from shell directly on the NAS:
Z:\<NAS HOST>\<PARENT DIRECTORY>\last-runs-check.sh
- The suite of files outputted by every host and parsed by the tool is located at
Z:\<NAS HOST>\<DOMAIN>_last-runs
- Logs are overwritten by every host with a timestamp indicating the last run time and date.
The Certificate Checker will output a list of each certificate inside the trusted-root-certificates
folder with the following details: File Name, Subject, Expiration, and an indicator as to whether the certificate expires in less than or equal to 45 days. This tool many only be executed on the NAS device and not the client-side and are excluded from the enforcement's copy process.
- To use the tool, execute the following command from shell directly on the NAS:
Z:\<NAS HOST>\<PARENT DIRECTORY>\cert-check.sh
- The suite of files outputted by every host and parsed by the tool is located at
Z:\<NAS HOST>\trusted_root_certificates