diff --git a/CHANGELOG.md b/CHANGELOG.md index 06dc09c8..d05268ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [Unreleased] + +- Build the release kit from the signed release tag instead of downloading + it, so that the Composer dependencies are locked for the PHP version of the + image and can be refreshed to fix vulnerabilities for the lifetime of the + version (#472) + ## [5.2.3.1] - 2025-10-08 - Remove leftover uploadprogress.tar.gz download after installation (#465) diff --git a/Dockerfile-alpine.template b/Dockerfile-alpine.template index 1611ca0b..0a1e7635 100644 --- a/Dockerfile-alpine.template +++ b/Dockerfile-alpine.template @@ -1,3 +1,81 @@ +# Build the release kit from the signed release tag instead of downloading it, so +# that the dependencies are locked for the PHP version of this image and can be +# updated to fix vulnerabilities for the lifetime of the version. +# See https://github.com/phpmyadmin/docker/issues/472 +FROM --platform=$BUILDPLATFORM php:%%PHP_VERSION%%-cli-trixie AS phpmyadmin-kit + +ENV PMA_VERSION="%%VERSION%%" \ + PMA_BRANCH="%%RELEASE_BRANCH%%" \ + PMA_TAG="%%TAG%%" \ + PMA_COMMIT="%%PMA_COMMIT%%" \ + PMA_GPG_KEY="%%GPG_KEY%%" \ + COREPACK_ENABLE_DOWNLOAD_PROMPT="0" + +# Official image, so no installer is downloaded from getcomposer.org +COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gettext \ + git \ + gnupg \ + libfreetype6-dev \ + libjpeg62-turbo-dev \ + libpng-dev \ + libzip-dev \ + make \ + nodejs \ + python3-sphinx \ + xz-utils \ + ; \ + docker-php-ext-install gd mysqli zip; \ + corepack enable; \ + rm -rf /var/lib/apt/lists/*; \ + echo 'memory_limit = 512M' > "$PHP_INI_DIR/conf.d/zz-build.ini" + +# The release tag must be signed by the phpMyAdmin release key and point at the +# commit pinned in the generated Dockerfile +RUN set -eux; \ + git init /src; \ + cd /src; \ + git remote add origin https://github.com/phpmyadmin/phpmyadmin.git; \ + git fetch --depth 1 origin "refs/tags/${PMA_TAG}:refs/tags/${PMA_TAG}"; \ + test "$(git rev-parse "${PMA_TAG}^{commit}")" = "$PMA_COMMIT"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver pgp.mit.edu --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver keys.openpgp.org --recv-keys "$PMA_GPG_KEY" \ + ; \ + gpg --batch --with-colons --list-keys "$PMA_GPG_KEY" | grep -q "^fpr:.*:${PMA_GPG_KEY}:"; \ + git verify-tag --raw "$PMA_TAG" > /tmp/verify-tag.log 2>&1; \ + ! grep -qE "REVKEYSIG|EXPKEYSIG|EXPSIG|BADSIG|ERRSIG" /tmp/verify-tag.log; \ + grep -qE "^\[GNUPG:\] VALIDSIG [0-9A-F]+ [0-9-]+ [0-9]+ .*${PMA_GPG_KEY}( |$)" /tmp/verify-tag.log; \ + git checkout -B "$PMA_BRANCH" "$PMA_COMMIT"; \ + gpgconf --kill all; \ + rm -r "$GNUPGHOME" + +# create-release.sh locks the dependencies for the minimum PHP version it +# parses out of composer.json, lock them for the one of this image instead +RUN set -eux; \ + cd /src; \ + php_version="$(php -r 'echo PHP_VERSION;')"; \ + sed -i "s|^PHP_REQ=.*|PHP_REQ=\"${php_version}\"|" scripts/create-release.sh; \ + grep -q "^PHP_REQ=\"${php_version}\"$" scripts/create-release.sh; \ + echo y | ./scripts/create-release.sh "$PMA_VERSION" "$PMA_BRANCH" \ + --kits all-languages --compressions txz --no-sign; \ + sha256sum "/src/release/phpMyAdmin-${PMA_VERSION}-all-languages.tar.xz" + +# Show the advisories left in the kit that actually ships +RUN set -eux; \ + mkdir -p /kit; \ + tar -xf "/src/release/phpMyAdmin-${PMA_VERSION}-all-languages.tar.xz" -C /kit --strip-components=1; \ + cd /kit; \ + composer --version; \ + composer audit --no-dev --format=table || true + FROM php:%%PHP_VERSION%%-%%VARIANT%% ENV UPLOAD_PROGRESS_EXT_URL="https://github.com/php/pecl-php-uploadprogress/archive/refs/tags/uploadprogress-2.0.2.tar.gz" @@ -6,8 +84,7 @@ ENV UPLOAD_PROGRESS_SHA256="fe3f6cdfcedad563c970c4fd1cda31e422cfc0df5cc9a217d8c8 # install and docker-entrypoint.sh dependencies RUN apk add --no-cache \ bash \ - tzdata \ - gnupg + tzdata # Install dependencies RUN set -ex; \ @@ -92,10 +169,8 @@ RUN set -ex; \ USER www-data:www-data -# Calculate download URL +# Version of phpMyAdmin built above ENV VERSION=%%VERSION%% -ENV SHA256=%%SHA256%% -ENV URL=https://files.phpmyadmin.net/phpMyAdmin/${VERSION}/phpMyAdmin-${VERSION}-all-languages.tar.xz LABEL org.opencontainers.image.title="Official phpMyAdmin Docker image" \ org.opencontainers.image.description="Run phpMyAdmin with Alpine, Apache and PHP FPM." \ @@ -107,23 +182,12 @@ LABEL org.opencontainers.image.title="Official phpMyAdmin Docker image" \ org.opencontainers.image.url="https://github.com/phpmyadmin/docker#readme" \ org.opencontainers.image.source="https://github.com/phpmyadmin/docker.git" -# Download tarball, verify it using gpg and extract +# Copy the kit built from the signed release tag +COPY --chown=www-data:www-data --from=phpmyadmin-kit /kit/ /var/www/html/ + RUN set -ex; \ \ - export GNUPGHOME="$(mktemp -d)"; \ - export GPGKEY="%%GPG_KEY%%"; \ - curl -fsSL -o phpMyAdmin.tar.xz $URL; \ - curl -fsSL -o phpMyAdmin.tar.xz.asc $URL.asc; \ - echo "$SHA256 *phpMyAdmin.tar.xz" | sha256sum -c -; \ - gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver pgp.mit.edu --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver keys.openpgp.org --recv-keys "$GPGKEY"; \ - gpg --batch --verify phpMyAdmin.tar.xz.asc phpMyAdmin.tar.xz; \ - tar -xf phpMyAdmin.tar.xz -C /var/www/html --strip-components=1; \ mkdir -p /var/www/html/tmp; \ - gpgconf --kill all; \ - rm -r "$GNUPGHOME" phpMyAdmin.tar.xz phpMyAdmin.tar.xz.asc; \ rm -r -v /var/www/html/setup/ /var/www/html/examples/ /var/www/html/js/src/ /var/www/html/babel.config.json /var/www/html/doc/html/_sources/ /var/www/html/RELEASE-DATE-$VERSION /var/www/html/CONTRIBUTING.md; \ grep -q -F "'configFile' => ROOT_PATH . 'config.inc.php'," /var/www/html/libraries/vendor_config.php; \ sed -i "s@'configFile' => .*@'configFile' => '/etc/phpmyadmin/config.inc.php',@" /var/www/html/libraries/vendor_config.php; \ diff --git a/Dockerfile-debian.template b/Dockerfile-debian.template index f8b424b4..48c9fcad 100644 --- a/Dockerfile-debian.template +++ b/Dockerfile-debian.template @@ -1,3 +1,81 @@ +# Build the release kit from the signed release tag instead of downloading it, so +# that the dependencies are locked for the PHP version of this image and can be +# updated to fix vulnerabilities for the lifetime of the version. +# See https://github.com/phpmyadmin/docker/issues/472 +FROM --platform=$BUILDPLATFORM php:%%PHP_VERSION%%-cli-trixie AS phpmyadmin-kit + +ENV PMA_VERSION="%%VERSION%%" \ + PMA_BRANCH="%%RELEASE_BRANCH%%" \ + PMA_TAG="%%TAG%%" \ + PMA_COMMIT="%%PMA_COMMIT%%" \ + PMA_GPG_KEY="%%GPG_KEY%%" \ + COREPACK_ENABLE_DOWNLOAD_PROMPT="0" + +# Official image, so no installer is downloaded from getcomposer.org +COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gettext \ + git \ + gnupg \ + libfreetype6-dev \ + libjpeg62-turbo-dev \ + libpng-dev \ + libzip-dev \ + make \ + nodejs \ + python3-sphinx \ + xz-utils \ + ; \ + docker-php-ext-install gd mysqli zip; \ + corepack enable; \ + rm -rf /var/lib/apt/lists/*; \ + echo 'memory_limit = 512M' > "$PHP_INI_DIR/conf.d/zz-build.ini" + +# The release tag must be signed by the phpMyAdmin release key and point at the +# commit pinned in the generated Dockerfile +RUN set -eux; \ + git init /src; \ + cd /src; \ + git remote add origin https://github.com/phpmyadmin/phpmyadmin.git; \ + git fetch --depth 1 origin "refs/tags/${PMA_TAG}:refs/tags/${PMA_TAG}"; \ + test "$(git rev-parse "${PMA_TAG}^{commit}")" = "$PMA_COMMIT"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver pgp.mit.edu --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver keys.openpgp.org --recv-keys "$PMA_GPG_KEY" \ + ; \ + gpg --batch --with-colons --list-keys "$PMA_GPG_KEY" | grep -q "^fpr:.*:${PMA_GPG_KEY}:"; \ + git verify-tag --raw "$PMA_TAG" > /tmp/verify-tag.log 2>&1; \ + ! grep -qE "REVKEYSIG|EXPKEYSIG|EXPSIG|BADSIG|ERRSIG" /tmp/verify-tag.log; \ + grep -qE "^\[GNUPG:\] VALIDSIG [0-9A-F]+ [0-9-]+ [0-9]+ .*${PMA_GPG_KEY}( |$)" /tmp/verify-tag.log; \ + git checkout -B "$PMA_BRANCH" "$PMA_COMMIT"; \ + gpgconf --kill all; \ + rm -r "$GNUPGHOME" + +# create-release.sh locks the dependencies for the minimum PHP version it +# parses out of composer.json, lock them for the one of this image instead +RUN set -eux; \ + cd /src; \ + php_version="$(php -r 'echo PHP_VERSION;')"; \ + sed -i "s|^PHP_REQ=.*|PHP_REQ=\"${php_version}\"|" scripts/create-release.sh; \ + grep -q "^PHP_REQ=\"${php_version}\"$" scripts/create-release.sh; \ + echo y | ./scripts/create-release.sh "$PMA_VERSION" "$PMA_BRANCH" \ + --kits all-languages --compressions txz --no-sign; \ + sha256sum "/src/release/phpMyAdmin-${PMA_VERSION}-all-languages.tar.xz" + +# Show the advisories left in the kit that actually ships +RUN set -eux; \ + mkdir -p /kit; \ + tar -xf "/src/release/phpMyAdmin-${PMA_VERSION}-all-languages.tar.xz" -C /kit --strip-components=1; \ + cd /kit; \ + composer --version; \ + composer audit --no-dev --format=table || true + FROM php:%%PHP_VERSION%%-%%VARIANT%% ENV UPLOAD_PROGRESS_EXT_URL="https://github.com/php/pecl-php-uploadprogress/archive/refs/tags/uploadprogress-2.0.2.tar.gz" @@ -7,10 +85,6 @@ ENV UPLOAD_PROGRESS_SHA256="fe3f6cdfcedad563c970c4fd1cda31e422cfc0df5cc9a217d8c8 RUN set -ex; \ \ apt-get update; \ - apt-get install -y --no-install-recommends \ - gnupg \ - dirmngr \ - ; \ \ savedAptMark="$(apt-mark showmanual)"; \ \ @@ -107,10 +181,8 @@ RUN set -ex; \ USER www-data:www-data -# Calculate download URL +# Version of phpMyAdmin built above ENV VERSION=%%VERSION%% -ENV SHA256=%%SHA256%% -ENV URL=https://files.phpmyadmin.net/phpMyAdmin/${VERSION}/phpMyAdmin-${VERSION}-all-languages.tar.xz LABEL org.opencontainers.image.title="Official phpMyAdmin Docker image" \ org.opencontainers.image.description="Run phpMyAdmin with Alpine, Apache and PHP FPM." \ @@ -122,22 +194,11 @@ LABEL org.opencontainers.image.title="Official phpMyAdmin Docker image" \ org.opencontainers.image.url="https://github.com/phpmyadmin/docker#readme" \ org.opencontainers.image.source="https://github.com/phpmyadmin/docker.git" -# Download tarball, verify it using gpg and extract +# Copy the kit built from the signed release tag +COPY --chown=www-data:www-data --from=phpmyadmin-kit /kit/ /var/www/html/ + RUN set -ex; \ - export GNUPGHOME="$(mktemp -d)"; \ - export GPGKEY="%%GPG_KEY%%"; \ - curl -fsSL -o phpMyAdmin.tar.xz $URL; \ - curl -fsSL -o phpMyAdmin.tar.xz.asc $URL.asc; \ - echo "$SHA256 *phpMyAdmin.tar.xz" | sha256sum -c -; \ - gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver pgp.mit.edu --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver keys.openpgp.org --recv-keys "$GPGKEY"; \ - gpg --batch --verify phpMyAdmin.tar.xz.asc phpMyAdmin.tar.xz; \ - tar -xf phpMyAdmin.tar.xz -C /var/www/html --strip-components=1; \ mkdir -p /var/www/html/tmp; \ - gpgconf --kill all; \ - rm -r "$GNUPGHOME" phpMyAdmin.tar.xz phpMyAdmin.tar.xz.asc; \ rm -r -v /var/www/html/setup/ /var/www/html/examples/ /var/www/html/js/src/ /var/www/html/babel.config.json /var/www/html/doc/html/_sources/ /var/www/html/RELEASE-DATE-$VERSION /var/www/html/CONTRIBUTING.md; \ grep -q -F "'configFile' => ROOT_PATH . 'config.inc.php'," /var/www/html/libraries/vendor_config.php; \ sed -i "s@'configFile' => .*@'configFile' => '/etc/phpmyadmin/config.inc.php',@" /var/www/html/libraries/vendor_config.php; \ diff --git a/apache/Dockerfile b/apache/Dockerfile index eaf234e4..811766bc 100644 --- a/apache/Dockerfile +++ b/apache/Dockerfile @@ -1,4 +1,82 @@ # DO NOT EDIT: created by update.sh from Dockerfile-debian.template +# Build the release kit from the signed release tag instead of downloading it, so +# that the dependencies are locked for the PHP version of this image and can be +# updated to fix vulnerabilities for the lifetime of the version. +# See https://github.com/phpmyadmin/docker/issues/472 +FROM --platform=$BUILDPLATFORM php:8.3-cli-trixie AS phpmyadmin-kit + +ENV PMA_VERSION="5.2.3" \ + PMA_BRANCH="QA_5_2" \ + PMA_TAG="RELEASE_5_2_3" \ + PMA_COMMIT="962857e4f63d42e38f11ff4d63f5e722018add76" \ + PMA_GPG_KEY="3D06A59ECE730EB71B511C17CE752F178259BD92" \ + COREPACK_ENABLE_DOWNLOAD_PROMPT="0" + +# Official image, so no installer is downloaded from getcomposer.org +COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gettext \ + git \ + gnupg \ + libfreetype6-dev \ + libjpeg62-turbo-dev \ + libpng-dev \ + libzip-dev \ + make \ + nodejs \ + python3-sphinx \ + xz-utils \ + ; \ + docker-php-ext-install gd mysqli zip; \ + corepack enable; \ + rm -rf /var/lib/apt/lists/*; \ + echo 'memory_limit = 512M' > "$PHP_INI_DIR/conf.d/zz-build.ini" + +# The release tag must be signed by the phpMyAdmin release key and point at the +# commit pinned in the generated Dockerfile +RUN set -eux; \ + git init /src; \ + cd /src; \ + git remote add origin https://github.com/phpmyadmin/phpmyadmin.git; \ + git fetch --depth 1 origin "refs/tags/${PMA_TAG}:refs/tags/${PMA_TAG}"; \ + test "$(git rev-parse "${PMA_TAG}^{commit}")" = "$PMA_COMMIT"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver pgp.mit.edu --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver keys.openpgp.org --recv-keys "$PMA_GPG_KEY" \ + ; \ + gpg --batch --with-colons --list-keys "$PMA_GPG_KEY" | grep -q "^fpr:.*:${PMA_GPG_KEY}:"; \ + git verify-tag --raw "$PMA_TAG" > /tmp/verify-tag.log 2>&1; \ + ! grep -qE "REVKEYSIG|EXPKEYSIG|EXPSIG|BADSIG|ERRSIG" /tmp/verify-tag.log; \ + grep -qE "^\[GNUPG:\] VALIDSIG [0-9A-F]+ [0-9-]+ [0-9]+ .*${PMA_GPG_KEY}( |$)" /tmp/verify-tag.log; \ + git checkout -B "$PMA_BRANCH" "$PMA_COMMIT"; \ + gpgconf --kill all; \ + rm -r "$GNUPGHOME" + +# create-release.sh locks the dependencies for the minimum PHP version it +# parses out of composer.json, lock them for the one of this image instead +RUN set -eux; \ + cd /src; \ + php_version="$(php -r 'echo PHP_VERSION;')"; \ + sed -i "s|^PHP_REQ=.*|PHP_REQ=\"${php_version}\"|" scripts/create-release.sh; \ + grep -q "^PHP_REQ=\"${php_version}\"$" scripts/create-release.sh; \ + echo y | ./scripts/create-release.sh "$PMA_VERSION" "$PMA_BRANCH" \ + --kits all-languages --compressions txz --no-sign; \ + sha256sum "/src/release/phpMyAdmin-${PMA_VERSION}-all-languages.tar.xz" + +# Show the advisories left in the kit that actually ships +RUN set -eux; \ + mkdir -p /kit; \ + tar -xf "/src/release/phpMyAdmin-${PMA_VERSION}-all-languages.tar.xz" -C /kit --strip-components=1; \ + cd /kit; \ + composer --version; \ + composer audit --no-dev --format=table || true + FROM php:8.3-apache ENV UPLOAD_PROGRESS_EXT_URL="https://github.com/php/pecl-php-uploadprogress/archive/refs/tags/uploadprogress-2.0.2.tar.gz" @@ -8,10 +86,6 @@ ENV UPLOAD_PROGRESS_SHA256="fe3f6cdfcedad563c970c4fd1cda31e422cfc0df5cc9a217d8c8 RUN set -ex; \ \ apt-get update; \ - apt-get install -y --no-install-recommends \ - gnupg \ - dirmngr \ - ; \ \ savedAptMark="$(apt-mark showmanual)"; \ \ @@ -108,10 +182,8 @@ RUN set -ex; \ USER www-data:www-data -# Calculate download URL +# Version of phpMyAdmin built above ENV VERSION=5.2.3 -ENV SHA256=57881348297c4412f86c410547cf76b4d8a236574dd2c6b7d6a2beebe7fc44e3 -ENV URL=https://files.phpmyadmin.net/phpMyAdmin/${VERSION}/phpMyAdmin-${VERSION}-all-languages.tar.xz LABEL org.opencontainers.image.title="Official phpMyAdmin Docker image" \ org.opencontainers.image.description="Run phpMyAdmin with Alpine, Apache and PHP FPM." \ @@ -123,22 +195,11 @@ LABEL org.opencontainers.image.title="Official phpMyAdmin Docker image" \ org.opencontainers.image.url="https://github.com/phpmyadmin/docker#readme" \ org.opencontainers.image.source="https://github.com/phpmyadmin/docker.git" -# Download tarball, verify it using gpg and extract +# Copy the kit built from the signed release tag +COPY --chown=www-data:www-data --from=phpmyadmin-kit /kit/ /var/www/html/ + RUN set -ex; \ - export GNUPGHOME="$(mktemp -d)"; \ - export GPGKEY="3D06A59ECE730EB71B511C17CE752F178259BD92"; \ - curl -fsSL -o phpMyAdmin.tar.xz $URL; \ - curl -fsSL -o phpMyAdmin.tar.xz.asc $URL.asc; \ - echo "$SHA256 *phpMyAdmin.tar.xz" | sha256sum -c -; \ - gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver pgp.mit.edu --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver keys.openpgp.org --recv-keys "$GPGKEY"; \ - gpg --batch --verify phpMyAdmin.tar.xz.asc phpMyAdmin.tar.xz; \ - tar -xf phpMyAdmin.tar.xz -C /var/www/html --strip-components=1; \ mkdir -p /var/www/html/tmp; \ - gpgconf --kill all; \ - rm -r "$GNUPGHOME" phpMyAdmin.tar.xz phpMyAdmin.tar.xz.asc; \ rm -r -v /var/www/html/setup/ /var/www/html/examples/ /var/www/html/js/src/ /var/www/html/babel.config.json /var/www/html/doc/html/_sources/ /var/www/html/RELEASE-DATE-$VERSION /var/www/html/CONTRIBUTING.md; \ grep -q -F "'configFile' => ROOT_PATH . 'config.inc.php'," /var/www/html/libraries/vendor_config.php; \ sed -i "s@'configFile' => .*@'configFile' => '/etc/phpmyadmin/config.inc.php',@" /var/www/html/libraries/vendor_config.php; \ diff --git a/fpm-alpine/Dockerfile b/fpm-alpine/Dockerfile index dcac4fcd..52d9e4b2 100644 --- a/fpm-alpine/Dockerfile +++ b/fpm-alpine/Dockerfile @@ -1,4 +1,82 @@ # DO NOT EDIT: created by update.sh from Dockerfile-alpine.template +# Build the release kit from the signed release tag instead of downloading it, so +# that the dependencies are locked for the PHP version of this image and can be +# updated to fix vulnerabilities for the lifetime of the version. +# See https://github.com/phpmyadmin/docker/issues/472 +FROM --platform=$BUILDPLATFORM php:8.3-cli-trixie AS phpmyadmin-kit + +ENV PMA_VERSION="5.2.3" \ + PMA_BRANCH="QA_5_2" \ + PMA_TAG="RELEASE_5_2_3" \ + PMA_COMMIT="962857e4f63d42e38f11ff4d63f5e722018add76" \ + PMA_GPG_KEY="3D06A59ECE730EB71B511C17CE752F178259BD92" \ + COREPACK_ENABLE_DOWNLOAD_PROMPT="0" + +# Official image, so no installer is downloaded from getcomposer.org +COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gettext \ + git \ + gnupg \ + libfreetype6-dev \ + libjpeg62-turbo-dev \ + libpng-dev \ + libzip-dev \ + make \ + nodejs \ + python3-sphinx \ + xz-utils \ + ; \ + docker-php-ext-install gd mysqli zip; \ + corepack enable; \ + rm -rf /var/lib/apt/lists/*; \ + echo 'memory_limit = 512M' > "$PHP_INI_DIR/conf.d/zz-build.ini" + +# The release tag must be signed by the phpMyAdmin release key and point at the +# commit pinned in the generated Dockerfile +RUN set -eux; \ + git init /src; \ + cd /src; \ + git remote add origin https://github.com/phpmyadmin/phpmyadmin.git; \ + git fetch --depth 1 origin "refs/tags/${PMA_TAG}:refs/tags/${PMA_TAG}"; \ + test "$(git rev-parse "${PMA_TAG}^{commit}")" = "$PMA_COMMIT"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver pgp.mit.edu --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver keys.openpgp.org --recv-keys "$PMA_GPG_KEY" \ + ; \ + gpg --batch --with-colons --list-keys "$PMA_GPG_KEY" | grep -q "^fpr:.*:${PMA_GPG_KEY}:"; \ + git verify-tag --raw "$PMA_TAG" > /tmp/verify-tag.log 2>&1; \ + ! grep -qE "REVKEYSIG|EXPKEYSIG|EXPSIG|BADSIG|ERRSIG" /tmp/verify-tag.log; \ + grep -qE "^\[GNUPG:\] VALIDSIG [0-9A-F]+ [0-9-]+ [0-9]+ .*${PMA_GPG_KEY}( |$)" /tmp/verify-tag.log; \ + git checkout -B "$PMA_BRANCH" "$PMA_COMMIT"; \ + gpgconf --kill all; \ + rm -r "$GNUPGHOME" + +# create-release.sh locks the dependencies for the minimum PHP version it +# parses out of composer.json, lock them for the one of this image instead +RUN set -eux; \ + cd /src; \ + php_version="$(php -r 'echo PHP_VERSION;')"; \ + sed -i "s|^PHP_REQ=.*|PHP_REQ=\"${php_version}\"|" scripts/create-release.sh; \ + grep -q "^PHP_REQ=\"${php_version}\"$" scripts/create-release.sh; \ + echo y | ./scripts/create-release.sh "$PMA_VERSION" "$PMA_BRANCH" \ + --kits all-languages --compressions txz --no-sign; \ + sha256sum "/src/release/phpMyAdmin-${PMA_VERSION}-all-languages.tar.xz" + +# Show the advisories left in the kit that actually ships +RUN set -eux; \ + mkdir -p /kit; \ + tar -xf "/src/release/phpMyAdmin-${PMA_VERSION}-all-languages.tar.xz" -C /kit --strip-components=1; \ + cd /kit; \ + composer --version; \ + composer audit --no-dev --format=table || true + FROM php:8.3-fpm-alpine ENV UPLOAD_PROGRESS_EXT_URL="https://github.com/php/pecl-php-uploadprogress/archive/refs/tags/uploadprogress-2.0.2.tar.gz" @@ -7,8 +85,7 @@ ENV UPLOAD_PROGRESS_SHA256="fe3f6cdfcedad563c970c4fd1cda31e422cfc0df5cc9a217d8c8 # install and docker-entrypoint.sh dependencies RUN apk add --no-cache \ bash \ - tzdata \ - gnupg + tzdata # Install dependencies RUN set -ex; \ @@ -93,10 +170,8 @@ RUN set -ex; \ USER www-data:www-data -# Calculate download URL +# Version of phpMyAdmin built above ENV VERSION=5.2.3 -ENV SHA256=57881348297c4412f86c410547cf76b4d8a236574dd2c6b7d6a2beebe7fc44e3 -ENV URL=https://files.phpmyadmin.net/phpMyAdmin/${VERSION}/phpMyAdmin-${VERSION}-all-languages.tar.xz LABEL org.opencontainers.image.title="Official phpMyAdmin Docker image" \ org.opencontainers.image.description="Run phpMyAdmin with Alpine, Apache and PHP FPM." \ @@ -108,23 +183,12 @@ LABEL org.opencontainers.image.title="Official phpMyAdmin Docker image" \ org.opencontainers.image.url="https://github.com/phpmyadmin/docker#readme" \ org.opencontainers.image.source="https://github.com/phpmyadmin/docker.git" -# Download tarball, verify it using gpg and extract +# Copy the kit built from the signed release tag +COPY --chown=www-data:www-data --from=phpmyadmin-kit /kit/ /var/www/html/ + RUN set -ex; \ \ - export GNUPGHOME="$(mktemp -d)"; \ - export GPGKEY="3D06A59ECE730EB71B511C17CE752F178259BD92"; \ - curl -fsSL -o phpMyAdmin.tar.xz $URL; \ - curl -fsSL -o phpMyAdmin.tar.xz.asc $URL.asc; \ - echo "$SHA256 *phpMyAdmin.tar.xz" | sha256sum -c -; \ - gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver pgp.mit.edu --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver keys.openpgp.org --recv-keys "$GPGKEY"; \ - gpg --batch --verify phpMyAdmin.tar.xz.asc phpMyAdmin.tar.xz; \ - tar -xf phpMyAdmin.tar.xz -C /var/www/html --strip-components=1; \ mkdir -p /var/www/html/tmp; \ - gpgconf --kill all; \ - rm -r "$GNUPGHOME" phpMyAdmin.tar.xz phpMyAdmin.tar.xz.asc; \ rm -r -v /var/www/html/setup/ /var/www/html/examples/ /var/www/html/js/src/ /var/www/html/babel.config.json /var/www/html/doc/html/_sources/ /var/www/html/RELEASE-DATE-$VERSION /var/www/html/CONTRIBUTING.md; \ grep -q -F "'configFile' => ROOT_PATH . 'config.inc.php'," /var/www/html/libraries/vendor_config.php; \ sed -i "s@'configFile' => .*@'configFile' => '/etc/phpmyadmin/config.inc.php',@" /var/www/html/libraries/vendor_config.php; \ diff --git a/fpm/Dockerfile b/fpm/Dockerfile index 4b6fc4b9..7defa52e 100644 --- a/fpm/Dockerfile +++ b/fpm/Dockerfile @@ -1,4 +1,82 @@ # DO NOT EDIT: created by update.sh from Dockerfile-debian.template +# Build the release kit from the signed release tag instead of downloading it, so +# that the dependencies are locked for the PHP version of this image and can be +# updated to fix vulnerabilities for the lifetime of the version. +# See https://github.com/phpmyadmin/docker/issues/472 +FROM --platform=$BUILDPLATFORM php:8.3-cli-trixie AS phpmyadmin-kit + +ENV PMA_VERSION="5.2.3" \ + PMA_BRANCH="QA_5_2" \ + PMA_TAG="RELEASE_5_2_3" \ + PMA_COMMIT="962857e4f63d42e38f11ff4d63f5e722018add76" \ + PMA_GPG_KEY="3D06A59ECE730EB71B511C17CE752F178259BD92" \ + COREPACK_ENABLE_DOWNLOAD_PROMPT="0" + +# Official image, so no installer is downloaded from getcomposer.org +COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gettext \ + git \ + gnupg \ + libfreetype6-dev \ + libjpeg62-turbo-dev \ + libpng-dev \ + libzip-dev \ + make \ + nodejs \ + python3-sphinx \ + xz-utils \ + ; \ + docker-php-ext-install gd mysqli zip; \ + corepack enable; \ + rm -rf /var/lib/apt/lists/*; \ + echo 'memory_limit = 512M' > "$PHP_INI_DIR/conf.d/zz-build.ini" + +# The release tag must be signed by the phpMyAdmin release key and point at the +# commit pinned in the generated Dockerfile +RUN set -eux; \ + git init /src; \ + cd /src; \ + git remote add origin https://github.com/phpmyadmin/phpmyadmin.git; \ + git fetch --depth 1 origin "refs/tags/${PMA_TAG}:refs/tags/${PMA_TAG}"; \ + test "$(git rev-parse "${PMA_TAG}^{commit}")" = "$PMA_COMMIT"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver pgp.mit.edu --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$PMA_GPG_KEY" \ + || gpg --batch --keyserver keys.openpgp.org --recv-keys "$PMA_GPG_KEY" \ + ; \ + gpg --batch --with-colons --list-keys "$PMA_GPG_KEY" | grep -q "^fpr:.*:${PMA_GPG_KEY}:"; \ + git verify-tag --raw "$PMA_TAG" > /tmp/verify-tag.log 2>&1; \ + ! grep -qE "REVKEYSIG|EXPKEYSIG|EXPSIG|BADSIG|ERRSIG" /tmp/verify-tag.log; \ + grep -qE "^\[GNUPG:\] VALIDSIG [0-9A-F]+ [0-9-]+ [0-9]+ .*${PMA_GPG_KEY}( |$)" /tmp/verify-tag.log; \ + git checkout -B "$PMA_BRANCH" "$PMA_COMMIT"; \ + gpgconf --kill all; \ + rm -r "$GNUPGHOME" + +# create-release.sh locks the dependencies for the minimum PHP version it +# parses out of composer.json, lock them for the one of this image instead +RUN set -eux; \ + cd /src; \ + php_version="$(php -r 'echo PHP_VERSION;')"; \ + sed -i "s|^PHP_REQ=.*|PHP_REQ=\"${php_version}\"|" scripts/create-release.sh; \ + grep -q "^PHP_REQ=\"${php_version}\"$" scripts/create-release.sh; \ + echo y | ./scripts/create-release.sh "$PMA_VERSION" "$PMA_BRANCH" \ + --kits all-languages --compressions txz --no-sign; \ + sha256sum "/src/release/phpMyAdmin-${PMA_VERSION}-all-languages.tar.xz" + +# Show the advisories left in the kit that actually ships +RUN set -eux; \ + mkdir -p /kit; \ + tar -xf "/src/release/phpMyAdmin-${PMA_VERSION}-all-languages.tar.xz" -C /kit --strip-components=1; \ + cd /kit; \ + composer --version; \ + composer audit --no-dev --format=table || true + FROM php:8.3-fpm ENV UPLOAD_PROGRESS_EXT_URL="https://github.com/php/pecl-php-uploadprogress/archive/refs/tags/uploadprogress-2.0.2.tar.gz" @@ -8,10 +86,6 @@ ENV UPLOAD_PROGRESS_SHA256="fe3f6cdfcedad563c970c4fd1cda31e422cfc0df5cc9a217d8c8 RUN set -ex; \ \ apt-get update; \ - apt-get install -y --no-install-recommends \ - gnupg \ - dirmngr \ - ; \ \ savedAptMark="$(apt-mark showmanual)"; \ \ @@ -105,10 +179,8 @@ RUN set -ex; \ USER www-data:www-data -# Calculate download URL +# Version of phpMyAdmin built above ENV VERSION=5.2.3 -ENV SHA256=57881348297c4412f86c410547cf76b4d8a236574dd2c6b7d6a2beebe7fc44e3 -ENV URL=https://files.phpmyadmin.net/phpMyAdmin/${VERSION}/phpMyAdmin-${VERSION}-all-languages.tar.xz LABEL org.opencontainers.image.title="Official phpMyAdmin Docker image" \ org.opencontainers.image.description="Run phpMyAdmin with Alpine, Apache and PHP FPM." \ @@ -120,22 +192,11 @@ LABEL org.opencontainers.image.title="Official phpMyAdmin Docker image" \ org.opencontainers.image.url="https://github.com/phpmyadmin/docker#readme" \ org.opencontainers.image.source="https://github.com/phpmyadmin/docker.git" -# Download tarball, verify it using gpg and extract +# Copy the kit built from the signed release tag +COPY --chown=www-data:www-data --from=phpmyadmin-kit /kit/ /var/www/html/ + RUN set -ex; \ - export GNUPGHOME="$(mktemp -d)"; \ - export GPGKEY="3D06A59ECE730EB71B511C17CE752F178259BD92"; \ - curl -fsSL -o phpMyAdmin.tar.xz $URL; \ - curl -fsSL -o phpMyAdmin.tar.xz.asc $URL.asc; \ - echo "$SHA256 *phpMyAdmin.tar.xz" | sha256sum -c -; \ - gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver pgp.mit.edu --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver keyserver.pgp.com --recv-keys "$GPGKEY" \ - || gpg --batch --keyserver keys.openpgp.org --recv-keys "$GPGKEY"; \ - gpg --batch --verify phpMyAdmin.tar.xz.asc phpMyAdmin.tar.xz; \ - tar -xf phpMyAdmin.tar.xz -C /var/www/html --strip-components=1; \ mkdir -p /var/www/html/tmp; \ - gpgconf --kill all; \ - rm -r "$GNUPGHOME" phpMyAdmin.tar.xz phpMyAdmin.tar.xz.asc; \ rm -r -v /var/www/html/setup/ /var/www/html/examples/ /var/www/html/js/src/ /var/www/html/babel.config.json /var/www/html/doc/html/_sources/ /var/www/html/RELEASE-DATE-$VERSION /var/www/html/CONTRIBUTING.md; \ grep -q -F "'configFile' => ROOT_PATH . 'config.inc.php'," /var/www/html/libraries/vendor_config.php; \ sed -i "s@'configFile' => .*@'configFile' => '/etc/phpmyadmin/config.inc.php',@" /var/www/html/libraries/vendor_config.php; \ diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh index 09074e82..28b16d51 100755 --- a/generate-stackbrew-library.sh +++ b/generate-stackbrew-library.sh @@ -18,29 +18,72 @@ dirCommit() { Dockerfile \ $(git show HEAD:./Dockerfile | awk ' toupper($1) == "COPY" { + # a file taken from another build stage is not in the repository + from = 0 + for (i = 2; i <= NF; i++) { + if ($i ~ /^--from=/) { + from = 1 + } + } + if (from) { + next + } + # the last argument is the destination, the options are not paths for (i = 2; i < NF; i++) { - print $i + if ($i !~ /^-/) { + print $i + } } } ') ) } +# the image of the final FROM instruction, without its options +finalFrom() { + awk ' + toupper($1) == "FROM" { + image = "" + for (i = 2; i <= NF; i++) { + if ($i !~ /^-/ && toupper($i) != "AS") { + image = $i + break + } + } + } + END { + if (image != "") { + print image + } + } + ' "$1" +} + getArches() { local repo="$1"; shift local officialImagesUrl='https://github.com/docker-library/official-images/raw/master/library/' eval "declare -A -g parentRepoToArches=( $( find -name 'Dockerfile' -exec awk ' - toupper($1) == "FROM" && $2 !~ /^('"$repo"'|scratch|.*\/.*)(:|$)/ { - print "'"$officialImagesUrl"'" $2 + toupper($1) == "FROM" { + image = "" + for (i = 2; i <= NF; i++) { + if ($i !~ /^-/ && toupper($i) != "AS") { + image = $i + break + } + } } - ' '{}' + \ + END { + if (image != "" && image !~ /^('"$repo"'|scratch|.*\/.*)(:|$)/) { + print "'"$officialImagesUrl"'" image + } + } + ' '{}' \; \ | sort -u \ | xargs bashbrew cat --format '[{{ .RepoName }}:{{ .TagName }}]="{{ join " " .TagEntry.Architectures }}"' ) )" } -getArches 'phpmyadmin' if ! command -v bashbrew --version &> /dev/null then @@ -49,6 +92,8 @@ then exit 1 fi +getArches 'phpmyadmin' + cat <<-EOH # This file is generated via https://github.com/phpmyadmin/docker/blob/$(fileCommit "$self")/$self Maintainers: Isaac Bennetch (@ibennetch), @@ -63,7 +108,7 @@ join() { echo "${out#$sep}" } -latest="$(curl -fsSL 'https://www.phpmyadmin.net/home_page/version.json' | jq -r '.version' | grep -E '^[0-9]{1,}.[0-9]{1,}.[0-9]{1,}$')" +latest="$(curl -fsSL 'https://www.phpmyadmin.net/home_page/version.json' | jq -r '.version' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?$')" for variant in apache fpm fpm-alpine; do commit="$(dirCommit "$variant")" @@ -81,7 +126,7 @@ for variant in apache fpm fpm-alpine; do variantAliases+=( "${versionAliases[@]}" ) fi - variantParent="$(awk 'toupper($1) == "FROM" { print $2 }' "$variant/Dockerfile")" + variantParent="$(finalFrom "$variant/Dockerfile")" variantArches="${parentRepoToArches[$variantParent]}" diff --git a/update.sh b/update.sh index 15f3da11..76f798a0 100755 --- a/update.sh +++ b/update.sh @@ -29,17 +29,73 @@ function download_url() { echo "https://files.phpmyadmin.net/phpMyAdmin/$1/phpMyAdmin-$1-all-languages.tar.xz" } +# Commit the signed release tag points at; the Dockerfiles build from it +# Release tags are RELEASE___[_], the format the +# daily-composer script of phpmyadmin/scripts relies on to process releases +release_tag_re='RELEASE_[0-9]+_[0-9]+_[0-9]+(_[0-9]+)?' + +# The version 5.2.3 is released as the tag RELEASE_5_2_3 +function release_tag() { + local version="$1" + local tag="RELEASE_${version//./_}" + + if ! grep -qE "^${release_tag_re}$" <<< "$tag"; then + echo >&2 "'$version' does not match the release tag format $release_tag_re. Aborting." + exit 1 + fi + + echo "$tag" +} + +function release_commit() { + local tag="$1" + local repo='https://github.com/phpmyadmin/phpmyadmin.git' + local tags commit + + if ! grep -qE "refs/tags/${release_tag_re}$" <<< "refs/tags/${tag}"; then + echo >&2 "'$tag' does not match the release tag format $release_tag_re. Aborting." + exit 1 + fi + + # One request, so the known tags can be listed when this one is missing + tags="$(git ls-remote --tags "$repo")" || exit 1 + + if ! grep -qE "refs/tags/${tag}$" <<< "$tags"; then + echo >&2 "Unable to find the tag $tag in $repo. The latest release tags are:" >&2 + grep -oE "refs/tags/${release_tag_re}$" <<< "$tags" \ + | sed -e 's@refs/tags/@@' \ + | sort -t_ -k2,2n -k3,3n -k4,4n -k5,5n \ + | tail -n 5 >&2 + exit 1 + fi + + # An annotated tag is listed twice, the tag object and its peeled commit + commit="$(grep -E "refs/tags/${tag}\^\{\}$" <<< "$tags" | cut -f1)" + if [ -z "$commit" ]; then + commit="$(grep -E "refs/tags/${tag}$" <<< "$tags" | cut -f1)" + fi + if [ -z "$commit" ]; then + echo >&2 "Unable to resolve the commit of $tag in $repo. Aborting." + exit 1 + fi + + echo "$commit" +} + function create_variant() { local variant="$1" local version="$2" - local sha256="$3" - local branch="$(sed -ne 's/^\([0-9]*\.[0-9]*\)\..*$/\1/p' <<< "$version")" - local url="$(download_url "$version")" - local ascUrl="$(download_url "$version").asc" + local branch + branch="$(sed -ne 's/^\([0-9]*\.[0-9]*\)\..*$/\1/p' <<< "$version")" local phpVersion="${php_version[$version]-${php_version[default]}}" + local tag + local releaseBranch="QA_${branch//./_}" + local commit + tag="$(release_tag "$version")" + commit="$(release_commit "$tag")" - echo "updating $version [$branch] $variant" + echo "updating $version [$branch] $variant (tag $tag, commit $commit)" # Create the variant directory with a Dockerfile mkdir -p "$variant" @@ -52,11 +108,11 @@ function create_variant() { sed -ri -e ' s/%%VARIANT%%/'"$variant"'/; s/%%VERSION%%/'"$version"'/; - s/%%SHA256%%/'"$sha256"'/; - s/%%DOWNLOAD_URL%%/'"$(sed -e 's/[\/&]/\\&/g' <<< "$url")"'/; - s/%%DOWNLOAD_URL_ASC%%/'"$(sed -e 's/[\/&]/\\&/g' <<< "$ascUrl")"'/; s/%%PHP_VERSION%%/'"$phpVersion"'/g; s/%%GPG_KEY%%/'"$gpg_key"'/g; + s/%%RELEASE_BRANCH%%/'"$releaseBranch"'/g; + s/%%TAG%%/'"$tag"'/g; + s/%%PMA_COMMIT%%/'"$commit"'/g; s/%%CMD%%/'"${cmd[$variant]}"'/; ' "$variant/Dockerfile" @@ -70,32 +126,18 @@ function create_variant() { # Copy config.inc.php and helpers.php cp config.inc.php "$variant/config.inc.php" cp helpers.php "$variant/helpers.php" - - # Add variant to versions.json - versionVariantsJson="$(jq -e \ - --arg branch "$branch" --arg variant "$variant" --arg base "${base[$variant]}" --arg phpVersion "$phpVersion" \ - '.[$branch].variants[$variant] = {"variant": $variant, "base": $base, "phpVersion": $phpVersion}' versions.json)" - versionJson="$(jq -e \ - --arg branch "$branch" --arg version "$version" --arg sha256 "$sha256" --arg url "$url" --arg ascUrl "$ascUrl" --argjson variants "$versionVariantsJson" \ - '.[$branch] = {"branch": $branch, "version": $version, "sha256": $sha256, "url": $url, "ascUrl": $ascUrl, "variants": $variants[$branch].variants}' versions.json)" - printf '%s\n' "$versionJson" > versions.json } # Check script dependencies command -v curl >/dev/null 2>&1 || { echo >&2 "'curl' is required but not found. Aborting."; exit 1; } +command -v git >/dev/null 2>&1 || { echo >&2 "'git' is required but not found. Aborting."; exit 1; } command -v jq >/dev/null 2>&1 || { echo >&2 "'jq' is required but not found. Aborting."; exit 1; } [ -n "${BASH_VERSINFO}" ] && [ -n "${BASH_VERSINFO[0]}" ] && [ ${BASH_VERSINFO[0]} -ge 4 ] \ || { echo >&2 "Bash 4.0 or greater is required. Aborting."; exit 1; } # Create variants -printf '%s\n' "{}" > versions.json - -latest="$(curl -fsSL 'https://www.phpmyadmin.net/home_page/version.json' | jq -r '.version' | grep -E '^[0-9]{1,}.[0-9]{1,}.[0-9]{1,}$')" -sha256="$(curl -fsSL "$(download_url "$latest").sha256" | cut -f1 -d ' ' | tr -cd 'a-f0-9' | cut -c 1-64)" - +latest="$(curl -fsSL 'https://www.phpmyadmin.net/home_page/version.json' | jq -r '.version' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?$')" for variant in "${variants[@]}"; do - create_variant "$variant" "$latest" "$sha256" + create_variant "$variant" "$latest" done -# Cleanup the file as for now it's not wanted in the repository -rm versions.json