Skip to content

[pull] dev from KelvinTegelaar:dev#105

Open
pull[bot] wants to merge 559 commits into
isgq-github01:devfrom
KelvinTegelaar:dev
Open

[pull] dev from KelvinTegelaar:dev#105
pull[bot] wants to merge 559 commits into
isgq-github01:devfrom
KelvinTegelaar:dev

Conversation

@pull

@pull pull Bot commented Jun 16, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

@pull pull Bot locked and limited conversation to collaborators Jun 16, 2026
@pull pull Bot added the ⤵️ pull label Jun 16, 2026
KelvinTegelaar and others added 28 commits June 30, 2026 20:59
…2112)

## What

Adds a deterministic post-processing stage that enriches the generated
`openapi.json` with typed `200` response schemas and a unique
`operationId` per operation, and publishes the result as a Release
asset. It does **not** replace the existing generator; it runs on its
output.

## Why

The generated spec types request bodies but leaves every `200` response
as the generic `StandardResults` envelope, and carries no `operationId`
on any operation. Two practical consequences:

- OpenAPI importers that key on `operationId` skip every operation.
Tested against a real importer: the unmodified spec imported as **0**
actions; with `operationId` injected it imports as **all 582**.
- Downstream tools get no typed output fields to map against.

## How

A PowerShell stage (`.build/Add-OpenApiResponseSchemas.ps1`) with two
passes, both pure functions of checked-in sources (no live API calls,
byte-identical output across runs):

- **operationId**: bare endpoint name per operation; method-prefixed
only where one path carries multiple methods (e.g. `GetExecCSPLicense` /
`PostExecCSPLicense`). Existing `operationId`s are preserved; any
collision is a hard failure.
- **typed 200 responses**: derived from the frontend shape baselines
(`Tests/Shapes/*.json`) and page `simpleColumns` declarations. The `{
Results, Metadata }` envelope is preserved exactly as the API returns it
(no flattening, so the schema stays truthful to the wire).

Endpoints with no typed source keep `StandardResults`, which is correct
for write/exec operations.

## Publishing + CI

- `openapi-enriched-release.yml` builds and uploads
`openapi.enriched.json` as an asset on each GitHub Release (no commits
back to the tree).
- `openapi-enriched-check.yml` runs the test suite and **strictly lints
the enriched spec** against a committed ignore-baseline
(`.redocly.lint-ignore.yaml`) that pins pre-existing findings, so any
*new* finding fails CI.
- `.github/workflows/` is gitignored in this repo (the existing
workflows are force-added), so these two were added with `git add -f`,
matching the repo convention.

## Tests

50 Pester tests + PSScriptAnalyzer (0 findings), run via
`Tests/Build/Invoke-BuildTests.ps1`. Covers operationId rules
(bare/disambiguated/preserve/collision-throws), response typing,
idempotency, and the frontend-scan edge cases.

## Known limitations (documented in `.build/README.md`)

- Only `get/post/put/patch/delete` are processed (the spec has no other
methods today).
- Paths are assumed to start with `/api/` (all current paths do).
- A typed `200` replaces the existing `200.content` (today only
`StandardResults` exists there).
- Conditional/ternary `simpleColumns` expressions are intentionally not
parsed (a conservative miss is preferred over capturing non-column
strings).

## Side benefit

Injecting `operationId` also removes the `operation-operationId` lint
warning that previously applied to every operation in the spec.


## CI activation note

Both workflows are guarded with `if: github.repository_owner ==
'KelvinTegelaar'`, matching the convention of the existing workflows in
this repo (forks do not run them). As a result they will **not** appear
as status checks on this PR from the fork; they activate once merged
into the upstream tree. Verification was therefore done locally before
opening this PR:

- `Tests/Build/Invoke-BuildTests.ps1`: 50 Pester tests passing,
PSScriptAnalyzer 0 findings
- strict Redocly lint of the generated `openapi.enriched.json`: 0
errors, 0 warnings, 5 pre-existing findings ignored via the committed
baseline; verified to fail on an injected new finding
- both workflow YAML files parse clean
- enrichment is deterministic: same inputs produce byte-identical output
across runs
This pull request enhances the `Push-BECRun` PowerShell function by
adding the retrieval and logging of sent message traces for a user, and
includes this data in the output object. These changes improve the
auditing and incident response capabilities of the function by providing
more comprehensive information about user activity.

**Enhancements to auditing and user activity tracking:**

* Added retrieval of sent message traces using the `Get-MessageTraceV2`
cmdlet, with error handling and logging in case of failures. The trace
includes message details such as status, subject, recipient, received
time, and sender IP.
* Included the collected sent message trace data as a new property
(`SentMessages`) in the output object returned by the function.
Introduce support for ExcludeGroupIds and ExcludeGroupNames in
assignment functions.

Frontend PR: KelvinTegelaar/CIPP#6244
Overhaul of the rather interesting way to construct a JSON payload and
add in severity and resolving comment functionality.

