Multi-Team Quickstart
One Sirr instance, two isolated teams. Each org has its own principals and secrets — no cross-contamination. The master key can audit everything from a single view.
You need a running Sirr instance with the master key. If you have not installed Sirr yet, start with the Solo Dev Quickstart.
Create two orgs
Create an org for each team. The master key can create orgs; only org admins can manage secrets within their org.
Create platform-team org
export SIRR_SERVER=http://localhost:39999
curl -X POST $SIRR_SERVER/orgs \
-H "Authorization: Bearer $SIRR_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "platform-team"}'
# Save:
export PLATFORM_ORG=org_platform_xxxx
Create product-team org
curl -X POST $SIRR_SERVER/orgs \
-H "Authorization: Bearer $SIRR_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "product-team"}'
export PRODUCT_ORG=org_product_yyyy
Set up each team
Create an admin principal in each org. This principal manages the org's secrets and invites other members.
Create platform-team admin
curl -X POST $SIRR_SERVER/orgs/$PLATFORM_ORG/principals \
-H "Authorization: Bearer $SIRR_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "platform-admin", "role": "admin"}'
# Create a key for this principal
curl -X POST $SIRR_SERVER/orgs/$PLATFORM_ORG/principals/<platform-admin-id>/keys \
-H "Authorization: Bearer $SIRR_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "platform-admin-key"}'
export PLATFORM_ADMIN_KEY=sirr_pk_platform_XXXX
Create product-team admin
curl -X POST $SIRR_SERVER/orgs/$PRODUCT_ORG/principals \
-H "Authorization: Bearer $SIRR_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "product-admin", "role": "admin"}'
curl -X POST $SIRR_SERVER/orgs/$PRODUCT_ORG/principals/<product-admin-id>/keys \
-H "Authorization: Bearer $SIRR_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "product-admin-key"}'
export PRODUCT_ADMIN_KEY=sirr_pk_product_YYYY
Push team-scoped secrets
Each team pushes secrets into their own org. Principals from platform-team cannot see product-team secrets and vice versa — isolation is enforced at the org boundary.
platform-team pushes infra secrets
# Platform team stores their Terraform cloud token
curl -X POST $SIRR_SERVER/orgs/$PLATFORM_ORG/secrets \
-H "Authorization: Bearer $PLATFORM_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"key": "infra/TF_CLOUD_TOKEN",
"value": "tfc-XXXXXXXXXXXXXXXXXXXXXXXX",
"delete": false
}'
# Platform team stores their registry credentials
curl -X POST $SIRR_SERVER/orgs/$PLATFORM_ORG/secrets \
-H "Authorization: Bearer $PLATFORM_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"key": "infra/REGISTRY_PASS",
"value": "my-registry-password",
"delete": false
}'
product-team pushes app secrets
# Product team stores their Stripe key
curl -X POST $SIRR_SERVER/orgs/$PRODUCT_ORG/secrets \
-H "Authorization: Bearer $PRODUCT_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"key": "app/STRIPE_SECRET_KEY",
"value": "your-stripe-secret-key",
"max_reads": 10,
"delete": false
}'
# Product team stores their Datadog API key
curl -X POST $SIRR_SERVER/orgs/$PRODUCT_ORG/secrets \
-H "Authorization: Bearer $PRODUCT_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"key": "app/DATADOG_API_KEY",
"value": "dda-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"delete": false
}'
Confirm isolation — platform admin cannot see product secrets:
Isolation check
curl $SIRR_SERVER/orgs/$PRODUCT_ORG/secrets/app/STRIPE_SECRET_KEY \
-H "Authorization: Bearer $PLATFORM_ADMIN_KEY"
# → 403 Forbidden (different org)
Query the audit log
The master key can query audit logs for any org. This gives you a unified compliance view across the entire instance.
Audit all reads in platform-team (last 24h)
curl "$SIRR_SERVER/orgs/$PLATFORM_ORG/audit?action=secret.read&since=$(date -d '24 hours ago' +%s)" \
-H "Authorization: Bearer $SIRR_MASTER_KEY"
Audit all secret operations in product-team
curl "$SIRR_SERVER/orgs/$PRODUCT_ORG/audit?limit=100" \
-H "Authorization: Bearer $SIRR_MASTER_KEY"
Example audit entry
{
"entries": [
{
"id": "01HX...",
"action": "secret.read",
"key": "app/STRIPE_SECRET_KEY",
"principal": "product-admin",
"timestamp": 1700003600,
"metadata": {
"read_count": 1,
"max_reads": 10
}
}
]
}
Audit entries never contain secret values — only metadata about who accessed what and when. Use action=secret.read filters during incident response to trace which principal read a compromised key.
Each team can also query their own org's audit log using their admin principal key — they only see their org.
product-team self-audits (only sees their org)
curl "$SIRR_SERVER/orgs/$PRODUCT_ORG/audit" \
-H "Authorization: Bearer $PRODUCT_ADMIN_KEY"
What is next
- Audit Logs — full filter reference (by action, key prefix, time range)
- API Keys — scoped API keys with prefix restrictions within an org
- Webhooks — receive real-time events when secrets are read or burned
- Self-Hosting — production deployment with TLS, backups, and monitoring