From df3e69dd1304dd6b4a34d5cedea2599a6855a083 Mon Sep 17 00:00:00 2001 From: Andreas Braun Date: Fri, 10 May 2024 10:29:10 +0200 Subject: [PATCH] PHPC-1584: Sign releases (#1544) * Create signed git artifacts upon release * Generate signature for PECL package * Fix writing release message to file * Remove unnecessary pip install * Change image variable usage * Sign Windows DLLs * Move composite actions to separate directory * Extract signing functionality to composite actions * Add release integrity information * Use garasign actions from drivers-github-tools * Add comment explaining cross-os cache * Remove submodule install for Windows signing job * Fix name and contents of Windows build artifacts" * Don't hardcode tag message file name * Restore original tag message * Add newline to tag message --- .../linux/build/action.yml | 0 .../windows/build/action.yml | 2 +- .../windows/prepare-build/action.yml | 0 .github/workflows/commit-and-tag.sh | 16 ++++ .github/workflows/package-release.yml | 95 ++++++++++++++++--- .github/workflows/release.yml | 47 ++++++--- .github/workflows/tests.yml | 2 +- .github/workflows/windows-tests.yml | 4 +- README.md | 48 +++++++++- 9 files changed, 184 insertions(+), 30 deletions(-) rename .github/{workflows => actions}/linux/build/action.yml (100%) rename .github/{workflows => actions}/windows/build/action.yml (93%) rename .github/{workflows => actions}/windows/prepare-build/action.yml (100%) create mode 100755 .github/workflows/commit-and-tag.sh diff --git a/.github/workflows/linux/build/action.yml b/.github/actions/linux/build/action.yml similarity index 100% rename from .github/workflows/linux/build/action.yml rename to .github/actions/linux/build/action.yml diff --git a/.github/workflows/windows/build/action.yml b/.github/actions/windows/build/action.yml similarity index 93% rename from .github/workflows/windows/build/action.yml rename to .github/actions/windows/build/action.yml index ec35bf1bc..e32153426 100644 --- a/.github/workflows/windows/build/action.yml +++ b/.github/actions/windows/build/action.yml @@ -19,7 +19,7 @@ runs: steps: - name: Prepare build environment id: prepare-build-env - uses: ./.github/workflows/windows/prepare-build + uses: ./.github/actions/windows/prepare-build with: version: ${{ inputs.version }} arch: ${{ inputs.arch }} diff --git a/.github/workflows/windows/prepare-build/action.yml b/.github/actions/windows/prepare-build/action.yml similarity index 100% rename from .github/workflows/windows/prepare-build/action.yml rename to .github/actions/windows/prepare-build/action.yml diff --git a/.github/workflows/commit-and-tag.sh b/.github/workflows/commit-and-tag.sh new file mode 100755 index 000000000..fb6bf9978 --- /dev/null +++ b/.github/workflows/commit-and-tag.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -e + +PACKAGE_VERSION=$1 +GPG_KEY_ID=$2 +TAG_MESSAGE_FILE=$3 + +gpgloader + +# Create signed "Package x.y.z" commit +echo "Create package commit" +git commit -m "Package ${PACKAGE_VERSION}" -s --gpg-sign=${GPG_KEY_ID} phongo_version.h + +# Create signed "Release x.y.z" tag +echo "Create release tag" +git tag -F ${TAG_MESSAGE_FILE} -s --local-user=${GPG_KEY_ID} ${PACKAGE_VERSION} diff --git a/.github/workflows/package-release.yml b/.github/workflows/package-release.yml index b913658c2..d87baadb2 100644 --- a/.github/workflows/package-release.yml +++ b/.github/workflows/package-release.yml @@ -21,7 +21,7 @@ jobs: submodules: true - name: "Build Driver" - uses: ./.github/workflows/linux/build + uses: ./.github/actions/linux/build with: version: "8.3" @@ -38,27 +38,43 @@ jobs: # PECL always uses the version for the package name. # Read it from the version file and store in env to use when uploading artifacts - name: "Read current package version" - run: echo "PACKAGE_VERSION=$(./bin/update-release-version.php get-version)" >> "$GITHUB_ENV" + run: | + PACKAGE_VERSION=$(./bin/update-release-version.php get-version) + echo "PACKAGE_VERSION=${PACKAGE_VERSION}" >> "$GITHUB_ENV" + echo "PACKAGE_FILE=mongodb-${PACKAGE_VERSION}.tgz" >> "$GITHUB_ENV" + + - name: "Create detached signature for PECL package" + uses: mongodb-labs/drivers-github-tools/garasign/gpg-sign@main + with: + filenames: ${{ env.PACKAGE_FILE }} + garasign_username: ${{ secrets.GRS_CONFIG_USER1_USERNAME }} + garasign_password: ${{ secrets.GRS_CONFIG_USER1_PASSWORD }} + artifactory_username: ${{ secrets.ARTIFACTORY_USER }} + artifactory_password: ${{ secrets.ARTIFACTORY_PASSWORD }} - name: "Install release archive to verify correctness" - run: sudo pecl install mongodb-${{ env.PACKAGE_VERSION }}.tgz + run: sudo pecl install ${{ env.PACKAGE_FILE }} - - name: "Upload artifact" + - name: "Upload artifacts" uses: actions/upload-artifact@v4 with: - name: mongodb-${{ env.PACKAGE_VERSION }}.tgz - path: mongodb-${{ env.PACKAGE_VERSION }}.tgz + name: ${{ env.PACKAGE_FILE }} + path: | + ${{ env.PACKAGE_FILE }} + ${{ env.PACKAGE_FILE }}.sig retention-days: 3 - - name: "Upload release artifact" - run: gh release upload ${{ github.ref_name }} mongodb-${{ env.PACKAGE_VERSION }}.tgz + - name: "Upload release artifacts" + run: gh release upload ${{ github.ref_name }} ${{ env.PACKAGE_FILE }} ${{ env.PACKAGE_FILE }}.sig continue-on-error: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} build-windows: name: "Create Windows package" - runs-on: windows-2022 + # windows-latest is required to use enableCrossOsArchive with Ubuntu in the + # next step. See https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cross-os-cache + runs-on: windows-latest defaults: run: shell: cmd @@ -78,7 +94,7 @@ jobs: - name: "Build Driver" id: build-driver - uses: ./.github/workflows/windows/build + uses: ./.github/actions/windows/build with: version: ${{ matrix.php }} arch: ${{ matrix.arch }} @@ -91,20 +107,73 @@ jobs: env: BUILD_DIR: ${{ steps.build-driver.outputs.build-dir }} + - name: "Cache build artifacts for subsequent builds" + uses: actions/cache/save@v4 + with: + key: ${{ github.sha }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.arch }} + enableCrossOsArchive: true + path: | + php_mongodb.dll + php_mongodb.pdb + + sign-and-publish-windows: + name: "Sign and Publish Windows package" + needs: [build-windows] + # ubuntu-latest is required to use enableCrossOsArchive + # See https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cross-os-cache + runs-on: "ubuntu-latest" + + strategy: + fail-fast: false + matrix: + # Note: keep this in sync with the Windows matrix in windows-tests.yml + php: [ "7.4", "8.0", "8.1", "8.2", "8.3" ] + arch: [ x64, x86 ] + ts: [ ts, nts ] + + steps: + - uses: actions/checkout@v4 + + - name: Restore cached build artifacts + id: cache-build-artifacts + uses: actions/cache/restore@v4 + with: + fail-on-cache-miss: true + key: ${{ github.sha }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.arch }} + enableCrossOsArchive: true + path: | + php_mongodb.dll + php_mongodb.pdb + + - name: "Create detached DLL signature" + uses: mongodb-labs/drivers-github-tools/garasign/gpg-sign@main + with: + filenames: php_mongodb.dll + garasign_username: ${{ secrets.GRS_CONFIG_USER1_USERNAME }} + garasign_password: ${{ secrets.GRS_CONFIG_USER1_PASSWORD }} + artifactory_username: ${{ secrets.ARTIFACTORY_USER }} + artifactory_password: ${{ secrets.ARTIFACTORY_PASSWORD }} + - name: "Upload DLL and PDB files as build artifacts" uses: actions/upload-artifact@v4 with: name: php_mongodb-${{ github.ref_name }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.arch }} path: | php_mongodb.dll + php_mongodb.dll.sig php_mongodb.pdb + CREDITS + CONTRIBUTING.md + LICENSE + README.md + THIRD_PARTY_NOTICES retention-days: 3 - name: "Create and upload release artifact" run: | - set ARCHIVE=php_mongodb-${{ github.ref_name }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.arch }}.zip - zip %ARCHIVE% php_mongodb.dll php_mongodb.pdb CREDITS CONTRIBUTING.md LICENSE README.md THIRD_PARTY_NOTICES - gh release upload ${{ github.ref_name }} %ARCHIVE% + ARCHIVE=php_mongodb-${{ github.ref_name }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.arch }}.zip + zip ${ARCHIVE} php_mongodb.dll php_mongodb.dll.sig php_mongodb.pdb CREDITS CONTRIBUTING.md LICENSE README.md THIRD_PARTY_NOTICES + gh release upload ${{ github.ref_name }} ${ARCHIVE} continue-on-error: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 90f4c1569..cd1a0e67d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -89,10 +89,6 @@ jobs: git config user.name "${GIT_AUTHOR_NAME}" git config user.email "${GIT_AUTHOR_EMAIL}" - # Create the "Package x.y.z" commit that will be the base of our tag - - name: "Create release commit" - run: git commit -m "Package ${{ env.PACKAGE_VERSION }}" phongo_version.h - # Create a draft release with a changelog # TODO: Consider using the API to generate changelog - name: "Create draft release with generated changelog" @@ -101,14 +97,39 @@ jobs: - name: "Read changelog from draft release" run: gh release view ${{ env.PACKAGE_VERSION }} --json body --template '{{ .body }}' >> changelog - # TODO: Sign tag - - name: "Create release tag" - run: git tag -a -F changelog ${{ env.PACKAGE_VERSION }} - - - name: "Update version information to next patch development release" + - name: "Prepare tag message" run: | - ./bin/update-release-version.php to-next-patch-dev - git commit -m "Back to -dev" phongo_version.h + echo -e "Release ${PACKAGE_VERSION}\n" > tag-message + cat changelog >> tag-message + + # This step creates the "Package x.y.z" commit that will be the base of + # our tag and creates the release tag. This is run inside the container in + # order to create signed git artifacts + - name: "Create package commit and release tag" + uses: mongodb-labs/drivers-github-tools/garasign/git-sign@main + with: + command: "$(pwd)/.github/workflows/commit-and-tag.sh ${{ env.PACKAGE_VERSION }} ${{ vars.GPG_KEY_ID }} tag-message" + garasign_username: ${{ secrets.GRS_CONFIG_USER1_USERNAME }} + garasign_password: ${{ secrets.GRS_CONFIG_USER1_PASSWORD }} + artifactory_username: ${{ secrets.ARTIFACTORY_USER }} + artifactory_password: ${{ secrets.ARTIFACTORY_PASSWORD }} + + # This step needs to happen outside of the container, as PHP is not + # available within. + - name: "Bump to next development release" + run: ./bin/update-release-version.php to-next-patch-dev + + # Create a signed "back to -dev" commit, again inside the container + - name: "Create dev commit" + uses: mongodb-labs/drivers-github-tools/garasign/git-sign@main + with: + # Setup can be skipped as it was already done before + skip_setup: true + command: "git commit -m 'Back to -dev' -s --gpg-sign=${{ vars.GPG_KEY_ID }} phongo_version.h" + garasign_username: ${{ secrets.GRS_CONFIG_USER1_USERNAME }} + garasign_password: ${{ secrets.GRS_CONFIG_USER1_PASSWORD }} + artifactory_username: ${{ secrets.ARTIFACTORY_USER }} + artifactory_password: ${{ secrets.ARTIFACTORY_PASSWORD }} # TODO: Manually merge using ours strategy. This avoids merge-up pull requests being created # Process is: @@ -122,7 +143,9 @@ jobs: - name: "Prepare release message" run: | - echo "${{ format(env.default-release-message, env.PACKAGE_VERSION, inputs.jira-version-number) }}" > release-message + cat > release-message <<'EOL' + ${{ format(env.default-release-message, env.PACKAGE_VERSION, inputs.jira-version-number) }} + EOL cat changelog >> release-message # Update release with correct release information diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 018ca327f..74306605c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -64,7 +64,7 @@ jobs: - name: "Build Driver" id: build-driver - uses: ./.github/workflows/linux/build + uses: ./.github/actions/linux/build with: version: ${{ matrix.php-version }} diff --git a/.github/workflows/windows-tests.yml b/.github/workflows/windows-tests.yml index 569e47ad7..ea2021f14 100644 --- a/.github/workflows/windows-tests.yml +++ b/.github/workflows/windows-tests.yml @@ -35,7 +35,7 @@ jobs: - name: "Build Driver" id: build-driver - uses: ./.github/workflows/windows/build + uses: ./.github/actions/windows/build with: version: ${{ matrix.php }} arch: ${{ matrix.arch }} @@ -74,7 +74,7 @@ jobs: - name: Prepare build environment id: prepare-build - uses: ./.github/workflows/windows/prepare-build + uses: ./.github/actions/windows/prepare-build with: version: ${{ matrix.php }} arch: ${{ matrix.arch }} diff --git a/README.md b/README.md index 928f37e43..2ad1d104c 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,53 @@ This extension is intended to be used alongside the [MongoDB PHP Library](https://github.com/mongodb/mongo-php-library), which is distributed as the [`mongodb/mongodb`](https://packagist.org/packages/mongodb/mongodb) package for -for [Composer](https://getcomposer.org). +[Composer](https://getcomposer.org). + +## Release Integrity + +Releases are created automatically and signed using the +[PHP team's GPG key](https://pgp.mongodb.com/php-driver.asc). This applies to +the git tag as well as all release packages provided as part of a +[GitHub release](https://github.com/mongodb/mongo-php-library/releases). To +verify the provided packages, download the key and import it using `gpg`: + +```shell +gpg --import php-driver.asc +``` + +### PECL package + +PECL packages are made available as release artifacts on GitHub, as well as on +the [PECL homepage](https://pecl.php.net/mongodb). The GitHub release will also +contain a detached signature file for the PECL package (named +`mongodb-X.Y.Z.tgz.sig`). + +To verify the integrity of the downloaded package, run the following command: + +```shell +gpg --verify mongodb-X.Y.Z.tgz.sig mongodb-X.Y.Z.tgz +``` + +> [!NOTE] +> No verification is done when using `pecl` to install the package. To ensure +> release integrity when using `pecl`, download the tarball manually from the +> GitHub release, verify the signature, then install the package from the +> downloaded tarball using `pecl install mongodb-X.Y.Z.tgz`. + +### Windows + +Windows binaries distributed through GitHub releases contain a detached +signature for the `php_mongodb.dll` file named `php_mongodb.dll.sig`. To verify +the integrity of the DLL, run the following command: + +```shell +gpg --verify php_mongodb.dll.sig php_mongodb.dll.tgz +``` + +> [!NOTE] +> Windows binaries distributed directly through PECL are not signed by MongoDB +> and cannot be verified. If you need to verify the integrity of the downloaded +> binary, always download them from the GitHub release. ## Reporting Issues