Skip to content

CI/CD Identity Least Privilege Audit — LPRIV-008, LPRIV-009

Audit of GitHub Actions deployment identity permissions across Azure and AWS. Completed April 2026 as part of the LPRIV least privilege workstream.


LPRIV-008 — github-deploy-main Azure RBAC

Identity: github-deploy-app (App ID: 8e01e97f-090c-45b1-9659-a99ded5d217c) Service Principal: 484de69a-ed8a-4202-b0b9-2616b91e1a67Type: Federated credential — GitHub Actions OIDC (Cirius-Group-Inc/azure-infra, main branch only)

Date audited: April 15, 2026

Azure RBAC Role Assignments

RoleScopeSubscription / ResourceWorkflow Requirement
Resource Policy ContributorManagement Groupd477c9f8 (tenant root)Azure Policy assignment across all subscriptions
ContributorSubscriptionLogging (3946532a)Terraform resource management — all logging resources
Resource Policy ContributorSubscriptionLogging (3946532a)Azure Policy assignment in logging sub
User Access AdministratorSubscriptionLogging (3946532a)RBAC role assignment in Terraform (managed identities)
ContributorResource Grouprg-logging-logsScoped Terraform apply (superceded by sub-level Contributor)
Key Vault Secrets UserResourcecirius-openai-kv-prodCI/CD secret reads during plan/apply
Key Vault Secrets OfficerResourcecirius-openai-kv-prodSecret rotation via Terraform random_password resources
ContributorSubscriptionProd (db824d94)Terraform resource management — all prod resources
Key Vault AdministratorSubscriptionProd (db824d94)Key Vault management plane (create vaults, set policies, manage keys)
User Access AdministratorSubscriptionProd (db824d94)RBAC role assignment in Terraform
ContributorSubscriptionFirewall (0412f98f)Terraform resource management — Palo Alto firewall infra
Key Vault AdministratorSubscriptionFirewall (0412f98f)Key Vault management for firewall CMK
Key Vault Crypto UserSubscriptionFirewall (0412f98f)CMK key operations
Key Vault ReaderSubscriptionFirewall (0412f98f)Key Vault metadata reads
User Access AdministratorSubscriptionFirewall (0412f98f)RBAC role assignments
ContributorSubscriptionIdentity (ac212528)Terraform resource management — AD/identity resources
Key Vault AdministratorSubscriptionIdentity (ac212528)Key Vault management in identity sub
Resource Policy ContributorSubscriptionIdentity (ac212528)Azure Policy assignment
User Access AdministratorSubscriptionIdentity (ac212528)RBAC role assignments

Flagged: Contributor + User Access Administrator = Functional Owner

The combination of Contributor + User Access Administrator at subscription level is functionally equivalent to Owner in all four subscriptions where both are assigned. This is flagged per least privilege requirements.

Justification (from azure-infra CLAUDE.md): Terraform CI/CD requires Contributor to create and manage all resource types. User Access Administrator is required to assign managed identity RBAC roles (e.g., AcrPull, Key Vault Secrets User) via Terraform. Without UAA, role assignments would need to be pre-created out-of-band — a known Terraform limitation.

Flagged: Key Vault Administrator at Subscription Level

Key Vault Administrator grants full management plane access to all Key Vaults in a subscription. This is broader than necessary — typically only specific Key Vaults need management operations.

Proposed: Narrow Key Vault Administrator to specific Key Vault resources rather than subscription scope. This would require enumerating all KV management actions in Terraform.

Flagged: Resource Policy Contributor at Management Group Level

Resource Policy Contributor at the tenant management group allows assigning Azure Policies across all subscriptions. This is a very broad permission.

Justification: Required to assign HIPAA/HITRUST and ISO 27001 policies at management group scope via Terraform. There is no narrower built-in role.

Verdict: FLAGGED — Contributor + UAA = functional Owner across 4 subscriptions. Key Vault Administrator at subscription scope is broader than ideal. These are conscious tradeoffs for Terraform CI/CD. No immediate action — tracked for future hardening when custom role implementation is resourced.


LPRIV-009 — github-deploy-main AWS IAM

Identity: Per-account IAM roles assumed by GitHub Actions via OIDC from management account

Date audited: April 15, 2026

Role Structure

GitHub Actions assumes github-deploy-main in the management account (206820231356) via OIDC, then assumes per-account cross-account roles for operations in other accounts.

RoleAccountAccount IDPolicies
github-deploy-mainManagement206820231356AdministratorAccess (AWS managed)
github-deploy-prodProduction807267566999AdministratorAccess (AWS managed) + AllowDescribeImages (custom)
github-deploy-loggingLogging038901680748Custom scoped policies (see below)
github-deploy-firewallNetworking238342914131(see Terraform)
github-deploy-identityIdentity414134953818(see Terraform)
github-deploy-backupBackup863609217450(see Terraform)
github-deploy-devDev040067931468(see Terraform)

Flagged: AdministratorAccess on Management and Prod Accounts

AdministratorAccess grants Action: "*" and Resource: "*" — the broadest possible AWS policy.

json
{
  "Effect": "Allow",
  "Action": "*",
  "Resource": "*"
}

Flagged per LPRIV-009 requirements. Both github-deploy-main and github-deploy-prod use this policy.

Justification (from aws-infra Terraform — Checkov skip comment):Infrastructure deploy role requires AdministratorAccess for full IaC lifecycle management

The full IaC lifecycle (create, modify, delete any resource type) cannot easily be scoped without enumerating every action used by every Terraform resource. This is a conscious architectural decision.

Positive Finding: github-deploy-logging Uses Scoped Policies

The logging account deployment role (github-deploy-logging, internally org_access_role) uses custom purpose-built policies rather than AdministratorAccess:

  • GitHubDeployLoggingAccess-Firehose — Kinesis Firehose + CloudWatch Logs destination management
  • GitHubDeployLoggingAccess-Extra — additional logging-specific resource management
  • GitHubDeployLoggingAccess-ObjectLock — S3 Object Lock configuration for WORM compliance
  • Additional scoped policies per resource type

This pattern is the correct approach and should be adopted for other accounts over time.

Proposed Remediation Path

For accounts using AdministratorAccess, the logging account pattern should be the target state:

  1. Enable CloudTrail in the account to capture all API calls made by the deployment role
  2. Run 30-60 days of Terraform deployments to capture the full action surface
  3. Use IAM Access Advisor or CloudTrail analysis to enumerate exact actions used
  4. Build scoped policies per action group (EC2, RDS, IAM, S3, etc.)
  5. Replace AdministratorAccess with the scoped policy set

Effort: Large — significant engineering effort per account. Track as a separate story.

Verdict: FLAGGED — Action: "*" / Resource: "*" on management and prod accounts. github-deploy-logging is a positive exception demonstrating the right pattern. No immediate action — add to long-term hardening backlog.


Summary

StoryComponentFlagged ItemsAction
LPRIV-008github-deploy-app Azure RBACContributor + UAA = Owner (4 subs); KV Admin at sub scope; Resource Policy Contributor at tenantDocument and track — required for IaC
LPRIV-009github-deploy-* AWS IAMAdministratorAccess on main/prod accountsDocument and track — adopt logging account pattern per account

Document History

DateChangeAuthor
April 2026Initial audit — LPRIV-008 and LPRIV-009Kobe

Internal use only — Cirius Group