AI SecurityGRCOktaGitHubDatadogAWSOffboardingSOC 2Agent Workflows

Agentic Security: Your GRC Platform Is Already a Detection Engine

Every GRC integration is a queryable API endpoint. Here's how to use the access data your compliance platform already collects to run automated offboarding sweeps across GitHub, Datadog, Okta, Entra ID, and AWS, with a timestamped audit trail in return.

Luis Torres-Villarreal

1. Use Case Context

A GRC platform with 20-plus active integrations is most commonly treated as a compliance evidence collector. You connect Workday, GitHub, CrowdStrike, Datadog, and your cloud accounts during audit prep, let the platform collect evidence on schedule, and move on. Between assessments, the integrations sit idle.

That framing leaves the actual value on the table.

Every integration is a queryable API endpoint. Every HR event in Workday is a trigger. The access data, activity logs, and configuration state that your GRC platform collects for compliance purposes are also real-time detection inputs. The gap is not the data. It is the absence of a layer that continuously correlates across platforms.

That layer is the agent.

Three structural patterns generate most of the detectable gaps in connected environments:

HR event propagation failures. Workday processes a termination. Your GRC platform updates the person’s status to FORMER. Your IdP deprovisions the account. In theory, every SSO-connected SaaS platform follows. In practice, platforms with SCIM mapping errors, local credential bypass paths, or delayed sync schedules stay active. The gap is invisible in any single platform. It only surfaces when you query each one against the HR record.

Ownership drift over time. Employees leave. The infrastructure they owned stays: GitHub Actions they authored, Datadog monitors they created, AWS resources tagged to their email. None of these trigger an alert. None produce a compliance finding. They accumulate silently until an incident surfaces the gap: a critical deploy pipeline with no active owner, a P1 monitor with broken routing, a cloud resource with no one applying patches.

Pre-departure data access. The highest-risk window for data exfiltration is the two weeks before a known termination date, when the employee has full legitimate access but may have motivation to pull data. Standard DLP does not flag this because the access is authorized. The signal only appears when you correlate termination dates against download activity in connected systems.

The workflows below target the first two patterns. Each is a discrete agent run, either HR-event-triggered or scheduled, using APIs your GRC platform already has access to.


2. Scenario

A weekly agent run surfaces two findings that arrived in the same 72-hour window.

A senior engineer who departed 11 days ago still owns two GitHub Actions workflows that run on a nightly cron schedule and deploy to a staging environment. The engineer’s org membership was removed correctly. The workflow YAML files still list them as the commit author and the deploy secrets are scoped to their former identity. The workflows are still running.

The same sweep checks Datadog and finds four P1 monitors (all owned by a different former employee) where the notification routing points to a Slack handle that no longer resolves. The monitors are active. When they fire, the alerts go nowhere.

Both findings were in the data before the agent ran. The issue is not that detection was hard. No single platform surfaces the cross-system correlation. The agent is the correlation step.


3. Prompt Chain

Prompt 1: Build the population

Query your GRC platform (e.g., Vanta /people) for all records where status = FORMER
and terminatedAt is within the last 60 days.

For each person, return: name, email, terminatedAt, and the list of connected
integrations active at time of termination.

Also query Workday for anyone with a confirmed termination date within the next 14 days
(pre-departure risk window). For this group, return: name, email,
scheduled_termination_date, department, and current access profile.

Prompt 2: Run parallel checks

For each FORMER person, run ALL of the following checks concurrently.
Do not wait for one to complete before starting the next.

1. IdP check: confirm account status in your IdP (Okta, Entra ID, or equivalent).
   Pull active app assignments. Query post-termination authentication events.

2. GitHub ownership check: search org repos for workflow YAML files where the last
   commit author matches the person's email. Check for active PATs in the audit log.
   Look for any scheduled triggers still active on those workflows.

3. Datadog access check: confirm account status. Pull any API keys issued to the
   person's user ID. Query audit logs for API activity after terminatedAt.

4. Infrastructure ownership check: scan AWS resources (EC2, Lambda, RDS, S3) across
   all accounts for owner, creator, and engineer tags matching the person's email.

