Elevating CI/CD Pipeline Security: Zero Trust Authentication
Why Secure CI/CD Pipelines? Addressing Modern Threats
Today’s engineering teams rely heavily on automated CI/CD pipelines to deliver, test, and deploy software at scale. These pipelines—whether orchestrating updates to cloud infrastructure or managing sensitive credentials—frequently require access to privileged systems. Providing this access introduces several critical security challenges:
- Credential Leakage: Static secrets and long-lived tokens are vulnerable to accidental exposure or theft, increasing the risk of unauthorized entry.
- Insider Threats and Lateral Movement: Compromised service accounts and poorly scoped identities are attractive targets for attackers seeking to move deeper into a network.
- Operational Complexity: Manually rotating secrets or configuring granular permissions for every repository does not scale, especially in larger organizations.
Given these challenges, it’s vital to adopt an authentication model that not only limits risk but can be managed efficiently as your organization grows.
Traditional CI/CD Authentication: Where It Falls Short
Historically, CI/CD systems—including GitHub Actions running on Kubernetes—have authenticated using static credentials or shared secrets. These mechanisms fall short in terms of security and scalability, especially when dealing with two primary categories of target systems:
- HashiCorp Vault for secrets management (database credentials, API keys, encryption keys)
- Cloud Providers for infrastructure operations (KMS, storage buckets, container registries)
Limitations of Secrets-Based Authentication
- Static secrets require manual rotation and careful distribution—mistakes are costly.
- Revocation is slow; if a credential is exposed, it may remain valid for hours, days, or longer.
- Identity is often coarse-grained, tied to broad service accounts or repository configurations.
- Auditing and compliance are limited—hard to know which workflow triggered access.
Solution Landscape: Evaluating Authentication Models
There are a variety of approaches to authenticating CI/CD pipelines. The table below summarizes several solutions and how they address the security and operational challenges highlighted above:
| Solution | Token Lifetime | Per-Workflow Identity | Automatic Rotation | Scalability |
|---|---|---|---|---|
| Static Secrets in Code | Permanent | No | No | Poor |
| GitHub Repository Secrets | 30-90 days | No | No | Medium |
| LDAP Auth via Secrets | 1 hour | No | Partial | Medium |
| Kubernetes Workload Identity | 1 hour | Namespace-level | Yes | Low (coarse-grained) |
| GitHub OIDC Native | 15 minutes | Repository-level | Yes | Medium (manual per-repo) |
| SPIRE + Custom Attestor | 30 minutes | Dynamic | Yes | High (team-based) |
- Static Secrets in Code are easy to implement but pose the greatest security risk, as credentials rarely change and can be inadvertently exposed.
- GitHub Repository Secrets improve security by supporting rotation and separation from code, but still require manual updates and do not scale well with large repository counts.
- LDAP Authentication via Secrets and Kubernetes Workload Identity provide more granular access but can become operationally complex and often rely on static secrets or role assignments that must be manually configured.
- GitHub OIDC Native introduces short-lived tokens and automated identity issuance. These tokens are tied to repository executions and can be automatically rotated. However, they require per-repository integration with systems like Vault, which can lead to operational overhead for large organizations.
- SPIRE with a Custom Attestor shifts authentication to dynamic, context-driven identity that is mapped at the team level and issued per workflow. This model achieves the strongest security guarantees and minimal operational burden; adding repositories simply involves updating team mapping, not reconfiguring secrets or roles.
Recommendations: Select the Approach That Matches Your Scale and Risk Profile
While our SPIRE-based implementation offers the highest level of automation, scalability, and security, it involves additional infrastructure and development effort that may not be justified for smaller organizations or teams with simple requirements. For most use cases, leveraging native solutions such as GitHub OIDC provides a significant security improvement over static secrets, supports automated rotation, and requires less custom engineering.
We strongly recommend starting with native cloud or platform authentication methods, which deliver robust identity, scalability, and ease of operational management out of the box. If your requirements exceed what native integrations offer (for example, if you need cross-platform workload attestation, team-level abstraction, or highly granular audit trails), then consider investing in advanced architectures such as SPIRE with custom attestation plugins.
Why Zero Trust? Shifting to Attestation-Based Identity
Zero Trust security asserts that no workload, system, or user should be trusted implicitly. Instead, each must continually prove its identity and context before receiving access—replacing “what you know” (secrets) with “what you are” (attested identity):
- Dynamic Identity: Each workflow receives a unique, short-lived identity computed from its environment and context.
- Instant Revocation: Credentials expire quickly; compromised identities cannot be reused.
- Auditability and Scalability: Fine-grained identities are mapped at the team level, eliminating manual effort as repositories grow.
Enter SPIFFE and SPIRE: Authentication Without Secrets
SPIFFE (Secure Production Identity Framework For Everyone) is an open standard for federated workload identity. Its reference implementation, SPIRE (SPIFFE Runtime Environment), delivers key benefits:
- Node and Workload Attestation: Proves not just where code is running, but also what it is.
- Cryptographic Identity Issuance: Workloads get verifiable identities (JWT-SVIDs) without storing long-lived secrets.
- Automatic Rotation & Revocation: Credentials are refreshed and invalidated automatically.
- Defense-in-Depth: Multiple selectors (Kubernetes, GitHub OIDC, team mapping) ensure only legitimate workflows receive sensitive access.
Our SPIRE-Based Solution: Dynamic GitHub Actions Attestation
We implemented a custom workload attestor plugin for SPIRE, combining GitHub Actions OIDC context with Kubernetes selectors. Here’s how it works:
1. Detect GitHub Actions Context in the Container
// Check for GitHub Actions execution
if env["GITHUB_ACTIONS"] != "true" {
return nil
}
// Extract OIDC token metadata
oidcURL := env["ACTIONS_ID_TOKEN_REQUEST_URL"]
requestToken := env["ACTIONS_ID_TOKEN_REQUEST_TOKEN"]
2. Fetch the GitHub OIDC Token
Pulls a signed JWT containing workflow metadata:
{
"repository": "devops/infrastructure",
"actor": "john-doe",
"workflow": "Deploy Production",
"ref": "refs/heads/main"
}
3. Map Repository to Team Identity
Configurable YAML mappings centralize identities:
team_mapping:
'devops/*': 'devops-team'
'platform/*': 'platform-team'
4. Combined Attestation with SPIRE
SPIRE issues identity only when both Kubernetes and GitHub selectors match:
Kubernetes Selectors:
k8s:ns:arc-runners
k8s:sa:arc-runners
GitHub Selectors:
github:repo:devops/infrastructure
github:actor:john-doe
github:team:devops-team
5. Team-Based Cluster Registration
A single entry covers all team repositories—no per-repo registration:
apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterStaticEntry
metadata:
name: github-actions-devops-team
spec:
spiffeID: 'spiffe://example.com/github-actions/devops-team'
selectors:
- 'k8s:ns:arc-runners'
- 'github:team:devops-team'
Add a repository? Just update the team mapping.
Integrating Target Systems
HashiCorp Vault
SPIRE’s OIDC discovery provider is trusted by Vault, enabling team-level authentication:
# Point Vault to SPIRE for identity validation
vault write auth/jwt/config \
jwks_url="https://spire-oidc.example.com/keys" \
bound_issuer="https://spire-oidc.example.com"
# Single role per team
vault write auth/jwt/role/github-actions-devops \
bound_subject="spiffe://example.com/github-actions/devops-team" \
token_policies="devops-secrets-policy"
Secure Workflow Usage
# Request team identity from SPIRE
JWT=$(spire-agent api fetch jwt \
-socketPath /spiffe-workload-api/agent.sock \
-audience vault)
# Authenticate to Vault with the team role
VAULT_TOKEN=$(curl -s -X POST \
-d "{\"role\":\"github-actions-devops\",\"jwt\":\"$JWT\"}" \
$VAULT_ADDR/v1/auth/jwt/login | jq -r '.auth.client_token')
# Access secrets as needed
curl -H "X-Vault-Token: $VAULT_TOKEN" \
$VAULT_ADDR/v1/secret/data/production/database
Cloud Provider Integration (GCP)
Configure Workload Identity Federation to accept SPIRE-issued JWTs, eliminating the need for static service account keys in cloud-native workflows.
Practical Considerations for Adoption
- Development Effort: Building the custom workload attestor took roughly 2-3 weeks including testing and validation.
- Infrastructure Needs: Requires deploying SPIRE server, agents, SPIFFE CSI driver, and OIDC provider within your cluster.
- Migration Path: Run SPIRE alongside legacy secrets; migrate teams incrementally; deprecate static credentials only after validation.
Key Takeaways
- Credential Lifetimes Matter: Short-lived, auto-rotated identity tokens narrow attackers’ exploitation window.
- Identity Should Be Computed, Not Stored: Platform-derived secrets are non-exportable, dramatically reducing reuse risk.
- Defense in Depth: Multi-dimensional attestations (Kubernetes, workflow context, team mapping) foil impersonation.
- Scale Through Abstraction: Team-based configuration saves hours of manual role creation as workloads grow.
- Audit Everything: Central logging of every authentication cycle empowers compliance and incident response.
Conclusion
Transitioning from static secrets to dynamic, context-driven attestation is more than an enhancement—it’s an imperative for resilient CI/CD security. With SPIRE, custom workload attestation for GitHub Actions empowers organizations to:
- Eliminate static credentials
- Scale authentication as repositories and teams grow
- Achieve compliance through deep audit trails
- Minimize operational burden
- Enable instant revocation and rapid response
For modern engineering teams, Zero Trust authentication isn’t just an option—it’s the future-ready standard.
Technologies Mentioned:
- SPIFFE/SPIRE — Zero Trust workload identity
- HashiCorp Vault — Secure secrets management
- GitHub Actions OIDC
- GCP Workload Identity Federation
Further Reading:
Comments