Skip to content

Ops-Automation Identity Least Privilege Audit — LPRIV-010 through LPRIV-016

Audit of ops-automation pipeline identities, API keys, and service tokens. Completed April 2026 as part of the LPRIV least privilege workstream.


Identity Overview

StoryIdentityUsed ByType
LPRIV-010kobe-security-auditMaester M365 auditAzure AD app registration
LPRIV-011kobe-security-auditpim-audit.ymlAzure AD app registration (same)
LPRIV-012kobe-security-auditHIPAA/compliance dashboardsAzure AD app registration (same)
LPRIV-013Cortex XDR API keycortex-weekly-report.yml + cortex_agent.pyAPI key pair
LPRIV-014SES send identityAll email-reporting workflowsAWS IAM via github-deploy-main
LPRIV-015cirius-kobe-botBranch creation, PRs, commitsGitHub personal access token
LPRIV-016Telegram bot tokenSecOps platform notificationsTelegram Bot API token

LPRIV-010, LPRIV-011, LPRIV-012 — kobe-security-audit App Registration

App: kobe-security-audit (App ID: 8f9a3c24-8d9b-40b9-99e0-34a8c76759f6) SP Object ID: a373da7a-cb84-4520-b9a1-3040be9a1db6Type: Federated credential (GitHub Actions OIDC — Cirius-Group-Inc/ops-automation)

Date audited: April 15, 2026

This single app registration is used by multiple workflows in ops-automation. The same AZURE_CLIENT_ID GitHub secret is referenced by:

  • maester-m365-audit.yml (LPRIV-010)
  • pim-audit.yml (LPRIV-011)
  • weekly-hipaa-audit.yml, prod-security-dashboard.yml, intune-audit.yml, purview-audit.yml, dde-security-dashboard.yml (LPRIV-012)

Consented Graph Permissions (Application roles)

PermissionPurposeStatus
Policy.Read.ConditionalAccessMaester: audit CA policies✅ Required
RoleEligibilitySchedule.Read.Directorypim-audit: read PIM eligibility schedules✅ Required
DeviceManagementManagedDevices.Read.AllIntune audit: read managed devices✅ Required
BitlockerKey.ReadBasic.AllHIPAA audit: verify BitLocker key escrow✅ Required
UserAuthenticationMethod.Read.AllMaester: audit MFA registration✅ Required
Mail.ReadWriteUnused — removed 2026-04-15 (LPRIV-018)REMOVED
OnPremDirectorySynchronization.Read.AllMaester: Entra Connect sync health✅ Required
SharePointTenantSettings.Read.AllMaester: SharePoint security settings✅ Required
PrivilegedAccess.Read.AzureADpim-audit: read PIM role assignments✅ Required
SecurityIdentitiesHealth.Read.AllMaester: identity security health✅ Required
DirectoryRecommendations.Read.AllMaester: security recommendations✅ Required
Directory.Read.AllMaester: read directory objects✅ Required
ReportSettings.Read.AllMaester: reporting configuration✅ Required
RoleManagement.Read.Allpim-audit: read role assignments✅ Required
User.Read.Allpim-audit: read user objects✅ Required
DeviceManagementRBAC.Read.AllIntune audit: read Intune RBAC✅ Required
SecurityIdentitiesSensors.Read.AllMaester: security sensor health✅ Required
DeviceManagementConfiguration.Read.AllIntune audit: read device config✅ Required
Mail.SendUnused — email delivery uses SES; removed 2026-04-15 (LPRIV-018)REMOVED
IdentityRiskEvent.Read.AllMaester: identity risk events✅ Required
AuditLog.Read.AllMaester: audit log access✅ Required
Policy.Read.AllMaester: all policy reads✅ Required
Reports.Read.AllDashboard: usage reports✅ Required
ThreatHunting.Read.AllMaester: advanced threat hunting✅ Required

Exchange Online Permission (Application role)

PermissionPurposeStatus
Exchange.ManageAsAppConnect-ExchangeOnline in Maester⚠️ FLAGGED