For each check: return account_active (bool), post_term_activity (bool),
activity_summary, severity (CRITICAL/HIGH/MEDIUM/CLEAN).
If a check fails or times out, return status=ERROR. Do not skip silently.

Also run the following on a weekly cadence, regardless of any specific person:

5. Datadog monitor ownership: for every monitor and dashboard, check the creator
   email against Workday status. Flag items owned by FORMER employees, sorted by
   monitor priority (P1 first).

6. GitHub Actions scheduled workflow audit: find all org workflows with a schedule:
   trigger where the last commit author resolves to FORMER in Workday.

Prompt 3: Route output

For each CRITICAL or HIGH finding:
- Post a structured finding report to the security alert channel.
- Open a Jira ticket with: person or resource, affected platforms, root cause,
  and recommended action.
- For accounts still active: include the exact API call needed to deprovision.

For MEDIUM findings:
- Open a Jira task with recommended action. No immediate alert required.

For CLEAN results:
- Write a summary record to the offboarding audit log.

For all results:
Produce a consolidated summary table: person or resource | terminatedAt |
platforms checked | risk level | action taken.

Deduplication rule: a former employee appearing across multiple checks gets one
consolidated finding ticket, not one per platform. Open separate remediation
tasks per platform action required.

4. Agent Workflow

Workflow A: GitHub Actions Owned by Terminated Employees

Step 1: Find workflow files authored by the former employee

GitHub Actions files live in .github/workflows/. Use the search API to scope to repos with recent workflow changes, then pull the latest commit per file:

GET https://api.github.com/search/code?q=org:{org}+path:.github/workflows+extension:yml
Authorization: Bearer {token}

For each result, check the last commit’s author:

GET https://api.github.com/repos/{owner}/{repo}/commits
  ?path=.github/workflows/{filename}&per_page=1
Authorization: Bearer {token}

Compare commit.author.email against the terminated employee’s email.

Step 2: Check for active scheduled triggers

Parse the workflow YAML for any schedule: block:

on:
  schedule:
    - cron: '0 2 * * *'

Any workflow with a schedule: trigger runs independently of whether its author has active credentials. It will continue running until the workflow file is modified or disabled. Org membership removal does not stop it.

Step 3: Check for active PATs in the audit log

GET https://api.github.com/enterprises/{enterprise}/audit-log
  ?phrase=actor:{username}+action:personal_access_token.create
Authorization: Bearer {enterprise_admin_token}

Filter for tokens created before terminatedAt with no subsequent revoke event. PATs do not expire when org membership is removed.

Step 4: Decision logic

Condition Severity Action
Workflow authored by FORMER, no scheduled trigger LOW Flag for ownership transfer; no urgency
Workflow with scheduled trigger, author is FORMER HIGH Disable workflow; open Jira ticket for CODEOWNERS update
Scheduled workflow + active PAT from former identity CRITICAL Disable immediately; revoke PAT via Admin API; audit recent run logs
Deploy workflow with write access to production environment CRITICAL Suspend workflow; rotate any secrets the workflow could access

Workflow B: Datadog Access Surviving Deprovisioning

The structural cause is the same as most SaaS offboarding failures: SCIM sync confirms account deactivation, but API keys issued to that user live outside the IdP session. They persist until explicitly revoked.

Step 1: Check account status

GET https://api.datadoghq.com/api/v1/user/{email}
DD-API-KEY: {api_key}
DD-APPLICATION-KEY: {app_key}

Check disabled (boolean). A deprovisioned user should have disabled: true.

Step 2: Pull API keys issued to the user

GET https://api.datadoghq.com/api/v2/api_keys?filter[user_id]={user_id}
DD-API-KEY: {api_key}
DD-APPLICATION-KEY: {app_key}

Datadog API keys do not deactivate when the user account is disabled. A former employee’s key can still query metrics, read logs, or trigger monitors until explicitly revoked, even if the account shows disabled: true.

Step 3: Check for post-termination API activity

