Join our Newsletter — 33% off our NHI Course
Home› Guides› Spinnaker Security: Configure Fiat, Cloud Accounts and Pipeline…
Guide Software & AI Supply Chain

Spinnaker Security: Configure Fiat, Cloud Accounts and Pipeline Permissions

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 8 November 2026 12 min read
On this page

Spinnaker holds deployment rights in every cloud account and Kubernetes cluster it manages, so whoever can run a pipeline or reach its internal services can change production. This guide covers the customer side of securing a self-managed Spinnaker installation: authentication at Gate, authorisation with the Fiat service, account and application permissions, Fiat service accounts and managed service accounts for triggered pipelines, the cloud and Kubernetes credentials held by Clouddriver, TLS and logging. It is written for platform and release engineering teams and the security reviewers who sign off continuous delivery. For controls common to every delivery platform, see the CI/CD Security Guide and the GitOps Security Guide.

This is an independent guide from NHI Mgmt Group, based on Spinnaker's public documentation as of November 2026. It is not sponsored or reviewed by the Spinnaker project. Product features change, so confirm settings against Spinnaker's current documentation for the version you run.

Key takeaways

  • Turn on Fiat, then define permissions everywhere. Fiat is off by default and, once on, resources with no permissions block stay unrestricted, so add READ and WRITE roles to every account and READ, WRITE and EXECUTE roles to every application.
  • Expose only Gate and Deck. Gate (port 8084) is the API entry point and Deck (port 9000) the UI; Orca, Clouddriver, Front50, Fiat and the other services belong on a private network.
  • Use managed service accounts for triggers. Pipeline permissions create a Fiat service account per pipeline from the roles the author holds, and only users with all those roles can then edit the pipeline.
  • Scope Clouddriver's cloud credentials. Prefer node or pod roles over IAM users, narrow the managed-account role beyond the documented starting point, and restrict Kubernetes accounts to named namespaces with Roles rather than cluster-admin.
  • Keep the admin role small. Members of fiat.admin.roles bypass almost all READ and WRITE restrictions; the docs themselves advise caution.

How identity and access work in Spinnaker

Spinnaker is a set of microservices. Deck is the browser UI and Gate is the API gateway that the UI and API callers talk to. Behind Gate, Orca orchestrates pipelines, Clouddriver makes mutating calls to cloud providers, Front50 stores application and pipeline metadata, Igor and Echo handle CI triggers, events and webhooks, Rosco bakes images, and Fiat makes authorisation decisions. Spinnaker integrates with your existing identity systems rather than running its own login.

LayerComponentOptions in the docsCustomer action
AuthenticationGateOAuth 2.0 (including Azure, G Suite, GitHub Organizations and Oracle Cloud), SAML 2.0, LDAP, X.509 client certificatesUse your corporate IdP with MFA for people; X.509 or an IdP-issued identity for API automation
Role resolutionFiat role providersYAML file, GitHub Teams, Google Groups, LDAP, SAML or OIDC groups (EXTERNAL roles fixed at login)Map roles to groups owned by your IdP, not a hand-edited file
AuthorisationFiatAccount READ and WRITE; application READ, WRITE and EXECUTEEnable Fiat and set permissions on every account and application
Automation identityFiat service accounts and managed service accountsRun As User, or roles on the pipeline triggerManaged service accounts per pipeline
Cloud identityClouddriver and RoscoAssumed roles in managed AWS accounts, kubeconfig per Kubernetes accountWorkload identity, narrow roles, per-account scoping

Fiat grants permissions to roles, never directly to users. Its documented model is an approve list that is open by default, so a resource with no access definition is available to everyone who can log in. Restricted applications disappear from the applications list and direct navigation returns 403 Forbidden.

Admin roles and privileged access

Account and application permissions

The authorisation docs give concrete examples of what each permission allows: deleting a load balancer needs WRITE on the account; updating a pipeline needs WRITE on the application; running a pipeline needs only EXECUTE on the application; and running an application's pipeline that deploys to another account needs EXECUTE on the application and WRITE on the target account.

ResourcePermissionAllowsNotes
AccountREADView cloud resources in the accountWRITE does not imply READ; grant both together
AccountWRITEChange resources, deploy into the accountReserve production accounts for release roles
ApplicationREADView the application and its pipelinesBy default READ also grants EXECUTE
ApplicationEXECUTERun pipelinesSet fiat.executeFallback: 'WRITE' in fiat-local.yml so READ no longer grants EXECUTE
ApplicationWRITEEdit pipelines and application settingsPipeline editors control what runs with the pipeline's identity

Our recommendation at NHI Mgmt Group: set fiat.executeFallback to WRITE so viewing an application never implies the right to deploy it, and give production account WRITE only to the roles behind managed service accounts and a small release group.

Administrators

The admin page describes a role listed under fiat.admin.roles in fiat-local.yml (devops-admin in the example) whose members are freed from virtually all READ and WRITE restrictions, with a warning to proceed with caution. Keep this role mapped to a small IdP group with MFA, review membership quarterly and log its use. Separately, anyone with write access to the Spinnaker configuration (for example the *-local.yml files, the Kubernetes namespace that runs Spinnaker, or the Front50 storage bucket) can change authorisation itself, so treat those as administrative too.

Internal services

The docs describe Gate as the point where the UI and API callers enter, and user authentication is configured there. Design on the basis that Orca, Clouddriver, Front50 and Fiat should only ever be called by other Spinnaker services. Run them on a private network, use Kubernetes NetworkPolicy so only expected services can reach each port (for example Fiat on 7003 and Clouddriver on 7002), and expose only Gate and Deck through your ingress. The Fiat and Front50 service account endpoints used below are administrative APIs: keep them off any public listener.

Integrations, API tokens and service accounts

Triggered pipelines

Automated triggers (CI jobs, webhooks, schedules) run without a human session, so they need an identity to pass Fiat checks. Spinnaker documents two models.

  • Fiat service accounts: permission abstractions, not authenticated accounts. An administrator creates one with a POST to Front50's /serviceAccounts endpoint containing a name and memberOf roles, then runs a Fiat sync (POST to /roles/sync). In the trigger, Run As User lists the service accounts a user may use. A user can assign one only if they hold every role it has, and the service account needs EXECUTE on the application. At run time the normal account and application checks apply.
  • Managed service accounts (pipeline permissions): enabled with tasks.useManagedServiceAccounts: true in orca-local.yml and window.spinnakerSettings.feature.managedServiceAccounts = true in Deck's settings-local.js. The author selects roles they hold in the trigger's permissions, and a service account is created for that pipeline. After that only users holding all the selected roles can edit it. tasks.useSharedManagedServiceAccounts: true creates one account per unique role set, and migrations.migrateToManagedServiceAccounts: true in front50-local.yml migrates existing Run As User triggers.

The docs recommend pipeline permissions for most users. Plan the migration: when several triggers use different Run As User values, the managed account receives the combined roles, which can stop some users editing the pipeline. Pilot on a few applications first and keep the previous trigger JSON for rollback.

AWS accounts

The AWS EC2 provider docs describe a managing account where Spinnaker runs, with a spinnaker role that holds ec2:DescribeAvailabilityZones, ec2:DescribeRegions and sts:AssumeRole, and a spinnakerManaged role in each target account that trusts it. In Clouddriver configuration each aws.accounts entry sets assumeRole: role/spinnakerManaged, accountId, regions and a permissions block with READ and WRITE groups. The docs recommend IAM roles over IAM users with access keys, and node or pod roles (with pod identity or IRSA for advanced setups) for Spinnaker itself.

  • Narrow the assume scope: the documented starting policy allows sts:AssumeRole on any resource; list the specific spinnakerManaged role ARNs instead.
  • Narrow the managed role: the documented example attaches PowerUserAccess plus an inline PassRole-and-Certificates policy granting iam:PassRole and iam:ListServerCertificates. Replace these with the actions your deployments use, and restrict iam:PassRole to the instance roles you deploy with.
  • Separate baking: the docs suggest scoping the Packer bake permissions to Rosco through service accounts or IRSA, rather than adding them to the main role.
  • Permissions on every account: add a permissions block to each account entry so Fiat restricts who can deploy there.

See the Workload Identity Federation Guide for removing static keys.

Kubernetes accounts

Each Kubernetes account maps to a kubeconfig that the docs describe as acting like a private key for the cluster. The example creates spinnaker-service-account in the spinnaker namespace and binds it to cluster-admin, noting that more restrictive roles can be applied, and shows a spinnaker-role ClusterRole as an alternative. Setting the namespaces option limits an account to named namespaces, in which case use a Role and RoleBinding in each managed namespace. The documented role includes read on secrets, so scope it carefully. Our recommendation: one Spinnaker account per cluster and environment, restricted to named namespaces, with its kubeconfig stored as a Kubernetes secret readable only by Clouddriver. See the Kubernetes RBAC Guide.

TLS

The SSL docs cover enabling TLS on Gate in gate-local.yml (server.ssl.enabled: true with a PKCS12 key store) and on Deck through an Apache virtual host on port 9000 with SSLEngine on, or terminating TLS at a load balancer with gateHost, deck.baseUrl and Tomcat proxy header settings. Use certificates from your internal CA or a public CA rather than the self-signed example in production.

