Skip to content

[User Story] OIDC-Based Identity Federation #164

@noahwhite

Description

@noahwhite

Story Summary

As an Infrastructure Engineer, I want to federate GitHub Actions with Aembit using OIDC, so that I can generate short-lived enrollment tokens for Flatcar nodes without storing a master Aembit key in GitHub secrets.

Phase: 1 - Identity & Provisioning (The "Secret Zero" Solution)


✅ Acceptance Criteria

  • GitHub Action can successfully exchange its OIDC token for an Aembit Enrollment Token
  • Aembit policy restricts token generation to main or develop branch of ghost-stack repository
  • Environment-specific policies (dev/stage/prod) based on OIDC claims
  • All Aembit configuration managed via OpenTofu using aembit/aembit provider
  • Documentation for OIDC trust and policy architecture

📝 Additional Context

Architecture

GitHub Actions Workflow (tofu apply)
    │
    ├─► Request OIDC token from GitHub
    │   Claims: repository, environment, ref, job_workflow_ref
    │
    ▼
Aembit Cloud
    │
    ├─► Trust Provider validates GitHub OIDC token
    │   - Issuer: https://token.actions.githubusercontent.com
    │   - Repository: noahwhite/ghost-stack
    │   - Ref: refs/heads/main OR refs/heads/develop
    │
    ├─► Access Policy evaluates environment
    │   - dev: environment:dev OR ref:develop
    │   - stage: environment:staging OR ref:staging  
    │   - prod: environment:production OR ref:main
    │
    └─► Returns short-lived Enrollment Token
        (scoped to specific environment)

OpenTofu Resources

provider "aembit" {
  # Authenticates via GitHub OIDC - no stored credentials
}

resource "aembit_trust_provider" "github_actions" {
  name = "GitHub Actions"
  type = "github_action_id_token"
  
  github_action {
    issuer     = "https://token.actions.githubusercontent.com"
    repository = "noahwhite/ghost-stack"
    # Restrict to main/develop branches
  }
}

resource "aembit_client_workload" "ghost" {
  for_each = toset(["dev", "stage", "prod"])
  name     = "ghost-${each.key}"
  # Match rules based on environment/ref claims
}

resource "aembit_access_policy" "enrollment" {
  for_each = toset(["dev", "stage", "prod"])
  # Allows enrollment token generation for matching workload
}

Security Benefits

  • No static credentials - GitHub OIDC token is short-lived, generated per workflow run
  • Branch restrictions - Only main/develop can generate tokens
  • Environment isolation - Each environment has separate policies
  • Audit trail - All token generation logged in Aembit

📦 Definition of Ready

  • Acceptance criteria defined
  • No unresolved external dependencies
  • Story is estimated
  • Team has necessary skills and access
  • Priority is clear
  • Business value understood

✅ Definition of Done

  • All acceptance criteria met
  • Aembit provider added to OpenTofu configuration
  • GitHub Actions workflow can authenticate via OIDC
  • Enrollment token generation tested for dev environment
  • Policy restrictions verified (wrong branch = denied)
  • Documentation updated

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions