Spinnaker is Netflix's open-source continuous delivery platform, designed for multi-cloud deployments at scale. It manages deployments to AWS, GCP, Azure, and Kubernetes from a single interface. That breadth of access makes security paramount — a misconfigured Spinnaker instance is a skeleton key to your entire cloud infrastructure.
This guide covers the security configurations necessary for production Spinnaker deployments.
Why Spinnaker Security Matters
Spinnaker's architecture includes several microservices, each with specific responsibilities:
- Gate: API gateway, the entry point for all user and API traffic.
- Orca: Orchestration engine that executes pipelines.
- Clouddriver: Interfaces with cloud providers (holds cloud credentials).
- Front50: Stores pipeline configurations, applications, and metadata.
- Fiat: Authorization service.
- Igor: Integrates with CI systems (Jenkins, Travis, etc.).
- Echo: Handles notifications and triggers.
Clouddriver holds credentials for every cloud account Spinnaker manages. Igor has access to your CI systems. Gate is internet-facing. Compromising any of these components gives an attacker significant leverage.
Authentication with Gate
Configure authentication on Gate using one of the supported providers:
OAuth 2.0 / OIDC
# gate-local.yml
security:
oauth2:
enabled: true
client:
clientId: spinnaker-gate
clientSecret: ${OAUTH_CLIENT_SECRET}
accessTokenUri: https://idp.example.com/oauth/token
userAuthorizationUri: https://idp.example.com/oauth/authorize
scope: openid profile email
resource:
userInfoUri: https://idp.example.com/userinfo
userInfoMapping:
email: email
firstName: given_name
lastName: family_name
SAML
security:
saml:
enabled: true
metadataUrl: https://idp.example.com/metadata
keyStore: /opt/spinnaker/keystore.jks
keyStorePassword: ${KEYSTORE_PASSWORD}
keyStoreAliasName: saml
issuerId: spinnaker
serviceAddress: https://spinnaker.example.com
Regardless of the provider:
- Disable anonymous access entirely.
- Enforce MFA at the identity provider level.
- Set session timeouts appropriate for your risk tolerance.
- Log all authentication events.
Authorization with Fiat
Fiat provides fine-grained authorization. Without it, any authenticated user can do anything. Enable Fiat and configure roles:
# fiat-local.yml
fiat:
enabled: true
auth:
groupMembership:
service: EXTERNAL
# Or GOOGLE, GITHUB, LDAP, FILE
Define service accounts for automated pipelines:
# Create a service account for CI triggers
curl -X POST \
-H "Content-Type: application/json" \
-d '{"name":"ci-trigger","memberOf":["deploy-dev"]}' \
https://spinnaker.example.com/serviceAccounts
Map roles to permissions at the application and account level:
- Application permissions: Control who can view, create, and execute pipelines for each application.
- Account permissions: Control who can deploy to which cloud accounts (dev, staging, production).
# Application permissions
{
"name": "my-app",
"permissions": {
"READ": ["dev-team", "security-team"],
"WRITE": ["dev-team"],
"EXECUTE": ["dev-team", "ci-trigger"]
}
}
Production accounts should only be writable by senior engineers and automated service accounts that have been reviewed.
Pipeline Security
Pipeline Templates
Use pipeline templates (Managed Pipeline Templates v2) to enforce standardized, security-reviewed pipeline stages:
{
"schema": "1",
"id": "secure-deploy-template",
"metadata": {
"name": "Secure Deployment Pipeline",
"description": "Standard deployment pipeline with required security stages"
},
"pipeline": {
"stages": [
{
"type": "findImage",
"name": "Find Approved Image"
},
{
"type": "manualJudgment",
"name": "Security Review",
"requisiteStageRefIds": ["findImage"]
},
{
"type": "deploy",
"name": "Deploy to Production",
"requisiteStageRefIds": ["securityReview"]
}
]
}
}
Templates ensure that every deployment pipeline includes mandatory stages like security scanning, manual approval, or canary analysis.
Pipeline Constraints
Add constraints to prevent pipelines from running under unexpected conditions:
- Restricted execution windows: Production deployments only during business hours.
- Manual judgment stages: Require human approval before production deployments.
- Pipeline expressions: Validate conditions before proceeding.
{
"type": "checkPreconditions",
"name": "Verify Security Scan Passed",
"preconditions": [
{
"type": "expression",
"context": {
"expression": "${trigger.buildInfo.scans.passed == true}"
}
}
]
}
Artifact Constraints
Configure Spinnaker to only deploy artifacts that meet specific criteria:
- Artifacts must come from approved registries.
- Container images must have specific labels or tags.
- Artifacts must have been produced by a trusted CI pipeline.
Cloud Account Security
Spinnaker needs credentials for every cloud account it manages. Minimize the blast radius:
- Use separate IAM roles per cloud account with least-privilege permissions.
- For AWS, use AssumeRole from a central Spinnaker role rather than storing individual account credentials.
- For Kubernetes, use kubeconfig with token-based authentication and short TTLs.
- Rotate cloud credentials on a schedule.
- Audit which pipelines deploy to which accounts.
# clouddriver-local.yml
kubernetes:
accounts:
- name: production
kubeconfigFile: /opt/spinnaker/kubeconfig-production
namespaces:
- production
omitNamespaces:
- kube-system
permissions:
READ:
- ops-team
- security-team
WRITE:
- ops-team
The namespaces and omitNamespaces fields restrict which namespaces Spinnaker can see and deploy to. Never give Spinnaker access to kube-system or other infrastructure namespaces.
Network Architecture
Spinnaker's microservices communicate over HTTP by default. In production:
- Enable TLS between all Spinnaker microservices.
- Put Gate behind a load balancer with TLS termination and WAF rules.
- Restrict network access to Clouddriver — it holds cloud credentials and should only be accessible from other Spinnaker services.
- Igor communicates with external CI systems — restrict its outbound access to specific CI endpoints.
Monitoring and Audit
Spinnaker generates extensive logs across its microservices. Centralize them:
- Gate logs: Authentication attempts, API calls, authorization decisions.
- Orca logs: Pipeline execution details, stage outcomes.
- Fiat logs: Authorization evaluations, role changes.
- Echo logs: Trigger events, notification deliveries.
Create alerts for:
- Failed authentication attempts.
- Pipeline executions by service accounts outside normal patterns.
- Deployments to production accounts.
- Changes to application permissions.
- New service account creation.
How Safeguard.sh Helps
Safeguard.sh provides centralized security monitoring across Spinnaker and the cloud accounts it manages. It audits Spinnaker's configuration for overly permissive accounts, missing authorization rules, and pipelines that skip security stages. By correlating Spinnaker deployment data with vulnerability and SBOM information, Safeguard.sh gives your security team a complete picture of what is deployed where, whether it passed security checks, and what risks it carries — across every cloud account and Kubernetes cluster in your Spinnaker infrastructure.