Logging and detection

SourceWhat to watchWhy
Gate and IdP logsLogins, failed logins, admin role sessions, API calls from automation identitiesAccount takeover and misuse of automation
Front50 and FiatCreation or deletion of service accounts, changes to application permissions, pipeline edits that change triggers or rolesPrivilege changes inside Spinnaker
Orca execution historyPipelines run outside change windows, manual runs of production pipelines, pipelines that deploy to unexpected accountsUnauthorised deployment
Cloud audit logsAssumeRole into spinnakerManaged from anything other than the spinnaker role; IAM and PassRole useCredential misuse outside Spinnaker (ATT&CK T1078.004)
Kubernetes audit logsRequests from spinnaker-service-account outside managed namespaces; secret readsScope creep and credential harvesting
NetworkConnections to internal service ports from outside the Spinnaker namespaceTraffic that did not pass through Gate

Metrics that show it is working:

  • Percentage of accounts and applications with an explicit permissions block (target 100 per cent).
  • Percentage of triggered pipelines using managed service accounts.
  • Number of members in fiat.admin.roles, reviewed quarterly.
  • Number of long-lived cloud keys used by Spinnaker components (target zero).
  • Kubernetes accounts bound to cluster-admin (target zero).

Hardening baseline

  1. Inventory: list every Spinnaker account, its credential type and target, every application and its permissions, and every trigger and its identity. Apply Spinnaker releases promptly and follow the project's release notes.
  2. Authenticate at Gate with SAML or OAuth 2.0 against your IdP, with MFA, and enable TLS on Gate and Deck.
  3. Enable Fiat with an IdP-backed role provider, in a staging installation first, then add permissions to every account and application before production cut-over.
  4. Set fiat.executeFallback to WRITE and review who holds EXECUTE on production applications.
  5. Move triggers to managed service accounts and retire broad manual service accounts.
  6. Narrow cloud credentials: pod or node roles, specific AssumeRole targets, least-privilege managed roles, namespace-scoped Kubernetes accounts.
  7. Isolate internal services with NetworkPolicy and private networking.
  8. Roll back safely: keep previous *-local.yml files and account definitions in version control so an authorisation change that blocks deployments can be reverted quickly.

Common misconfigurations

  • Fiat enabled but permissions left empty. Because unrestricted is the default for undefined resources, every logged-in user can still deploy to accounts without a permissions block.
  • READ implying EXECUTE. With the default fallback, anyone who can view an application can run its pipelines.
  • Broad Run As User accounts. A single service account with production roles reused across many pipelines spreads deployment rights widely.
  • Starter cloud roles kept in production. PowerUserAccess and AssumeRole on any resource were documented to get started; replace them with scoped policies.
  • Cluster-admin kubeconfigs. The example binding is convenient but gives Spinnaker, and anyone who can deploy through it, full control of the cluster.
  • Internal services reachable. Orca, Clouddriver and Front50 are meant to sit behind Gate; keep them off public listeners so every user request passes through Gate.

Framework mapping

Control areaNIST SP 800-53 Rev 5NIST CSF 2.0ISO/IEC 27001:2022 Annex A
Fiat roles, admin role and least privilegeAC-6PR.AA-05A.8.2 Privileged access rights
Cloud and Kubernetes credentialsIA-5PR.AA-05A.5.17 Authentication information
Pipeline and platform configurationCM-6PR.PS-01A.8.9 Configuration management
Deployment logging and reviewAU-2, AU-6DE.CM-09A.8.15 Logging

See the OWASP CI/CD Top 10 CICD-SEC-5 Insufficient PBAC Guide for pipeline-based access controls across platforms.

Practitioner checklist

  • Authenticate at Gate with your IdP and MFA; enable TLS on Gate and Deck.
  • Enable Fiat with an IdP-backed role provider.
  • Add READ and WRITE to every account and READ, WRITE and EXECUTE to every application.
  • Set fiat.executeFallback to WRITE.
  • Keep fiat.admin.roles to a small, reviewed group.
  • Use managed service accounts for triggered pipelines.
  • Run Spinnaker on node or pod roles and scope AssumeRole and managed roles to what deployments use.
  • Restrict Kubernetes accounts to named namespaces with Roles.
  • Keep internal services on a private network behind NetworkPolicy.
  • Alert on service account changes, permission changes and AssumeRole from unexpected principals.

Standards and references

Related NHI Mgmt Group resources: CI/CD Pipeline Identity Security Guide · Software Supply Chain Security Guide · Kubernetes NHI Security Guide · Secrets Management Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 8 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org