Direct contact opnemen? T 0318-762620 E info@masero.nl

Een Codeless Connector Platform (CCP) data-connector bouwen: deel 1

Gepubliceerd: 20-03-2025

In deze blogserie neem ik je stap voor stap mee in het proces om je eigen Codeless Connector Platform (CCP) data-connector voor Microsoft Sentinel te bouwen. Als je niet bekend bent met CCP, raad ik je om mijn vorige blog te lezen: Microsoft Sentinel Codeless Connector Platform (CCP). De korte samenvatting: het is de meest efficiënte manier om loggegevens in Sentinel te importeren.

 

Het Codeless Connector Platform (CCP) is een vrij complex onderwerp, dus wees je ervan bewust dat deze blogserie behoorlijk uitgebreid zal worden. Maar als je samen met mij door honderden regels ARM-templates werkt, zul je uiteindelijk uitgroeien tot een echte CCP-expert. Laten we aan de slag gaan!

 

Benodigdheden voor een Codeless Connector Platform (CCP) data-connector

Om een data-connector te bouwen, moeten we een toepassing vinden die we kunnen onboarden. De toepassing moet voldoen aan de volgende criteria:

  • Een openbaar toegankelijke API aanbieden (internet-facing API).
  • Authenticatie, verzoekafhandeling en paginering ondersteunen volgens de CCP-vereisten.
  • Idealiter beveiligingsgerelateerde gegevens blootstellen.

Voor deze blogserie gaan we 1Password gebruiken als de applicatie die we onboarden. Dit komt doordat 1Password beveiligings-gerelateerde gegevens, zoals aanmeldingslogboeken, via een API beschikbaar stelt. Daarnaast vind ik het gewoon een geweldig product. Je kunt hier een gratis proefperiode van 2 weken krijgen, waarmee je kunt meedoen, bouwen en testen zonder verplichtingen (geen creditcard nodig).

Om onze CCP-connector voor 1Password te schrijven, moeten we de API volledig doorgronden. We moeten weten:

  • Welke authenticatiemethode wordt gebruikt.
  • Welk pagineringsmechanisme de API hanteert (indien van toepassing).
  • Hoe de API-respons is gestructureerd.

Later in deze blogserie zullen we onze connector ook implementeren en testen. Hiervoor heb je toegang nodig tot een Sentinel-werkruimte. De stappen om een Sentinel-werkruimte in te richten vind je hier.

De API verkennen

Als je je hebt aangemeld voor de 1Password-proefversie, kom je terecht op de 1Password startpagina. Om de API aan te roepen, hebben we eerst een geldig API-token nodig. Laten we er een verkrijgen door naar het “Integrations”-gedeelte te navigeren.

Navigatiemenu
Navigeer naar ‘integrations’.

 

Kies vervolgens voor ‘Sentinel’ onder ‘Events Reporting’:

 

Selecteer Sentinel

 

Navigeer naar de sectie “Set up token” en maak je API-token aan.

 

Events Reporting
Genereer je token.

 

Klik op “Issue Token” en zorg ervoor dat je het token opslaat, aangezien het slechts één keer wordt weergegeven.

 

Onze tests starten

Nu we een geldige API-token hebben, kunnen we beginnen met het verkennen van de API. Hiervoor raadplegen we de API-referentie. Bij een snelle blik op de documentatie vallen de volgende zaken op:

  • Aangezien onze proefversie een 1Password for Business-licentie gebruikt, moeten we API-aanroepen doen naar https://events.1password.com. Let op: als we willen dat onze connector alle licentietypen ondersteunt, moeten we dit eindpunt later parameteriseren in onze connector.
  • Authenticatie wordt uitgevoerd via een Authorization-header met een unieke token. We moeten de gebruiker een manier bieden om deze token in onze connector in te voeren. Daarnaast moeten we een Content-Type-header toevoegen.
  • We moeten de POST methode gebruiken om aanmeldingsgebeurtenissen op te halen.
  • In het eerste verzoek geven we een cursor op die bepaalt hoeveel gebeurtenissen we per verzoek willen ontvangen. We geven ook een starttijd mee om te specificeren vanaf welk moment we gebeurtenissen willen ophalen. Optioneel kunnen we een eindtijd toevoegen.

Ik heb al deze informatie samengevoegd in een klein PowerShell-script, waarmee we interactief met de API kunnen werken en aanmeldingsgebeurtenissen kunnen ophalen:

$token = “<your token here>”
$headers = @{
“Authorization”= “Bearer $token
“Content-Type”= “application/json”
}

$lastHour = (get-date).AddHours(-1).ToUniversalTime().ToString(“yyyy-MM-ddTHH:mm:ssZ”)
$body = @{“limit” = 200; “start_time” = $lastHour} | ConvertTo-Json

### Getting signinattempts
$uri = “https://events.1password.com/api/v1/signinattempts”
$response = Invoke-WebRequest -Method Post -Uri $uri -Headers $headers -Body $body
$content = ($response.Content | ConvertFrom-Json)
$content

Als je geen gebeurtenissen ontvangt, controleer dan of je in het afgelopen uur hebt ingelogd in 1Password. Als dat niet het geval is, probeer dan een paar keer in en uit te loggen – dit zou binnen 5 minuten enkele gebeurtenissen moeten genereren.

De eigenschappen van ons object.
De eigenschappen van ons object.

 

