Repository navigation
Change default user in container image #46
Description
Activity
Thanks for raising this — and for pointing at OpenShift specifically, because that turns out to be the part that decides the design.
This topic has some history: it came up twice on the predecessor image (jacobalberty/firebird-docker#35, #128, the latter also a non-root read-only Kubernetes environment), but it has never been addressed in the image itself. So let me put some measured facts on the table first, because the current situation is better than "it needs root" and worse than "just add a
USERline".Where we are today. Everything in the container runs as uid 0 —
tini, the entrypoint,fbguardandfirebird. Firebird does not drop privileges by itself; thefirebirdaccount (uid/gid 84) exists and already owns the interesting runtime files, but nothing ever switches to it.docker run --user firebirdalready works for the simple case. I testedfirebirdsql/firebird-amd64:5(5.0.4): with--user 84:84the server starts and serves normally, becausesecurity5.fdb,firebird.log,fb_guard, the/tmp/firebirdlock directory and/var/lib/firebird/dataare all owned byfirebirdalready. Exactly three things break, all of them in the entrypoint:Symptom Cause sed: couldn't open temporary file /opt/firebird/sedXXXXXXwhen anyFIREBIRD_CONF_*variable orFIREBIRD_USE_LEGACY_AUTHis setfirebird.confisroot:root 0644inside aroot:root 0755directoryrm: cannot remove '/opt/firebird/SYSDBA.password'afterFIREBIRD_ROOT_PASSWORDis appliedthe file is root:root 0400/opt/firebird/.firebird_env: Permission deniedwhenFIREBIRD_DATABASEis set/opt/firebirdis not writable by the firebird userOpenShift needs more than a
USERdirective. Under the restricted SCC theUSERline is ignored and the pod gets a random UID from the project's range with GID 0, so the fix has to be permission-based (root:0ownership plusg=u), not user-based. I simulated that (--user 12345:0on an image withchown -R root:0andchmod -R g=uapplied to/opt/firebird, the data directory and the lock directory) and got two further results worth knowing:- with group-root-writable permissions, the config edits and the SYSDBA password change work fine;
- creating
FIREBIRD_USERstill fails withno permission for INSERT access to TABLE PLG$SRP_VIEW, because the local (embedded) connection derives its identity from the OS user, and a random UID has no/etc/passwdentry, so it is not SYSDBA. Passing-user SYSDBAexplicitly fixes it — embedded connections bypass authentication, and the entrypoint already does this in one place but not in the others.
One implementation detail for whoever picks this up:
$FIREBIRD_DATAis declared as aVOLUME, so its ownership must be set in the image layer — a runtimechowninside the container does not persist into the anonymous volume.Also worth noting: Firebird listens on 3050, so no
NET_BIND_SERVICEcapability or any other privileged capability is needed. Nothing here requires root at runtime; it is purely a file-ownership question.What I propose. Make the image fully non-root-capable while keeping root as the default user, rather than flipping the default straight away. Concretely: set
root:0ownership withg=upermissions on/opt/firebird, the data directory and the lock directory at build time, and make the entrypoint robust — guard the removal ofSYSDBA.password, pass-user SYSDBAon the local connections that create the user and the database, and write.firebird_envsomewhere writable. That makes--user firebird,--user <any-uid>:0, KubernetesrunAsUser/fsGroupand OpenShift's injected UID all work, and it costs existing users nothing.The reason for not simply adding
USER firebirdtoday is backwards compatibility: every existing volume and bind mount out there contains root-owned database files, so changing the default user would break running deployments on upgrade until users chown their data — and, as noted above, it would not even solve the OpenShift case. Once the image is non-root-capable, flipping the default becomes a small, well-understood change that belongs in a major release with explicit release notes.@henryx — two questions, if you don't mind: is your environment OpenShift's restricted SCC (random UID + GID 0), or a fixed
runAsUser? And would you be able to test images from a branch before this is merged? Your environment is the one that matters here, and I'd rather validate against it than against my simulation of it.Thank you for the reply.
Currently, I don't have a Openhift or Kubernetes environment that restrict image permission.
I'm a cloud engineer and I have dealt with these issues, in particular when custom images released by developers aren't approved from security systems.
Also, I'm a developer, and at the moment I
writevibecode a Kubernetes operator for Firebird. To do it, I've choosed to use official images becaue I think is the more afordable solution repect to made custom images. So when I viewed this particular choice for Firebird image, I've opened this issue.And yes, I'm able to to test images from a particular branch before this is merged (at the moment I use a kind/k3s environment for development, but I can switch a Microshift or a OKD environment without problems)
@henryx the non-root support is implemented in #51, and an unofficial test image is available. It would be great if you could test it in your environment.
Unofficial test image
ghcr.io/fdcastel/firebird(Debian Trixie, amd64), with tags5/5.0.4,4/4.0.7and3/3.0.14. It is for testing only: it is built from a branch that combines #51 with two other pending PRs (#49 and #52, see "Also in this image" below).What changed
- The image still runs as root by default, so nothing changes for existing users.
- It now also runs fully as user
firebird(UID 84), or as any UID with GID 0, which is what OpenShift's restricted SCC assigns. This covers everything the entrypoint does:FIREBIRD_CONF_*,FIREBIRD_ROOT_PASSWORD,FIREBIRD_USER,FIREBIRD_DATABASEand init scripts. /opt/firebird, the data directory and the lock directory are owned byfirebirdwith group0, and group permissions equal owner permissions (g=u).- Any other UID/GID combination is not supported: the entrypoint prints a warning and Firebird will not be able to write its files.
- Databases created earlier by a container running as root are owned by root. Before reusing such a data directory as non-root, change its ownership, e.g.
chown -R 84:0 <data dir>.
Examples
# As the 'firebird' user docker run -d --user firebird -e FIREBIRD_ROOT_PASSWORD=masterkey -e FIREBIRD_DATABASE=test.fdb ghcr.io/fdcastel/firebird:5 # As an arbitrary UID with GID 0 (what OpenShift does) docker run -d --user 12345:0 -e FIREBIRD_ROOT_PASSWORD=masterkey -e FIREBIRD_USER=alice -e FIREBIRD_PASSWORD=bird -e FIREBIRD_DATABASE=test.fdb ghcr.io/fdcastel/firebird:5
Kubernetes (on plain Kubernetes,
runAsUsermust be set, because the image's default user is still root andrunAsNonRoot: truealone would reject it):apiVersion: v1 kind: Pod metadata: name: firebird spec: securityContext: runAsNonRoot: true runAsUser: 84 # or any UID runAsGroup: 0 containers: - name: firebird image: ghcr.io/fdcastel/firebird:5 env: - name: FIREBIRD_ROOT_PASSWORD value: masterkey - name: FIREBIRD_DATABASE value: test.fdb ports: - containerPort: 3050 volumeMounts: - name: data mountPath: /var/lib/firebird/data volumes: - name: data emptyDir: {}
What would help most
Since you offered: please test on OKD or MicroShift under the default
restricted/restricted-v2SCC, notanyuid, letting OpenShift inject the UID. That is the case the design targets and the one we can only simulate here. A run with a persistent volume for/var/lib/firebird/data(instead ofemptyDir) would also be very useful. Your kind/k3s setup withrunAsUsercovers the plain Kubernetes case.Please report back here: does the pod start, does the entrypoint print any warnings, and can you connect and create/use a database? Logs are welcome if something fails.
Also in this image
- Fix SYSDBA.password not working in Firebird 3 images #49 (issue Stock image cannot authenticate: security3.fdb lacks PLG$SRP tables for default Srp UserManager #47): fixes the SYSDBA password in Firebird 3 images.
- Generate a per-container SYSDBA password instead of sharing the build-time one #52 (issue SYSDBA password in SYSDBA.password is a build-time constant shared by all containers of an image #48): if
FIREBIRD_ROOT_PASSWORDis not set, each container now generates its own random SYSDBA password on first start and stores it in/opt/firebird/SYSDBA.password.
Current image uses root to run Firebird database. This is considered a security problem, and doesn't permit a correct execution without special permissions (in particular on Openshift).
Is it possible to set an unprivileged user in build stage for the images?