Semperis Lightning 4.1.0: merge CCF into existing offer (Function App + CCF) - #2
Semperis Lightning 4.1.0: merge CCF into existing offer (Function App + CCF)#2MitchellGulledge3 wants to merge 8 commits into
Conversation
Reference implementation for the Semperis CCF migration. Opened for discussion only. Auth shape is unresolved pending Semperis confirmation. Multi-account follows the shipped Auth0 / Citrix DaaS pattern: addOnAttributes are merged into each polled event, declared in the DCR input stream, and projected by transformKql so every row carries its source tenant. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0efd0d8a-38ae-499b-bef8-a0062c4819f3
Defect B (blocked all deployments, including greenfield): 'bool' is not a valid column type for DCR streamDeclarations or for workspaces/tables. Portal rejected the DCR with InvalidStreamDeclaration. Now 'boolean' in every artifact, including the deployed mainTemplate. Defect A (blocked workspaces with a prior 3.1.0 deploy): Log Analytics custom tables allow additive schema changes only. Dropping ConnectorName failed against existing tables. ConnectorName is restored in all 7 tables and populated via ConnectorName=tostring(SemperisInstanceName). Root enabler: mainTemplate.json was hand-maintained, so it drifted from the reviewed artifacts and was never covered by tests. It is now generated, and tests scan it directly. Suite: 14/14. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0efd0d8a-38ae-499b-bef8-a0062c4819f3
Two deployment blockers found in live testing, now fixed (
|
| Resource | Allowed |
|---|---|
workspaces/tables |
string, int, long, real, boolean, datetime, dynamic, guid |
DCR streamDeclarations |
string, int, long, real, boolean, datetime, dynamic (no guid) |
bool is in neither.
Defect A — blocked workspaces with a prior 3.1.0 deploy
Log Analytics custom tables are additive only. You can add columns, never drop or retype them. Dropping ConnectorName failed against existing tables:
Invalid output table schema: The following columns which exist in the current
schema do not exist in the new schema or have different types
ConnectorName is restored in all 7 tables and populated via ConnectorName=tostring(SemperisInstanceName), so existing customer queries keep working.
Only conditional on a prior CCF deploy. The legacy Function App schema is fully additively compatible — 0 conflicts.
Root enabler
mainTemplate.json was hand-maintained. It is the artifact that actually deploys, but tests only validated the standalone files. So it drifted and shipped invalid while the suite passed.
It is now generated from the same constants, and tests scan it directly. Type validation also runs at generation time, so an invalid type fails the build rather than the deployment.
Suite: 8/14 → 14/14. Every new guard was mutation-tested.
Still open
Not yet validated against a live workspace. Both fixes are verified against the ARM/DCR schema contracts and the portal's own error text. The next redeploy is the real test.
Auth remains the blocking question for Semperis — unchanged.
…orName DO NOT MERGE. Reference only. Every custom table now ends in V2_CL (LightningTier0NodesV2_CL and the six others), matching the shipped SailPoint convention (SailPointIDN_EventsV2_CL). The legacy Solutions/SemperisLightning Function App solution keeps writing the v1 tables, so the two solutions now share no schema and can run side by side in one workspace with no interaction. Renamed everywhere: table resources and filenames, DCR streamDeclarations keys, dataFlows streams and outputStream, poller streamName and dataType, the connector definition graph/sample/dataType queries, and mainTemplate.json. ConnectorName is dropped as redundant with SemperisInstanceName. It existed only to satisfy the Log Analytics additive-only constraint against tables a prior 3.1.0 deploy created; the V2 tables are new, so no such constraint applies. Version 4.0.0 — renaming every table is a breaking change. ARM contentVersion stays 1.0.0.0, matching every shipped solution, because ARM validates it against a four-part pattern. MULTI-ACCOUNT.md is restored (it was dropped by the previous commit) and updated with the V2 mapping. Auth is still unresolved and unchanged: the Semperis token endpoint takes a single apiKey field while CCF JwtToken models a userName/password pair, so the config still pads with an invented ccfCompatibility field. This needs live verification against real Semperis credentials. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0efd0d8a-38ae-499b-bef8-a0062c4819f3
4.0.0 — all seven tables renamed to
|
| Legacy (unchanged, still written by the Function App) | This solution now writes |
|---|---|
LightningTier0Nodes_CL |
LightningTier0NodesV2_CL |
LightningAttackPaths_CL |
LightningAttackPathsV2_CL |
LightningAttackPathLinks_CL |
LightningAttackPathLinksV2_CL |
LightningTier0Attackers_CL |
LightningTier0AttackersV2_CL |
LightningIndicatorExecutions_CL |
LightningIndicatorExecutionsV2_CL |
LightningIOEsMetadata_CL |
LightningIOEsMetadataV2_CL |
LightningIOEResults_CL |
LightningIOEResultsV2_CL |
Form matches the shipped SailPoint convention (SailPointIDN_EventsV2_CL).
Why
Zero overlap with the legacy Solutions/SemperisLightning Function App solution, which keeps writing the v1 tables. The two connectors now share no schema, so they can run side by side in one workspace with no interaction — no additive-only conflicts, no column fights, no ambiguity about which connector produced a row.
Scope of the rename
Table resources and filenames, DCR streamDeclarations keys, dataFlows[].streams[] and outputStream, poller dcrConfig.streamName and dataType, the connector definition graphQueries / sampleQueries / dataTypes / lastDataReceivedQuery, mainTemplate.json, and the package zip. A test fails the build if any v1 name survives anywhere, including inside the zip.
ConnectorName dropped
It only existed to satisfy the Log Analytics additive-only rule against tables a prior 3.1.0 deploy had created, and it duplicated SemperisInstanceName. V2 tables are brand new, so there is no constraint and no legacy consumer. Use SemperisInstanceName. The schema baseline was re-based to the V2 schemas rather than deleted, so once 4.0.0 ships a later column drop or retype is still caught.
Version
4.0.0, not 3.2.0 — renaming every table breaks every existing query, workbook and rule. ARM contentVersion deliberately stays 1.0.0.0: ARM validates it against a four-part pattern and rejects a three-part semver.
Validation
pwsh .script/local-validation/build-and-validate.ps1 -SolutionName SemperisLightningCCF -SkipPackaging → BUILD SUCCESSFUL, 11 passed / 0 failed / 6 skipped, ARM-TTK 48/48. Candidate suite 17/17. Skipped validators need .NET 3.1/8.0 and trufflehog, which are not installed locally.
⚠️ Still unresolved — auth
Unchanged and unverified. The Semperis token endpoint takes a single apiKey field. CCF JwtToken models a userName/password pair. The config still pads with an invented ccfCompatibility field. If Semperis rejects unknown JSON fields, token acquisition fails and no stream ingests. This needs live verification against real credentials — it is the first thing to check on deploy.
Still DO NOT MERGE — reference only.
…p rule Three verified findings, none of which change the shipped config: - Documented JwtToken limitations say it requires username/password token acquisition and does not support API-key token requests, so the invented ccfCompatibility field has no documented basis. APIKey with IsApiKeyInPostPayload and OAuth2 client credentials are the documented alternatives. Recorded as options to raise with Semperis, not applied. - Poller resource names are unchanged from 3.1.1, so upgrading updates the six pollers in place and repoints them at the V2 tables. The v1 tables are left behind with their data. - A DCR transform projecting a column the destination table does not declare is silently discarded, billed but not stored. This is why the transform/table coherence test exists. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0efd0d8a-38ae-499b-bef8-a0062c4819f3
Addendum — three verified findings (
|
Ports the two live-deployment fixes validated against a real Sentinel workspace:
4.0.1 - quoted deferred workspace reference. Inside a [[ expression the portal
textually substitutes parameters('workspace'), so it must be quoted as shipped
connectors do; the unquoted form produced concat(westus2, ...) and failed with
'expected token LeftParenthesis'.
4.0.2 - zone is a single-select Dropdown (scalar) but was declared type: array
and indexed parameters('zone')[0], producing the portal error 'Cannot read
properties of undefined (reading map)'. zone is now securestring everywhere.
Both fixes also close repeated drift where Package/mainTemplate.json was
hand-maintained; the generator now owns poller name, addOnAttributes, auth,
request, response and connection parameter types.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0efd0d8a-38ae-499b-bef8-a0062c4819f3
Ship Function App and CCF connectors in one solution (Netskope/SailPoint pattern), reuse offer azure-sentinel-solution-semperislightning, and keep the zone dropdown as an array read via [0]. Package 4.1.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c9e9ef59-ac68-42ed-9911-c166bcaddd0f
Portal was still serving the 4.0.2 CCF content item after the offer merge. Align dataConnectorCCPVersion with the solution version so Connect uses the array-typed zone parameter. Verified Connect in workspace centralus. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c9e9ef59-ac68-42ed-9911-c166bcaddd0f
|
Pushed
Reference tree: https://github.com/MitchellGulledge3/Azure-Sentinel/tree/semperis-lightning-ccf-multi-account-reference/Solutions/SemperisLightningCCF |
Make MULTI-ACCOUNT.md shippable (drop Do not merge), match workspace filters to /resourceGroups/<name>/, fix set up wording, and keep ReleaseNotes aligned with the 4.1.0 Function App + CCF merge. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c9e9ef59-ac68-42ed-9911-c166bcaddd0f
|
Addressed Copilot nits from Azure#14949 in |
Tested 4.1.0 package for Semperis Lightning.
What this is
Update to the existing Content Hub offer
azure-sentinel-solution-semperislightning(Netskope/SailPoint pattern):*_CL*V2_CLPortal Connect succeeded in workspace
centralusafter treating the zone dropdown as an array (parameters('zone')[0]) and bumping the CCF content version to 4.1.0.Copilot review on Azure#14949
Addressed here:
MULTI-ACCOUNT.mdis shippable (no “Do not merge”)ReleaseNotes.mdtable alignmentcreateUiDefinition.jsonworkspace filter uses/resourceGroups/<name>/testParameters.json“set up”Reference tree:
Solutions/SemperisLightningCCFPartner PR to apply these onto: Azure#14949