Skapa kodlösa datakopplingar för hämtning med kapslad API-pollning

Vissa REST-API:er kräver sekventiella anrop, där svaret från en slutpunkt tillhandahåller indata som måste skickas till en annan slutpunkt. Microsoft Sentinel Codeless Connector Framework (CCF) stöder det här mönstret genom kapslad API-pollning för RestApiPoller anslutningar.

Viktigt!

Kapslad API-pollning finns för närvarande i offentlig förhandsversion. Azure Preview Supplemental Terms innehåller fler juridiska villkor som gäller för Azure-funktioner i beta, förhandsvisning eller på annat sätt som ännu inte har släppts till allmän tillgänglighet.

Använd kapslad API-avsökning när ett överordnat API-anrop returnerar identifierare, markörer eller andra värden som krävs av ett eller flera underordnade API-anrop. CCF extraherar de värden som krävs från det överordnade svaret, infogar dem i den underordnade begäran och skickar de underordnade svaren till den konfigurerade destinationstabellen.

Konfigurera nästlad API-polling i en CCF-pull-koppling genom att definiera nästlingslogiken i anslutningsreglerna RestApiPoller .

Information om processen från slutpunkt till slutpunkt för att skapa och paketera en CCF-anslutningsapp finns i Skapa en kodlös anslutningsapp för Microsoft Sentinel. Du kan också använda Microsoft Sentinel-tillägget för Visual Studio Code för att implementera och testa nästlade API-polling-arbetsflöden. För information om installation och användning, se Bygg anpassade kopplingar med AI i Microsoft Sentinel. För RestApiPoller standardegenskaperna för begäran, svar, autentisering, sidindelning och DCR, se referensen för anslutningsregler för RestApiPoller-datakopplingen.

Note

Om du är en oberoende programvaruleverantör (ISV) som skapar en Microsoft Sentinel integrering med hjälp av Codeless Connector Framework kanske Microsoft App Assure-teamet kan hjälpa till. Om du vill engagera App Assure-teamet skickar du ett e-postmeddelande till azuresentinelpartner@microsoft.com.

Förutsättningar

Innan du konfigurerar kapslad API-avsökning måste du förstå:

  • DE API-slutpunkter som anslutningsappen måste anropa.
  • Vilka svarsvärden från det överordnade API-anropet krävs av det underordnade API-anropet.
  • Utdataschemat för måltabellen.
  • Så här skapar du en ccf-standardanslutning RestApiPoller .

En fullständig CCF-anslutning innehåller följande komponenter:

  • Tabell: Den Log Analytics anpassade tabellen där inmatade data lagras.
  • DCR: Datainsamlingsregeln som definierar inmatningstransformeringen.
  • Anslutningsprogrammets användargränssnitt: Definitionen av dataanslutningen som visas i innehållshubben i Microsoft Sentinel.
  • Regler för dataanslutning: Anslutningskonfigurationen som hämtar data från käll-API:et.

Nästlad API-pollning är konfigurerad i reglerna för dataanslutning för ett RestApiPoller anslutningsprogram.

Vad är kapslad API-avsökning?

Kapslad API-avsökning är ett CCF-avsökningsmönster som kedjar REST API-anrop. Det första API-anropet, som kallas det överordnade steget, returnerar värden som krävs av senare API-anrop, så kallade underordnade steg.

Ett API kan till exempel använda det här mönstret:

  1. GET /incidents returnerar en lista över incident-ID:er.
  2. GET /incidents/{incidentId}/details returnerar den fullständiga incidentposten för varje ID.

Ett enda API-anrop returnerar inte fullständiga data. Anslutningen måste anropa listslutpunkten, extrahera varje incidentId och sedan anropa detaljslutpunkten en gång för varje ID.

Använd kapslad API-avsökning när:

  • En listslutpunkt returnerar resurs-ID:t och en informationsslutpunkt kräver varje ID i URL-sökvägen eller frågesträngen.
  • Ett svar på en överordnad begäran returnerar en markör, en sessionstoken, ett fråge-ID eller ett referens-ID som en underordnad begäran behöver.
  • Ett svar innehåller en matris med värden som var och en måste skickas individuellt till en annan slutpunkt.
  • Det överordnade svaret innehåller fält som du vill behålla och det underordnade svaret lägger till berikningsdata som ska kopplas till samma utdatarad.

Om ett enda API-anrop returnerar alla data som du behöver krävs inte kapslad API-avsökning. Använd standardegenskapen eventsJsonPaths för att extrahera poster från svaret.

Så här fungerar kapslad API-avsökning

