Skip to content

[pull] dev from KelvinTegelaar:dev#105

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

[pull] dev from KelvinTegelaar:dev#105
pull[bot] wants to merge 566 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 22:39
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
add scheduling capability in API
add pester test
## Summary

Today, every CIPP-generated HaloPSA ticket lands on the client's
**General User** contact (`userlookup.id = -1`), regardless of which
end-user the alert is actually about. This PR adds a single integration
toggle that, when enabled, splits per-user alerts into one ticket each
and links them to the matching HaloPSA contact - or falls back cleanly
to the General User when no match exists.

Companion PR for the CIPP frontend: KelvinTegelaar/CIPP equivalent
(linked separately).

- **New integration setting `HaloPSA.LinkTicketsToUsers`** (default off,
no behavioural change for existing installs until opted in).
- **New helper `Get-HaloUser`** that looks up a HaloPSA contact by Azure
Object ID first (via `?advanced_search=` against
`azureoid`/`aaduserid`), falling back to email/UPN against
`emailaddress`/`networklogin`/`aaduserid`. The basic `?search=`
parameter doesn't index the AD-sync fields, so we exact-match via
advanced_search where possible and silently fall back when an instance
doesn't whitelist those filter names. IDs are cast to `[int]` so
PowerShell doesn't serialise them back as `95.0`.
- **Per-user splitter in `Send-CIPPScheduledTaskAlert`** - when the
toggle is on and a scheduled-alert task returns rows containing a
UPN-like field
(`UserPrincipalName`/`userPrincipalName`/`UPN`/`userId`/`Userkey`),
groups by user and emits one PSA call per user with an `AffectedUser`
payload.
- **`AffectedUser` parameter on `Send-CIPPAlert -Type 'psa'`** that
threads through to `New-CippExtAlert` and `New-HaloPSATicket`.
- **Audit-log path** (`Invoke-CippWebhookProcessing`) now extracts the
affected user from `ObjectId`/`UserId`/`Userkey` (and their CIPP-mapped
variants) so role-change, password-reset, sessions-revoked,
MFA-disabled, inbox-rule etc. tickets land on the right contact too.
- **`New-HaloPSATicket`** populates `userlookup.id`, `user_name` and
`site_id` from the matched contact when found, and casts `client_id` to
`[int]` so storage-resident IDs (which are stored as strings) don't
break Halo's payload validation.
- **Unmatched users** keep today's General User behaviour but get an
italic notice appended to the description and a Warning logged for
follow-up.
- **Recovery from note-add failures** in the consolidation path: when
adding a note to an existing ticket fails (permission on the configured
outcome, ticket type mismatch, etc.) the function now falls through to
creating a new ticket so the alert isn't silently lost.
- **Diagnostics** in the PSA branch of `Send-CIPPAlert`: explicit "PSA
delivery skipped" message when `sendtoIntegration` is off, plus surfaces
the result string from the Halo call.
Resolves KelvinTegelaar/CIPP#6246

## Problem

Intune assignment resolves group and assignment-filter names with
PowerShell's `-like`
operator. `-like` treats `[ ]` as wildcard character-class syntax, so a
literal group
named `[WIN] Company Devices` never matches itself. Deploying an app (or
policy) to such
a group fails with `No matching groups resolved for assignment
request.`, even though the
group exists with that exact name. Bracket-prefixed naming schemes
(`[WIN]`, `[PROD]`,
`[Pilot]`, ...) are common, so this hits real tenants. Other wildcard
metacharacters in a
literal name (`?`, `*`) are affected the same way.

## Fix

Escape only the square brackets in the supplied name (`` `[ `` / `` `]
``) before the `-like`
match, so `[` and `]` are treated as literal characters instead of a
wildcard character-class.
`*` and `?` are left untouched, so the documented wildcard matching (the
assignment UI labels
say "Wildcards (*) are allowed") keeps working exactly as before. Only
the unintended
bracket-as-character-class behaviour is fixed.

The same root cause is present in every Intune assignment group-name
lookup, so all six
group-resolution sites are fixed together rather than only the one path
in the report:

| File | Group lookups fixed |
|---|---|
| `Set-CIPPAssignedApplication.ps1` | include, exclude |
| `Set-CIPPAssignedPolicy.ps1` | include, exclude |
| `Compare-CIPPIntuneAssignments.ps1` | include, exclude |

This covers app deployment (Standards "Deploy Application", the
Chrome-extension standard,
Office-app deploy, the assign-app endpoint), configuration-policy
assignment, and the
assignment drift/comparison reporting, all of which share the predicate.

Assignment-filter name matching (which also uses `-like`) is
deliberately left unchanged:
`Compare-CIPPIntuneAssignments` documents the filter name as supporting
wildcards, so
escaping it would remove a documented feature. Only group-name
resolution, which is matched
against exact names, is made literal here.

## Behaviour note

Wildcards `*` and `?` still work exactly as documented - only `[` and
`]` are escaped. So
`Sales*` keeps matching every Sales group, while a literal `[WIN]
Company Devices` now
resolves to itself instead of being read as the character-class `[WIN]`.

## Verification

Validated by inspection plus a standalone logic harness that reproduces
the resolution
predicate (old vs new) against a realistic group set including
bracketed, parenthesised and
near-collision names. The harness confirms: the bug pre-fix (bracketed
name resolves to
nothing), the fix post-fix (resolves to the correct group only), plain
names still resolve,
comma-separated multi-group input works, and no over-matching across
similar names.

## Related (separate issue)

`Get-CIPPAlertGroupMembershipChange` uses the same `-like` pattern when
matching audit-log
group names against the admin's monitored-group list. Bracketed
monitored group names would
silently never alert. It is intentionally left out of this PR and raised
separately, because
that path may be intended to support wildcard monitoring and the desired
behaviour is a
maintainer decision.
Return only 1 line instead of 5 per device. 
It's not much more readable. Each device that is added, also is written
to logdata making it a lot easier to find tenants devices were added to.
Zacgoose and others added 30 commits July 20, 2026 12:42
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
Guard the forced SSO migration prompt behind initial setup completion. The setup wizard must run first and the SAM app must be configured before ExecSSOSetup can create the CIPP-SSO registration. Backend checks ApplicationID env var; frontend passes setupCompleted prop to ForcedSsoMigrationDialog.

Synced from CyberDrain/CIPP@805cd1b
Add a new Super Admin custom domains experience for the CIPP App Service. This includes a backend endpoint to list, validate, add, secure, and remove hostname bindings, plus a frontend wizard and tab entry to guide DNS setup and managed certificate provisioning.

Synced from CyberDrain/CIPP@48b0ca6
Add '*/organization' to the list of URIs that bypass tenant authorization checks, allowing organization-level Graph API calls to proceed without tenant filtering.

Synced from CyberDrain/CIPP@a47d53f
…anagement

Updated the Invoke-CIPPSharePointTemplateDeploy function to support site type differentiation (SharePoint or Teams) and added an override option for site types. Enhanced the UI components to reflect these changes, including site type selection in the template builder.

Synced from CyberDrain/CIPP@9ff328b
… deployment

Enhanced the Invoke-CIPPSharePointTemplateDeploy function to track and log failures during permission setting for sites and libraries. Introduced a mechanism to summarize failures and update deployment status accordingly. Updated UI text for clarity in permission management options.

Synced from CyberDrain/CIPP@a683180
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