Skip to content

feat(compliance): implement CIS 1.3.9 shared bookings restriction - #333

Open
yergaliev98 wants to merge 2 commits into
mainfrom
feature/cis-1-3-9-bookings-restrictions
Open

feat(compliance): implement CIS 1.3.9 shared bookings restriction#333
yergaliev98 wants to merge 2 commits into
mainfrom
feature/cis-1-3-9-bookings-restrictions

Conversation

@yergaliev98

Copy link
Copy Markdown

Summary

Extends the existing OWA mailbox policy collector to also retrieve the tenant-level BookingsEnabled setting via Get-OrganizationConfig, rather than building a brand-new collector — this avoids a duplicate Exchange Online authentication/collection call. Adds the Rego policy for CIS 1.3.9, which evaluates compliance across both the default OWA policy path (BookingsMailboxCreationEnabled) and the org-wide configuration path (BookingsEnabled), backed by unit tests covering compliant, non-compliant, both-disabled, and missing-data scenarios. Moves control 1.3.9 from not_started to ready in metadata.json.

Type of Change

  • New feature
  • Bug fix
  • Breaking change
  • Refactor / code cleanup
  • Documentation
  • CI/CD / infrastructure
  • Security

Affected Components

  • /backend-api
  • /frontend
  • /engine (collectors / policies)
  • /security
  • /infrastructure
  • /.github/workflows
  • /docs

Motivation

Control 1.3.9 (Ensure Shared Bookings pages are restricted to select users) was not_started in the CIS Microsoft 365 Foundations Benchmark v6.0.0 mapping — no collector or policy existed. Implementing it was part of my individual contribution plan for this trimester (tracked on the team Planner board), alongside 5.1.4.4.

Testing Done

  • Unit tests pass locally — describe: opa test tests/test_1_3_9_bookings_restrictions.rego policies/ — 6/6 tests pass, covering: OWA-policy-level bookings disabled (compliant), org-level bookings disabled (compliant), both disabled (compliant), both enabled (non-compliant), missing evidence (does not falsely report compliant), and result-details structure.
  • Tested manually — describe: ran the updated collector directly against the test tenant to confirm BookingsMailboxCreationEnabled and BookingsEnabled are returned correctly; restarted the Compliance Engine and ran a full scan to confirm control 1.3.9 loads and evaluates correctly end-to-end in the AutoAudit dashboard.
  • No tests required — explain why:

Security Considerations

No new secrets or credentials introduced. Uses the existing Exchange.Manage PowerShell scope already declared in metadata.json for this collector — no new permission scope requested. Get-OrganizationConfig is a read-only call; no data is written back to the tenant.

Breaking Changes

  • No breaking changes
  • Yes — describe below:

Field additions to OwaMailboxPolicyDataCollector's output are additive only; no existing fields were renamed or removed, so nothing consuming the old collector output is affected.

Rollback Plan

  • Revert commit is sufficient
  • Requires additional steps — describe below:

No DB migrations involved; reverting the commit restores control 1.3.9 to not_started.

Checklist

  • Code follows project conventions
  • No secrets, credentials, or tokens committed
  • Relevant documentation updated (if applicable) — not applicable, no user-facing docs reference this control yet
  • CI/CD workflows pass on this branch — pending CI run on this PR
  • PR is focused on one thing

Screenshots

N/A — backend/policy-engine change only, no UI changes. See dashboard verification screenshots in my 5.1P/10.1P evidence report if a visual is wanted.

Extend the OWA mailbox policy collector to retrieve the tenant-level
BookingsEnabled setting via Get-OrganizationConfig instead of building
a new collector, avoiding a duplicate Exchange Online call. Add the
Rego policy evaluating compliance across both the default OWA policy
and org-wide configuration paths, with unit tests covering compliant,
non-compliant, both-disabled and missing-data scenarios. Moves 1.3.9
from not_started to ready.
@yergaliev98
yergaliev98 requested a review from a team as a code owner August 24, 2026 00:51
@github-actions

Copy link
Copy Markdown
Contributor

Preview Environment

A preview environment can be spun up on demand for this PR.

Action Label Includes
Spin up preview deploy-preview Frontend, backend, database, Redis, OPA, worker
Spin up preview with M365 deploy-preview-m365 Everything above + PowerShell service for Exchange/Teams scan testing
Tear down preview teardown-preview Stops the environment early

The environment will also be torn down automatically when the PR is closed or merged.
Preview URLs will appear in a follow-up comment once the deploy completes (~5–8 min).
M365 scans require real tenant credentials added through the frontend UI.

@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

CI: Engine

Job Result
Security analysis (CodeQL) success
Lint success
Tests success

All checks passed.

…ctor

Capture the raw Get-OwaMailboxPolicy result as Any before normalizing,
instead of letting mypy lock the policies variable to dict[str, Any]
from run_cmdlet's declared return type on first assignment — mypy was
then treating every 'for p in policies' as iterating dict keys (str)
rather than list items, causing 9 false type errors. Also removes a
duplicate default_policy_bookings_mailbox_creation_enabled key in the
returned dict.
yergaliev98 added a commit that referenced this pull request Aug 24, 2026
…oint support

Explicitly annotate client as PowerShellClient | SharePointClient | GraphClient
instead of letting mypy infer its type from whichever if/elif branch it
processes first. Add scoped type: ignore[arg-type] on the two collector.collect()
calls, since BaseDataCollector.collect()'s declared signature only accepts
GraphClient and hasn't been generalised for PowerShell/SharePoint collectors —
a pre-existing base-class limitation out of scope for this change.

Note: this file imports collectors.registry, which registers every collector
in the project. mypy follows that import and reports ~100 pre-existing type
errors across registry.py and ~15 other Exchange collector files that share
an identical, pre-existing None/dict/list normalisation bug (the same class
of issue fixed for one instance of it, owa_mailbox_policy.py, in PR #333).
None of those errors are introduced by this change - test_collector.py
itself now type-checks clean aside from one pre-existing issue in
get_credentials() (line 75, also predating this diff). Raising the wider
debt with the team separately rather than fixing ~16 unrelated files here.
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.

1 participant