Kapslad API-avsökning konfigureras med följande avsnitt:

Section Plats Purpose
request Föräldrasteg Definierar den överordnade API-begäran. Egenskaper för tidsfönster konfigureras här.
response Föräldrasteg Definierar hur poster extraheras från det överordnade svaret.
stepInfo Föräldrasteg Möjliggör nästlad pollning och definierar de underordnade steg som ska köras därefter.
stepCollectorConfigs Föräldrasteg Definierar varje underordnat steg, inklusive den underordnade begäran och svarshanteringen.
shouldJoinNestedData Underordnat steg Definierar om det underordnade svaret ersätter de överordnade utdata eller är kopplat till den överordnade posten.

Det kapslade avsökningsflödet fungerar på följande sätt:

  1. Den överordnade begäran körs.
  2. Det överordnade svaret delas upp i poster med hjälp av response.eventsJsonPaths.
  3. stepPlaceholdersParsingKql extraherar platshållarvärden från varje överordnad post.
  4. CCF ersätter platshållarna i den underordnade stegkonfigurationen.
  5. CCF utför underbegäranden.
  6. Det underordnade svaret skickas antingen som utdatarad eller sammanfogas med den överordnade posten, beroende på värdet på shouldJoinNestedData.

Kapslat avsökningskonfigurationsskelett

Följande exempel visar strukturen för en nästlad RestApiPoller-kontakt. CcF-standardegenskaper förkortas med ....

{
  "kind": "RestApiPoller",
  "properties": {
    "connectorDefinitionName": "...",
    "dcrConfig": { },
    "dataType": "...",
    "auth": { },
    "request": {
      "apiEndpoint": "https://api.example.com/incidents",
      "httpMethod": "GET",
      "queryWindowInMin": 60,
      "queryTimeFormat": "yyyy-MM-ddTHH:mm:ssZ",
      "startTimeAttributeName": "startTime",
      "endTimeAttributeName": "endTime"
    },
    "response": {
      "eventsJsonPaths": [ "$.incidents" ],
      "format": "json"
    },
    "stepInfo": {
      "stepType": "Nested",
      "nextSteps": [
        {
          "stepId": "fetchIncidentDetails",
          "stepPlaceholdersParsingKql": "source | project res = parse_json(data) | project incidentId = res.incidentId"
        }
      ]
    },
    "stepCollectorConfigs": {
      "fetchIncidentDetails": {
        "shouldJoinNestedData": false,
        "request": {
          "httpMethod": "GET",
          "apiEndpoint": "https://api.example.com/incidents/$incidentId$/details"
        },
        "response": {
          "eventsJsonPaths": [ "$" ],
          "format": "json"
        }
      }
    }
  }
}

Kapslade pollningsegenskaper

Fastighet Plats Description
stepInfo.stepType Föräldrasteg Måste anges till Nested för att aktivera kapslad API-pollning.
stepInfo.nextSteps[].stepId Föräldrasteg Det underordnade stegnamnet. Det här värdet måste matcha en nyckel i stepCollectorConfigs.
stepInfo.nextSteps[].stepPlaceholdersParsingKql Föräldrasteg KQL som extraherar värden från det överordnade svaret. Frågan körs mot source, där kolumnen data innehåller varje överordnad post som en rå JSON-sträng. Varje projicerad kolumn blir en platshållare.
stepCollectorConfigs Föräldrasteg En mappning av underordnade stegdefinitioner, med nycklar baserade på de stepId-värden som deklareras i stepInfo.nextSteps.
shouldJoinNestedData Underordnat steg Styr hur undersvaret levereras till strömmen. Ange false när det underordnade svaret innehåller hela utdataposten. Ställ in på true när du behöver fält från både det överordnade och underordnade svaret i samma utdatarad.
joinedDataStepName Underordnat steg Namnet på den kolumn dynamic som lagrar det sammanfogade underordnade svaret när shouldJoinNestedData är true. Används inte när shouldJoinNestedData är false.

Ersättning av platshållare

Platshållare extraheras av stepPlaceholdersParsingKql och refereras till med $placeholderName$ syntax.

Den här KQL:n skapar till exempel en platshållare med namnet incidentId:

source
| project res = parse_json(data)
| project incidentId = res.incidentId

Det underordnade steget kan sedan hänvisa till platshållaren som $incidentId$:

"apiEndpoint": "https://api.example.com/incidents/$incidentId$/details"

Ersättning av platshållare stöds i konfigurationen för underordnade steg, inklusive den underordnade begäran apiEndpoint, headers, queryParameters och queryParametersTemplate.

