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.
Share links point at the storage endpoint
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.