Skip to content
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions .github/workflows/signjars.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: Sign jars and internal native libraries

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:
runs-on: macos-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'

- name: Codesign JARs and Internal Native Libraries
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
run: |
# Step 1: Decode and import the certificate into a keychain
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
/usr/bin/security create-keychain -p espressif build.keychain
/usr/bin/security default-keychain -s build.keychain
/usr/bin/security unlock-keychain -p espressif build.keychain
/usr/bin/security import certificate.p12 -k build.keychain -P $MACOS_CERTIFICATE_PWD -T /usr/bin/codesign
/usr/bin/security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k espressif build.keychain

# Step 2: Define the directory containing the JARs and native libraries and the temp directory for signed JARs
LIB_DIR="${PWD}/BUNDLES/com.espressif.idf.serial.monitor/lib"
SIGNED_JARS_DIR="${RUNNER_TEMP}/signed-jars" # Use GitHub's RUNNER_TEMP for storing signed JARs
mkdir -p "$SIGNED_JARS_DIR"

# Step 3: Extract, sign native libraries, repackage, and sign the JARs with Apple codesign
for jar in "${LIB_DIR}"/*.jar; do
echo "Processing JAR file: ${jar}"

# Check if the JAR exists
if [ -f "$jar" ]; then
echo "JAR file found: ${jar}"
else
echo "JAR file not found: ${jar}"
continue
fi

# Create a temporary directory to extract the JAR contents
TEMP_DIR=$(mktemp -d)
unzip -q "$jar" -d "$TEMP_DIR"

# Find and sign all .jnilib and .dylib files in the extracted JAR directory
find "$TEMP_DIR" -name "*.jnilib" -o -name "*.dylib" | while read lib; do
echo "Signing native library: ${lib}"
/usr/bin/codesign -vvvv --entitlements $PWD/releng/com.espressif.idf.product/entitlements/espressif-ide.entitlement --options runtime --force -s "ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD. (QWXF6GB4AV)" --timestamp --deep "$lib"
done

# Repackage the signed JAR
pushd "$TEMP_DIR"
zip -r "${SIGNED_JARS_DIR}/$(basename "$jar")" * # Save signed JAR to the temporary signed directory
popd

# Sign the entire JAR with Apple codesign, using the same entitlements
echo "Signing repackaged JAR: ${SIGNED_JARS_DIR}/$(basename "$jar")"
/usr/bin/codesign -vvvv --entitlements $PWD/releng/com.espressif.idf.product/entitlements/espressif-ide.entitlement --force --deep --options runtime --timestamp -s "ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD. (QWXF6GB4AV)" "${SIGNED_JARS_DIR}/$(basename "$jar")"

# Verify the signed JAR
echo "Verifying signed JAR: ${SIGNED_JARS_DIR}/$(basename "$jar")"
/usr/bin/codesign -dvv "${SIGNED_JARS_DIR}/$(basename "$jar")"

# Clean up extracted directory (but leave the signed JAR in SIGNED_JARS_DIR)
rm -rf "$TEMP_DIR"
done
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Optimize JAR processing and signing.

The current implementation works, but it can be improved for better performance, reliability, and security:

  1. Use parallel processing for signing multiple JARs.
  2. Add error checking and logging for each step.
  3. Use read -r to prevent backslash mangling in filenames.
  4. Quote variables to prevent word splitting and globbing.

Here's an optimized version of the JAR processing logic:

export -f codesign_and_verify
find "$LIB_DIR" -name "*.jar" -print0 | parallel -0 process_jar {}

process_jar() {
  local jar_file="$1"
  echo "Processing JAR file: $jar_file"
  local temp_dir
  temp_dir=$(mktemp -d) || { echo "Failed to create temp directory"; return 1; }
  
  if ! unzip -q "$jar_file" -d "$temp_dir"; then
    echo "Error extracting $jar_file"
    rm -rf "$temp_dir"
    return 1
  fi

  find "$temp_dir" \( -name "*.jnilib" -o -name "*.dylib" \) -print0 | 
    xargs -0 -I {} bash -c 'codesign_and_verify "$@"' _ {} "$PWD/releng/com.espressif.idf.product/entitlements/espressif-ide.entitlement"

  if ! (cd "$temp_dir" && zip -qr "$jar_file" .); then
    echo "Error repackaging $jar_file"
    rm -rf "$temp_dir"
    return 1
  fi

  if ! codesign_and_verify "$jar_file" "$PWD/releng/com.espressif.idf.product/entitlements/espressif-ide.entitlement"; then
    echo "Error signing JAR $jar_file"
    rm -rf "$temp_dir"
    return 1
  fi

  rm -rf "$temp_dir"
  echo "Successfully processed $jar_file"
}

codesign_and_verify() {
  local file="$1"
  local entitlements="$2"
  echo "Signing file: $file"
  if ! /usr/bin/codesign --entitlements "$entitlements" --options runtime --force -s "ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD. (QWXF6GB4AV)" --timestamp --deep "$file"; then
    echo "Error signing $file"
    return 1
  fi
  if ! /usr/bin/codesign --verify --deep --strict --verbose=2 "$file"; then
    echo "Verification failed for $file"
    return 1
  fi
  echo "Successfully signed and verified $file"
}

This version uses GNU Parallel for concurrent processing, adds error checking, uses read -r, and quotes variables for improved security and reliability.


- name: Verify Signed JAR Files Before Upload
run: |
for jar in ${{ runner.temp }}/signed-jars/*; do
echo "Verifying signed JAR: ${jar}"
/usr/bin/codesign -dvv "${jar}"
done

- name: Display Signed JAR Files
run: |
echo "Displaying the signed JAR directory:"
ls -al ${{ runner.temp }}/signed-jars/
echo "Listing all files in the signed JAR directory:"
find ${{ runner.temp }}/signed-jars/ -type f

- name: Upload Signed JAR Files
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: signed-jar-files
path: ${{ runner.temp }}/signed-jars/*