Konfigurera egenskaper för underordnade begäranden

request-blocket i ett understeg stöder de vanliga egenskaperna för begäran som används för API-pollning.

Vanliga egenskaper för underbegäranden är:

Fastighet Description
apiEndpoint Den underordnade API-slutpunkten. Du kan inkludera platshållare som $incidentId$.
httpMethod HTTP-metoden för underbegäran, till exempel GET eller POST.
headers Begärandehuvuden för det underordnade API-anropet. Ersättning av platshållare stöds.
queryParameters Frågesträngsparametrar för det underordnade API-anropet. Ersättning av platshållare stöds.
queryParametersTemplate Mall som används i scenarier med brödtext i begäran eller frågenyttolast. Ersättning av platshållare stöds.
isPostPayloadJson Ange till true när POST-nyttolasten ska skickas som JSON.
rateLimitQPS Det maximala antalet begäranden per sekund.
rateLimitConfig Konfiguration för frekvensbegränsning som kan använda header-fält för frekvensbegränsning som returneras av API:et.
retryCount Antal återförsök. Standardvärde: 3. Intervall som stöds: 1 till 6.
timeoutInSeconds Tidsgräns för begäran i sekunder. Standardvärde: 20. Intervall som stöds: 1 till 180.

Den överordnade förfrågan styr tidsfönstret för polling. Konfigurera egenskaper för tidsfönster, till exempel queryWindowInMin, queryTimeFormat, startTimeAttributeName och endTimeAttributeName, endast i den överordnade begäran. Delsteg styrs vanligtvis av platshållarvärden som extraheras från föräldrasvaret.

Konfigurera parallellitet för underbegäranden

maxParallelism styr hur många underordnade anrop som kan köras samtidigt. Standardvärdet är 15.

maxParallelism ingår inte i standardkonfigurationen för det överordnade anslutningsprogrammet och kan inte anges i det överordnade steget. Eftersom underordnade steg skickas vidare utan översättning av fältnamn kan du ställa in maxParallelism i blocket request i ett underordnat steg om en justering behövs.

"stepCollectorConfigs": {
  "fetchIncidentDetails": {
    "shouldJoinNestedData": false,
    "request": {
      "httpMethod": "GET",
      "apiEndpoint": "https://api.contoso.com/incidents/$incidentId$/details",
      "maxParallelism": 15
    },
    "response": {
      "eventsJsonPaths": [ "$" ],
      "format": "json"
    }
  }
}

Välj om överordnade och underordnade data ska sammanfogas

Använd shouldJoinNestedData för att styra hur undersvar skickas till strömmen.

Använd shouldJoinNestedData: false

Ställ in shouldJoinNestedDatafalse när det överordnade svaret bara innehåller de värden som krävs för den underordnade begäran och det underordnade svaret innehåller den fullständiga posten som du vill importera.

Använd till exempel false när:

  • Det överordnade anropet returnerar endast incident-ID:n.
  • Underanropet returnerar fullständiga incidentposter.
  • Du behöver inte behålla några överordnade fält i målraden.
"stepCollectorConfigs": {
  "fetchIncidentDetails": {
    "shouldJoinNestedData": false,
    "request": {
      "httpMethod": "GET",
      "apiEndpoint": "https://api.contoso.com/incidents/$incidentId$/details"
    },
    "response": {
      "eventsJsonPaths": [ "$" ],
      "format": "json"
    }
  }
}

Använd shouldJoinNestedData: true

Ange shouldJoinNestedData till true när du behöver fält från både det överordnade svaret och det underordnade svaret på samma målrad.

Använd till exempel true när:

  • Det överordnade anropet returnerar aviseringsfält som aviserings-ID, allvarlighetsgrad och detekteringstid.
  • Underanropet returnerar fält för berikning, till exempel berörd användare, käll-IP-adress eller geografisk plats.
  • DCR-transformeringen måste mappa både överordnade fält och underordnade fält till destinationstabellen.

När shouldJoinNestedData är true, anger du joinedDataStepName som namnet på kolumnen dynamic som lagrar det underliggande svaret.

"stepCollectorConfigs": {
  "fetchAlertEnrichment": {
    "shouldJoinNestedData": true,
    "joinedDataStepName": "enrichment",
    "request": {
      "httpMethod": "GET",
      "apiEndpoint": "https://api.contoso.com/alerts/$alertId$/enrichment"
    },
    "response": {
      "eventsJsonPaths": [ "$" ],
      "format": "json"
    }
  }
}

Exempel: GET-underordnad begäran