Frontend PR: KelvinTegelaar/CIPP#6234
Updated to write to and read from cetralised CIPP database
Frontend PR: KelvinTegelaar/CIPP#6238

The `SetAuthMethod` endpoint only toggled state and group targeting, so
every method-specific option was unreachable from the portal. This
forwards those settings through `Invoke-SetAuthMethod` and applies them
in `Set-CIPPAuthenticationPolicy`.

**Added/exposed settings**
- TAP: `isUsableOnce`, min/max/default lifetime, default length
- Microsoft Authenticator: software OATH + display-app-info /
display-location / companion-app feature states
- Email OTP: external-ID state, exclude groups (empty list now
explicitly clears `excludeTargets`)
- QR Code PIN: lifetime + PIN length
- FIDO2: `isAttestationEnforced` + `isSelfServiceRegistrationAllowed`
(were hardcoded on enable)
- Voice: `isOfficePhoneAllowed`
- SMS: `isUsableForSignIn` (stamped onto each include-target)

Log messages now spell out the changed values per method.

**Tests:** adds `Tests/Private/Set-CIPPAuthenticationPolicy.Tests.ps1`
(7 cases) — `Invoke-Pester -Path
./Tests/Private/Set-CIPPAuthenticationPolicy.Tests.ps1`.
Add the SMTP client authentication state to the mailbox details
response, enhancing the information available for mailbox configuration.

Frontend: KelvinTegelaar/CIPP#6180
Introduce functionality to allow specific user profile fields to be
cleared when editing a user. Currently the property is just quietly
dropped with a success message.