Exchange.ManageAsApp grants Exchange management-plane access for the service principal. Required by Maester to run Connect-ExchangeOnline for Exchange security tests. This is a Maester architectural requirement — Exchange Online does not support read-only app-only connectivity at the data plane level for PowerShell.

Mitigating control: The kobe-security-audit SP is registered in Exchange Online via New-ServicePrincipal but no management role assignments are granted — Maester runs read-only Exchange health checks only.

Windows Defender ATP Permissions (Application roles)

PermissionPurposeStatus
Machine.Read.AllRead machine/endpoint inventory from Defender✅ Required
Vulnerability.Read.AllRead vulnerability findings from Defender✅ Required

Flagged Findings

Remediated (2026-04-15): Mail.ReadWrite and Mail.Send removed (LPRIV-018).

Mail.ReadWrite was not used by any identified workflow. Email delivery in ops-automation uses AWS SES (via github-deploy-main role). Confirmed: no Python or PowerShell script in ops-automation calls the Graph mail send API. Both permissions were removed from the SP via Graph API DELETE appRoleAssignments. Count: 27 → 25.

Remaining flag: Exchange.ManageAsApp is very broad.

Full Exchange management access. Required for Maester Exchange tests. No narrower alternative for app-only Exchange Online connectivity. Mitigated by the absence of Exchange role group assignments for the SP.

Verdict: ✅ PASS (post-remediation) — 25 permissions remain (27 − 2 removed). Mail.ReadWrite and Mail.Send removed 2026-04-15. All remaining permissions are read-only except Exchange.ManageAsApp (required for Maester, tracked as broad).


LPRIV-013 — Cortex XDR API Key Scope

Key type: Advanced (HMAC-SHA256) or Standard — determined by CORTEX_API_KEY_TYPE secret Date audited: April 15, 2026

API Operations Used

EndpointOperationPurpose
endpoints/get_endpointsGETEndpoint inventory and agent health
incidents/get_incidentsGETActive incident list
vulnerabilities/get_vulnerabilitiesGETVulnerability findings
alerts/get_alertsGETActive alert list

All operations are read-only data retrieval. No write, remediation, or response operations are performed via the API key.

Two consumers of this key:

  1. ops-automation/cortex-weekly-report.yml — weekly scheduled report via GitHub Actions
  2. bedrock-hub/agents/cortex_agent.py — 4-hour monitoring cycle

The agent reads the key from Key Vault cirius-openai-kv-prod secrets cortex-api-key and cortex-api-key-id at runtime.

Cortex XDR API Key Roles

Cortex XDR API keys have role-based access configured in the Cortex XDR console (Settings → Configurations → Integrations → API Keys). This audit cannot verify the assigned role without console access.

Finding (unverified): The key should have the minimum Cortex XDR API role that allows read-only access to endpoints, incidents, vulnerabilities, and alerts. This is typically the "Viewer" or read-only role in Cortex XDR.

Proposed action: Verify in Cortex XDR console that the API key is assigned the "Viewer" role (or equivalent minimum read role), not "Responder", "Analyst", or "Instance Admin". If a higher role is assigned, downgrade to Viewer.

Verdict: ⚠️ UNVERIFIED — operations are read-only but console access required to confirm the key's assigned role. Verify and report back.


LPRIV-014 — SES Sending Identity

Date audited: April 15, 2026

Email Delivery Architecture

All email sending in ops-automation workflows uses AWS SES, not Microsoft Graph:

  • Sender identity: configured via EMAIL_SENDER GitHub secret
  • Recipients: SES_RECIPIENTS GitHub secret
  • AWS auth: github-deploy-main role in management account (206820231356) via OIDC
  • Region: us-east-1

The AWS role github-deploy-main has AdministratorAccess (flagged in LPRIV-009), which includes SES send permissions. There is no separate scoped SES-only IAM role.

Finding: SES send operations run under the broad AdministratorAccess policy (Action: "*") on the management account deployment role. While this is an existing LPRIV-009 finding, SES-specific isolation is not currently possible given the CI/CD role architecture.

