DevSecOps

Spinnaker Deployment Security

Securing Spinnaker's multi-cloud deployment pipelines with authentication, authorization, pipeline constraints, and artifact verification.

Nayan Dey
DevSecOps Lead
5 min read

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.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.