Bij het inspecteren van het geretourneerde object komen we tot de volgende inzichten:

  • De respons bevat een cursor, die we kunnen gebruiken voor paginering.
  • De respons bevat een has_more-vlag, die aangeeft of er meer gebeurtenissen beschikbaar zijn. Als de vlag True is, moeten we blijven verzoeken sturen totdat deze False wordt. Anders missen we mogelijk gebeurtenissen!
  • De daadwerkelijke gebeurtenissen bevinden zich onder de eigenschap items.

Misschien vind je het nog wat verwarrend hoe paginering werkt—dat vond ik ook toen ik er voor het eerst mee werkte. Als je dat nog niet hebt gedaan, log dan een paar keer in en uit bij 1Password. Dit genereert extra gebeurtenissen, zodat we een dataset hebben om doorheen te pagineren. Nu je extra gebeurtenissen hebt gegenereerd, gaan we het pagineringsysteem stap voor stap ontleden. We stellen de “limit” op onze cursor in op 1, wat betekent dat we per API-aanroep slechts 1 gebeurtenis terugkrijgen. Dit dwingt ons om meerdere verzoeken te sturen en zorgt ervoor dat we de paginering correct implementeren.

# Token / header definition here, see first script snippet

$lastHour = (get-date).AddHours(-1).ToUniversalTime().ToString(“yyyy-MM-ddTHH:mm:ssZ”)
$body = @{“limit” = 1; “start_time” = $lastHour} | ConvertTo-Json

### Getting signinattempts
$uri = “https://events.1password.com/api/v1/signinattempts”
$response = Invoke-WebRequest -Method Post -Uri $uri -Headers $headers -Body $body
$content = ($response.Content | ConvertFrom-Json)

# printing the cursor. this will be a long string.
$content.cursor
#printing the has_more flag. This is a boolean, and it’ll be True.
$content.has_more
# printing the single log entry which we’ve retrieved.
$content.items

 

Om het volgende logbestand op te halen, moeten we de cursor doorgeven die we hebben ontvangen van het vorige verzoek. Dit kunnen we doen door ons script uit te breiden, zodat het er als volgt uitziet:

 

# Token / header definition here, see first script snippet

$lastHour = (get-date).AddHours(-1).ToUniversalTime().ToString(“yyyy-MM-ddTHH:mm:ssZ”)
$body = @{“limit” = 1; “start_time” = $lastHour} | ConvertTo-Json

### Getting signinattempts
$uri = “https://events.1password.com/api/v1/signinattempts”
$response = Invoke-WebRequest -Method Post -Uri $uri -Headers $headers -Body $body
$content = ($response.Content | ConvertFrom-Json)

# printing the cursor. this will be a long string.
$content.cursor
#printing the has_more flag. This is a boolean, and it’ll be True.
$content.has_more
# printing the single log entry which we’ve retrieved.
$content.items

# Using the response’s cursor object to create our new request:
$new_cursor = $content.cursor
$new_body = @{“cursor” = $new_cursor;} | ConvertTo-Json
$response = Invoke-WebRequest -Method Post -Uri $uri -Headers $headers -Body $new_body
$content = ($response.Content | ConvertFrom-Json)
$content.items

 

Je zult zien dat je nu ook de tweede gebeurtenis hebt ontvangen, welke verschilt van de eerste. Dit script is natuurlijk nog geen efficiënte implementatie van paginering, maar door het stap voor stap op te bouwen, wordt het principe duidelijker. Hier is een meer elegante implementatie:

# Token / header definition here, see first script snippet

$lastHour = (get-date).AddHours(-1).ToUniversalTime().ToString(“yyyy-MM-ddTHH:mm:ssZ”)
$body = @{“limit” = 1; “start_time” = $lastHour} | ConvertTo-Json
$uri = “https://events.1password.com/api/v1/signinattempts”

### Getting signinattempts
$collected_events = @()

# has_more is true untill proven otherwise
$has_more = $true

while($has_more){
Write-Host “Getting events…” -ForegroundColor Yellow
$response = Invoke-WebRequest -Method Post -Uri $uri -Headers $headers -Body $body
$content = ($response.Content | ConvertFrom-Json)
$collected_events += $content.items
$body = @{“cursor” = $content.cursor;} | ConvertTo-Json
$has_more = $content.has_more
}

# print all events
Write-Host “Collected $($collected_events.Count) events!” -ForegroundColor Green
$collected_events

 

Afhankelijk van het aantal beschikbare gebeurtenissen, wordt er iets weergegeven zoals in de onderstaande afbeelding.

Paginering in actie
Paginering in actie

 

Conclusie

We kunnen nu met zekerheid stellen dat we een diepgaand begrip van de API hebben. We weten ondertussen:

  • Hoe we authenticatieheaders moeten implementeren.
  • Welke eindpunten we moeten aanroepen.
  • Paginering correct toe te passen.
  • Hoe de API-respons eruitziet.

Het belangrijkste is dat we twee essentiële invoervelden hebben gedefinieerd die per gebruiker zullen verschillen:

  • De API-token.
  • De basis-URL (afhankelijk van het type licentie).

Dit betekent dat we klaar zijn om te beginnen met het bouwen van onze codeless connector! In de volgende blog laat ik je zien hoe we deze API-kennis vertalen naar een CCP-GUI, zodat we de benodigde gebruikersinvoer kunnen verzamelen. Zodra dat op zijn plaats staat, kunnen we verder met het bouwen van de logica van onze connector.