Lawliet LAWLIET
Book a demo

44. Compliance exports: Group Policy, Ansible and the signed shell bundle

This guide describes Lawliet 1.5.14.s (the current release). Screens, commands and procedures may change in later versions; the usage guide is updated with each release. Check the version your server runs under Settings > Platform or with ./lawliet version, and see the Releases page for what changed.

An export takes a role profile (40.2) outside Lawliet, for hosts you harden with your own tools or that no agent reaches:

ProfileExports
Windows workstation, member server, domain controllerGPO backup: a Group Policy backup for Group Policy Management "Import Settings" (registry.pol, a security template, advanced audit policy), with a how-to-import and Security Filtering guide
Ubuntu serverAnsible role (check mode, idempotent, tags per control and family, a rollback playbook from the recorded prior state); Signed shell bundle (one script with check / apply / rollback / report, signed with the vendor's release key when the release was built)

In every export:

Path: Compliance > Exports.

Permissions: seeing the profiles needs View compliance; creating, downloading, listing exports and importing a shell bundle report need Manage compliance. Four-eyes: no. Every creation and download is written to the audit trail.

The changes an export makes happen on your hosts, through your tools - not through Lawliet's approval and planner checks. Review each export before you apply it, and roll it out to a pilot group first.


44.1 What the page shows#

Procedure: create an export#

  1. Choose the Level on the profile's card.
  2. For a Windows profile, optionally type the AD domain (optional, recorded in the backup), for example corp.example.
  3. Press the export button ("Building..."). The file downloads.

What you see: "<kind>: N controls in the export, M exceptions excluded, K not expressible, J held back. The README inside lists each one." For a shell bundle, also "Signed with the vendor release key. Verify it before use: VERIFY.txt in the bundle." (or "NOT signed: <reason>") and "profile.conf SHA-256 (the script prints it before apply; it must match): <hash>". Note the hash.


44.2 Procedure: import the GPO backup in Group Policy Management#

You need: a computer with the Group Policy Management Console (a domain controller or RSAT), and rights to create and link GPOs.

Risk: once linked, every computer in scope applies the settings at its next policy refresh. Some settings can break legacy clients (NTLM, SMB, TLS). Rollback: unlink the GPO and run gpupdate /force. Registry values outside SOFTWARE\Policies stay set; the README in the backup says how to revert them.

  1. Unzip the archive. Keep the backup folder (named like {GUID}) next to manifest.xml.

  2. In GPMC, right-click Group Policy Objects > New. Name it as the export suggests. Do not link it yet.

  3. Right-click the new GPO > Import Settings... > Next > Next > Backup folder: the unzipped folder (the one that contains manifest.xml) > select the GPO > Next. Review "Scanning Backup" > Next > Finish.

    PowerShell equivalent (from HOW-TO-IMPORT.txt in the archive):

    Import-GPO -BackupId '<backup id>' -Path 'C:\path\to\unzipped' -TargetName '<GPO name>' -CreateIfNeeded
  4. Right-click the GPO > Edit and check Computer Configuration > Policies > Windows Settings > Security Settings, and the registry values.

  5. Security Filtering - pilot first:

    1. Create a security group, for example GPO-Lawliet-Pilot, and add the pilot computer accounts.
    2. Select the GPO > Scope tab > Security Filtering: add the group, remove Authenticated Users.
    3. Delegation tab > Advanced... > add Authenticated Users (or Domain Computers) with Read only - not "Apply group policy". Without Read for computers the GPO is not processed at all.
    4. Link the GPO to the OU that holds the computers (right-click the OU > Link an Existing GPO).
    5. On a pilot computer: gpupdate /force, then gpresult /h report.html, then run a Lawliet compliance scan to see the controls pass.
  6. To exclude computers (for example hosts with a host-scoped exception, listed in README.txt): put them in a group and give that group Apply group policy: Deny on the Delegation tab.


44.3 Procedure: run the Ansible role#

You need: Ansible on a control host that reaches the Ubuntu hosts with sudo.

Risk: the role changes SSH, PAM, firewall, kernel and service settings. Rollback: ansible-playbook rollback.yml puts back what the role recorded.

  1. Unzip the role. It holds site.yml, rollback.yml, ansible.cfg, inventory.example.ini, README.md and export.json.

  2. Copy inventory.example.ini to your inventory and list the hosts.

  3. Dry run, then apply:

    ansible-playbook site.yml --check --diff    # what would change
    ansible-playbook site.yml                   # apply
    ansible-playbook site.yml --tags UBU-SSH-ROOT-LOGIN   # one control (tags: control id, lawliet_family_<family>)
    ansible-playbook rollback.yml               # put back what the role changed
  4. Run a Lawliet compliance scan of the hosts to confirm.


44.4 Procedure: verify and run the signed shell bundle#

For air-gapped Ubuntu hosts with no Ansible. Run as root on the host.

Risk: apply changes the host's configuration. Rollback: ./lawliet-harden.sh rollback puts back what apply changed, from the state in /var/lib/lawliet/bundle - keep that directory until you no longer need to roll back.

  1. Copy the whole folder to the host.
  2. Verify the signature first (OpenSSL 3, Ubuntu 22.04 and later):
    openssl dgst -sha256 -binary lawliet-harden.sh > /tmp/lawliet.digest
    base64 -d lawliet-harden.sh.sig > /tmp/lawliet.sig
    openssl pkeyutl -verify -pubin -inkey lawliet-release-public.pem -rawin \
        -in /tmp/lawliet.digest -sigfile /tmp/lawliet.sig

    It must print Signature Verified Successfully. Anything else: do not run the script. Compare the key's fingerprint in VERIFY.txt with the one on Compliance > Exports (a key shipped inside the same archive proves nothing by itself). A bundle marked NOT signed cannot be verified this way: do not use it on production hosts.

  3. Check, then apply:
    ./lawliet-harden.sh check --level strict                  # changes nothing
    ./lawliet-harden.sh apply --level strict --json apply.json

    Before applying, the script prints the SHA-256 of profile.conf. It must match the hash the console showed. profile.conf is not signed: it holds the approved exceptions and can only exclude controls, but an edited copy could exclude controls you meant to enforce.

  4. To undo: ./lawliet-harden.sh rollback.
  5. To report: ./lawliet-harden.sh report --level strict > report.json, then import it (44.5). ./lawliet-harden.sh help lists every option.

44.5 Procedure: import a shell bundle report as evidence#

Permission: Manage compliance. Four-eyes: no.

  1. On Compliance > Exports, under Import a shell bundle report, press Choose report.json and pick the file from lawliet-harden.sh report.

What you see: "Imported N control results as evidence bundle #M." The bundle is on Evidence (chapter 27) and is marked self-reported by the host - the results come from the host's own script, not from a Lawliet agent.

If it fails: "Import failed." or the server's reason (not a bundle report, or malformed JSON).