Separate note: The cirius-acs-smtp Azure AD app registration (App ID: 03cc0f1f-0cc4-4598-9df3-a403ccadcc49) is used for Azure Communication Services SMTP relay — a separate email path from the SES sending in ops-automation. ACS SMTP authenticates with Azure AD client credentials; no Graph permissions are assigned to this app (confirmed: zero app role assignments).

Verdict: ⚠️ FLAGGED — SES send runs under AdministratorAccess (LPRIV-009 tracking). ACS SMTP app is minimal (no permissions). No separate action for SES beyond LPRIV-009.


LPRIV-015 — Kobe GitHub Token Permissions

Account: cirius-kobe-bot (GitHub user — org member, not owner) Date audited: April 15, 2026

GitHub Org Role

AttributeValue
Org rolemember (not owner)
StateActive

Repository Access

Verified on azure-infra (representative):

PermissionGrantedNotes
pull (read)Read repository content, clone
push (write)Create branches, push commits
triageLabel and manage issues/PRs (no merge)
maintainNo repository settings changes
adminNo admin access

Finding: push access is required for the bot to create branches and push commits during automated PR workflows. triage allows labeling — appropriate for CI automation. admin and maintain are correctly absent.

Branch protection (1 required review) prevents the bot from merging its own PRs — the bot can push but cannot self-merge. This is the correct design.

Verdict: ✅ PASS — member role (not owner), write access scoped to repository operations, branch protection prevents self-merge, no admin access.


LPRIV-016 — Telegram Bot Token Scope

Date audited: April 15, 2026

Telegram Bot API Token Architecture

Telegram bot tokens do not have granular permission scopes — a token grants access to all Bot API methods the bot is eligible to use. Scope is controlled at the architectural level by which API methods the application calls.

Actual Usage (from codebase audit)

The Telegram bot is used exclusively for outbound notifications:

  • sendMessage — send alert notifications to the SecOps Telegram channel
  • editMessageText — update progress messages during long operations
  • sendReaction — add emoji reactions to messages

The bot does NOT call:

  • Any admin methods (channel administration, user banning)
  • Message deletion (deleteMessage)
  • File upload methods (sendDocument, sendPhoto) except via explicit attachment flows
  • Webhook configuration endpoints

Key mitigating control: The bot token only functions in chats where the bot has been explicitly added. It cannot read messages from arbitrary Telegram chats.

CLAUDE.md architectural constraint: "Telegram is read-only — no buttons, no actions. All approvals in SecOps app only." This ensures no privileged operations are triggered via Telegram.

Verdict: ✅ PASS — No Telegram-side scope isolation mechanism exists (Bot API limitation), but architectural controls prevent misuse. Token access is limited to the SecOps notification channel. Bot does not perform admin or write operations.


Summary

StoryIdentityFindingAction
LPRIV-010kobe-security-audit (Maester)Mail.ReadWrite + Mail.Send removed (LPRIV-018)✅ Done
LPRIV-011kobe-security-audit (pim-audit)Shares identity with LPRIV-010✅ Done
LPRIV-012kobe-security-audit (compliance)Shares identity with LPRIV-010✅ Done
LPRIV-013Cortex XDR API keyRole unverified — console access neededVerify Viewer role in Cortex console
LPRIV-014SES via github-deploy-mainAdministratorAccess (tracked in LPRIV-009)No separate action
LPRIV-015cirius-kobe-bot GitHubmember role, push-only, no self-merge✅ PASS
LPRIV-016Telegram bot tokenNo API scope isolation; architectural controls✅ PASS

Priority Remediations

PriorityActionStoryStatus
HIGHRemove Mail.ReadWrite from kobe-security-auditLPRIV-010/011/012✅ Done 2026-04-15
HIGHRemove Mail.Send from kobe-security-auditLPRIV-018✅ Done 2026-04-15
MEDIUMVerify Cortex XDR API key assigned Viewer roleLPRIV-013Pending Rory console access

Document History

DateChangeAuthor
April 2026Removed Mail.ReadWrite and Mail.Send from kobe-security-audit (LPRIV-018)Kobe
April 2026Initial audit — LPRIV-010 through LPRIV-016Kobe

Internal use only — Cirius Group