Skip to content

TrendAI Vision One (CCF): Add multi-tenant support, fix pagination, dedupe OAT records - #15300

Open
V1ManagedServices wants to merge 10 commits into
Azure:masterfrom
V1ManagedServices:MXDR-5375-v1-sentinel-ccf-multitenant
Open

V1ManagedServices wants to merge 10 commits into
Azure:masterfrom
V1ManagedServices:MXDR-5375-v1-sentinel-ccf-multitenant

Conversation

@V1ManagedServices

@V1ManagedServices V1ManagedServices commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Add multi-tenant Vision One support to the CCF connector
  • Fix OAT/Workbench pagination to use NextPageUrl and correct ingestion timing
  • Fix out-of-range datetime values dropping OAT records
  • Deduplicate OAT records in the complete parser and rebuild the package
  • Fix CCF connector packaging for portal deployment
  • Update default values of excludeThirdPartyOat and ApiDomain fields
  • Fix OAT rt column to allow non-destructive 3.0.1 upgrade

Test plan

  • Deploy connector solution to a QA Sentinel workspace
  • Verify multi-tenant Vision One ingestion works end-to-end
  • Verify OAT and Workbench pagination correctly ingests all pages
  • Verify no duplicate OAT records after parser update
  • Verify 3.0.1 -> 3.0.2 upgrade is non-destructive

kiran-trendai and others added 8 commits October 12, 2026 10:22
The Vision One v3 API returns the continuation URL in the response body
as `nextLink`, not in an HTTP `Link` header. The connectors declared
`pagingType: LinkHeader` with `linkHeaderTokenJsonPath: $.nextLink`,
which never matched, so polling stopped after the first page.

Measured impact on OAT:
  - API reports totalCount 433, first page returns 200
  - continuation request returns an empty page
  - clients relying on nextLink retrieve at most 200 of 433 records

Switch both pollers to `NextPageUrl`, matching the legacy pre-CCF poller
which already used NextPageUrl for the same endpoints.

Co-Authored-By: Claude <noreply@anthropic.com>
The OAT transform converted three detail fields to datetime using
unguarded epoch-millisecond arithmetic:

  todatetime(datetime(1970-01-01) + tolong(d.<field>) * 1ms)

`rt` is not an epoch-millisecond timestamp. It is a Windows FILETIME
value (100ns intervals since 1601-01-01). Two real records confirm this:

  uuid 01a0c961-1c46-7580-a96a-0cfb1769e38f
    rt = 134345584181707458
    as FILETIME      -> 2026-09-22T13:46:58.170746Z
    detectedDateTime -> 2026-09-22T13:46:58Z
    firstSeen (ms)   -> 2026-09-22T13:46:58.170Z

The old expression interpreted that value as ~4.26 million years,
overflowing the datetime range (max 9999-12-31T23:59:59.999 =
253402300799999 ms). The result was a null datetime, which the
ingestion pipeline rejects, dropping the entire record.

Changes:
  - firstSeen / lastSeen keep epoch-ms conversion but are now bounded,
    so unexpected magnitudes yield null instead of dropping the record.
  - rt is stored verbatim as a string (detail_rt_g) with no conversion,
    matching the legacy Python connector which kept rt untransformed
    and matched what the Vision One UI displays.
  - OAT table column detail_rt_t (datetime) replaced by
    detail_rt_g (string).

Co-Authored-By: Claude <noreply@anthropic.com>
The connector previously supported a single Vision One tenant. The CCF
model separates the connector UI definition from individual connection
resources, so a single connector can now host multiple independent
connections.

Connector definitions (Workbench and OAT):
  - Add a DataConnectorsGrid listing deployed connections, mapping the
    Connection Alias, Vision One Business ID and API Domain columns from
    properties.addOnAttributes, with a DeleteConnector row action.
  - Move configuration inputs into a ContextPane "Add Connection" form
    with friendlyName, apiDomain, customerId, apiToken and the existing
    TMV1 filter fields. Document delete-and-re-add for token rotation,
    since existing connections cannot be edited in place.

Poller configuration:
  - Store friendlyName, apiDomain and customerId in addOnAttributes so
    each connection is identifiable in the grid.
  - Build the dataConnectors resource name from
    uniqueString(friendlyName, apiDomain) so a new connection creates a
    new resource instead of overwriting an existing one.

Ingestion:
  - Add a customerId field to both DCR input streams and map it to
    xdrCustomerID_g / xdrCustomerId_g, restoring the per-record tenant
    identifier the legacy Python connector wrote from clp_id.

Packaged solution template mainTemplate.json updated accordingly.

Co-Authored-By: Claude <noreply@anthropic.com>
- Switch paging from NextPageUrl to LinkHeader with
  linkHeaderTokenJsonPath $.nextLink: NextPageUrl re-appends query
  parameters to the nextLink, which the Vision One API rejects with
  HTTP 400, dropping the entire window's batch.
- Add queryWindowDelayInMin 10 on both pollers: OAT events are
  ingested in Vision One up to several minutes after detection time;
  querying by detection time without a delay missed late-arriving rows.
- OAT: force the v2 search flow with search_v3=false so pagination
  returns full pages (the v3 flow returns an empty second page and
  caps at top).
- OAT: top 200 (API page cap).

Verified end-to-end on a fresh Sentinel workspace with two Vision One
tenants: Workbench 8/8 per tenant, OAT 419/419 per tenant over the
same UTC window, zero missing rows.

