Skip to main content

Security

No local passwords​

Authentication is entirely delegated to your OIDC provider — see OIDC setup.

Access control​

Orbit has no authorization model. Every user who completes the OIDC flow gets the same, full access. There is no admin tier, no read-only tier, and no per-user or per-group restriction inside the application.

Two consequences worth being deliberate about:

  • Connection profiles are per-user. Users cannot see each other's storage endpoints or credentials, and the stored secret is never returned by the API.
  • Branding settings are global. The application name, logo and accent are shared, and any signed-in user can change them.

So "who may use this console" is a question you answer at your identity provider, not here. Restrict the client to a group or role rather than leaving it open to everyone in the realm, tenant or directory — the application will admit whoever the provider lets through. The provider sections in OIDC setup note where that setting lives for Keycloak, Entra ID and Google.

Encryption at rest​

Profile secret access keys are AES-256-GCM encrypted with ENCRYPTION_KEY before being stored; access key IDs (not the secret) are stored in plaintext since they're identifiers, not secrets. Secrets are write-only through the API — no response ever returns a stored secret.

ENCRYPTION_KEY must be a 32-byte key, either 64 hex characters or base64. Generate one with:

openssl rand -hex 32

Back it up. There is no way to recover encrypted secrets without it.

When running the Helm chart without supplying encryption.key or encryption.existingSecret, the chart generates a key on first install, stores it in the release Secret, and reuses it on upgrades (it's read back from the cluster rather than regenerated). This generated key is still your responsibility to back up — see Kubernetes for the rename-related caveat about carrying it forward into a fresh install.

Encryption key rotation​

Changing ENCRYPTION_KEY — deliberately or by losing the original — makes every previously-stored connection profile secret undecryptable. Affected profiles start returning a PROFILE_SECRET_INVALID error and the UI prompts for the secret to be re-entered. There is no automatic re-encryption or migration path: users must re-enter their storage credentials for every affected profile.

Treat this key as long-lived and back it up alongside your database.

Verify-TLS toggle​

Each connection profile has a "verify TLS" switch. On (the default), the server validates the storage endpoint's TLS certificate normally. Off disables certificate validation for that profile's connection — intended only for self-signed or internal endpoints reached over a network you trust. Don't disable it for anything reachable over the open internet.

POST /api/share returns a presigned URL against the S3-compatible endpoint itself — it is not proxied through Orbit. The link is only usable by recipients who can reach that storage endpoint directly. A link to a bucket on a private/internal MinIO instance won't work for someone outside that network, even if they can reach the Orbit console itself.

This matters most when the profile's endpoint is only resolvable from inside a cluster. Pointing a profile at, say, http://rook-ceph-rgw-ceph-objectstore.rook-ceph.svc:80 is perfectly fine for everything the console does itself — listing, upload, download and preview all stream through the server — but Share will produce a link that always fails for the recipient, because their browser cannot resolve a .svc name. The button gives no warning; the failure surfaces only when someone opens the link.

If sharing matters for such a deployment, give the storage endpoint a publicly resolvable hostname and point the profile at that. If it does not, treat Share as unavailable for that profile and say so to your users, rather than leaving them to discover it through a broken link.

Keyless AWS IAM: shared identity​

Connection profiles with authMode: 'aws-iam' (see Kubernetes: Keyless AWS IAM) authenticate as the server's own AWS identity — EKS Pod Identity, IRSA, instance profile, or ambient environment credentials — optionally narrowed by assuming a role via roleArn. There is no per-user credential isolation for these profiles: every signed-in user of the deployment who creates a keyless profile shares that same identity and its permissions. This is why the feature is off by default (AWS_KEYLESS_ENABLED=false / awsKeyless.enabled=false) and must be deliberately opted into. Grant the underlying IAM role no more access than you are comfortable giving every user of the deployment.

Turning the flag back off immediately stops every existing keyless profile from being usable: any request that would use one (testing the connection, browsing buckets/objects, generating a share link, ...) is refused with 403 KeylessDisabled. It does not delete those profiles — their rows remain in the database, still marked authMode: 'aws-iam', and they resume working the moment the flag is turned back on. Delete them explicitly if you want them gone for good.