Amazon GuardDuty
The GuardDuty integration sends Amazon GuardDuty findings from your AWS accounts to Elastio, which can then schedule hunts on the affected assets. Enabling it for an account creates an Amazon EventBridge event bus and rule that route that account’s GuardDuty findings to Elastio.
The setup is hub and spoke: you enable the integration on a hub account in one region, then link other (spoke) accounts that forward their GuardDuty events through the hub.
1. Pick the hub account
Section titled “1. Pick the hub account”Lists the active AWS accounts connected to your tenant, both cloud connectors (cloud_connector) and protected accounts (protected_account). The hub and every spoke must be one of these.
curl "https://acme.app.elastio.com/gateway/ingestion/v1/accounts" \ -H "Authorization: Bearer $ELASTIO_TOKEN"import os, requests
BASE = "https://acme.app.elastio.com"HEADERS = {"Authorization": f"Bearer {os.environ['ELASTIO_TOKEN']}"}
resp = requests.get(f"{BASE}/gateway/ingestion/v1/accounts", headers=HEADERS, timeout=30)resp.raise_for_status()for acct in resp.json()["accounts"]: print(acct["account_id"], acct["region"], acct["type"])$Base = "https://acme.app.elastio.com"$Headers = @{ Authorization = "Bearer $env:ELASTIO_TOKEN" }(Invoke-RestMethod -Uri "$Base/gateway/ingestion/v1/accounts" -Headers $Headers).accounts{ "accounts": [ { "account_id": "123456789012", "region": "us-east-1", "type": "cloud_connector" }, { "account_id": "987654321098", "region": "eu-west-1", "type": "protected_account" } ]}2. Enable the integration on the hub
Section titled “2. Enable the integration on the hub”Send integration: "guardduty", the hub’s account_id and the region where your hub is deployed. If the integration is already enabled, you get the existing configuration back, so the call is safe to repeat.
curl -X POST "https://acme.app.elastio.com/gateway/ingestion/v1/enable" \ -H "Authorization: Bearer $ELASTIO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"integration": "guardduty", "account_id": "123456789012", "region": "us-east-1"}'resp = requests.post( f"{BASE}/gateway/ingestion/v1/enable", headers=HEADERS, json={"integration": "guardduty", "account_id": "123456789012", "region": "us-east-1"}, timeout=60,)resp.raise_for_status()print(resp.json()["event_bus_name"])$body = @{ integration = "guardduty"; account_id = "123456789012"; region = "us-east-1" } | ConvertTo-JsonInvoke-RestMethod -Method Post -Uri "$Base/gateway/ingestion/v1/enable" ` -Headers $Headers -ContentType "application/json" -Body $body{ "event_bus_name": "elastio-acme-corp-123456789012", "rule_name": "elastio-acme-corp-123456789012-guardduty", "eventbridge_rule_name": "elastio-acme-corp-123456789012-guardduty", "status": "enabled", "message": "ok"}A 404 means the account isn’t one of your tenant’s active accounts.
3. Link spoke accounts
Section titled “3. Link spoke accounts”/gateway/ingestion/v1/guardduty/{hub_account_id}/{hub_region}/linked-accountsAdd linked accounts to a hubAdd the accounts that forward their GuardDuty events through the hub. Each must be an active cloud connector or protected account. The call succeeds if at least one account is valid: added, already_linked and failed (with validation_errors) tell you what happened to each. It returns 409 only when every account fails validation.
curl -X POST "https://acme.app.elastio.com/gateway/ingestion/v1/guardduty/123456789012/us-east-1/linked-accounts" \ -H "Authorization: Bearer $ELASTIO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"account_ids": ["222222222222", "333333333333"]}'resp = requests.post( f"{BASE}/gateway/ingestion/v1/guardduty/123456789012/us-east-1/linked-accounts", headers=HEADERS, json={"account_ids": ["222222222222", "333333333333"]}, timeout=30,)resp.raise_for_status()result = resp.json()print("linked:", result["linked_account_ids"], "failed:", result.get("failed"))$body = @{ account_ids = @("222222222222", "333333333333") } | ConvertTo-JsonInvoke-RestMethod -Method Post -Uri "$Base/gateway/ingestion/v1/guardduty/123456789012/us-east-1/linked-accounts" ` -Headers $Headers -ContentType "application/json" -Body $body{ "hub_account_id": "123456789012", "linked_account_ids": ["222222222222", "333333333333"], "added": ["333333333333"], "already_linked": ["222222222222"], "message": "Accounts linked successfully"}To unlink spokes, send the same body with DELETE to the same path. Accounts that weren’t linked are reported in not_found and don’t cause an error.
4. Check that findings are flowing
Section titled “4. Check that findings are flowing”Returns enabled with one entry per hub, or disabled if no account has the integration. For each hub, last_event_at, events_last_24h and scans_scheduled_last_24h cover the hub and all of its currently linked spokes. Findings arriving without hunts being scheduled show up as scans_scheduled_last_24h lower than events_last_24h.
curl "https://acme.app.elastio.com/gateway/ingestion/v1/status" \ -H "Authorization: Bearer $ELASTIO_TOKEN" \ | jq '.status, (.accounts[]? | {account_id, region, linked_account_ids, last_event_at, events_last_24h, scans_scheduled_last_24h})'resp = requests.get(f"{BASE}/gateway/ingestion/v1/status", headers=HEADERS, timeout=30)resp.raise_for_status()status = resp.json()print(status["status"])for hub in status.get("accounts", []): print(hub["account_id"], hub["region"], hub.get("events_last_24h"), hub.get("scans_scheduled_last_24h"))$status = Invoke-RestMethod -Uri "$Base/gateway/ingestion/v1/status" -Headers $Headers$status.status$status.accounts | Select-Object account_id, region, last_event_at, events_last_24h, scans_scheduled_last_24h{ "status": "enabled", "accounts": [ { "account_id": "123456789012", "region": "us-east-1", "event_bus_name": "gd-123456789012-uat-development", "elastio_event_bus_arn": "arn:aws:events:eu-central-1:937593779230:event-bus/gd-123456789012-uat-development", "hub_event_bus_arn": "arn:aws:events:us-east-1:123456789012:event-bus/gd-123456789012-uat-development", "eventbridge_rule_name": "gd-123456789012-uat-development", "linked_account_ids": ["222222222222", "333333333333"], "last_event_at": "2026-09-01T11:10:02Z", "events_last_24h": 3, "scans_scheduled_last_24h": 3 } ]}Disable the integration
Section titled “Disable the integration”curl -X POST "https://acme.app.elastio.com/gateway/ingestion/v1/disable" \ -H "Authorization: Bearer $ELASTIO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"integration": "guardduty", "account_id": "123456789012", "region": "us-east-1"}'resp = requests.post( f"{BASE}/gateway/ingestion/v1/disable", headers=HEADERS, json={"integration": "guardduty", "account_id": "123456789012", "region": "us-east-1"}, timeout=60,)resp.raise_for_status()$body = @{ integration = "guardduty"; account_id = "123456789012"; region = "us-east-1" } | ConvertTo-JsonInvoke-RestMethod -Method Post -Uri "$Base/gateway/ingestion/v1/disable" ` -Headers $Headers -ContentType "application/json" -Body $bodyAll endpoints
Section titled “All endpoints”GuardDuty
6 operations in the reference →- GET
/gateway/ingestion/v1/accountsList AWS accounts for a tenant - POST
/gateway/ingestion/v1/enableEnable GuardDuty integration for an AWS account - POST
/gateway/ingestion/v1/disableDisable GuardDuty integration for an AWS account - POST
/gateway/ingestion/v1/guardduty/{hub_account_id}/{hub_region}/linked-accountsAdd linked accounts to a hub - DELETE
/gateway/ingestion/v1/guardduty/{hub_account_id}/{hub_region}/linked-accountsRemove linked accounts from a hub - GET
/gateway/ingestion/v1/statusGet GuardDuty integration status for a tenant