Co-Authored-By: Claude <noreply@anthropic.com>
Regenerated the package with the official packaging tool and fixed the
issues that broke the Sentinel portal "Add Connection" flow.

Connector sources:
- Fix ARM expression escaping in both pollers: use the single trailing
  bracket form ([[parameters('x')] / [[parameters('x')[0]]) instead of
  the doubled form that produced an extra ']' and failed ARM parsing.
- Index array-typed dropdown parameters ([[parameters('apiDomain')[0]]).
- OAT: wire excludeThirdPartyOat through addOnAttributes so the DCR
  transform can read it; replace the ARM expression previously embedded
  in transformKql, which could never resolve because the DCR's
  contentTemplate declares no parameters.
- Restore the excludeThirdPartyOat dropdown with its original
  defaultValue of ["true"].

Packaging:
- Add package.sh to build the deployable zip locally.
- Rebuild mainTemplate.json via package-generator.ps1 (single source of
  truth; both DCR copies now derive from the same files, so they cannot
  drift).
- Keep 3.0.1.zip and add 3.0.2.zip.

Co-Authored-By: Claude <noreply@anthropic.com>
Add arg_max dedupe by detail_uuid_g to TrendAIOAT_Complete so repeated CCF poller ingests of the same detection collapse to one row. Regenerate the packaged mainTemplate and 3.0.2.zip to match.

Co-Authored-By: Claude <noreply@anthropic.com>
The OAT table column detail_rt_t (datetime) was renamed to detail_rt_g (string)
in 8a17862. Azure tables are immutable, so upgrades from 3.0.1 failed with
'Invalid output table schema' when adding a connection, because the live table
still held the old column.

Restore detail_rt_t (datetime) so the 3.0.1 schema remains a strict subset, and
add detail_rt_s (string) carrying the raw FILETIME value that the DCR writes.
Existing workspaces gain the new column on upgrade; fresh installs declare both.
Regenerate the packaged mainTemplate and 3.0.2.zip.

Co-Authored-By: Claude <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

OAT deduplication is not tenant-scoped, and parser and release metadata are incomplete.

2 open findings
What changed in this PR

Adds multi-tenant TrendAI Vision One ingestion, improves OAT handling, and advances the solution to 3.0.2.

Changes:

  • Adds tenant-aware connector configuration and metadata.
  • Improves OAT timestamp handling and deduplication.
  • Rebuilds deployment artifacts for version 3.0.2.
File Description
Parsers/​TrendAIOAT_Complete.yaml Adds OAT deduplication.
Package/​testParameters.json Reorders workbook parameters; excluded from review.
Package/​package.sh Adds packaging helper; excluded from review.
Data/​system_generated_metadata.json Adds generated 3.0.2 metadata.
Data/​Solution_TrendAIVisionOne.json Bumps solution to 3.0.2.
...Workbench_PollerConfig.json Adds multi-tenant polling; excluded from review.
...Workbench_DCR.json Adds customer attribution; excluded from review.
...Workbench_ConnectorDefinition.json Adds multi-connection UI; excluded from review.
...OAT_table.json Adds string-form OAT timestamp; excluded from review.
...OAT_PollerConfig.json Updates OAT polling; excluded from review.
...OAT_DCR.json Updates OAT transformations; excluded from review.
...OAT_ConnectorDefinition.json Adds multi-connection UI; excluded from review.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Solutions/TrendAI Vision One(CCF)/Parsers/TrendAIOAT_Complete.yaml Outdated
@v-maheshbh

v-maheshbh (v-maheshbh) commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Hi V1ManagedServices

Kindly check the Copilot comments. If the feedback has been addressed, please mark the corresponding comments as resolved.

and attach a screenshot showing the CCF connector in a connected state for validation and review purposes.
Please update the release notes with the latest changes introduced as part of this PR.

Thanks!

    detail_uuid_g alone collapsed identical UUIDs across different Vision
    One tenants now that multiple tenants write into the same table.
    Group by xdrCustomerId_g, detail_uuid_g instead, synced into both
    mainTemplate.json copies. Also add the missing 3.0.2 ReleaseNotes.md
    entry per releasenotes.instructions.md.
@V1ManagedServices

Copy link
Copy Markdown
Contributor Author

Hi V1ManagedServices

Kindly check the Copilot comments. If the feedback has been addressed, please mark the corresponding comments as resolved.

and attach a screenshot showing the CCF connector in a connected state for validation and review purposes. Please update the release notes with the latest changes introduced as part of this PR.

Thanks!

Screenshot 2026-10-14 at 1 20 35 PM Screenshot 2026-10-14 at 1 20 16 PM

Hello v-maheshbh (@v-maheshbh) ,

The requested screenshots have been attached, and all Copilot-related issues have also been addressed. Kindly review and proceed with the necessary actions.

Thank you.

@v-maheshbh

Copy link
Copy Markdown
Contributor

Hi V1ManagedServices

image

Kindly remove the package.sh file from the Package folder as it is not required.

Thanks!

@v-maheshbh

Copy link
Copy Markdown
Contributor

Hi V1ManagedServices

Please check the above comments. Thanks!

@github-actions github-actions Bot added the ISV Solution 3P / ISV Partner-authored or Partner-integrated Sentinel solution label Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Codeless Connector Framework (CCF) Connector ISV Solution 3P / ISV Partner-authored or Partner-integrated Sentinel solution Solution Solution specialty review needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants