Skip to content

add scap_policy and scap_policy_info modules - #1988

Open
expeditioneer wants to merge 1 commit into
theforeman:developfrom
expeditioneer:add-scap-policy-module
Open

add scap_policy and scap_policy_info modules#1988
expeditioneer wants to merge 1 commit into
theforeman:developfrom
expeditioneer:add-scap-policy-module

Conversation

@expeditioneer

Copy link
Copy Markdown

Closes #748.

Supersedes #752, which was left as WIP in 2020. The module name follows @evgeni's suggestion there (foreman_scap_policy), minus the foreman_ prefix that has since been dropped collection-wide — so scap_policy, alongside scap_content and scap_tailoring_file.

What

  • scap_policy — CRUD for OpenSCAP compliance policies
  • scap_policy_info — matching info module

Why

Without a module, playbooks have to fall back to uri against /api/compliance/policies. The awkward part is not the CRUD but the profile lookup: the API wants scap_content_profile_id and tailoring_file_profile_id, which are only obtainable from the parent entity. scap_policy takes scap_content, scap_content_profile, tailoring_file, tailoring_file_profile and hostgroups by name/title and resolves the ids.

Notes for reviewers

  • entity_name='policy' — the apidoc resource is policies, so the name derived from the class does not exist. Same as installation_medium.py.
  • Why the profiles are resolved against the parent rather than via the scap_content_profiles resource with spec hints, as suggested in Add foreman_policy module #752: that resource cannot be filtered by scap_content_id (Field 'scap_content_id' not recognized for searching!), and titles are not unique. On a real instance with 45 profiles, one title occurred twice within the same SCAP content, and tailoring profiles had empty titles. A type='entity' lookup by title would fail with "too many results" and could not address the empty ones at all. Hence the parent-scoped lookup with a fallback to the XCCDF profile id.
  • lookup_entity() + set_entity() are used for that, per @mdellweg's note in Add foreman_policy module #752, so the parents are resolved once and the auto lookup in run() does not fetch them again.
  • deploy_by is in required_if for state=present — the apidoc marks it required: true on create.
  • New apidoc fixture tests/fixtures/apidoc/openscap.json instead of a symlink to an existing one: foreman.json has no openscap resources, and luna.json serves organizations under /katello/api/organizations, which does not match a plain Foreman + openscap recording. Per docs/testing.md the apidoc of the actual install is placed in the fixtures folder; both test names symlink to it.
  • Only name, location and organization are searchable on this resource — deploy_by, period and description return ScopedSearch::QueryNotSupported. The info module examples reflect that.
  • host_ids is deliberately not exposed. The API supports it, but I had no instance with directly assigned hosts to verify the response shape of the hosts key. Happy to add it if someone can confirm.

Testing

Fixtures recorded against Foreman 3.17.2 with foreman_openscap 12.0.1.

  • test_crud and test_check_mode pass for both modules in replay mode
  • ansible-test sanity --venv clean for both modules (24 tests)
  • yamllint, flake8, ansible-playbook --syntax-check clean
  • generate_action_groups.py produces no diff against the committedmeta/runtime.yml

Closes theforeman#748. Supersedes the abandoned WIP
in theforeman#752; the module name follows evgeni's suggestion there, minus the
foreman_ prefix that has since been dropped collection-wide.

The apidoc resource is "policies", not the name derived from the module, so
entity_name is set explicitly. Profile lookup resolves an XCCDF profile title
to scap_content_profile_id / tailoring_file_profile_id against the parent
entity and falls back to the profile id, since customized tailoring files
often carry an empty title. Resolving via the scap_content_profiles resource
instead is not viable: it cannot be filtered by scap_content_id and profile
titles are not unique, not even within a single SCAP content.

Changes:

- plugins/modules/scap_policy.py: new CRUD module; takes scap_content,
  tailoring_file and hostgroups by name/title and resolves the ids
- plugins/modules/scap_policy_info.py: matching info module; only name,
  location and organization are searchable on this resource
- tests/test_playbooks/scap_policy.yml: create/idempotency/tailoring/rename/
  delete against the ssg-firefox-ds fixtures
- tests/test_playbooks/scap_policy_info.yml: info test after the domain_info
  pattern
- tests/test_playbooks/tasks/scap_policy.yml: reusable task file
- tests/test_playbooks/fixtures/scap_policy*-*.yml: recorded against Foreman
  3.17.2 with foreman_openscap 12.0.1
- tests/fixtures/apidoc/openscap.json: apidoc of that install; foreman.json
  lacks the openscap resources and luna.json serves organizations under
  /katello/api, which does not match the recording
- meta/runtime.yml: register both modules in action_groups.foreman
- changelogs/fragments/add-scap-policy-module.yml: changelog

Signed-off-by: Dennis Lamm <dennis.lamm@pm.me>
@expeditioneer
expeditioneer force-pushed the add-scap-policy-module branch from f88d6ad to 801126b Compare August 3, 2026 10:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing module for policies

1 participant