GET https://api.datadoghq.com/api/v2/audit/events
  ?filter[query][email protected]:{email}
  &filter[from]={terminatedAt}
  &filter[to]={now}
Authorization: Bearer {dd_app_key}

Any authenticated API activity after terminatedAt is an immediate escalation regardless of whether the account is disabled. It indicates an active token is being used.

Step 4: Decision logic

Condition Severity Action
Account disabled, no API keys found CLEAN Document
Account disabled, orphaned API keys present HIGH Revoke via DELETE /api/v2/api_keys/{key_id}
Account active post-deprovisioning MEDIUM Disable via admin console; check for API keys
Active API key + post-term activity detected CRITICAL Revoke keys immediately; investigate activity scope; escalate

Workflow C: Orphaned Infrastructure

Two surfaces, same underlying check: for every resource, resolve the owner’s email against current Workday status.

Datadog monitors and dashboards

Pull all monitors and check creator.email against Workday:

GET https://api.datadoghq.com/api/v1/monitor?with_downtimes=false&page_size=100
DD-API-KEY: {api_key}
DD-APPLICATION-KEY: {app_key}

For dashboards, check author_handle:

GET https://api.datadoghq.com/api/v1/dashboard

For any monitor owned by a FORMER employee, inspect the message field. Notification routing embedded in the monitor body (Slack handles, email addresses) may reference the former employee directly and fail silently when the monitor fires.

AWS resources

Scan across accounts for resource tags matching the former employee’s email:

aws ec2 describe-instances \
  --filters "Name=tag-key,Values=owner,creator,engineer" \
  --query 'Reservations[].Instances[].[InstanceId,Tags,State.Name,Placement.AvailabilityZone]'

aws lambda list-functions --query 'Functions[].[FunctionName,Tags]'
aws rds describe-db-instances --query 'DBInstances[].[DBInstanceIdentifier,TagList,DBInstanceStatus]'

A single cross-account IAM role with tag read permissions is significantly easier to operate than per-account credentials. Set it up once and reference it from the agent’s execution environment.

Decision logic (combined)

Condition Severity Action
Monitor owned by FORMER, muted or disabled LOW Reassign ownership; no urgency
Monitor owned by FORMER, active, P4/P5 MEDIUM Open Jira task for ownership reassignment
Monitor owned by FORMER, active, P1/P2 HIGH Immediate reassignment; verify and fix notification routing
All monitors for a given service owned by FORMER employees HIGH Escalate to engineering lead; service has no monitoring owner
AWS resource tagged to FORMER, stopped/inactive LOW Update owner tag; schedule decommission review
AWS resource tagged to FORMER, running MEDIUM Open Jira task for ownership reassignment
Running resource in production account, no active owner HIGH Escalate to engineering lead
Running resource in CDE-scoped account, no active owner CRITICAL Immediate escalation; PCI scope gap

Workflow D: IdP Deprovisioning Verification

The IdP is the control plane for every other check. When Workflow B surfaces Datadog API keys that survived deprovisioning, or Workflow C finds orphaned infrastructure, the upstream question is always the same: did deprovisioning actually succeed at the IdP level, or did it fail silently there too? This workflow checks the root before assuming the downstream failures are the whole story.

Step 1: Confirm account status

For Okta:

GET https://{org}.okta.com/api/v1/users/{email}
Authorization: SSWS {api_token}

Check status. A correctly deprovisioned account should show DEPROVISIONED. Any other value (ACTIVE, SUSPENDED, LOCKED_OUT, RECOVERY) is a finding. SUSPENDED is not deprovisioned; the account can be reactivated and authenticated against.

For Entra ID:

GET https://graph.microsoft.com/v1.0/users/{userPrincipalName}
Authorization: Bearer {access_token}

Check accountEnabled. Should be false. Also pull signInActivity.lastSignInDateTime directly from this response: a single field that tells you whether the account has been used recently without a separate log query.

Step 2: Pull active app assignments

For Okta:

GET https://{org}.okta.com/api/v1/users/{userId}/appLinks
Authorization: SSWS {api_token}