I det här exemplet används ett contoso-incident-API i två steg:

  1. Den överordnade begäran anropar GET /incidents och får en lista över incident-ID:n.
  2. stepPlaceholdersParsingKql extraherar incidentId från varje överordnad post.
  3. Den underordnade förfrågan anropar GET /incidents/$incidentId$/details en gång per incident-ID.
  4. De underliggande svaren skickas till dataströmmen som platta dataposter.

Överordnat svar

{
  "incidents": [
    { "incidentId": "INC-001" },
    { "incidentId": "INC-002" },
    { "incidentId": "INC-003" }
  ]
}

Undersvar

{
  "incidentId": "INC-001",
  "title": "Suspicious login attempt",
  "severity": "High",
  "status": "Active",
  "createdAt": "2026-05-30T14:22:00Z",
  "affectedUser": "alice@contoso.com",
  "sourceIp": "198.51.100.42"
}

Avsökningskonfiguration

{
  "kind": "RestApiPoller",
  "properties": {
    "connectorDefinitionName": "ContosoIncidentsConnector",
    "dcrConfig": {
      "dataCollectionEndpoint": "{{dataCollectionEndpoint}}",
      "dataCollectionRuleImmutableId": "{{dataCollectionRuleImmutableId}}",
      "streamName": "Custom-ContosoIncidents_CL"
    },
    "dataType": "ContosoIncidents_CL",
    "auth": {
      "type": "APIKey",
      "ApiKey": "{{apiKey}}",
      "ApiKeyName": "x-functions-key"
    },
    "request": {
      "apiEndpoint": "https://api.contoso.com/incidents",
      "httpMethod": "GET",
      "queryWindowInMin": 60,
      "queryTimeFormat": "yyyy-MM-ddTHH:mm:ssZ",
      "startTimeAttributeName": "startTime",
      "endTimeAttributeName": "endTime",
      "headers": {
        "Accept": "application/json"
      }
    },
    "response": {
      "eventsJsonPaths": [ "$.incidents" ],
      "format": "json"
    },
    "stepInfo": {
      "stepType": "Nested",
      "nextSteps": [
        {
          "stepId": "fetchIncidentDetails",
          "stepPlaceholdersParsingKql": "source | project res = parse_json(data) | project incidentId = res.incidentId"
        }
      ]
    },
    "stepCollectorConfigs": {
      "fetchIncidentDetails": {
        "shouldJoinNestedData": false,
        "request": {
          "httpMethod": "GET",
          "apiEndpoint": "https://api.contoso.com/incidents/$incidentId$/details",
          "headers": {
            "Accept": "application/json"
          },
          "retryCount": 3,
          "timeoutInSeconds": 60
        },
        "response": {
          "eventsJsonPaths": [ "$" ],
          "format": "json"
        }
      }
    }
  }
}

Exempel: POST-underbegäran med en JSON-text

Vissa API:er kräver att identifierare från det överordnade svaret skickas i en POST-brödtext i stället för URL-sökvägen eller frågesträngen. Använd queryParametersTemplate med isPostPayloadJson för det här mönstret.

I det här exemplet returnerar det överordnade svaret en incidentId, och den underordnade begäran skickar det värdet i en JSON-POST-begärandetext.

"stepCollectorConfigs": {
  "fetchIncidentDetails": {
    "shouldJoinNestedData": false,
    "request": {
      "httpMethod": "POST",
      "apiEndpoint": "https://api.contoso.com/incidents/details:batchGet",
      "headers": {
        "Accept": "application/json",
        "Content-Type": "application/json"
      },
      "queryParametersTemplate": "{'ids': ['$incidentId$']}",
      "isPostPayloadJson": true,
      "retryCount": 3,
      "timeoutInSeconds": 60
    },
    "response": {
      "eventsJsonPaths": [ "$.items" ],
      "format": "json"
    }
  }
}

Exempel: Koppla underordnade berikningsdata till den överordnade posten

I det här exemplet används ett Contoso-aviserings-API där det överordnade svaret innehåller fält som ska bevaras och det underordnade svaret innehåller berikningsdata.

Överordnat svar

{
  "alerts": [
    {
      "alertId": "ALT-001",
      "severity": "High",
      "detectedAt": "2026-05-30T14:22:00Z",
      "riskScore": 92
    }
  ]
}

Undersvar

{
  "alertId": "ALT-001",
  "affectedUser": "bob@contoso.com",
  "sourceIp": "198.51.100.77",
  "geolocation": "US/Virginia",
  "relatedIncidentId": "INC-042"
}

Avsökningskonfiguration

