diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 5d783c4..a08221b 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -26,6 +26,24 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: 6.0.x + - name: Setup GCP credentials + working-directory: ${{ github.workspace }} + run: | + printf '%s' "$GCP_SA_KEY_RAW" > $RUNNER_TEMP/gcp-sa-key.json + chmod 600 $RUNNER_TEMP/gcp-sa-key.json + echo "GOOGLE_APPLICATION_CREDENTIALS=$RUNNER_TEMP/gcp-sa-key.json" >> $GITHUB_ENV + env: + GCP_SA_KEY_RAW: ${{ secrets.GCP_SA_KEY }} + shell: bash + - name: Install google-auth + working-directory: ${{ github.workspace }} + run: python3 -m pip install google-auth requests + shell: bash + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' - name: Run Integration Tests env: BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} @@ -33,27 +51,25 @@ jobs: run: dotnet test BrowserStackLocalIntegrationTests --no-build -p:Configuration=Release - name: Pack NuGet Package run: msbuild BrowserStackLocal -t:pack -p:Configuration=Release - - name: Setup nuget - uses: nuget/setup-nuget@v1 - with: - nuget-api-key: ${{ secrets.NUGET_API_KEY }} - nuget-version: '5.x' - - name: Create PFX certificate - id: createPfx - shell: pwsh - env: - PFX_CONTENT: ${{ secrets.BASE64_PFX_CONTENT }} - run: | - $pfxPath = Join-Path -Path $env:RUNNER_TEMP -ChildPath "cert.pfx"; - $encodedBytes = [System.Convert]::FromBase64String($env:PFX_CONTENT); - Set-Content $pfxPath -Value $encodedBytes -AsByteStream; - Write-Output "::set-output name=PFX_PATH::$pfxPath"; - name: Sign Nuget Package - run: nuget sign .\BrowserStackLocal\bin\Release\*.nupkg -certificatePath "${{ steps.createPfx.outputs.PFX_PATH }}" -certificatePassword "${{secrets.CERT_PASSWORD}}" -Timestamper "http://timestamp.comodoca.com" + working-directory: ${{ github.workspace }} + run: | + chmod +x ./scripts/sign_nupkg.sh + ./scripts/sign_nupkg.sh + shell: bash - name: Save artifact uses: actions/upload-artifact@v4 with: name: BrowserStackLocal.nupkg path: .\BrowserStackLocal\BrowserStackLocal\bin\Release\*.nupkg - name: Push package to Nuget Repository - run: nuget push **\*.nupkg -Source 'https://api.nuget.org/v3/index.json' -ApiKey ${{secrets.NUGET_API_KEY}} + working-directory: ${{ github.workspace }} + run: dotnet nuget push BrowserStackLocal/BrowserStackLocal/bin/Release/*.nupkg --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + shell: bash + - name: Cleanup credentials + if: always() + working-directory: ${{ github.workspace }} + run: rm -f $RUNNER_TEMP/gcp-sa-key.json + shell: bash diff --git a/comodo_signing_cert.crt b/comodo_signing_cert.crt new file mode 100644 index 0000000..33a8a1e Binary files /dev/null and b/comodo_signing_cert.crt differ diff --git a/scripts/sign_nupkg.sh b/scripts/sign_nupkg.sh new file mode 100755 index 0000000..836b080 --- /dev/null +++ b/scripts/sign_nupkg.sh @@ -0,0 +1,50 @@ +#!/bin/bash +set -e + +if [ -z "$GOOGLE_APPLICATION_CREDENTIALS" ] || [ ! -f "$GOOGLE_APPLICATION_CREDENTIALS" ]; then + echo "ERROR: GOOGLE_APPLICATION_CREDENTIALS is not set or file does not exist" + exit 1 +fi + +# Exchange SA credentials for an OAuth access token scoped to cloudkms. +# gcloud is NOT installed on windows-latest runners; google-auth Python lib +# is the reliable path (see browserstack-csharp-sdk PR #704 for the +# enumeration of failed alternatives). +GCP_ACCESS_TOKEN=$(python3 -c " +import google.auth +import google.auth.transport.requests +creds, _ = google.auth.default(scopes=['https://www.googleapis.com/auth/cloudkms']) +creds.refresh(google.auth.transport.requests.Request()) +print(creds.token) +") + +# Download Jsign 7.0 + SHA-256 verify (supply-chain integrity). +JSIGN_VERSION="7.0" +JSIGN_SHA256="325df319621e7fa74384c8852efdb5828871bf6405648a4c621ee5fc37c59b6c" +curl -fsL "https://github.com/ebourg/jsign/releases/download/${JSIGN_VERSION}/jsign-${JSIGN_VERSION}.jar" -o jsign.jar +echo "${JSIGN_SHA256} jsign.jar" | sha256sum -c - || { echo "ERROR: Jsign checksum verification failed"; exit 1; } + +# Sign every nupkg produced by the pack step. +SIGNED_ANY=0 +for NUPKG in BrowserStackLocal/BrowserStackLocal/bin/Release/*.nupkg; do + if [ ! -f "$NUPKG" ]; then + continue + fi + echo "Signing $NUPKG" + java -jar jsign.jar \ + --storetype GOOGLECLOUD \ + --storepass "$GCP_ACCESS_TOKEN" \ + --keystore "projects/browserstack-production/locations/us-east1/keyRings/prod-comodo-win-cert-keyring" \ + --alias "prod-comodo-win-cert-key/cryptoKeyVersions/1" \ + --certfile comodo_signing_cert.crt \ + --tsaurl http://timestamp.sectigo.com \ + "$NUPKG" + SIGNED_ANY=1 +done + +if [ "$SIGNED_ANY" -eq 0 ]; then + echo "ERROR: no .nupkg files found under BrowserStackLocal/BrowserStackLocal/bin/Release/" + exit 1 +fi + +echo "Signing complete"