From 6b7c7b03919b3b66dd98c304f4c0262e9c8c9b26 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 27 Jul 2025 07:18:23 +0000 Subject: [PATCH 1/2] Initial plan From 21c49bc8e22bce13239ff7055fdf8da09d21271f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 27 Jul 2025 07:25:24 +0000 Subject: [PATCH 2/2] Add macOS code signing and notarization support to all workflows Co-authored-by: commjoen <1457214+commjoen@users.noreply.github.com> --- .github/workflows/compile_c.yml | 15 +++ .github/workflows/compile_cplus.yml | 15 +++ .github/workflows/compile_dotnet.yml | 18 +++ .github/workflows/compile_golang.yml | 20 ++- .github/workflows/compile_rust.yml | 15 +++ .github/workflows/compile_swift.yml | 15 +++ .github/workflows/macos-sign-notarize.yml | 141 ++++++++++++++++++++++ docs/MACOS_SIGNING.md | 57 +++++++++ 8 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/macos-sign-notarize.yml create mode 100644 docs/MACOS_SIGNING.md diff --git a/.github/workflows/compile_c.yml b/.github/workflows/compile_c.yml index 42de677..cc0cd7f 100644 --- a/.github/workflows/compile_c.yml +++ b/.github/workflows/compile_c.yml @@ -136,3 +136,18 @@ jobs: with: name: executables-C-Musl-x64.zip path: target/* + + # Sign and notarize macOS binaries + sign-macos-c: + name: Sign and Notarize macOS C Binaries + needs: build-darwin + uses: ./.github/workflows/macos-sign-notarize.yml + with: + binary_path: target/ + binary_name: executables-C-MacOS.zip + secrets: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_DEVELOPER_ID: ${{ secrets.APPLE_DEVELOPER_ID }} + APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} diff --git a/.github/workflows/compile_cplus.yml b/.github/workflows/compile_cplus.yml index b236e63..8b9f46e 100644 --- a/.github/workflows/compile_cplus.yml +++ b/.github/workflows/compile_cplus.yml @@ -122,3 +122,18 @@ jobs: with: name: executable-Cplus-Musl-x64 path: target/* + + # Sign and notarize macOS binaries + sign-macos-cplus: + name: Sign and Notarize macOS C++ Binaries + needs: build-darwin + uses: ./.github/workflows/macos-sign-notarize.yml + with: + binary_path: target/ + binary_name: executable-CPlus-MacOS + secrets: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_DEVELOPER_ID: ${{ secrets.APPLE_DEVELOPER_ID }} + APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} diff --git a/.github/workflows/compile_dotnet.yml b/.github/workflows/compile_dotnet.yml index d88d6b8..5608b5b 100644 --- a/.github/workflows/compile_dotnet.yml +++ b/.github/workflows/compile_dotnet.yml @@ -31,3 +31,21 @@ jobs: with: name: executable-dotnet-${{ matrix.runtime }} path: /home/runner/work/wrongsecrets-binaries/wrongsecrets-binaries/dotnet/dotnetproject/bin/Release/net8.0/${{ matrix.runtime }}/publish/ + + # Sign and notarize macOS binaries + sign-macos-dotnet: + name: Sign and Notarize macOS .NET Binaries + needs: build + uses: ./.github/workflows/macos-sign-notarize.yml + strategy: + matrix: + runtime: ["osx-x64", "osx-arm64"] + with: + binary_path: /home/runner/work/wrongsecrets-binaries/wrongsecrets-binaries/dotnet/dotnetproject/bin/Release/net8.0/${{ matrix.runtime }}/publish/ + binary_name: executable-dotnet-${{ matrix.runtime }} + secrets: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_DEVELOPER_ID: ${{ secrets.APPLE_DEVELOPER_ID }} + APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} diff --git a/.github/workflows/compile_golang.yml b/.github/workflows/compile_golang.yml index 590fed1..515298e 100644 --- a/.github/workflows/compile_golang.yml +++ b/.github/workflows/compile_golang.yml @@ -94,4 +94,22 @@ jobs: uses: actions/upload-artifact@v4 with: name: executable-Go-Windows - path: target/* \ No newline at end of file + path: target/* + + # Sign and notarize macOS binaries + sign-macos-golang: + name: Sign and Notarize macOS Golang Binaries + needs: build-darwin + uses: ./.github/workflows/macos-sign-notarize.yml + strategy: + matrix: + binary: ["executable-Go-MacOS"] + with: + binary_path: target/ + binary_name: ${{ matrix.binary }} + secrets: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_DEVELOPER_ID: ${{ secrets.APPLE_DEVELOPER_ID }} + APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} \ No newline at end of file diff --git a/.github/workflows/compile_rust.yml b/.github/workflows/compile_rust.yml index 4a266e3..91285e4 100644 --- a/.github/workflows/compile_rust.yml +++ b/.github/workflows/compile_rust.yml @@ -121,3 +121,18 @@ jobs: with: name: executable-Rust-Musl(x86) path: rust/target/x86_64-unknown-linux-musl/release/rust + + # Sign and notarize macOS binaries + sign-macos-rust: + name: Sign and Notarize macOS Rust Binary + needs: build-darwin + uses: ./.github/workflows/macos-sign-notarize.yml + with: + binary_path: rust/target/x86_64-apple-darwin/release/rust + binary_name: executable-Rust-MacOS + secrets: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_DEVELOPER_ID: ${{ secrets.APPLE_DEVELOPER_ID }} + APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} diff --git a/.github/workflows/compile_swift.yml b/.github/workflows/compile_swift.yml index 52a071d..e2f2e94 100644 --- a/.github/workflows/compile_swift.yml +++ b/.github/workflows/compile_swift.yml @@ -84,4 +84,19 @@ jobs: with: name: wrongsecrets-swift-linux-musl path: swift/.build/x86_64-swift-linux-musl/release/swift + + # Sign and notarize macOS binaries + sign-macos-swift: + name: Sign and Notarize macOS Swift Binary + needs: build-non-musl + uses: ./.github/workflows/macos-sign-notarize.yml + with: + binary_path: swift/wrongsecrets-swift.universal + binary_name: wrongsecrets-swift + secrets: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_DEVELOPER_ID: ${{ secrets.APPLE_DEVELOPER_ID }} + APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} diff --git a/.github/workflows/macos-sign-notarize.yml b/.github/workflows/macos-sign-notarize.yml new file mode 100644 index 0000000..6d302b3 --- /dev/null +++ b/.github/workflows/macos-sign-notarize.yml @@ -0,0 +1,141 @@ +name: "macOS Code Sign and Notarize" + +on: + workflow_call: + inputs: + binary_path: + description: 'Path to the binary file to sign and notarize' + required: true + type: string + binary_name: + description: 'Name of the binary (for output naming)' + required: true + type: string + secrets: + APPLE_CERTIFICATE: + description: 'Base64 encoded Apple Developer certificate (.p12)' + required: false + APPLE_CERTIFICATE_PASSWORD: + description: 'Password for the Apple Developer certificate' + required: false + APPLE_DEVELOPER_ID: + description: 'Apple Developer ID for notarization' + required: false + APPLE_APP_PASSWORD: + description: 'App-specific password for Apple ID' + required: false + APPLE_TEAM_ID: + description: 'Apple Developer Team ID' + required: false + +jobs: + sign-and-notarize: + runs-on: macos-latest + steps: + - name: Check if signing is possible + id: check_secrets + run: | + if [[ -n "${{ secrets.APPLE_CERTIFICATE }}" && -n "${{ secrets.APPLE_CERTIFICATE_PASSWORD }}" ]]; then + echo "signing_available=true" >> $GITHUB_OUTPUT + else + echo "signing_available=false" >> $GITHUB_OUTPUT + echo "⚠️ Apple signing certificate not available - skipping code signing" + fi + + if [[ -n "${{ secrets.APPLE_DEVELOPER_ID }}" && -n "${{ secrets.APPLE_APP_PASSWORD }}" && -n "${{ secrets.APPLE_TEAM_ID }}" ]]; then + echo "notarization_available=true" >> $GITHUB_OUTPUT + else + echo "notarization_available=false" >> $GITHUB_OUTPUT + echo "⚠️ Apple notarization credentials not available - skipping notarization" + fi + + - name: Download binary + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.binary_name }} + path: ./binary + + - name: Import signing certificate + if: steps.check_secrets.outputs.signing_available == 'true' + uses: Apple-Actions/import-codesign-certs@v3 + with: + p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }} + p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + + - name: Sign binary + if: steps.check_secrets.outputs.signing_available == 'true' + run: | + # Find the binary file + BINARY_FILE=$(find ./binary -type f -name "*" | head -1) + + if [[ -z "$BINARY_FILE" ]]; then + echo "❌ No binary file found in artifact" + exit 1 + fi + + echo "🔐 Signing binary: $BINARY_FILE" + + # Make binary executable + chmod +x "$BINARY_FILE" + + # Sign the binary + codesign --force --sign "Developer ID Application" \ + --options runtime \ + --timestamp \ + "$BINARY_FILE" + + # Verify the signature + codesign --verify --verbose "$BINARY_FILE" + echo "✅ Binary signed successfully" + + - name: Create ZIP for notarization + if: steps.check_secrets.outputs.signing_available == 'true' && steps.check_secrets.outputs.notarization_available == 'true' + run: | + BINARY_FILE=$(find ./binary -type f -name "*" | head -1) + BINARY_NAME=$(basename "$BINARY_FILE") + + # Create a zip file for notarization + cd ./binary + zip -r "../${BINARY_NAME}.zip" * + cd .. + + echo "📦 Created ZIP file for notarization: ${BINARY_NAME}.zip" + + - name: Notarize binary + if: steps.check_secrets.outputs.signing_available == 'true' && steps.check_secrets.outputs.notarization_available == 'true' + run: | + BINARY_FILE=$(find ./binary -type f -name "*" | head -1) + BINARY_NAME=$(basename "$BINARY_FILE") + ZIP_FILE="${BINARY_NAME}.zip" + + echo "🏃 Submitting ${ZIP_FILE} for notarization..." + + # Submit for notarization using notarytool + xcrun notarytool submit "$ZIP_FILE" \ + --apple-id "${{ secrets.APPLE_DEVELOPER_ID }}" \ + --password "${{ secrets.APPLE_APP_PASSWORD }}" \ + --team-id "${{ secrets.APPLE_TEAM_ID }}" \ + --wait + + echo "✅ Notarization completed" + + - name: Staple notarization + if: steps.check_secrets.outputs.signing_available == 'true' && steps.check_secrets.outputs.notarization_available == 'true' + run: | + BINARY_FILE=$(find ./binary -type f -name "*" | head -1) + + echo "📎 Stapling notarization to binary..." + + # Staple the notarization ticket to the binary + xcrun stapler staple "$BINARY_FILE" + + # Verify stapling + xcrun stapler validate "$BINARY_FILE" + + echo "✅ Notarization stapled successfully" + + - name: Upload signed binary + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.binary_name }}-signed + path: ./binary/* \ No newline at end of file diff --git a/docs/MACOS_SIGNING.md b/docs/MACOS_SIGNING.md new file mode 100644 index 0000000..6125d52 --- /dev/null +++ b/docs/MACOS_SIGNING.md @@ -0,0 +1,57 @@ +# macOS Code Signing and Notarization + +This document describes the macOS code signing and notarization process implemented for the wrongsecrets-binaries repository. + +## Overview + +All macOS binaries built in this repository are automatically signed and notarized for distribution. This process ensures that macOS users can run the binaries without security warnings. + +## Required Secrets + +To enable code signing and notarization, the following repository secrets must be configured: + +### Code Signing +- `APPLE_CERTIFICATE`: Base64 encoded Apple Developer certificate (.p12 file) +- `APPLE_CERTIFICATE_PASSWORD`: Password for the certificate + +### Notarization +- `APPLE_DEVELOPER_ID`: Apple ID (email) registered as a developer +- `APPLE_APP_PASSWORD`: App-specific password for the Apple ID +- `APPLE_TEAM_ID`: Apple Developer Team ID + +## How It Works + +1. **Conditional Execution**: The signing/notarization process only runs when the required secrets are available +2. **Code Signing**: Binaries are signed with the "Developer ID Application" certificate +3. **Notarization**: Signed binaries are submitted to Apple for automated security checks +4. **Stapling**: The notarization ticket is attached to the binary for offline verification + +## Supported Languages + +The following language workflows include macOS signing and notarization: + +- Swift (universal binaries) +- Golang (Intel and ARM binaries) +- Rust (Intel binaries) +- C (Intel and ARM binaries) +- C++ (Intel and ARM binaries) +- .NET (osx-x64 and osx-arm64 binaries) + +## Troubleshooting + +If signing or notarization fails: + +1. Check that all required secrets are properly configured +2. Verify that the Apple Developer certificate is valid and not expired +3. Ensure that the Apple ID has the necessary permissions for notarization +4. Check the workflow logs for specific error messages + +## Manual Testing + +To test the signing process locally: + +1. Import your Developer ID certificate into Keychain +2. Sign a binary: `codesign --force --sign "Developer ID Application" --options runtime --timestamp your_binary` +3. Verify: `codesign --verify --verbose your_binary` +4. Notarize: `xcrun notarytool submit your_binary.zip --apple-id your@email.com --password your_app_password --team-id TEAM_ID --wait` +5. Staple: `xcrun stapler staple your_binary` \ No newline at end of file