{
  "kind": "RestApiPoller",
  "properties": {
    "connectorDefinitionName": "ContosoAlertsConnector",
    "dcrConfig": {
      "dataCollectionEndpoint": "{{dataCollectionEndpoint}}",
      "dataCollectionRuleImmutableId": "{{dataCollectionRuleImmutableId}}",
      "streamName": "Custom-ContosoAlerts_CL"
    },
    "dataType": "ContosoAlerts_CL",
    "auth": {
      "type": "APIKey",
      "ApiKey": "{{apiKey}}",
      "ApiKeyName": "x-functions-key"
    },
    "request": {
      "apiEndpoint": "https://api.contoso.com/alerts",
      "httpMethod": "GET",
      "queryWindowInMin": 60,
      "queryTimeFormat": "yyyy-MM-ddTHH:mm:ssZ",
      "startTimeAttributeName": "startTime",
      "endTimeAttributeName": "endTime"
    },
    "response": {
      "eventsJsonPaths": [ "$.alerts" ],
      "format": "json"
    },
    "stepInfo": {
      "stepType": "Nested",
      "nextSteps": [
        {
          "stepId": "fetchAlertEnrichment",
          "stepPlaceholdersParsingKql": "source | project res = parse_json(data) | project alertId = res.alertId"
        }
      ]
    },
    "stepCollectorConfigs": {
      "fetchAlertEnrichment": {
        "shouldJoinNestedData": true,
        "joinedDataStepName": "enrichment",
        "request": {
          "httpMethod": "GET",
          "apiEndpoint": "https://api.contoso.com/alerts/$alertId$/enrichment"
        },
        "response": {
          "eventsJsonPaths": [ "$" ],
          "format": "json"
        }
      }
    }
  }
}

DCR-transformen kan sedan projicera fält från både huvudposten och den sammanfogade underordnade responsen.

Ett exempel:

source
| extend enrichment = todynamic(enrichment)
| project
    TimeGenerated = todatetime(detectedAt),
    AlertId = tostring(alertId),
    Severity = tostring(severity),
    RiskScore = toint(riskScore),
    AffectedUser = tostring(enrichment.affectedUser),
    SourceIp = tostring(enrichment.sourceIp),
    Geolocation = tostring(enrichment.geolocation),
    RelatedIncidentId = tostring(enrichment.relatedIncidentId)

Autentisering för understeg och fältnamn för sidindelning

Fältnamnsöversättning gäller endast för det överordnade steget. Varje post i stepCollectorConfigs skickas ordagrant och mappas inte om. Därför måste alla auth- eller paging-block i ett delsteg använda de fältnamn för delsteget som visas i följande tabeller.

Autentiseringsfält

Namn på överordnat stegfält Fältnamn för understeg
type AuthType
apiKey APIKey
apiKeyName APIKeyName
redirectUri för OAuth2 RedirectionEndpoint
isCredentialsInHeaders för OAuth2 eller JWT IsClientSecretInHeader
grantType för OAuth2 FlowName
queryParameters för JWT TokenEndpointQueryParameters
isJsonRequest för JWT IsTokenEndpointPostPayloadJson
userName / password nyckel/värde-par för JWT eller sessionsautentisering UsernameAttributeNameoch UsernameAttributeValue / PasswordAttributeNamePasswordAttributeValue

För OAuth2 transformeras även värdet FlowName. Använd till exempel ClientCredentials i stället för client_credentials, och AuthCode i stället för authorization_code.

Växlingsfält

Namn på överordnat stegfält Fältnamn för understeg
pageSizeParameterName pageSizeParaName

Alla andra namn på sidindelnings- och svarsfält är desamma för överordnade och underordnade steg.

Limits

Kapslad API-avsökning har följande gränser:

Limit Description
Underordnade steg i stepCollectorConfigs En kapslad konfiguration stöder upp till fyra poster i stepCollectorConfigs.
Poster i stepInfo.nextSteps stepInfo.nextSteps stöder upp till tre poster.
Cirkulära referenser Cirkelstegreferenser stöds inte och avvisas under valideringen.

Slutför anslutningsprogrammet

När du har konfigurerat de kapslade RestApiPoller anslutningsreglerna slutför du de återstående CCF-anslutningskomponenterna:

  • Skapa eller uppdatera måltabellen.
  • Skapa DCR och transformering.
  • Skapa definitionen för anslutningsgränssnittet.
  • Paketera anslutningsappen i en ARM-distributionsmall.
  • Distribuera och testa anslutningsappen.

Om du vill veta mer om hela processen, se Skapa ett anslutningsprogram utan kod för Microsoft Sentinel.