Wir betreiben eine Multi-Tenant-n8n-Bereitstellung auf AWS EKS — eine n8n-Instanz pro Kubernetes-Namespace, jeweils mit einer eigenen PostgreSQL-Datenbank, alle nutzen einen gemeinsamen S3-Bucket für die Speicherung von Binärdaten (Enterprise S3 externe Speicherfunktion).
Wir nutzen AWS Pod Identity mit Session-Tag ABAC, um die Pods jedes Mandanten an eine pro-Mandanten IAM-Rolle zu binden. Die beabsichtigte IAM-Ressourcen-ARN-Scoping lautet: arn:aws:s3:::our-shared-bucket/${aws:PrincipalTag/kubernetes-namespace}/*
Dies ist das von AWS empfohlene Muster für pro-Mandanten S3-Isolation in einem gemeinsamen Bucket. Es funktioniert nur, wenn die Schreibvorgänge jedes Mandanten unter einem mandantenspezifischen Schlüsselpräfix landen.
Derzeit schreibt n8n Binärdaten in S3 mit diesem Schlüsselformat: workflows/{workflowId}/executions/{executionId}/binary_data/{binaryFileId}
Da alle Schlüssel mit workflows/ beginnen, passt das ABAC-Ressourcen-Scoping zu keinem von ihnen, und jeder PutObject-Aufruf wird abgelehnt.
Wir würden gerne eine neue Umgebungsvariable — beispielsweise N8N_EXTERNAL_STORAGE_S3_BUCKET_PREFIX — haben, die vom Binärdaten-S3-Schlüssel-Builder beachtet wird, damit hochgeladene Schlüssel zu folgendem Format werden: /workflows//executions//binary_data/
Dies würde es jeder Mandanteninstanz ermöglichen, mit einem eindeutigen Präfix konfiguriert zu werden (z. B. dem Kubernetes-Namespace-Namen), was eine ordnungsgemäße ABAC-basierte Isolation in einem gemeinsamen Bucket ohne separate Buckets pro Mandanten ermöglicht.
@supera74 ur diagnosis is right — theres no env var for binary data S3 key prefix in current n8n core. the available external-storage env vars are HOST, BUCKET_NAME, BUCKET_REGION, ACCESS_KEY, ACCESS_SECRET, and AUTH_AUTO_DETECT. the workflows/{workflowId}/executions/{executionId}/binary_data/{binaryFileId} path is hardcoded in the binary data S3 manager.
immediate workaround if u can tolerate it — go bucket-per-tenant instead of shared bucket. set N8N_EXTERNAL_STORAGE_S3_BUCKET_NAME per pod from the namespace name (tenant-${KUBERNETES_NAMESPACE}-binary or similar). ur ABAC policy becomes:
trades bucket sprawl for working ABAC. cost-attribution actually gets easier too since per-tenant bucket = per-tenant CloudWatch metrics out of the box, and lifecycle policies / replication rules become per-tenant config instead of prefix-scoped.
if u absolutely cant move to bucket-per-tenant and need shared-bucket today, the only other working option is wrapping S3 writes through an S3 Object Lambda that rewrites the incoming key to inject the prefix server-side. adds latency to every binary write and is significantly more ops complexity than buckets-per-tenant tho.
for engineering teams that want it now — the binary data S3 client is a ~20-line change to honor a N8N_EXTERNAL_STORAGE_S3_BUCKET_PREFIX env var and prepend it in the key builder. could maintain a fork or submit upstream as a PR with this exact issue as the motivation, n8n usually merges narrow well-justified PRs from Enterprise users.
This is a real gap for Enterprise multi-tenant setups on EKS with shared S3. The Pod Identity ABAC approach you’ve described is exactly the AWS-recommended pattern - the problem is n8n hardcoding the key prefix breaks the IAM scoping entirely. A configurable N8N_BINARY_DATA_S3_KEY_PREFIX env var would solve this cleanly. Upvoted - this matters beyond just your setup, anyone running multiple n8n instances with shared S3 and IAM-based isolation hits this.
Quick note on the Object Lambda fallback though. I don’t think it actually works for this use case. Per the AWS docs, S3 Object Lambda only intercepts GET, LIST, and HEAD requests — “all other requests are processed as normal”, so PutObject passes straight through to the supporting access point untouched. There’s no write-side hook to rewrite the incoming key on.
On top of that, there is this:
As of November 7th, 2025, S3 Object Lambda is available only to existing customers that are currently using the service as well as to select AWS Partner Network (APN) partners.
This is a real gap for multi-tenant n8n on Kubernetes. The bucket-per-tenant approach works but adds operational overhead (more IAM roles, more bucket configs) compared to what should be a single env var. Worth a GitHub issue/PR - the change to honor N8N_EXTERNAL_STORAGE_S3_KEY_PREFIX sounds small enough to land.