diff --git a/DECISIONS.md b/DECISIONS.md index f05efb6..6313474 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -121,3 +121,15 @@ Also adds `tzdata` to Noble's distro `extraPackages` (matching Jammy). FB3 relie **Decision:** The `update-repo` job in `publish-fork.yaml` only commits and pushes regenerated `generated/` and `README.md` when running on the fork's default branch (`github.event.repository.default_branch`). Dispatches on PR or feature branches still run `Invoke-Build Prepare` and `Invoke-Build Update-Readme` (so a template-substitution regression still fails the workflow) but skip the `git commit` / `git push`. Amends D-014 for the publish-fork case; `publish.yaml` (the official-repo publish) is unchanged. **Rationale:** `publish-fork.yaml` passes `-Registry 'ghcr.io/'` to `Update-Readme`, which substitutes the fork's registry into the README table header. The previous unguarded auto-commit pushed that fork-specific README back to whatever branch was dispatched, including branches with open upstream PRs — directly polluting the PR diff with content that must not land upstream, and breaking GitHub's linear rebase when the upstream master had its own concurrent `README.md` changes (observed during PR #43, which required a force-pushed clean rebase to unblock). Branch-gating preserves D-014's "generated/ tracked in git" invariant on the fork's default branch while keeping PR/feature branches diff-clean against upstream. Confines the `-Registry` rewrite to the only place the fork wants it (its own showcased README on `master`). + +## D-019: FB3 library provisioning runs before the Firebird installer + +**Decision:** The FB3-only `libtommath.so.0` symlink and the `libncurses5`/`libtinfo5` provisioning (D-017) run inside the main `RUN` step, after the prerequisite `apt-get install` and before `./install.sh -silent`. They are no longer separate `RUN` steps after the install. Amends the placement described in D-017; the provisioning logic itself is unchanged. + +**Rationale:** The FB3 installer sets the generated SYSDBA password with `gsec -add sysdba -pw `, and then writes that password to `/opt/firebird/SYSDBA.password`. FB3's `gsec` (and `libfbclient`, `libSrp.so`) link against `libtommath.so.0` and `libncurses.so.5`/`libtinfo.so.5`. With the libraries provisioned only after the install, `gsec` failed with `error while loading shared libraries: libtommath.so.0`; the installer's `runSilent` wrapper printed the error and carried on. The image therefore shipped the tarball's pristine `security3.fdb` — no Srp user, no `PLG$SRP` table — alongside a `SYSDBA.password` file holding a password that was never set. Any Srp login then failed with the misleading `Install incomplete, please read the Compatibility chapter in the release notes for this version`. The defect stayed hidden because `FIREBIRD_ROOT_PASSWORD` (used in every documented example) and `FIREBIRD_USER` both go through the Srp user manager at container start, which creates the missing structures. The test suite now covers the stock, no-environment container. FB4+ is unaffected: its binaries' dependencies are satisfied by the prerequisite packages. See [issue #47](https://github.com/FirebirdSQL/firebird-docker/issues/47). + +## D-021: Random SYSDBA password on first start, gated by the security database checksum + +**Decision:** When `FIREBIRD_ROOT_PASSWORD` is not set, the entrypoint generates a random 20-character alphanumeric SYSDBA password, sets it with `CREATE OR ALTER USER SYSDBA ... USING PLUGIN Srp` (and `Legacy_UserManager` when `FIREBIRD_USE_LEGACY_AUTH=true`), and rewrites `/opt/firebird/SYSDBA.password` in the installer's format. This happens only while the security database still matches the SHA-256 checksum recorded at image build time (`/opt/firebird/.security.fdb.sha256`). Only the file's path is logged, not the password: container logs are often readable by more people than the container itself (log aggregators, CI output), so printing the password to stdout would re-expose it. The behaviour when `FIREBIRD_ROOT_PASSWORD` is set is unchanged. + +**Rationale:** The Firebird installer generates the SYSDBA password at image build time, so every container of an image shared the same password, readable by anyone who can pull the image. The security database lives in the container's writable layer, so the password must be replaced once per container: restarts keep it, recreated containers get a new one. The checksum is what makes the change idempotent and safe. After the first start the database no longer matches, so restarts leave it alone, with no marker file needed. A security database persisted outside the container and bind-mounted in ([issue #5](https://github.com/FirebirdSQL/firebird-docker/issues/5)) doesn't match either, so its SYSDBA password is never overwritten. A plain "first start" marker would have broken that use case on every container recreation. See [issue #48](https://github.com/FirebirdSQL/firebird-docker/issues/48). diff --git a/README.md b/README.md index afa59ea..ae2cbbf 100644 --- a/README.md +++ b/README.md @@ -199,10 +199,18 @@ The following environment variables can be used to customize the container. ### `FIREBIRD_ROOT_PASSWORD` -Firebird installer generates a one-off password for `SYSDBA` and stores it in `/opt/firebird/SYSDBA.password`. - If `FIREBIRD_ROOT_PASSWORD` is set, `SYSDBA` password will be changed. And the file `/opt/firebird/SYSDBA.password` will be removed. +Otherwise, a random password for `SYSDBA` is generated on the container's first start and stored in `/opt/firebird/SYSDBA.password`. It is not printed to the container log. To read it: + +```bash +docker exec MY_CONTAINER_NAME_OR_ID cat /opt/firebird/SYSDBA.password +``` + +The security database lives in the container (not in the data volume). Therefore, restarting a container keeps its password, while recreating it (e.g. `docker compose up` after an image update) generates a new one. Set `FIREBIRD_ROOT_PASSWORD` if you need a stable `SYSDBA` password. + +A security database changed since the image was built (e.g. a persisted `/opt/firebird/security5.fdb` bind-mounted into the container) is left untouched. + ### `FIREBIRD_USER` diff --git a/generated/3.0.10/bookworm/Dockerfile b/generated/3.0.10/bookworm/Dockerfile index 33a9de5..9e9c5aa 100644 --- a/generated/3.0.10/bookworm/Dockerfile +++ b/generated/3.0.10/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.10/bookworm/entrypoint.sh b/generated/3.0.10/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.10/bookworm/entrypoint.sh +++ b/generated/3.0.10/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.10/bullseye/Dockerfile b/generated/3.0.10/bullseye/Dockerfile index 923d45e..9f1664c 100644 --- a/generated/3.0.10/bullseye/Dockerfile +++ b/generated/3.0.10/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.10/bullseye/entrypoint.sh b/generated/3.0.10/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.10/bullseye/entrypoint.sh +++ b/generated/3.0.10/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.10/jammy/Dockerfile b/generated/3.0.10/jammy/Dockerfile index 3a3bb1d..3500386 100644 --- a/generated/3.0.10/jammy/Dockerfile +++ b/generated/3.0.10/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.10/jammy/entrypoint.sh b/generated/3.0.10/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.10/jammy/entrypoint.sh +++ b/generated/3.0.10/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.10/noble/Dockerfile b/generated/3.0.10/noble/Dockerfile index 6a38647..17f16b6 100644 --- a/generated/3.0.10/noble/Dockerfile +++ b/generated/3.0.10/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.10/noble/entrypoint.sh b/generated/3.0.10/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.10/noble/entrypoint.sh +++ b/generated/3.0.10/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.10/trixie/Dockerfile b/generated/3.0.10/trixie/Dockerfile index 9c0b884..16be858 100644 --- a/generated/3.0.10/trixie/Dockerfile +++ b/generated/3.0.10/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.10/trixie/entrypoint.sh b/generated/3.0.10/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.10/trixie/entrypoint.sh +++ b/generated/3.0.10/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.11/bookworm/Dockerfile b/generated/3.0.11/bookworm/Dockerfile index 652383c..83e6790 100644 --- a/generated/3.0.11/bookworm/Dockerfile +++ b/generated/3.0.11/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.11/bookworm/entrypoint.sh b/generated/3.0.11/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.11/bookworm/entrypoint.sh +++ b/generated/3.0.11/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.11/bullseye/Dockerfile b/generated/3.0.11/bullseye/Dockerfile index 0f4a13c..aa5843d 100644 --- a/generated/3.0.11/bullseye/Dockerfile +++ b/generated/3.0.11/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.11/bullseye/entrypoint.sh b/generated/3.0.11/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.11/bullseye/entrypoint.sh +++ b/generated/3.0.11/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.11/jammy/Dockerfile b/generated/3.0.11/jammy/Dockerfile index 2dd64b2..43db329 100644 --- a/generated/3.0.11/jammy/Dockerfile +++ b/generated/3.0.11/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.11/jammy/entrypoint.sh b/generated/3.0.11/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.11/jammy/entrypoint.sh +++ b/generated/3.0.11/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.11/noble/Dockerfile b/generated/3.0.11/noble/Dockerfile index 3c2e520..a20bb11 100644 --- a/generated/3.0.11/noble/Dockerfile +++ b/generated/3.0.11/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.11/noble/entrypoint.sh b/generated/3.0.11/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.11/noble/entrypoint.sh +++ b/generated/3.0.11/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.11/trixie/Dockerfile b/generated/3.0.11/trixie/Dockerfile index c5ed8c1..e84e1ad 100644 --- a/generated/3.0.11/trixie/Dockerfile +++ b/generated/3.0.11/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.11/trixie/entrypoint.sh b/generated/3.0.11/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.11/trixie/entrypoint.sh +++ b/generated/3.0.11/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.12/bookworm/Dockerfile b/generated/3.0.12/bookworm/Dockerfile index 7861cfc..9b982de 100644 --- a/generated/3.0.12/bookworm/Dockerfile +++ b/generated/3.0.12/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.12/bookworm/entrypoint.sh b/generated/3.0.12/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.12/bookworm/entrypoint.sh +++ b/generated/3.0.12/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.12/bullseye/Dockerfile b/generated/3.0.12/bullseye/Dockerfile index 8cca737..d43cb28 100644 --- a/generated/3.0.12/bullseye/Dockerfile +++ b/generated/3.0.12/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.12/bullseye/entrypoint.sh b/generated/3.0.12/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.12/bullseye/entrypoint.sh +++ b/generated/3.0.12/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.12/jammy/Dockerfile b/generated/3.0.12/jammy/Dockerfile index e7d841a..ae6865a 100644 --- a/generated/3.0.12/jammy/Dockerfile +++ b/generated/3.0.12/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.12/jammy/entrypoint.sh b/generated/3.0.12/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.12/jammy/entrypoint.sh +++ b/generated/3.0.12/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.12/noble/Dockerfile b/generated/3.0.12/noble/Dockerfile index e8883d0..0c49bd3 100644 --- a/generated/3.0.12/noble/Dockerfile +++ b/generated/3.0.12/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.12/noble/entrypoint.sh b/generated/3.0.12/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.12/noble/entrypoint.sh +++ b/generated/3.0.12/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.12/trixie/Dockerfile b/generated/3.0.12/trixie/Dockerfile index 3f2b4d7..32cf682 100644 --- a/generated/3.0.12/trixie/Dockerfile +++ b/generated/3.0.12/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.12/trixie/entrypoint.sh b/generated/3.0.12/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.12/trixie/entrypoint.sh +++ b/generated/3.0.12/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.13/bookworm/Dockerfile b/generated/3.0.13/bookworm/Dockerfile index 8fc958c..04b39d4 100644 --- a/generated/3.0.13/bookworm/Dockerfile +++ b/generated/3.0.13/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.13/bookworm/entrypoint.sh b/generated/3.0.13/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.13/bookworm/entrypoint.sh +++ b/generated/3.0.13/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.13/bullseye/Dockerfile b/generated/3.0.13/bullseye/Dockerfile index 6a33d34..b4da81c 100644 --- a/generated/3.0.13/bullseye/Dockerfile +++ b/generated/3.0.13/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.13/bullseye/entrypoint.sh b/generated/3.0.13/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.13/bullseye/entrypoint.sh +++ b/generated/3.0.13/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.13/jammy/Dockerfile b/generated/3.0.13/jammy/Dockerfile index 9afb0b4..8d28ff1 100644 --- a/generated/3.0.13/jammy/Dockerfile +++ b/generated/3.0.13/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.13/jammy/entrypoint.sh b/generated/3.0.13/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.13/jammy/entrypoint.sh +++ b/generated/3.0.13/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.13/noble/Dockerfile b/generated/3.0.13/noble/Dockerfile index dff334e..c911d2b 100644 --- a/generated/3.0.13/noble/Dockerfile +++ b/generated/3.0.13/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.13/noble/entrypoint.sh b/generated/3.0.13/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.13/noble/entrypoint.sh +++ b/generated/3.0.13/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.13/trixie/Dockerfile b/generated/3.0.13/trixie/Dockerfile index 5f9f67c..71e0ad2 100644 --- a/generated/3.0.13/trixie/Dockerfile +++ b/generated/3.0.13/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.13/trixie/entrypoint.sh b/generated/3.0.13/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.13/trixie/entrypoint.sh +++ b/generated/3.0.13/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.14/bookworm/Dockerfile b/generated/3.0.14/bookworm/Dockerfile index 4c850b0..6012c42 100644 --- a/generated/3.0.14/bookworm/Dockerfile +++ b/generated/3.0.14/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.14/bookworm/entrypoint.sh b/generated/3.0.14/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.14/bookworm/entrypoint.sh +++ b/generated/3.0.14/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.14/bullseye/Dockerfile b/generated/3.0.14/bullseye/Dockerfile index 4779946..d7430a9 100644 --- a/generated/3.0.14/bullseye/Dockerfile +++ b/generated/3.0.14/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.14/bullseye/entrypoint.sh b/generated/3.0.14/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.14/bullseye/entrypoint.sh +++ b/generated/3.0.14/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.14/jammy/Dockerfile b/generated/3.0.14/jammy/Dockerfile index 1c3c449..ce3dd1c 100644 --- a/generated/3.0.14/jammy/Dockerfile +++ b/generated/3.0.14/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.14/jammy/entrypoint.sh b/generated/3.0.14/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.14/jammy/entrypoint.sh +++ b/generated/3.0.14/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.14/noble/Dockerfile b/generated/3.0.14/noble/Dockerfile index eafebd0..0a199a4 100644 --- a/generated/3.0.14/noble/Dockerfile +++ b/generated/3.0.14/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.14/noble/entrypoint.sh b/generated/3.0.14/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.14/noble/entrypoint.sh +++ b/generated/3.0.14/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.14/trixie/Dockerfile b/generated/3.0.14/trixie/Dockerfile index 96f3f62..283aac8 100644 --- a/generated/3.0.14/trixie/Dockerfile +++ b/generated/3.0.14/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.14/trixie/entrypoint.sh b/generated/3.0.14/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.14/trixie/entrypoint.sh +++ b/generated/3.0.14/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.9/bookworm/Dockerfile b/generated/3.0.9/bookworm/Dockerfile index 1edf8d1..2d9f3ca 100644 --- a/generated/3.0.9/bookworm/Dockerfile +++ b/generated/3.0.9/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.9/bookworm/entrypoint.sh b/generated/3.0.9/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.9/bookworm/entrypoint.sh +++ b/generated/3.0.9/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.9/bullseye/Dockerfile b/generated/3.0.9/bullseye/Dockerfile index 8c9760f..2c94a58 100644 --- a/generated/3.0.9/bullseye/Dockerfile +++ b/generated/3.0.9/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.9/bullseye/entrypoint.sh b/generated/3.0.9/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.9/bullseye/entrypoint.sh +++ b/generated/3.0.9/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.9/jammy/Dockerfile b/generated/3.0.9/jammy/Dockerfile index a650711..3d558ba 100644 --- a/generated/3.0.9/jammy/Dockerfile +++ b/generated/3.0.9/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.9/jammy/entrypoint.sh b/generated/3.0.9/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.9/jammy/entrypoint.sh +++ b/generated/3.0.9/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.9/noble/Dockerfile b/generated/3.0.9/noble/Dockerfile index e151d28..4f8b678 100644 --- a/generated/3.0.9/noble/Dockerfile +++ b/generated/3.0.9/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.9/noble/entrypoint.sh b/generated/3.0.9/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.9/noble/entrypoint.sh +++ b/generated/3.0.9/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/3.0.9/trixie/Dockerfile b/generated/3.0.9/trixie/Dockerfile index 7362a0b..a419b66 100644 --- a/generated/3.0.9/trixie/Dockerfile +++ b/generated/3.0.9/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/3.0.9/trixie/entrypoint.sh b/generated/3.0.9/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/3.0.9/trixie/entrypoint.sh +++ b/generated/3.0.9/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.0/bookworm/Dockerfile b/generated/4.0.0/bookworm/Dockerfile index fd0f375..7eeb44e 100644 --- a/generated/4.0.0/bookworm/Dockerfile +++ b/generated/4.0.0/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.0/bookworm/entrypoint.sh b/generated/4.0.0/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.0/bookworm/entrypoint.sh +++ b/generated/4.0.0/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.0/bullseye/Dockerfile b/generated/4.0.0/bullseye/Dockerfile index e46610c..d769a29 100644 --- a/generated/4.0.0/bullseye/Dockerfile +++ b/generated/4.0.0/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.0/bullseye/entrypoint.sh b/generated/4.0.0/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.0/bullseye/entrypoint.sh +++ b/generated/4.0.0/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.0/jammy/Dockerfile b/generated/4.0.0/jammy/Dockerfile index 4e92ede..183ddc7 100644 --- a/generated/4.0.0/jammy/Dockerfile +++ b/generated/4.0.0/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.0/jammy/entrypoint.sh b/generated/4.0.0/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.0/jammy/entrypoint.sh +++ b/generated/4.0.0/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.0/noble/Dockerfile b/generated/4.0.0/noble/Dockerfile index bb272eb..1f5c8de 100644 --- a/generated/4.0.0/noble/Dockerfile +++ b/generated/4.0.0/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.0/noble/entrypoint.sh b/generated/4.0.0/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.0/noble/entrypoint.sh +++ b/generated/4.0.0/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.0/trixie/Dockerfile b/generated/4.0.0/trixie/Dockerfile index ead67a4..98bba71 100644 --- a/generated/4.0.0/trixie/Dockerfile +++ b/generated/4.0.0/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.0/trixie/entrypoint.sh b/generated/4.0.0/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.0/trixie/entrypoint.sh +++ b/generated/4.0.0/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.1/bookworm/Dockerfile b/generated/4.0.1/bookworm/Dockerfile index b07bb8c..4f96547 100644 --- a/generated/4.0.1/bookworm/Dockerfile +++ b/generated/4.0.1/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.1/bookworm/entrypoint.sh b/generated/4.0.1/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.1/bookworm/entrypoint.sh +++ b/generated/4.0.1/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.1/bullseye/Dockerfile b/generated/4.0.1/bullseye/Dockerfile index d685b6c..4e16df5 100644 --- a/generated/4.0.1/bullseye/Dockerfile +++ b/generated/4.0.1/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.1/bullseye/entrypoint.sh b/generated/4.0.1/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.1/bullseye/entrypoint.sh +++ b/generated/4.0.1/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.1/jammy/Dockerfile b/generated/4.0.1/jammy/Dockerfile index dcdf5cc..f6c47b5 100644 --- a/generated/4.0.1/jammy/Dockerfile +++ b/generated/4.0.1/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.1/jammy/entrypoint.sh b/generated/4.0.1/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.1/jammy/entrypoint.sh +++ b/generated/4.0.1/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.1/noble/Dockerfile b/generated/4.0.1/noble/Dockerfile index a0c96fb..16759be 100644 --- a/generated/4.0.1/noble/Dockerfile +++ b/generated/4.0.1/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.1/noble/entrypoint.sh b/generated/4.0.1/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.1/noble/entrypoint.sh +++ b/generated/4.0.1/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.1/trixie/Dockerfile b/generated/4.0.1/trixie/Dockerfile index e05defa..9b0c216 100644 --- a/generated/4.0.1/trixie/Dockerfile +++ b/generated/4.0.1/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.1/trixie/entrypoint.sh b/generated/4.0.1/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.1/trixie/entrypoint.sh +++ b/generated/4.0.1/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.2/bookworm/Dockerfile b/generated/4.0.2/bookworm/Dockerfile index d72ad5f..5b750ee 100644 --- a/generated/4.0.2/bookworm/Dockerfile +++ b/generated/4.0.2/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.2/bookworm/entrypoint.sh b/generated/4.0.2/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.2/bookworm/entrypoint.sh +++ b/generated/4.0.2/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.2/bullseye/Dockerfile b/generated/4.0.2/bullseye/Dockerfile index ffec909..b3ee048 100644 --- a/generated/4.0.2/bullseye/Dockerfile +++ b/generated/4.0.2/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.2/bullseye/entrypoint.sh b/generated/4.0.2/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.2/bullseye/entrypoint.sh +++ b/generated/4.0.2/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.2/jammy/Dockerfile b/generated/4.0.2/jammy/Dockerfile index 054feb1..32d5f7f 100644 --- a/generated/4.0.2/jammy/Dockerfile +++ b/generated/4.0.2/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.2/jammy/entrypoint.sh b/generated/4.0.2/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.2/jammy/entrypoint.sh +++ b/generated/4.0.2/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.2/noble/Dockerfile b/generated/4.0.2/noble/Dockerfile index ff8914e..d08afd1 100644 --- a/generated/4.0.2/noble/Dockerfile +++ b/generated/4.0.2/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.2/noble/entrypoint.sh b/generated/4.0.2/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.2/noble/entrypoint.sh +++ b/generated/4.0.2/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.2/trixie/Dockerfile b/generated/4.0.2/trixie/Dockerfile index 877ca13..c24f045 100644 --- a/generated/4.0.2/trixie/Dockerfile +++ b/generated/4.0.2/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.2/trixie/entrypoint.sh b/generated/4.0.2/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.2/trixie/entrypoint.sh +++ b/generated/4.0.2/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.3/bookworm/Dockerfile b/generated/4.0.3/bookworm/Dockerfile index 4884ae3..b778ed3 100644 --- a/generated/4.0.3/bookworm/Dockerfile +++ b/generated/4.0.3/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.3/bookworm/entrypoint.sh b/generated/4.0.3/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.3/bookworm/entrypoint.sh +++ b/generated/4.0.3/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.3/bullseye/Dockerfile b/generated/4.0.3/bullseye/Dockerfile index 03484db..de3e5b7 100644 --- a/generated/4.0.3/bullseye/Dockerfile +++ b/generated/4.0.3/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.3/bullseye/entrypoint.sh b/generated/4.0.3/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.3/bullseye/entrypoint.sh +++ b/generated/4.0.3/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.3/jammy/Dockerfile b/generated/4.0.3/jammy/Dockerfile index 6d8cae3..d1cc4ce 100644 --- a/generated/4.0.3/jammy/Dockerfile +++ b/generated/4.0.3/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.3/jammy/entrypoint.sh b/generated/4.0.3/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.3/jammy/entrypoint.sh +++ b/generated/4.0.3/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.3/noble/Dockerfile b/generated/4.0.3/noble/Dockerfile index 6e9e7b8..0b21b84 100644 --- a/generated/4.0.3/noble/Dockerfile +++ b/generated/4.0.3/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.3/noble/entrypoint.sh b/generated/4.0.3/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.3/noble/entrypoint.sh +++ b/generated/4.0.3/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.3/trixie/Dockerfile b/generated/4.0.3/trixie/Dockerfile index 3d03792..2ce6f70 100644 --- a/generated/4.0.3/trixie/Dockerfile +++ b/generated/4.0.3/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.3/trixie/entrypoint.sh b/generated/4.0.3/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.3/trixie/entrypoint.sh +++ b/generated/4.0.3/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.4/bookworm/Dockerfile b/generated/4.0.4/bookworm/Dockerfile index 9a355b5..2de02c3 100644 --- a/generated/4.0.4/bookworm/Dockerfile +++ b/generated/4.0.4/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.4/bookworm/entrypoint.sh b/generated/4.0.4/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.4/bookworm/entrypoint.sh +++ b/generated/4.0.4/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.4/bullseye/Dockerfile b/generated/4.0.4/bullseye/Dockerfile index 84ca99f..3af45ec 100644 --- a/generated/4.0.4/bullseye/Dockerfile +++ b/generated/4.0.4/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.4/bullseye/entrypoint.sh b/generated/4.0.4/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.4/bullseye/entrypoint.sh +++ b/generated/4.0.4/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.4/jammy/Dockerfile b/generated/4.0.4/jammy/Dockerfile index f0c5992..6c137b4 100644 --- a/generated/4.0.4/jammy/Dockerfile +++ b/generated/4.0.4/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.4/jammy/entrypoint.sh b/generated/4.0.4/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.4/jammy/entrypoint.sh +++ b/generated/4.0.4/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.4/noble/Dockerfile b/generated/4.0.4/noble/Dockerfile index 51ef49f..87684ea 100644 --- a/generated/4.0.4/noble/Dockerfile +++ b/generated/4.0.4/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.4/noble/entrypoint.sh b/generated/4.0.4/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.4/noble/entrypoint.sh +++ b/generated/4.0.4/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.4/trixie/Dockerfile b/generated/4.0.4/trixie/Dockerfile index 2906a6e..a25974c 100644 --- a/generated/4.0.4/trixie/Dockerfile +++ b/generated/4.0.4/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.4/trixie/entrypoint.sh b/generated/4.0.4/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.4/trixie/entrypoint.sh +++ b/generated/4.0.4/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.5/bookworm/Dockerfile b/generated/4.0.5/bookworm/Dockerfile index e9b450f..822417b 100644 --- a/generated/4.0.5/bookworm/Dockerfile +++ b/generated/4.0.5/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.5/bookworm/entrypoint.sh b/generated/4.0.5/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.5/bookworm/entrypoint.sh +++ b/generated/4.0.5/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.5/bullseye/Dockerfile b/generated/4.0.5/bullseye/Dockerfile index fa82a48..a8bca6c 100644 --- a/generated/4.0.5/bullseye/Dockerfile +++ b/generated/4.0.5/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.5/bullseye/entrypoint.sh b/generated/4.0.5/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.5/bullseye/entrypoint.sh +++ b/generated/4.0.5/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.5/jammy/Dockerfile b/generated/4.0.5/jammy/Dockerfile index ef6f30d..cc7e221 100644 --- a/generated/4.0.5/jammy/Dockerfile +++ b/generated/4.0.5/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.5/jammy/entrypoint.sh b/generated/4.0.5/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.5/jammy/entrypoint.sh +++ b/generated/4.0.5/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.5/noble/Dockerfile b/generated/4.0.5/noble/Dockerfile index 35e9467..1f9f8dd 100644 --- a/generated/4.0.5/noble/Dockerfile +++ b/generated/4.0.5/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.5/noble/entrypoint.sh b/generated/4.0.5/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.5/noble/entrypoint.sh +++ b/generated/4.0.5/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.5/trixie/Dockerfile b/generated/4.0.5/trixie/Dockerfile index 105e14e..8710724 100644 --- a/generated/4.0.5/trixie/Dockerfile +++ b/generated/4.0.5/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.5/trixie/entrypoint.sh b/generated/4.0.5/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.5/trixie/entrypoint.sh +++ b/generated/4.0.5/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.6/bookworm/Dockerfile b/generated/4.0.6/bookworm/Dockerfile index f64e601..f27c320 100644 --- a/generated/4.0.6/bookworm/Dockerfile +++ b/generated/4.0.6/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.6/bookworm/entrypoint.sh b/generated/4.0.6/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.6/bookworm/entrypoint.sh +++ b/generated/4.0.6/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.6/bullseye/Dockerfile b/generated/4.0.6/bullseye/Dockerfile index 733b01b..8b350fa 100644 --- a/generated/4.0.6/bullseye/Dockerfile +++ b/generated/4.0.6/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.6/bullseye/entrypoint.sh b/generated/4.0.6/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.6/bullseye/entrypoint.sh +++ b/generated/4.0.6/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.6/jammy/Dockerfile b/generated/4.0.6/jammy/Dockerfile index 2e507c4..1bb9c49 100644 --- a/generated/4.0.6/jammy/Dockerfile +++ b/generated/4.0.6/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.6/jammy/entrypoint.sh b/generated/4.0.6/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.6/jammy/entrypoint.sh +++ b/generated/4.0.6/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.6/noble/Dockerfile b/generated/4.0.6/noble/Dockerfile index 7469096..48ee51e 100644 --- a/generated/4.0.6/noble/Dockerfile +++ b/generated/4.0.6/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.6/noble/entrypoint.sh b/generated/4.0.6/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.6/noble/entrypoint.sh +++ b/generated/4.0.6/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.6/trixie/Dockerfile b/generated/4.0.6/trixie/Dockerfile index cb094ff..0044323 100644 --- a/generated/4.0.6/trixie/Dockerfile +++ b/generated/4.0.6/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.6/trixie/entrypoint.sh b/generated/4.0.6/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.6/trixie/entrypoint.sh +++ b/generated/4.0.6/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.7/bookworm/Dockerfile b/generated/4.0.7/bookworm/Dockerfile index cb02b6e..bf8a32f 100644 --- a/generated/4.0.7/bookworm/Dockerfile +++ b/generated/4.0.7/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.7/bookworm/entrypoint.sh b/generated/4.0.7/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.7/bookworm/entrypoint.sh +++ b/generated/4.0.7/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.7/bullseye/Dockerfile b/generated/4.0.7/bullseye/Dockerfile index d490cad..dd2002f 100644 --- a/generated/4.0.7/bullseye/Dockerfile +++ b/generated/4.0.7/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.7/bullseye/entrypoint.sh b/generated/4.0.7/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.7/bullseye/entrypoint.sh +++ b/generated/4.0.7/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.7/jammy/Dockerfile b/generated/4.0.7/jammy/Dockerfile index 914f687..38c23a7 100644 --- a/generated/4.0.7/jammy/Dockerfile +++ b/generated/4.0.7/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.7/jammy/entrypoint.sh b/generated/4.0.7/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.7/jammy/entrypoint.sh +++ b/generated/4.0.7/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.7/noble/Dockerfile b/generated/4.0.7/noble/Dockerfile index b3a5c6b..3692bc7 100644 --- a/generated/4.0.7/noble/Dockerfile +++ b/generated/4.0.7/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -62,60 +96,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.7/noble/entrypoint.sh b/generated/4.0.7/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.7/noble/entrypoint.sh +++ b/generated/4.0.7/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/4.0.7/trixie/Dockerfile b/generated/4.0.7/trixie/Dockerfile index 2d006c0..34ec817 100644 --- a/generated/4.0.7/trixie/Dockerfile +++ b/generated/4.0.7/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/4.0.7/trixie/entrypoint.sh b/generated/4.0.7/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/4.0.7/trixie/entrypoint.sh +++ b/generated/4.0.7/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.0/bookworm/Dockerfile b/generated/5.0.0/bookworm/Dockerfile index 785100b..dbda187 100644 --- a/generated/5.0.0/bookworm/Dockerfile +++ b/generated/5.0.0/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.0/bookworm/entrypoint.sh b/generated/5.0.0/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.0/bookworm/entrypoint.sh +++ b/generated/5.0.0/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.0/bullseye/Dockerfile b/generated/5.0.0/bullseye/Dockerfile index a9fcc69..243e56f 100644 --- a/generated/5.0.0/bullseye/Dockerfile +++ b/generated/5.0.0/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.0/bullseye/entrypoint.sh b/generated/5.0.0/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.0/bullseye/entrypoint.sh +++ b/generated/5.0.0/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.0/jammy/Dockerfile b/generated/5.0.0/jammy/Dockerfile index 0266f19..d2405de 100644 --- a/generated/5.0.0/jammy/Dockerfile +++ b/generated/5.0.0/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -66,60 +100,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.0/jammy/entrypoint.sh b/generated/5.0.0/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.0/jammy/entrypoint.sh +++ b/generated/5.0.0/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.0/noble/Dockerfile b/generated/5.0.0/noble/Dockerfile index f541232..c7b9383 100644 --- a/generated/5.0.0/noble/Dockerfile +++ b/generated/5.0.0/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -66,60 +100,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.0/noble/entrypoint.sh b/generated/5.0.0/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.0/noble/entrypoint.sh +++ b/generated/5.0.0/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.0/trixie/Dockerfile b/generated/5.0.0/trixie/Dockerfile index 1a0f1ca..bb239de 100644 --- a/generated/5.0.0/trixie/Dockerfile +++ b/generated/5.0.0/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.0/trixie/entrypoint.sh b/generated/5.0.0/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.0/trixie/entrypoint.sh +++ b/generated/5.0.0/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.1/bookworm/Dockerfile b/generated/5.0.1/bookworm/Dockerfile index f12214e..3f8df01 100644 --- a/generated/5.0.1/bookworm/Dockerfile +++ b/generated/5.0.1/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.1/bookworm/entrypoint.sh b/generated/5.0.1/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.1/bookworm/entrypoint.sh +++ b/generated/5.0.1/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.1/bullseye/Dockerfile b/generated/5.0.1/bullseye/Dockerfile index 9eb494c..82a895b 100644 --- a/generated/5.0.1/bullseye/Dockerfile +++ b/generated/5.0.1/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.1/bullseye/entrypoint.sh b/generated/5.0.1/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.1/bullseye/entrypoint.sh +++ b/generated/5.0.1/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.1/jammy/Dockerfile b/generated/5.0.1/jammy/Dockerfile index b232966..e74e184 100644 --- a/generated/5.0.1/jammy/Dockerfile +++ b/generated/5.0.1/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -66,60 +100,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.1/jammy/entrypoint.sh b/generated/5.0.1/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.1/jammy/entrypoint.sh +++ b/generated/5.0.1/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.1/noble/Dockerfile b/generated/5.0.1/noble/Dockerfile index 712a51f..99e838f 100644 --- a/generated/5.0.1/noble/Dockerfile +++ b/generated/5.0.1/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -66,60 +100,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.1/noble/entrypoint.sh b/generated/5.0.1/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.1/noble/entrypoint.sh +++ b/generated/5.0.1/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.1/trixie/Dockerfile b/generated/5.0.1/trixie/Dockerfile index f470973..1abd43c 100644 --- a/generated/5.0.1/trixie/Dockerfile +++ b/generated/5.0.1/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.1/trixie/entrypoint.sh b/generated/5.0.1/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.1/trixie/entrypoint.sh +++ b/generated/5.0.1/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.2/bookworm/Dockerfile b/generated/5.0.2/bookworm/Dockerfile index 6fb9081..cff72e2 100644 --- a/generated/5.0.2/bookworm/Dockerfile +++ b/generated/5.0.2/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.2/bookworm/entrypoint.sh b/generated/5.0.2/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.2/bookworm/entrypoint.sh +++ b/generated/5.0.2/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.2/bullseye/Dockerfile b/generated/5.0.2/bullseye/Dockerfile index 0de59be..991acea 100644 --- a/generated/5.0.2/bullseye/Dockerfile +++ b/generated/5.0.2/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.2/bullseye/entrypoint.sh b/generated/5.0.2/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.2/bullseye/entrypoint.sh +++ b/generated/5.0.2/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.2/jammy/Dockerfile b/generated/5.0.2/jammy/Dockerfile index 14c6815..95db732 100644 --- a/generated/5.0.2/jammy/Dockerfile +++ b/generated/5.0.2/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -66,60 +100,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.2/jammy/entrypoint.sh b/generated/5.0.2/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.2/jammy/entrypoint.sh +++ b/generated/5.0.2/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.2/noble/Dockerfile b/generated/5.0.2/noble/Dockerfile index dacf5b6..d9251ec 100644 --- a/generated/5.0.2/noble/Dockerfile +++ b/generated/5.0.2/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -66,60 +100,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.2/noble/entrypoint.sh b/generated/5.0.2/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.2/noble/entrypoint.sh +++ b/generated/5.0.2/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.2/trixie/Dockerfile b/generated/5.0.2/trixie/Dockerfile index 4b17087..0eb720f 100644 --- a/generated/5.0.2/trixie/Dockerfile +++ b/generated/5.0.2/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.2/trixie/entrypoint.sh b/generated/5.0.2/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.2/trixie/entrypoint.sh +++ b/generated/5.0.2/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.3/bookworm/Dockerfile b/generated/5.0.3/bookworm/Dockerfile index cba1ef7..11719d3 100644 --- a/generated/5.0.3/bookworm/Dockerfile +++ b/generated/5.0.3/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.3/bookworm/entrypoint.sh b/generated/5.0.3/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.3/bookworm/entrypoint.sh +++ b/generated/5.0.3/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.3/bullseye/Dockerfile b/generated/5.0.3/bullseye/Dockerfile index c397c41..ff98503 100644 --- a/generated/5.0.3/bullseye/Dockerfile +++ b/generated/5.0.3/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.3/bullseye/entrypoint.sh b/generated/5.0.3/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.3/bullseye/entrypoint.sh +++ b/generated/5.0.3/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.3/jammy/Dockerfile b/generated/5.0.3/jammy/Dockerfile index 52eed8d..289c612 100644 --- a/generated/5.0.3/jammy/Dockerfile +++ b/generated/5.0.3/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -66,60 +100,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.3/jammy/entrypoint.sh b/generated/5.0.3/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.3/jammy/entrypoint.sh +++ b/generated/5.0.3/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.3/noble/Dockerfile b/generated/5.0.3/noble/Dockerfile index f47b26d..ab0feaa 100644 --- a/generated/5.0.3/noble/Dockerfile +++ b/generated/5.0.3/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -66,60 +100,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.3/noble/entrypoint.sh b/generated/5.0.3/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.3/noble/entrypoint.sh +++ b/generated/5.0.3/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.3/trixie/Dockerfile b/generated/5.0.3/trixie/Dockerfile index 0df8a3a..7ef5e5c 100644 --- a/generated/5.0.3/trixie/Dockerfile +++ b/generated/5.0.3/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.3/trixie/entrypoint.sh b/generated/5.0.3/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.3/trixie/entrypoint.sh +++ b/generated/5.0.3/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.4/bookworm/Dockerfile b/generated/5.0.4/bookworm/Dockerfile index 1c9b378..69240de 100644 --- a/generated/5.0.4/bookworm/Dockerfile +++ b/generated/5.0.4/bookworm/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.4/bookworm/entrypoint.sh b/generated/5.0.4/bookworm/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.4/bookworm/entrypoint.sh +++ b/generated/5.0.4/bookworm/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.4/bullseye/Dockerfile b/generated/5.0.4/bullseye/Dockerfile index 3e63ebe..538a80f 100644 --- a/generated/5.0.4/bullseye/Dockerfile +++ b/generated/5.0.4/bullseye/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.4/bullseye/entrypoint.sh b/generated/5.0.4/bullseye/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.4/bullseye/entrypoint.sh +++ b/generated/5.0.4/bullseye/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.4/jammy/Dockerfile b/generated/5.0.4/jammy/Dockerfile index bb11a63..585ab43 100644 --- a/generated/5.0.4/jammy/Dockerfile +++ b/generated/5.0.4/jammy/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -66,60 +100,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.4/jammy/entrypoint.sh b/generated/5.0.4/jammy/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.4/jammy/entrypoint.sh +++ b/generated/5.0.4/jammy/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.4/noble/Dockerfile b/generated/5.0.4/noble/Dockerfile index fa12063..39feec7 100644 --- a/generated/5.0.4/noble/Dockerfile +++ b/generated/5.0.4/noble/Dockerfile @@ -35,6 +35,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -66,60 +100,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.4/noble/entrypoint.sh b/generated/5.0.4/noble/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.4/noble/entrypoint.sh +++ b/generated/5.0.4/noble/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/generated/5.0.4/trixie/Dockerfile b/generated/5.0.4/trixie/Dockerfile index 2d6ae21..086bd65 100644 --- a/generated/5.0.4/trixie/Dockerfile +++ b/generated/5.0.4/trixie/Dockerfile @@ -34,6 +34,40 @@ RUN set -eux; \ ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -65,60 +99,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/generated/5.0.4/trixie/entrypoint.sh b/generated/5.0.4/trixie/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/generated/5.0.4/trixie/entrypoint.sh +++ b/generated/5.0.4/trixie/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/src/Dockerfile.template b/src/Dockerfile.template index f1764a5..a798b66 100644 --- a/src/Dockerfile.template +++ b/src/Dockerfile.template @@ -30,6 +30,40 @@ RUN set -eux; \ {{EXTRA_PACKAGES}} ca-certificates \ curl; \ \ + # FB 3.0 only: provide libtommath.so.0 and libncurses5/libtinfo5 BEFORE running the installer. + # The installer sets the SYSDBA password with 'gsec', which cannot start without them. + # See DECISIONS.md D-019 and https://github.com/FirebirdSQL/firebird-docker/issues/47 + if [ "$FIREBIRD_MAJOR" = "3" ]; then \ + # Fix libtommath -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 + MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + ln -sf /usr/lib/$MULTIARCH/libtommath.so.1 /usr/lib/$MULTIARCH/libtommath.so.0; \ + \ + # libncurses5/libtinfo5 were dropped from apt on Debian Trixie and Ubuntu Noble; pull them from the previous release pool. + # See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 + . /etc/os-release; \ + case "$ID-$VERSION_CODENAME" in \ + debian-bookworm|debian-bullseye|ubuntu-jammy) \ + apt-get install -y --no-install-recommends libtinfo5 libncurses5 \ + ;; \ + debian-trixie) \ + curl -fSL -o /tmp/libtinfo5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + ubuntu-noble) \ + curl -fSL -o /tmp/libtinfo5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.3_amd64.deb; \ + curl -fSL -o /tmp/libncurses5.deb http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.3_amd64.deb; \ + dpkg -i /tmp/libtinfo5.deb /tmp/libncurses5.deb; \ + rm -f /tmp/libtinfo5.deb /tmp/libncurses5.deb \ + ;; \ + *) \ + echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ + exit 1 \ + ;; \ + esac; \ + fi; \ + \ # Download ARCH=$(dpkg --print-architecture); \ case "$ARCH" in \ @@ -61,60 +95,16 @@ RUN set -eux; \ /opt/firebird/include; \ # Remove 'employee' sample database from 'databases.conf' sed -i '/^employee/d' /opt/firebird/databases.conf; \ + # Record the checksum of the security database as shipped in the image. The entrypoint replaces the SYSDBA + # password generated by the installer (the same for every container of this image) only while the security + # database still matches it. See DECISIONS.md D-021 and https://github.com/FirebirdSQL/firebird-docker/issues/48 + sha256sum /opt/firebird/security${FIREBIRD_MAJOR}.fdb > /opt/firebird/.security.fdb.sha256; \ \ # Clean up temporary packages (curl, ca-certificates) and apt lists apt-get purge -y --auto-remove curl ca-certificates; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* -# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN set -eux; \ - ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ - [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true - -# FB 3.0 needs libncurses5/libtinfo5. On Debian Trixie and Ubuntu Noble those -# packages were dropped from apt; pull them from the previous release pool. -# See DECISIONS.md D-017 and https://github.com/FirebirdSQL/firebird-docker/issues/42 -RUN set -eux; \ - if [ "$FIREBIRD_MAJOR" = "3" ]; then \ - . /etc/os-release; \ - case "$ID-$VERSION_CODENAME" in \ - debian-bookworm|debian-bullseye|ubuntu-jammy) \ - apt-get update; \ - apt-get install -y --no-install-recommends libtinfo5 libncurses5; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - debian-trixie) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb; \ - curl -fSL -O http://deb.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb; \ - dpkg -i libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - rm -f libtinfo5_6.4-4_amd64.deb libncurses5_6.4-4_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - ubuntu-noble) \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates curl; \ - cd /tmp; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.2_amd64.deb; \ - curl -fSL -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - dpkg -i libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - rm -f libtinfo5_6.3-2ubuntu0.2_amd64.deb libncurses5_6.3-2ubuntu0.2_amd64.deb; \ - apt-get purge -y --auto-remove curl ca-certificates; \ - apt-get clean; \ - rm -rf /var/lib/apt/lists/* \ - ;; \ - *) \ - echo "FB3: no libncurses5 provisioning path for $ID-$VERSION_CODENAME" >&2; \ - exit 1 \ - ;; \ - esac; \ - fi - # System path ENV PATH=/opt/firebird/bin:$PATH diff --git a/src/README.md.template b/src/README.md.template index 42506ac..622eca2 100644 --- a/src/README.md.template +++ b/src/README.md.template @@ -101,10 +101,18 @@ The following environment variables can be used to customize the container. ### `FIREBIRD_ROOT_PASSWORD` -Firebird installer generates a one-off password for `SYSDBA` and stores it in `/opt/firebird/SYSDBA.password`. - If `FIREBIRD_ROOT_PASSWORD` is set, `SYSDBA` password will be changed. And the file `/opt/firebird/SYSDBA.password` will be removed. +Otherwise, a random password for `SYSDBA` is generated on the container's first start and stored in `/opt/firebird/SYSDBA.password`. It is not printed to the container log. To read it: + +```bash +docker exec MY_CONTAINER_NAME_OR_ID cat /opt/firebird/SYSDBA.password +``` + +The security database lives in the container (not in the data volume). Therefore, restarting a container keeps its password, while recreating it (e.g. `docker compose up` after an image update) generates a new one. Set `FIREBIRD_ROOT_PASSWORD` if you need a stable `SYSDBA` password. + +A security database changed since the image was built (e.g. a persisted `/opt/firebird/security5.fdb` bind-mounted into the container) is left untouched. + ### `FIREBIRD_USER` diff --git a/src/entrypoint.sh b/src/entrypoint.sh index 21a0cfa..f249fd7 100644 --- a/src/entrypoint.sh +++ b/src/entrypoint.sh @@ -142,39 +142,96 @@ set_config() { fi } -# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. -set_sysdba() { - read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' - if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then - echo 'Changing SYSDBA password.' +# Security database as shipped in the image, and its checksum recorded at image build time. +SECURITY_DB_CHECKSUM_FILE=/opt/firebird/.security.fdb.sha256 + +# usage: generate_password +# Prints a random 20-character alphanumeric password. +generate_password() { + local password + password=$(head -c 512 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9') + printf '%s' "${password:0:20}" +} - local escaped_password - escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") +# usage: change_sysdba_password PASSWORD +# Sets SYSDBA password in the security database (also for Legacy_UserManager if FIREBIRD_USE_LEGACY_AUTH is 'true'). +change_sysdba_password() { + local escaped_password + escaped_password=$(escape_sql_string "$1") - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL - if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then - # [Tabs ahead] - /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL - fi + fi +} +# Sets SYSDBA password. +# If FIREBIRD_ROOT_PASSWORD variable is set, uses it and removes /opt/firebird/SYSDBA.password. +# Otherwise, if the security database is still the one shipped in the image, generates a random password and stores it +# in /opt/firebird/SYSDBA.password. The password generated by the Firebird installer at image build time is the same +# for every container of an image. See https://github.com/FirebirdSQL/firebird-docker/issues/48 +# A security database changed since the image build (by a previous start of this container, or bind-mounted by +# the user) is left untouched. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + change_sysdba_password "$FIREBIRD_ROOT_PASSWORD" rm -rf /opt/firebird/SYSDBA.password + elif sha256sum --status --check "$SECURITY_DB_CHECKSUM_FILE" 2>/dev/null; then + echo 'Generating random SYSDBA password.' + + local password + password=$(generate_password) + change_sysdba_password "$password" + + # Stores it using the same format of Firebird installer. + # The file is read-only (0440): removes and recreates it. + rm -f /opt/firebird/SYSDBA.password + # [Tabs ahead] + (umask 0337; cat > /opt/firebird/SYSDBA.password <<-EOL + # + # Firebird generated password for user SYSDBA is: + # + ISC_USER=sysdba + ISC_PASSWORD=${password} + # + # Also set legacy variable though it can't be exported directly + # + ISC_PASSWD=${password} + # + # generated on ${HOSTNAME} at time $(date) + # + # Your password can be changed to a more suitable one using + # SQL operator ALTER USER. + # + EOL + ) + + # The password is not printed: container logs are often readable by more people than the container itself. + echo 'SYSDBA password stored in /opt/firebird/SYSDBA.password.' fi } # Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +# Runs before any other initialization step, so an invalid configuration fails without changing anything. requires_user_password() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then # [Tabs ahead] cat >&2 <<-EOL @@ -190,11 +247,7 @@ requires_user_password() { # Create Firebird user. create_user() { - read_from_file_or_env 'FIREBIRD_USER' - read_from_file_or_env 'FIREBIRD_PASSWORD' - if [ -n "$FIREBIRD_USER" ]; then - requires_user_password echo "Creating user '$FIREBIRD_USER'..." local quoted_user @@ -345,6 +398,7 @@ run_daemon_and_wait() { # main() # if [ "$1" = 'firebird' ]; then + requires_user_password set_config set_sysdba diff --git a/src/image.tests.ps1 b/src/image.tests.ps1 index 3689c07..f8243c5 100644 --- a/src/image.tests.ps1 +++ b/src/image.tests.ps1 @@ -284,11 +284,136 @@ task FIREBIRD_USER_can_create_user { docker exec $cId test -f /opt/firebird/SYSDBA.password | ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected SYSDBA.password file to exist when a new user is created." + # SYSDBA password from SYSDBA.password file still works? + $sysdbaPassword = docker exec $cId awk -F= '/^ISC_PASSWORD/{print $2}' /opt/firebird/SYSDBA.password + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u SYSDBA -p $sysdbaPassword inet:///var/lib/firebird/data/test.fdb | + ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected successful login with SYSDBA password from SYSDBA.password file when a new user is created." + docker logs $cId | Contains -Pattern "Creating user 'alice'" -ErrorMessage "Expected log message indicating creation of user 'alice'." } } +task SYSDBA_password_file_allows_remote_login { + # Stock container, no environment variables: the password generated by the Firebird installer must work. + # https://github.com/FirebirdSQL/firebird-docker/issues/47 + Use-Container -ScriptBlock { + param($cId) + + $sysdbaPassword = docker exec $cId awk -F= '/^ISC_PASSWORD/{print $2}' /opt/firebird/SYSDBA.password + assert $sysdbaPassword "Expected SYSDBA.password file to contain ISC_PASSWORD." + + # Correct password (creates the database through the server, which authenticates the user) + "CREATE DATABASE 'inet:///var/lib/firebird/data/test.fdb' USER 'SYSDBA' PASSWORD '$sysdbaPassword';" | + docker exec -i $cId isql -b -q | + ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected CREATE DATABASE over the network to succeed with SYSDBA password from SYSDBA.password file." + + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u SYSDBA -p $sysdbaPassword inet:///var/lib/firebird/data/test.fdb | + ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected successful login with SYSDBA password from SYSDBA.password file." + + # Incorrect password + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u SYSDBA -p tiger inet:///var/lib/firebird/data/test.fdb 2>&1 | + ExitCodeIs -ExpectedValue 1 -ErrorMessage "Expected failed login with incorrect SYSDBA password." + } +} + +task SYSDBA_password_is_generated_on_container_first_start { + # The password generated by the Firebird installer at image build time is the same for every container of an image. + # https://github.com/FirebirdSQL/firebird-docker/issues/48 + $imagePassword = docker run --rm $env:FULL_IMAGE_NAME awk -F= '/^ISC_PASSWORD/{print $2}' /opt/firebird/SYSDBA.password + assert $imagePassword "Expected SYSDBA.password file in the image to contain ISC_PASSWORD." + + Use-Container -Parameters '-e', 'FIREBIRD_DATABASE=test.fdb' { + param($cId) + + $sysdbaPassword = docker exec $cId awk -F= '/^ISC_PASSWORD/{print $2}' /opt/firebird/SYSDBA.password + assert ($sysdbaPassword -cmatch '^[A-Za-z0-9]{20}$') "Expected a 20-character alphanumeric SYSDBA password, got '$sysdbaPassword'." + assert ($sysdbaPassword -cne $imagePassword) "Expected SYSDBA password to differ from the one generated at image build time." + + # Generated password + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u SYSDBA -p $sysdbaPassword inet:///var/lib/firebird/data/test.fdb | + ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected successful login with generated SYSDBA password." + + # Password generated at image build time + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u SYSDBA -p $imagePassword inet:///var/lib/firebird/data/test.fdb 2>&1 | + ExitCodeIs -ExpectedValue 1 -ErrorMessage "Expected failed login with SYSDBA password generated at image build time." + + $logs = docker logs $cId + $logs | Contains -Pattern 'SYSDBA password stored in /opt/firebird/SYSDBA.password' -ErrorMessage "Expected log message indicating where the generated SYSDBA password is stored." + $logs | ContainsExactly -Pattern $sysdbaPassword -ExpectedCount 0 -ErrorMessage "Expected generated SYSDBA password to not be printed in the log." + + # Restarting the container keeps the password. + docker restart --time 5 $cId > $null + Wait-Port -ContainerName $cId -Port 3050 + + $passwordAfterRestart = docker exec $cId awk -F= '/^ISC_PASSWORD/{print $2}' /opt/firebird/SYSDBA.password + assert ($passwordAfterRestart -ceq $sysdbaPassword) "Expected SYSDBA password to be kept after container restart." + + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u SYSDBA -p $sysdbaPassword inet:///var/lib/firebird/data/test.fdb | + ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected successful login with generated SYSDBA password after container restart." + + docker logs $cId | + ContainsExactly -Pattern 'Generating random SYSDBA password' -ExpectedCount 1 -ErrorMessage "Expected SYSDBA password to be generated only once." + } +} + +task FIREBIRD_USE_LEGACY_AUTH_generated_sysdba_password_works_with_legacy_auth { + # Only Legacy_Auth is accepted by the server: the generated password must also be set for Legacy_UserManager. + Use-Container -Parameters '-e', 'FIREBIRD_DATABASE=test.fdb', '-e', 'FIREBIRD_USE_LEGACY_AUTH=true', '-e', 'FIREBIRD_CONF_AuthServer=Legacy_Auth' { + param($cId) + + $sysdbaPassword = docker exec $cId awk -F= '/^ISC_PASSWORD/{print $2}' /opt/firebird/SYSDBA.password + + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u SYSDBA -p $sysdbaPassword inet:///var/lib/firebird/data/test.fdb | + ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected successful Legacy_Auth login with generated SYSDBA password." + + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u SYSDBA -p tiger inet:///var/lib/firebird/data/test.fdb 2>&1 | + ExitCodeIs -ExpectedValue 1 -ErrorMessage "Expected failed Legacy_Auth login with incorrect SYSDBA password." + } +} + +task SYSDBA_password_is_kept_for_bind_mounted_security_database { + # A security database persisted outside the container (changed since the image build) must be left untouched. + # https://github.com/FirebirdSQL/firebird-docker/issues/5 + $securityDbFolder = New-TemporaryDirectory + try { + $securityDb = "security$(docker run --rm $env:FULL_IMAGE_NAME printenv FIREBIRD_MAJOR).fdb" + + # Extract a security database with a known SYSDBA password. + $cId = docker run --detach --tmpfs /var/lib/firebird/data -e FIREBIRD_ROOT_PASSWORD=passw0rd $env:FULL_IMAGE_NAME + try { + Wait-Port -ContainerName $cId -Port 3050 + docker stop --time 5 $cId > $null + docker cp "$($cId):/opt/firebird/$securityDb" "$securityDbFolder" > $null + } + finally { + docker rm --force $cId > $null + } + + Use-Container -Parameters '-e', 'FIREBIRD_DATABASE=test.fdb', '-v', "$(Join-Path $securityDbFolder $securityDb):/opt/firebird/$securityDb" { + param($cId) + + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u SYSDBA -p passw0rd inet:///var/lib/firebird/data/test.fdb | + ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected successful login with SYSDBA password stored in the bind-mounted security database." + + docker logs $cId | + ContainsExactly -Pattern 'Generating random SYSDBA password' -ExpectedCount 0 -ErrorMessage "Expected no SYSDBA password generation for a bind-mounted security database." + } + } + finally { + Remove-Item $securityDbFolder -Force -Recurse + } +} + task FIREBIRD_ROOT_PASSWORD_can_change_sysdba_password { Use-Container -Parameters '-e', 'FIREBIRD_DATABASE=test.fdb', '-e', 'FIREBIRD_ROOT_PASSWORD=passw0rd' { param($cId)