From sentinel
Use before writing any Microsoft Sentinel connector ARM template, DCR, KQL transform, or createUiDefinition.json. Provides the complete CCF (Codeless Connector Framework) reference for RestApiPoller, Push, and GCP connector types — including escaping rules, authentication, pagination, UI definitions, and deployment gotchas. Also use when debugging connector deployment failures or reviewing existing CCP templates.
How this skill is triggered — by the user, by Claude, or both
Slash command
/sentinel:codeless-connectorsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
1. ARM template contains all 5 required resources with correct dependency chain (contentPackages first, all others dependsOn it).
references/arm-template-structure.mdreferences/asim-schemas.mdreferences/authentication-types.mdreferences/ccf-packaging-details.mdreferences/connector-builder.mdreferences/create-ui-definition.mdreferences/kql-transforms.mdreferences/packaging.mdreferences/pagination-types.mdreferences/production-examples.mdreferences/push-connectors.mdreferences/request-response-config.mdreferences/troubleshooting.mdreferences/ui-definitions.mdscripts/CLAUDE.mdscripts/README.mdscripts/test-ccp-mapping.ps1scripts/validate_connector.py[ in parent and DataConnector (deploy-time) templates, double [[ in ResourcesDataConnector (connect-time) templates. /metadata resources always use [[.'rdc' prefix.You are an expert on building data connectors for Microsoft Sentinel using the Codeless Connector Framework (CCF). This was formerly called the Codeless Connector Platform (CCP). Use only the current framework - never reference the legacy/v1 CCP.
Detailed references are in sibling files - read them as needed:
references/arm-template-structure.md -- ARM template resources, escaping, variablesreferences/authentication-types.md -- Basic, APIKey, OAuth2, JWT configurationsreferences/pagination-types.md -- All paging types and propertiesreferences/kql-transforms.md -- Complete supported/blocked KQL function listreferences/push-connectors.md -- CCF Push connector specifics (preview)references/ui-definitions.md -- Data connector UI instruction typesreferences/request-response-config.md -- Request, response, and DCR config propertiesreferences/troubleshooting.md -- Deployment errors, health monitoring, debuggingreferences/connector-builder.md -- Step-by-step builder workflow for creating connectors from scratch (all 4 destination types)references/asim-schemas.md -- ASIM normalization schema reference for all 10 supported event typesreferences/create-ui-definition.md -- createUiDefinition.json builder guide for Azure Portal deployment UIreferences/production-examples.md -- Annotated excerpts from production connectors (Cisco Meraki, 1Password, Auth0, Azure DevOps, Box, Jira, Proofpoint TAP, BigID)scripts/validate_connector.py -- Automated validation script for ARM templates (run after every template generation)scripts/test-ccp-mapping.ps1 -- Tests Definition->Poller->DCR->Table mapping via get-ccp-details.ps1 (run against extracted separate files)references/packaging.md -- Solution packaging with createSolutionV3.ps1, building block file structure, naming conventionsreferences/ccf-packaging-details.md -- CCF packaging: folder naming, file suffixes, cross-file mapping, multi-poller patterns, connector kind specificsscripts/README.md -- Packaging scripts guide: prerequisites, running createSolutionV3.ps1, data input format, script architectureThe CCF has more connector kinds than commonly documented. The three most frequently built are RestApiPoller, Push, and GCP, but the repo contains several additional specialised kinds:
| Kind | Model | Status | Example |
|---|---|---|---|
RestApiPoller | Sentinel polls a REST API on a schedule | GA | Most modern connectors |
Push | App pushes data via Logs Ingestion API | Public Preview (Feb 2026) | -- |
GCP | Pre-configured for Google Cloud Platform | GA | Google Cloud solutions |
AmazonWebServicesS3 | Reads from an AWS S3 bucket | GA | AWS WAF, AWS Network Firewall |
WebSocket | Connects to a WebSocket stream | GA | Proofpoint POD Email Security |
OCI | Oracle Cloud Infrastructure log stream | GA | Oracle Cloud Infrastructure |
PurviewAudit | Microsoft Purview audit log stream | GA | Microsoft Copilot, Business Applications |
StorageAccountBlobContainer | Event-driven ingest from Azure Blob Storage via Event Grid + Storage Queue | Public Preview (Feb 2026) | DataConnectors/Templates/Connector_StorageBlob_CCF_template.json |
Note: When writing about CCF connector kinds, do not claim RestApiPoller/Push/GCP are the only three -- the list above was verified against the Azure/Azure-Sentinel repo (Feb 2026). Always use "a new connector kind" not "the Nth connector kind" unless you have verified the current count.
Older connectors in DataConnectors/ use kind: "APIPolling" -- the v1 format. Key differences from v2 (RestApiPoller):
Microsoft.OperationalInsights/workspaces/providers/dataConnectors (not Microsoft.SecurityInsights/dataConnectors)auth.authType (not auth.type)pollingConfig + connectorUiConfig inline in one resource (no separate definition/poller files)"type": "SentinelKindsV2" (not "HasDataConnectors")Always use RestApiPoller (v2) for new connectors. The v1 format is documented here only for reference when reading legacy connectors (e.g., Proofpoint TAP, the original Atlassian Jira in DataConnectors/).
queryWindowInMin)transformKql transforms the datakind: "Customizable")Every resource must dependsOn the contentPackage. See references/arm-template-structure.md.
There are TWO types of nested templates (contentTemplates), and each has different escaping:
| Where the expression is | contentKind | Bracket syntax |
|---|---|---|
| Parent template (deploy-time) | n/a | "[parameters('x')]" |
| Deploy-time nested template (DCR, table, metadata) | DataConnector | "[parameters('x')]" |
| Connect-time nested template (poller, connections) | ResourcesDataConnector | "[[parameters('x')]" |
| CCP UI-collected parameter in connector props | (inside ResourcesDataConnector) | "[[parameters('x')]" |
Exception: /metadata resources inside ANY nested template use [[ for deferred content-hub evaluation, regardless of the template's contentKind.
[[ tells ARM: "don't evaluate now -- store as literal for later." The closing bracket is NOT doubled. In connect-time (ResourcesDataConnector) templates, this applies to ALL ARM functions: concat(), resourceId(), subscription(), resourceGroup(), etc.
Common mistake: Using [[ in a DataConnector template causes ARM to store the literal string (e.g. "[parameters('location')]") instead of evaluating it, leading to errors like InvalidResourceLocation.
Variables defined in the parent template are NOT accessible inside nested mainTemplate blocks. Define shared config within the nested template's own variables section or pass as parameters.
_solutionVersion must be "3.0.0" or above for CCF templates.
_CL suffixstreamDeclarations must start with Custom- prefix (even for ASIM destinations)outputStream prefix depends on destination: Custom- for custom tables, Microsoft- for ASIM standard tables (e.g., Microsoft-ASimNetworkSessionLogs)Describe the raw incoming data shape -- NOT the transformed output. If the API returns ts, eventType, srcIp, declare those names/types. Fields created by transformKql (like TimeGenerated) do NOT go in stream declarations.
Each dataFlow specifies: input streams, destinations, transformKql, and outputStream. Multiple dataFlows enable routing different event types to different tables from a single stream.
"source" for pass-through (no transformation)TimeGenerated column (datetime)\" inside the transformKql stringreferences/kql-transforms.md for the complete supported function listSupported: where, extend, project, project-away, project-rename, parse (max 10 cols), let, datatable, print, columnifexists -- Note: let and datatable were added in newer DCR API versions (2023+). Older references may list them as unsupported.
NOT supported: summarize, join, union, mv-expand, mv-apply, top, sort, distinct, project-reorder, parse_csv, invoke, scan, partition
Blocked functions: coalesce (use iif(isnotnull(a),a,b)), replace_string, replace_regex, bag_keys, bag_values, bag_set, bag_remove_keys, dynamic() literals (use parse_json())
Supported: has, has_cs, !has, contains, startswith, endswith, matches regex, in, !in
Special functions: geo_location (adds latency), parse_cef_dictionary
| Type | Use When |
|---|---|
Basic | Username + password |
APIKey | API key in header or POST body |
OAuth2 | authorization_code or client_credentials grant |
JwtToken | JWT token via username/password endpoint |
OAuth2 does NOT support client certificate credentials. See references/authentication-types.md.
| Type | Use When |
|---|---|
LinkHeader | Next/prev page URLs in headers or body |
PersistentLinkHeader | Same as LinkHeader but persists cursor across query windows |
NextPageUrl | Full next-page URL in response body |
NextPageToken | Token/cursor for next page |
PersistentToken | Token persists server-side across requests |
Offset | Skip/offset parameter |
CountBasedPaging | Page number parameter |
PersistentLinkHeader only allows one concurrent query to avoid race conditions. See references/pagination-types.md.
| Property | Description | Default |
|---|---|---|
apiEndpoint | URL to poll (required) | -- |
httpMethod | GET or POST | GET |
queryWindowInMin | Poll interval AND time window (min) | 5 |
rateLimitQPS | Max queries per second (integer) | -- |
retryCount | Retries on failure (1-6) | 3 |
timeoutInSeconds | Request timeout (1-180) | 20 |
queryTimeFormat | Date format for time params | ISO 8601 UTC |
startTimeAttributeName | Query param for start time | -- |
endTimeAttributeName | Query param for end time | -- |
isPostPayloadJson | POST body as JSON | false |
Built-in variables for queryParameters: {_QueryWindowStartTime}, {_QueryWindowEndTime}
Additional for queryParametersTemplate: {_APIKeyName}, {_APIKey}
| Property | Description |
|---|---|
eventsJsonPaths | JSONPath to data in response (required), e.g. ["$"] or ["$.value"] |
format | json, csv, or xml (required) |
isGzipCompressed | Response is gzip compressed |
successStatusJsonPath | JSONPath to success indicator |
convertChildPropertiesToArray | When API returns object instead of array |
kind must be "Customizable"connectivityCriteria.type: use "HasDataConnectors" for pull, "IsConnectedQuery" for pushgraphQueriesTableName: set to your actual table name (enables sample queries)| Type | Purpose |
|---|---|
Textbox | Text input (text, password, number, email) |
OAuthForm | OAuth-style credential input (works for API key + secret too) |
ConnectionToggleButton | Connect/disconnect button (triggers DCR deployment) |
CopyableLabel | Read-only copyable text (supports fillWith for auto-populated values) |
InfoMessage | Informational text (inline or block) |
Markdown | Markdown-formatted text |
Dropdown | Selection dropdown |
ContextPane | Side panel with additional inputs |
DataConnectorsGrid | Grid display of connections |
DeployPushConnectorButton | Push connector deployment trigger |
InstructionStepsGroup | Collapsible instruction group |
InstallAgent | Links to agent installation |
See references/ui-definitions.md for full property details.
A single connector definition can have multiple RestApiPoller connections with different:
queryWindowInMin)Pattern: Create separate named connections for each log source (e.g., auth logs at 1 min, activity logs at 5 min, config logs at 15 min).
DataConnector (deploy-time) templates use single [, ResourcesDataConnector (connect-time) templates use double [[. Using [[ in a DataConnector template causes literal strings instead of evaluated values (e.g. InvalidResourceLocation). Exception: /metadata resources always use [[.mainTemplate blocksworkspaceResourceId uses single brackets (it's in a DataConnector template, evaluated at deploy time), but dcrConfig properties use double brackets (they're in a ResourcesDataConnector template, evaluated at connect time)kind or location -- omit both properties.'rdc' prefix (not 'dc'). Use 'sl' for Solution, 'dc' for DataConnector, 'rdc' for ResourcesDataConnector.dynamic() literal syntax is blocked -- use parse_json('{"key":"val"}')coalesce() is blocked -- use iif(isnotnull(a), a, b)replace_string and replace_regex are blocked -- use extract with regex or parseparse limited to 10 columns per statement -- chain multiple parse statementsbag_keys, bag_values, bag_set, bag_remove_keys are all blockedqueryParametersTemplate is for connection validation only -- also define queryParameters for ongoing pollingqueryWindowInMin applies globallysecurestring for all credentials -- values unreadable after deploymentworkspace/Table_CL cause 404 from double-nesting (/workspaces/{ws}/tables/{ws}/Table_CL)_CL suffix and correct schematransformKql uses only supported KQL subsetTimeGenerated produced by every transformation[ in DataConnector templates, double [[ in ResourcesDataConnector templates (except /metadata resources which always use [[)securestring for all credentialsrateLimitQPS and retryCount set for source API limitsconnectivityCriteria type is HasDataConnectors (pull) or IsConnectedQuery (push)kind is CustomizablecontentPackages resource has contentProductId and packageId propertieskind or location properties'rdc' prefixRestApiPoller (v2) -- in Solutions/:
Solutions/Cisco Meraki Events via REST API/)Solutions/1Password/)Solutions/Auth0/)Solutions/AzureDevOpsAuditing/)Solutions/Box/)Solutions/BigID/)Solutions/AtlassianJiraAudit/)Legacy APIPolling (v1) -- in DataConnectors/:
All at: https://github.com/Azure/Azure-Sentinel/tree/master/
See references/production-examples.md for annotated excerpts from these connectors.
After generating any ARM template, run the validator script:
python scripts/validate_connector.py mainTemplate.json --verbose
The script runs 48 checks covering: resource count, bracket escaping, stream declarations, table names, KQL transforms, securestring usage, pagination, content template dependencies, contentProductId prefixes, nested table constraints, top-level table existence, and more. It exits with code 1 if any check fails.
For push connectors, add --connector-type push to adjust the connectivityCriteria check.
The script lives at: scripts/validate_connector.py (relative to this skill's directory).
Before presenting any ARM template, connector config, or KQL transform to the user:
scripts/validate_connector.py on the generated template and fix any failures.__gte vs [gte], created_at vs timestamp, date formats, etc. Don't assume based on examples -- test against the actual API.npx claudepluginhub dstreefkerk/claude-skills --plugin sentinelExpert guidance for Azure Sentinel: troubleshooting connectors, KQL/ASIM, Logic Apps playbooks, UEBA, multi-tenant MSSP, deployment, and cost optimization.
Manages Azure Connector Gateways, connections, and event-driven triggers to connect Microsoft 365 services (Teams, Forms, SharePoint, OneDrive) and external APIs to sandbox apps.
Guides on Azure Data Factory validation rules including activity nesting limitations, ForEach restrictions, pipeline validation, linked service authentication, resource limits, Set Variable rules, and Data Flow constraints.