Lawliet LAWLIET
Book a demo

40. The control catalog, profiles and frameworks

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.

Every hardening and compliance control Lawliet checks or fixes is one record in the control catalog. The catalog is the base of the whole hardening and compliance program: scans read their checks from it, the planner orders and guards its fixes (chapter 41), the do-not-disrupt baseline compares its declared effects with each host (chapter 42), framework scores and signed reports roll its results up (chapter 43), and exports turn it into Group Policy, Ansible or a shell bundle (chapter 44).

This chapter explains what is in the catalog, how the role profiles and their levels work, where a control applies, how the catalog is protected, and how to read it.

Permissions:

TaskPermissionFour-eyes
Read the catalog, its controls and the profilesView compliance-
Scan a host against a profileRun scansno
Create, change or delete a customer profileChange compliance profilesyes - critical action "Change a compliance profile"

40.1 What the catalog holds#

The catalog shipped with this release has 1,401 controls:

PlatformContent
Windows workstations (Windows 10 and 11)410 controls in 16 families: every Attack Surface Reduction rule as its own control (audit first, then block), Microsoft Defender Antivirus, BitLocker for system, fixed and removable drives, firewall logging, SmartScreen, exploit protection, virtualization-based security and memory integrity, Office macro policy, Edge and Chrome policy, removable storage and device installation, advanced audit policy and event log sizes, Windows Update, sign-in screen and screen lock, local accounts, software installation, telemetry and privacy
Windows member servers and domain controllers284 controls (srv-* and dc-* families): user rights, security options, the server audit set, SChannel (TLS) settings, SMB 3 encryption and dialects, features and services to remove, IIS, Windows LAPS, remote registry; on domain controllers Kerberos policy, LDAP signing and channel binding, anonymous directory access, DSRM, DNS zone transfers and secure updates, and Active Directory checks (machine account quota, delegation, Protected Users, AdminSDHolder, Recycle Bin, standing Enterprise/Schema Admins, tier-0 accounts on lower tiers, NTDS/SYSVOL/GPO permissions)
Windows sign-in and remote management53 controls (auth-* families): WinRM, NTLM on a host and across the domain, Kerberos armoring and AES, credential theft (Credential Guard, Remote Credential Guard, LSASS, CredSSP, UAC), relay and coercion (LDAP client signing, EFSRPC and DFSNM RPC filters, Print Spooler, WebClient, SMB SPN validation, AD CS Web Enrollment, Netlogon), remote administration (RDP over TLS, PowerShell transcription, auditing)
Ubuntu Server 20.04, 22.04 and 24.04316 controls in 20 families: filesystem, boot, AppArmor, devices, network, kernel, auditd, logging, time, SSH, PAM, sudo, accounts, cron, services, firewall, permissions, packages, AIDE, banners
The controls of earlier releasesThe 93 Windows and 112 Linux controls of 1.5.12.s, kept under their old ids, so scans, history, heatmap and trends are unchanged
VMware vSphere99 host, VM and port group controls (chapter 46)
AWS34 account controls (chapter 47)

Each control states, in plain words, what is wrong, why it matters and what may break. It carries:

PartWhat it means for you
IdA stable name such as WIN-WINRM-HTTP-LISTENER or UBU-SSH-ROOT-LOGIN. Older ids still match through the control's legacy id
Severitycritical, high, medium or low
Roles and OS versionsWhere it applies: workstation, member server, domain controller, server; the Windows or Ubuntu versions it covers
Levelsstrict, and also standard when the control belongs in the lighter level (see 40.2)
Stageenforce (fixed directly), audit_then_enforce (an audit step runs first; 41.5) or report_only (checked and reported; the fix is a manual runbook)
Requires / conflictsControls that must pass first, and controls that cannot both be enforced
GuardsSafety checks the planner runs before an enforce (41.4)
TelemetryThe usage signals the planner reads to predict breakage (chapter 45)
Effects (affects)The services, ports, packages, protocols, processes, kernel modules and scheduled tasks the change touches; compared with the host's do-not-disrupt baseline (chapter 42)
LockoutWhether the change can lock you out of the host, and the recovery artifact to issue first (26.5)
Check, fix, rollbackThe check, the remediation (which records the value it replaces) and the rollback (which puts exactly that value back, and says so when it could not)
MappingsThe framework requirements it satisfies: CIS, DISA STIG, NIST SP 800-53 Rev. 5, ISO/IEC 27001:2022, PCI DSS 4.0.1, GDPR, FSTEC, GOST R 57580.1, NIS2, DORA (and for cloud and virtualisation: AWS Foundational Security Best Practices, CIS AWS Foundations, the VMware vSphere Security Configuration Guide)

Some Windows controls are report-only by design because the change is irreversible or a judgement call: the krbtgt password reset, the AD Recycle Bin and directory permission repairs. They are checked and reported, and their runbook is in the control's text.

Framework mappings#

A control maps to framework requirements directly, and through topics (for example remote-admin-encryption): a control tagged with a topic reports against every framework id of that topic. The requirement lists shipped with this release:

FrameworkRequirements
NIST SP 800-53 Rev. 51014 controls and enhancements
ISO/IEC 27001:2022 Annex A93
PCI DSS 4.0.1280
GDPR security articles10
NIS2 Art. 21(2), with the Annex of Implementing Regulation 2024/269063
DORA Art. 9, 10 and 12, with the ICT risk RTS 2024/1774128
FSTEC orders 17, 21, 117 and 239113, 109, 38 and 152
GOST R 57580.1406 measures

Requirement ids are the public identifiers; titles are short wording of our own. FSTEC Order 117 replaced Order 17 on 1 March 2026; Order 17 stays for systems still certified under it, and everything mapped to Order 17 also reports against Order 117 through a transition table (our analysis; FSTEC published no official one). Checks that only test that a tool is installed count as "manual / evidence upload", not as automated.

The existing "PCI DSS v4.0" checks now carry their PCI DSS 4.0.1 numbers (for example password complexity is 8.3.6, not 8.2.3; firewall findings 1.3.1/1.3.2, not 1.2.1). Scan results stored before the upgrade keep their old numbers and still open the right check.


40.2 Role profiles and levels#

A profile is the set of catalog controls for one kind of host. Four are built in:

ProfileFramework code (Framework registry)Hosts
Windows workstationlawliet_windows_workstationWindows 10/11 endpoints
Windows member serverlawliet_windows_member_serverDomain-joined Windows Server
Windows domain controllerlawliet_windows_domain_controllerActive Directory domain controllers
Ubuntu serverlawliet_ubuntu_serverUbuntu 20.04/22.04/24.04 servers

Each profile has two levels:

LevelContent
strict (the default)Every catalog control of the platform that applies to the role. The strictest baseline: a control is relaxed only by an approved exception (25.2)
standardOnly the controls marked standard. Every standard control is also in strict

There is no separate CIS "Level 1 / Level 2" switch. Each control carries its CIS and DISA STIG references (shown in exports and reports), and the benchmark frameworks of earlier releases - for example cis_windows_workstation, cis_windows_server, stig_windows, cis_linux, stig_linux - stay in Compliance > Overview > Framework registry for scanning. A profile is scanned like any framework: choose its code in the scan form (22.2).

The planner offers both levels (the Profile list on Hardening > Planner); the exports offer both (the Level list on Compliance > Exports). A level is not stored per host: you choose it each time.

Customer profiles#

A customer profile derives from one built-in profile: the same controls at the level you choose, plus controls you add from the same platform. It never drops a control - a control that does not fit a host is an exception, which is time-limited, approved by a second person and reported as accepted risk. A customer profile becomes a framework of its own (code lawliet_profile_<id>, name "Profile: <name>") that scans, the fix plan and hardening use like any other.

There is no console screen for customer profiles in this release; they are managed through the API (40.5).


40.3 Where a control applies, and "not applicable"#

Every catalog check and change first checks the host's role and OS version (and, for Ubuntu content, that the host is Ubuntu). On a host outside its scope:

"Not applicable" is accepted only from a control that can be inapplicable on that host: the host has another role, a version the control does not cover, or a feature the control needs is absent - and the catalog says so explicitly for that control. Anywhere else a "not applicable" answer is scored as not met. A later scan that finds a control not applicable takes its older result out of framework scores. Three server checks (SMB encryption, SMB unencrypted access, legacy TLS usage) answer not assessed - not "not applicable" - when they cannot read the setting or have no evidence.

What this changes after an upgrade from 1.5.13.s: 31 of the migrated Windows controls (45 framework entries: 14 in CIS workstation, 21 in CIS server, 10 in STIG) now decline hosts outside their role or version - the server-only ones on workstations, and the local account policy and user-rights ones on domain controllers, whose Group Policy would revert a local change. Their scores on those hosts no longer count them.

A host whose role cannot be read is not guessed: role-specific controls are not run there until the agent reports the role (domain controller, member, standalone).


40.4 How the catalog is protected#

The catalog is signed with the vendor's release key when a bundle is built, and checked each time the product starts. A catalog changed after signing is refused.

The signature also covers the helper files under <platform>/lib/: the Group Policy library for Windows and, since 1.5.14.s, ubuntu/lib/lwfw.py.txt, the model of ufw's rule store that the Ubuntu firewall controls use. It is kept once there and put into each firewall script when the script is sent (to an agent, over SSH, into the shell bundle or the Ansible role); what runs on the host is the same as before.

What you see if the check fails: the catalog API answers 503 with the reason, and the built-in and customer profiles have no controls to scan. Scans of the older benchmark frameworks are not affected.

What to do: never edit the control catalog's files in the installation directory. Re-apply the release you run (sudo ./lawliet update <bundle> with the same bundle, chapter 4), or restore the installation directory from your backup, then contact [email protected] with the output of sudo ./lawliet diag if it persists.


40.5 Reading the catalog and managing customer profiles (API)#

The catalog has no console browser in this release. Its controls show up where they are used: scan results, the Fix plan, the planner, framework requirements and exports. To list or search it, use the API (any account with View compliance; a service-account key with the Read only scope works for reads, 15.7):

CallReturns
GET /api/v1/compliance/catalogControls, filtered by platform (windows, ubuntu, linux), role (workstation, member_server, domain_controller, server), family, framework (a mapping key such as cis, stig, nist_800_53, fstec) with optional mapping_id, severity, level (strict, standard), stage, os_version, legacy, q (text in the id or title); limit (at most 2000) and offset. An unknown filter value is refused (422), never silently empty
GET /api/v1/compliance/catalog/metaThe catalog version and counts
GET /api/v1/compliance/catalog/controls/{control_id}One control: its mappings, relations and commands
GET /api/v1/compliance/catalog/profilesThe built-in and customer profiles with their control counts
GET /api/v1/compliance/catalog/profiles/{ref}One profile and its controls (a built-in slug such as windows-workstation, or custom-<id>)

Example, every high-severity domain controller control mapped to NIST AC-17:

curl -H "Authorization: Bearer lwk_..." \
  "https://<server>/api/v1/compliance/catalog?role=domain_controller&severity=high&framework=nist_800_53&mapping_id=AC-17"

Procedure: create, change or delete a customer profile#

Permission: Change compliance profiles (administrator roles). Four-eyes: yes - the critical action "Change a compliance profile". API keys cannot reach these calls; they are made with an administrator's signed-in session.

Risk: a profile decides what is checked and enforced on its hosts. Adding a control that breaks a workload shows up as failing results, and hardening it still goes through the planner's guards and approval. Rollback: change the profile again (remove the added control or change the level), or delete it; its scan history stays.

CallBody
POST /api/v1/compliance/catalog/profilesname (unique), description, base (one of windows-workstation, windows-member-server, windows-domain-controller, ubuntu-server), level (strict or standard), add_controls (catalog ids of the same platform, at most 500, none twice)
PATCH /api/v1/compliance/catalog/profiles/{profile_id}Any of name, description, level, add_controls (the full new list). The base cannot change
DELETE /api/v1/compliance/catalog/profiles/{profile_id}-
  1. Send the call. An invalid body is refused at once (422) - before anything is held for approval - with the reason, for example "not windows catalog controls: ...".
  2. With dual control on, the call answers that the request is held for approval (HTTP 428). A second administrator approves it in Approvals > Waiting for me.
  3. Open Approvals > My requests and press Execute now within the execution window.

What you see: the profile, with its framework code lawliet_profile_<id>. It appears in the Framework registry as "Profile: <name>" and can be scanned at once. A deleted profile can no longer be scanned; its framework and scan history stay.

If it fails:

MessageCauseFix
409 "A profile with that name exists"Names are uniqueChoose another name
422 "base must be one of ..."Unknown baseUse one of the four built-in slugs
422 "a ... control twice" / "not ... catalog controls"A duplicate, or a control of another platformCorrect add_controls
403No Change compliance profilesAsk an administrator