This returns all applications the user is currently assigned to. A correctly deprovisioned account should return an empty list. Any active app assignment for a DEPROVISIONED user indicates a SCIM provisioning gap. The IdP removed the account but did not push the deprovisioning event downstream to the SaaS app.

For Entra ID:

GET https://graph.microsoft.com/v1.0/users/{userId}/appRoleAssignments
Authorization: Bearer {access_token}

Cross-reference results against your expected post-offboarding state. Any assignment to a production application is a gap.

Step 3: Query post-termination authentication events

For Okta, session starts after terminatedAt:

GET https://{org}.okta.com/api/v1/logs
  ?filter=actor.id eq "{userId}" and eventType eq "user.session.start"
  &since={terminatedAt}
Authorization: SSWS {api_token}

Also pull the broader event stream to catch token issuance, MFA challenges, and legacy protocol auth:

GET https://{org}.okta.com/api/v1/logs
  ?filter=actor.id eq "{userId}"
  &since={terminatedAt}
  &limit=100
Authorization: SSWS {api_token}

For Entra ID sign-in logs:

GET https://graph.microsoft.com/v1.0/auditLogs/signIns
  ?$filter=userPrincipalName eq '{email}' and createdDateTime ge {terminatedAt}
  &$orderby=createdDateTime desc
Authorization: Bearer {access_token}

Note: Entra sign-in logs require the AuditLog.Read.All permission scope. They are also only retained for 30 days on P1 and 7 days on free tier, so this check has a time window. Run it promptly.

A successful authentication after terminatedAt is an immediate CRITICAL finding regardless of current account status. A successful sign-in from a disabled account indicates a bypass path: a federated identity provider that was not updated, a legacy auth protocol (IMAP, SMTP, POP3) that bypasses modern auth policy, or a service account credential scoped to the former employee’s identity but not tied to their IdP session.

Step 4: Decision logic

Workflow D Step 4 Decision Logic: IdP Deprovisioning Verification


5. Output

Representative consolidated table:

Section 5 Output: Representative Consolidated Table across all four workflows

On check failures:

Any workflow returning ERROR for a check is flagged as UNCLEARED. A platform you cannot query is a platform you cannot clear. A former employee whose Datadog API key status returned a 500 is treated the same as one with a confirmed active key: unresolved until the check succeeds.


6. Prerequisites

Platform Credential Required Scope
GRC platform (Vanta, etc.) API key people:read, integrations:read
Your IdP (Okta, Entra ID, etc.) Admin token User status, app assignments, auth log read
Workday Integration System User Get_Workers report or REST API access
GitHub PAT or GitHub App read:org, read:repo, audit_log:read (Enterprise)
Datadog API + Application key monitors_read, dashboards_read, user_access_read, audit_read
AWS IAM role (cross-account) ec2:DescribeInstances, rds:DescribeDBInstances, lambda:ListFunctions, s3:GetBucketTagging

The pattern across all four workflows is the same: the data already exists in the platforms. Workday knows who left. GitHub knows who authored the workflow. Datadog knows who owns the monitor and who holds the API key. AWS knows what the tag says. What has been missing is the step that queries each platform, compares the result against the HR record, and surfaces the delta with a clear recommended action.

The agent is that step. It does not replace any platform and does not require new integrations. It uses the API access your GRC platform already has and adds the correlation logic that runs across all of them simultaneously.


Want to put your GRC data to work with automated security workflows? See how 543HQ builds agentic security operations.

Disclaimer: The AI-assisted workflows described in this article are intended to augment human judgment, not replace it. All agent outputs (verdicts, recommendations, and draft actions) require human review and verification before execution. Use of agentic tooling in security must align with your organization's policies, change management procedures, and applicable compliance requirements.

Luis Torres-Villarreal is a Senior Leader with 15+ years in IT, Information Security, PCI DSS, HITRUST, NIST CSF, and SOC 2 Type II compliance. He writes about AI agents, Security Automation, and the evolution of InfoSec Teams.

Need a hand with this at your company?

543HQ helps startups and growing companies build security programs that actually work. Start with a free 30-minute call.

Book a Free Call