diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3958f8421..2b1aff6b4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,8 @@ name: Release on: + workflow_dispatch: ~ + pull_request: ~ push: tags: # ex. "v1.2.3", "v1.2.3-rc1" @@ -9,7 +11,7 @@ on: jobs: publish: name: Publish to NuGet - runs-on: ubuntu-22.04 + runs-on: windows-latest steps: - name: Checkout repository uses: actions/checkout@v3 @@ -26,48 +28,55 @@ jobs: - name: Setup Nuget uses: NuGet/setup-nuget@v1.1.1 - - name: Load NuGet package cache - uses: actions/cache@v3 - with: - path: ~/.nuget/packages - key: ${{ runner.os }}-nuget-${{ matrix.framework }}-${{ hashFiles('**/packages.lock.json') }} - restore-keys: | - ${{ runner.os }}-nuget- - - name: Restore NuGet Packages run: make restore - name: Set up dotnet tools and dependencies run: make install - - name: Prep certificate imports - run: mkdir -p certs - - - name: Import authenticity certificate - run: echo "${{ secrets.AUTHENTICITY_CERT_ENC }}" > certs/authenticity_cert.pfx.enc - - - name: Import signing certificate - run: echo "${{ secrets.SIGNING_CERT_ENC }}" > cert/signing_cert.snk.enc - - - name: Decrypt certificates - run: make github-actions-certs-decrypt pass=${{ secrets.ENCRYPTION_KEY }} - - - name: Delete straggling .nupkg files - run: rm -f *.nupkg || true - - - name: Build NuGet package - run: make prep-release cert=certs/authenticity_cert.pfx sncert=certs/signing_cert.snk pass=${{ secrets.CERT_PASSWORD }} - - - name: Delete certificates - run: rm -rf certs - - - name: Publish to NuGet - run: make publish key=${{ secrets.NUGET_API_KEY }} - - - name: Create a GitHub release - uses: softprops/action-gh-release@v1 + - name: Set up authenticity certificate + run: | + echo "${{ secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12 + shell: bash + + - name: Set variables + id: variables + run: | + echo "SM_HOST=${{ secrets.SM_HOST }}" >> "$GITHUB_ENV" + echo "SM_API_KEY=${{ secrets.SM_API_KEY }}" >> "$GITHUB_ENV" + echo "SM_CLIENT_CERT_FILE=D:\\Certificate_pkcs12.p12" >> "$GITHUB_ENV" + echo "SM_CLIENT_CERT_PASSWORD=${{ secrets.SM_CLIENT_CERT_PASSWORD }}" >> "$GITHUB_ENV" + echo "C:\Program Files (x86)\Windows Kits\10\App Certification Kit" >> $GITHUB_PATH + echo "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools" >> $GITHUB_PATH + echo "C:\Program Files\DigiCert\DigiCert Keylocker Tools" >> $GITHUB_PATH + shell: bash + + - name: Setup Keylocker KSP on Windows + run: | + curl -X GET https://one.digicert.com/signingmanager/api-ui/v1/releases/Keylockertools-windows-x64.msi/download -H "x-api-key:%SM_API_KEY%" -o Keylockertools-windows-x64.msi + msiexec /i Keylockertools-windows-x64.msi /quiet /qn + smksp_registrar.exe list + smctl.exe keypair ls + C:\Windows\System32\certutil.exe -csp "DigiCert Signing Manager KSP" -key -user + shell: cmd + + - name: Sync Certificates + run: | + smctl windows certsync + shell: cmd + + - name: Build and Sign NuGet package + run: | + call scripts\win\build_release_nuget.bat EasyPost certs\signing_cert.snk "${{ secrets.SM_CODE_SIGNING_CERT_SHA1_HASH }}" Release + shell: cmd + + # - name: Publish to NuGet + # run: make publish key=${{ secrets.NUGET_API_KEY }} + + # - name: Create a GitHub release + # uses: softprops/action-gh-release@v1 # ref: https://github.com/softprops/action-gh-release#-customizing - with: - body_path: RELEASE_NOTES.md - files: | - "*.nupkg" \ No newline at end of file + # with: + # body_path: RELEASE_NOTES.md + # files: | + # "*.nupkg" \ No newline at end of file diff --git a/EasyPost.Integration/TestUtils.cs b/EasyPost.Integration/TestUtils.cs index e466cbf6e..4dccb3c23 100644 --- a/EasyPost.Integration/TestUtils.cs +++ b/EasyPost.Integration/TestUtils.cs @@ -63,7 +63,7 @@ internal static string GetApiKey(ApiKey apiKey) } // ReSharper disable once InconsistentNaming - internal static Client GetBasicVCRClient(string apiKey, HttpClient? vcrClient = null) => new(new ClientConfiguration(apiKey) + internal static Client GetBasicVCRClient(string apiKey, System.Net.Http.HttpClient? vcrClient = null) => new(new ClientConfiguration(apiKey) { CustomHttpClient = vcrClient, }); @@ -138,7 +138,7 @@ public VCR(string? testCassettesFolder = null, ApiKey apiKey = ApiKey.Test) internal bool IsRecording() => _vcr.Mode == Mode.Record; - internal Client SetUpTest(string cassetteName, Func getClientFunc, string? overrideApiKey = null) + internal Client SetUpTest(string cassetteName, Func getClientFunc, string? overrideApiKey = null) { // override api key if needed string apiKey = overrideApiKey ?? _apiKey; diff --git a/Makefile b/Makefile index db4acc6d0..4ea08ebe2 100644 --- a/Makefile +++ b/Makefile @@ -82,14 +82,6 @@ lint-fix: lint-scripts: scripts\win\lint_scripts.bat -## prep-release - Build, sign and package the project for distribution, signing with the provided certificate -# @parameters: -# sncert= - The strong-name certificate to use for signing the built assets. -# cert= - The authenticity certificate to use for signing the built assets. -# pass= - The password for the authenticity certificate. -prep-release: - bash scripts/unix/build_release_nuget.sh EasyPost ${sncert} ${cert} ${pass} Release - ## publish - Publish the project to NuGet # @parameters: # key= - The NuGet API key to use for publishing. diff --git a/scripts/unix/build_project.sh b/scripts/unix/build_project.sh deleted file mode 100755 index cb63f2610..000000000 --- a/scripts/unix/build_project.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# This script will restore and build a .NET project in a specified mode and platform. - -# Requirements: -# - dotnet is installed on the machine and is accessible everywhere (added to PATH) - -# Parse command line arguments -BUILD_MODE=$1 - -# Restore dependencies and build solution -echo "Restoring and building project..." -dotnet msbuild -property:Configuration="$BUILD_MODE" -target:Rebuild -restore || exit 1 diff --git a/scripts/unix/build_release_nuget.sh b/scripts/unix/build_release_nuget.sh deleted file mode 100755 index dfee0e74c..000000000 --- a/scripts/unix/build_release_nuget.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -# This script will build a .NET project in Release mode, sign the generated DLLs with a provided PFX certificate, -# package the DLLs into a NuGet package, and sign the NuGet package with the provided PFX certificate. -# This script also handles pre-run cleanup (will delete old DLLs and NuGet package files) - -# Requirements: -# - NuGet is installed on the machine and is accessible everywhere (added to PATH) -# - dotnet is installed on the machine and is accessible everywhere (added to PATH) -# - osslsigncode (https://github.com/mtrojnar/osslsigncode) is installed on the machine and is accessible everywhere (added to PATH) - -# Parse command line arguments -PROJECT_NAME=$1 -STRONG_NAME_CERT_FILE=$2 -AUTH_CERT_FILE=$3 -AUTH_CERT_PASSWORD=$4 -BUILD_MODE=$5 - -# Delete old files -bash scripts/unix/delete_old_assemblies.sh - -# Restore dependencies and build solution -bash scripts/unix/build_project.sh "$BUILD_MODE" || exit 1 - -# Strong-name sign the DLLs -bash scripts/unix/strong_name_dlls.sh "$STRONG_NAME_CERT_FILE" || exit 1 - -# Sign the DLLs for authenticity -bash scripts/unix/sign_dlls.sh "$AUTH_CERT_FILE" "$AUTH_CERT_PASSWORD" || exit 1 - -# Package the DLLs into a NuGet package (will fail if DLLs are missing) -bash scripts/unix/pack_nuget.sh "$PROJECT_NAME" || exit 1 - -# Sign the NuGet package for authenticity -bash scripts/unix/sign_nuget.sh "$AUTH_CERT_FILE" "$AUTH_CERT_PASSWORD" || exit 1 - -# Preset final information -NUGET_PACKAGE_FILE=$(find . -name "*.nupkg") -echo "NuGet file $NUGET_PACKAGE_FILE is ready." diff --git a/scripts/unix/delete_old_assemblies.sh b/scripts/unix/delete_old_assemblies.sh deleted file mode 100755 index de420d3df..000000000 --- a/scripts/unix/delete_old_assemblies.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -# This script will delete any DLLs and NuGet packages - -# Delete old DLLs -echo "Cleaning old files..." -rm -rf lib -rm -rf "*.nupkg" diff --git a/scripts/unix/gpg_decrypt.sh b/scripts/unix/gpg_decrypt.sh deleted file mode 100755 index f85adbd4d..000000000 --- a/scripts/unix/gpg_decrypt.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -# This script will decrypt a GPG encrypted file. - -# Usage: gpg_decrypt.sh - -INPUT_FILE=$1 -PASSWORD=$2 -OUTPUT_FILE=$3 - -gpg --decrypt --passphrase "$PASSWORD" --batch --output "$OUTPUT_FILE" "$INPUT_FILE" - -# Exit with success -exit 0 diff --git a/scripts/unix/gpg_decrypt_dir.sh b/scripts/unix/gpg_decrypt_dir.sh deleted file mode 100644 index 72a3356a6..000000000 --- a/scripts/unix/gpg_decrypt_dir.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# This script will encrypt all the files in a directory using GPG. - -# Usage: gpg_encrypt_dir.sh - -INPUT_DIR=$1 -PASSWORD=$2 -ENCRYPTED_SUFFIX=$3 - -# Loop through all the files in the input directory -for file in "$INPUT_DIR"/* -do - # Output is file name minus the ENCRYPTED_SUFFIX - output_file=${file%.$ENCRYPTED_SUFFIX} - # Decrypt the file - gpg --decrypt --passphrase "$PASSWORD" --batch --output "$output_file" "$file" 2>/dev/null # Ignore stderr -done \ No newline at end of file diff --git a/scripts/unix/gpg_encrypt.sh b/scripts/unix/gpg_encrypt.sh deleted file mode 100755 index 071db2c45..000000000 --- a/scripts/unix/gpg_encrypt.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -# This script will encrypt a file using GPG. - -# Usage: gpg_encrypt.sh - -INPUT_FILE=$1 -PASSWORD=$2 -OUTPUT_FILE=$3 - -gpg --symmetric --cipher-algo AES256 --passphrase "$PASSWORD" --batch --armor --yes --output "$OUTPUT_FILE" "$INPUT_FILE" - -# Exit with success -exit 0 diff --git a/scripts/unix/gpg_encrypt_dir.sh b/scripts/unix/gpg_encrypt_dir.sh deleted file mode 100644 index c92ddc958..000000000 --- a/scripts/unix/gpg_encrypt_dir.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# This script will encrypt all the files in a directory using GPG. - -# Usage: gpg_encrypt_dir.sh - -INPUT_DIR=$1 -PASSWORD=$2 -OUTPUT_SUFFIX=$3 - -# Loop through all the files in the input directory -for file in "$INPUT_DIR"/* -do - # Encrypt the file - gpg --symmetric --passphrase "$PASSWORD" --batch --output "$file.$OUTPUT_SUFFIX" "$file" -done \ No newline at end of file diff --git a/scripts/unix/install_osslsigncode.sh b/scripts/unix/install_osslsigncode.sh deleted file mode 100644 index f5c6eb389..000000000 --- a/scripts/unix/install_osslsigncode.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -# This script will install the osslsigncode dependency (https://github.com/mtrojnar/osslsigncode) required to release this project - -PATH_STORAGE=/usr/local/bin - -# Create a temporary folder -TEMP_FOLDER="temp" -mkdir -p "$TEMP_FOLDER" -cd "$TEMP_FOLDER" || exit - -# Download the latest macOS release -# Courtesy: https://gist.github.com/steinwaywhw/a4cd19cda655b8249d908261a62687f8 -REPO="mtrojnar/osslsigncode" -curl -s https://api.github.com/repos/$REPO/releases/latest \ -| grep "browser_download_url.*macOS.zip" \ -| cut -d : -f 2,3 \ -| tr -d \" \ -| wget -qi - - -# Find the file name of the downloaded file -ZIP_FILE=$(find . -name "*macOS.zip") - -# Unzip the file -unzip "$ZIP_FILE" - -# Find the executable -OSSLSIGNCODE_EXE=$(find . -name "osslsigncode") - -# Make the executable executable -chmod +x "$OSSLSIGNCODE_EXE" - -# Move the executable to the PATH_STORAGE folder -mv "$OSSLSIGNCODE_EXE" "$PATH_STORAGE" - -# Clean up -cd .. -rm -rf "$TEMP_FOLDER" diff --git a/scripts/unix/pack_nuget.sh b/scripts/unix/pack_nuget.sh deleted file mode 100755 index 186efb33b..000000000 --- a/scripts/unix/pack_nuget.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# This script will generate a NuGet package according the the project's .nuspec file. - -# Requirements: -# - NuGet is installed on the machine and is accessible everywhere (added to PATH) - -# Parse command line arguments -PROJECT_NAME=$1 - -# Generate the NuGet package (will fail if assemblies are missing) -echo "Generating NuGet package..." -nuget pack "$PROJECT_NAME.nuspec" || exit 1 diff --git a/scripts/unix/sign_dlls.sh b/scripts/unix/sign_dlls.sh deleted file mode 100755 index c4e2f293c..000000000 --- a/scripts/unix/sign_dlls.sh +++ /dev/null @@ -1,23 +0,0 @@ -# Parse command line arguments -CERT_FILE=$1 -CERT_PASSWORD=$2 - -# Set variables -AUTHOR_NAME="EasyPost" -AUTHOR_URL="http://www.easypost.com" -TIMESTAMP_SERVER="http://timestamp.digicert.com?alg=sha256" -FOLDER="lib" -SUFFIX=".signed" -FILE_PATTERN="*.dll" - -# Sign all DLLs found with our certificate to guarantee authenticity -echo "Signing DLLs with $CERT_FILE for authenticity..." -for file in $(find "$FOLDER" -name "$FILE_PATTERN"); do - echo "Signing $file..." - # Sign the file to a new file with added suffix - osslsigncode sign -pkcs12 "$CERT_FILE" -pass "$CERT_PASSWORD" -n "$AUTHOR_NAME" -i "$AUTHOR_URL" -ts "$TIMESTAMP_SERVER" -in "$file" -out "$file$SUFFIX" - # Delete original file - rm -f "$file" - # Rename signed file to original name - mv "$file$SUFFIX" "$file" -done diff --git a/scripts/unix/sign_nuget.sh b/scripts/unix/sign_nuget.sh deleted file mode 100755 index 87fcd16bf..000000000 --- a/scripts/unix/sign_nuget.sh +++ /dev/null @@ -1,22 +0,0 @@ -# This script will find and sign any NuGet packages with a provided PFX certificate for authenticity - -# Requirements: -# - NuGet is installed on the machine and is accessible everywhere (added to PATH) - -# Parse command line arguments -CERT_FILE=$1 -CERT_PASSWORD=$2 - -# Set variables -TIMESTAMP_SERVER="http://timestamp.digicert.com?alg=sha256" -FOLDER="." -FILE_PATTERN="*.nupkg" - -# Sign all NuGet packages found with our certificate to guarantee authenticity -echo "Signing NuGet packages with $CERT_FILE for authenticity..." -# Should only be one .nupkg file at this point, since we deleted the old ones -for file in $(find "$FOLDER" -name "$FILE_PATTERN"); do - # Sign the file in-place - echo "Signing $file..." - dotnet nuget sign "$file" --timestamper "$TIMESTAMP_SERVER" --certificate-path "$CERT_FILE" --certificate-password "$CERT_PASSWORD" -done diff --git a/scripts/unix/strong_name_dlls.sh b/scripts/unix/strong_name_dlls.sh deleted file mode 100755 index b6920de29..000000000 --- a/scripts/unix/strong_name_dlls.sh +++ /dev/null @@ -1,20 +0,0 @@ -# This script will find and finish strong-naming any DLLs with a provided PFX certificate - -# Requirements: -# - dotnet is installed on the machine and is accessible everywhere (added to PATH) -# - sn is installed on the machine and is accessible everywhere (added to PATH) - -# Parse command line arguments -CERT_FILE=$1 - -# Set variables -FOLDER="lib" -FILE_PATTERN="*.dll" - -# Strong-name all DLLs found in the lib folder -echo "Strong-naming (finishing delayed signing) DLLs with $CERT_FILE..." -for file in $(find "$FOLDER" -name "$FILE_PATTERN"); do - echo "Strong-naming $file..." - # Strong-name the file to a new file with added suffix - sn -R "$file" "$CERT_FILE" -done diff --git a/scripts/win/build_release_nuget.bat b/scripts/win/build_release_nuget.bat index 2ee1f2ecf..8965c2a94 100644 --- a/scripts/win/build_release_nuget.bat +++ b/scripts/win/build_release_nuget.bat @@ -11,9 +11,8 @@ :: Parse command line arguments SET projectName=%1 SET strongNameCertFile=%2 -SET authCertFile=%3 -SET authCertPass=%4 -SET buildMode=%5 +SET authCertFingerprint=%3 +SET buildMode=%4 :: Delete old files CALL "scripts\win\delete_old_assemblies.bat" @@ -25,13 +24,13 @@ CALL "scripts\win\build_project.bat" %buildMode% || GOTO :commandFailed CALL "scripts\win\strong_name_dlls.bat" %strongNameCertFile% || GOTO :commandFailed :: Sign the DLLs for authenticity -CALL "scripts\win\sign_dlls.bat" %authCertFile% %authCertPass% || GOTO :commandFailed +CALL "scripts\win\sign_dlls.bat" %authCertFingerprint% || GOTO :commandFailed :: Package the DLLs in a NuGet package (will fail if DLLs are missing) CALL "scripts\win\pack_nuget.bat" %projectName% || GOTO :commandFailed :: Sign the NuGet package for authenticity -CALL "scripts\win\sign_nuget.bat" %authCertFile% %authCertPass% || GOTO :commandFailed +CALL "scripts\win\sign_nuget.bat" %authCertFingerprint% || GOTO :commandFailed SET nugetFileName= FOR /R %%F IN (*.nupkg) DO ( SET nugetFileName="%%F" @@ -50,7 +49,7 @@ GOTO :eof :usage @ECHO: -@ECHO Usage: %0 +@ECHO Usage: %0 GOTO :exitWithError :commandFailed diff --git a/scripts/win/sign_nuget.bat b/scripts/win/sign_nuget.bat index c7190c3bf..aa99d55dd 100644 --- a/scripts/win/sign_nuget.bat +++ b/scripts/win/sign_nuget.bat @@ -6,15 +6,15 @@ @ECHO OFF :: Parse command line arguments -SET certFile=%1 -SET certPass=%2 +SET certFingerprint=%1 :: Sign all NuGet packages found with our certificate to guarantee authenticity @ECHO: @ECHO Signing NuGet package with %certFile% for authenticity... :: Should only be one .nupkg file at this point, since we deleted the old ones FOR /R %%F IN (*.nupkg) DO ( - nuget sign "%%F" -Timestamper http://timestamp.digicert.com -CertificatePath "%certFile%" -CertificatePassword "%certPass%" || GOTO :commandFailed + nuget sign "%%F" -Timestamper http://timestamp.digicert.com -CertificateFingerprint "%certFingerprint%" -HashAlgorithm SHA256 -Verbosity detailed -Overwrite || GOTO :commandFailed + nuget verify -All "%%F" || GOTO :commandFailed ) EXIT /B 0