Frontend PR: KelvinTegelaar/CIPP#6261
Group display names are matched with -like, which treats square brackets as
a wildcard character class, so a literal group such as [WIN] Company Devices
never matched itself and assignment failed with No matching groups resolved.
Escape only [ and ] before the match so bracketed names resolve literally,
while * and ? wildcards (documented in the assignment UI, 'Wildcards (*) are
allowed') keep working. Applied to the six group-resolution sites in
Set-CIPPAssignedApplication, Set-CIPPAssignedPolicy and
Compare-CIPPIntuneAssignments (include and exclude). Filter-name matching is
unchanged.

Resolves KelvinTegelaar/CIPP#6246
KelvinTegelaar and others added 30 commits July 19, 2026 18:11
Detect AADSTS7000229 token-acquisition failures in audit search creation and classify them as `AccessDenied` instead of generic transient errors. Update the webhook flow to handle `AccessDenied` like `AuditingDisabled`: cache the tenant in `AuditLogDisabledTenants` for 24 hours, stop further processing in the cycle, and defer remaining windows with a consistent bail reason.
…llowlists

The allowlist of special includeUsers/excludeUsers values spelled the
Graph value as 'GuestOrExternalUsers' (singular), but Microsoft's real
value is 'GuestsOrExternalUsers' (plural). In New-CIPPCAPolicy the
misspelled value fell through to the display-name lookup, found no
matching user, and was silently dropped - producing an empty
includeUsers array that Graph rejects on deploy. Also corrects the same
spelling in the New-CIPPCATemplate ID-to-name maps (benign fallthrough
there, fixed for consistency), and logs a warning naming any user value
that fails to resolve instead of dropping it silently.
… them

Eleven standards wrapped their remediation calls in try/catch with an
empty catch block, so any failure from Set-CIPPAuthenticationPolicy
(which throws on error) was silently discarded and the standard
appeared to succeed.
…/assignments

App Protection / managed-app policies reported NON-COMPLIANT on every drift
run regardless of settings: templates are stored with apps[], deployment
strips apps (Set-CIPPIntunePolicy), and the policy read-back never returns
apps, assignments, or a matching deployedAppCount (Get-CIPPIntunePolicy has
no $expand), so the generic deep-compare always flagged them.

- Exclude 'assignments' globally: read-back never includes assignments for
  any policy type, and assignment verification has its own dedicated path
  (Compare-CIPPIntuneAssignments via verifyAssignments).
- Exclude 'apps' and 'deployedAppCount' only for CompareType 'AppProtection'
  (what the Standards/drift engine passes), because Device configs carry
  legitimate nested 'apps' arrays (e.g. kiosk profiles) that must keep
  being compared.
- '@odata.context' already skipped by the existing *@OData* wildcard.
Templates synced from a gold tenant fetch App Protection policies via
their concrete type URL (e.g. androidManagedAppProtections('id')), and
Graph omits @odata.type from those responses. The stored RAWJson then
lacks @odata.type, so Set-CIPPIntunePolicy built the deploy URL as
deviceAppManagement/s and Graph returned "Resource not found for the
segment 's'.". Re-add @odata.type from the known ODataType when Graph
omits it, and fail with a clear error on deploy when a stored template
still has no @odata.type.
Two defects allowed Invoke-SherwebMigration scheduled tasks to keep
firing daily (sending alerts and performing real Sherweb purchases and
Pax8 subscription cancellations) after the Sherweb migration was
disabled:

- Invoke-SherwebMigration had no enabled-guard: it read the Sherweb
  extension config but never checked Enabled before acting. It now
  returns immediately unless the Sherweb config exists and Enabled is
  true, which neutralizes any stale scheduled task.

- Register-CIPPExtensionScheduledTasks created migration tasks in the
  enable branch, but the disable cleanup only filtered
  Push-CippExtensionData tasks, so migration tasks were never removed.
  Migration tasks are now queried at function scope, removed when the
  Sherweb extension is disabled, and removed when a tenant is no longer
  Sherweb-mapped.
…ve licensed users alert

The alert already fetched assignedLicenses and accountEnabled from Graph
but dropped them from the emitted alert data. Surface license display
names, raw SKU IDs, account enablement and days since last sign-in so
the alert can be actioned without a follow-up lookup.
…isfy its own check

The remediation enabled the MicrosoftAuthenticator method but never passed
the feature settings the compliance check grades against, so the standard
could never converge: displayAppInformationRequiredState was checked but
not set, and numberMatchingRequiredState was checked even though
Set-CIPPAuthenticationPolicy deliberately strips it from the PATCH body
(Microsoft now enforces number matching and the setting can no longer be
toggled). The empty catch around the remediation call also swallowed every
error, leaving no signal in the logs.

- Pass -MicrosoftAuthenticatorDisplayAppInfo 'enabled' in the remediation
  so the PATCH sets what the check grades
- Drop numberMatchingRequiredState from the check and the report
  comparison, matching Microsoft's enforced-by-default behavior
- Replace the empty catch with Get-CippException + Write-LogMessage error
  logging, matching the idiom in Invoke-CIPPStandardAuthenticationMethods
Update New-CIPPCATemplate to use the correct special value `GuestsOrExternalUsers` when processing include/exclude users and groups. This fixes a typo that could cause the selector to be treated like a normal ID instead of being preserved.
Update request parsing to support both PSCustomObject and IDictionary shapes from Azure Functions deserialization. `Get-CippMcpToolResult` now correctly flattens MCP arguments and clones headers when they are dictionaries, preventing lost params/headers (including EasyAuth context). `Invoke-ListMailboxes` now reads query parameter names from dictionary keys, so allowed mailbox filters are applied reliably.
… sending null

Untoggled "switch" inputs are omitted from a standard's settings, so
TeamsGlobalMeetingPolicy, TeamsExternalFileSharing, and
TeamsFederationConfiguration serialized null booleans to the Teams
ConfigApi, which rejects the write with 400 "Error converting value
{null} to type 'System.Boolean'". The null also poisoned the
$StateIsCorrect comparison ($CurrentState.X -eq $null is never true),
so affected tenants reported non-compliant and failed remediation on
every run.

Coalesce each switch to $false (the CIS recommended value, matching the
convention in TeamsExternalAccessPolicy/TeamsGuestAccess/
TeamsEmailIntegration) and use the coalesced variable in the state
comparison, remediation payload, and report expected values. In
TeamsExternalFileSharing the existing "?? $false" was dead code because
-eq binds tighter than ??.
Replace the null-check wrapper with a direct null filter when building `ComparisonResults`. This ensures the endpoint always returns an array containing only valid comparison entries, avoiding accidental null items in the response.
Add `Sync-CippContainerUpdateState` and use it in both timer and container management endpoints so stale "update available" results are corrected after a restart. The update-check flow now also captures and preserves `RemoteBuildDate` and `CheckedTag`, and the settings/status response includes build-date metadata for both running and remote images.
Ensure container image build timestamps are converted from PowerShell DateTime values into UTC ISO 8601 strings before they are returned or stored. This avoids ambiguous unspecified kinds and keeps timer-driven update checks and container management responses consistent.
Resolve container update settings through the shared sync path so never-saved fields default to auto-restart on, hourly checks, and 23:00 while still respecting explicit disabled or empty values. Also tighten status reconciliation after restarts and fix check-time validation/formatting so early UTC hours are accepted correctly.
Refactors the SSO migration checks in `Test-CIPPAccess` to use explicit permission flags. This keeps the forced migration prompt limited to users who can manage app settings and skips migration lookups for users with no assigned permissions.
Add a shared Autopilot profile name validator and use it in both the HTTP endpoint and default deployment profile flow. This catches unsupported Intune characters before submission so the API returns a clear bad request or logged error instead of an opaque service-side 500.
Add `Resolve-CIPPDlpAdvancedRule` and apply it across template capture, policy deploy, and drift comparison so DLP rules keep either `AdvancedRule` or flat condition fields, never both. Update DLP rule field metadata to expose `RuleConditions` and include `AdvancedRule`, then normalize advanced-rule JSON during comparison to avoid false drift from formatting or key-order differences.
Suppress the SSO migration prompt until the SAM app is configured, matching the same setup-completion check used by GetCippAlerts.
chore: Update repository links to new owner

Synced from CyberDrain/CIPP@15b92c3
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants