Skip to content
144 changes: 144 additions & 0 deletions .github/workflows/nuget-sign-artifacts.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
name: Sign NuGet Artifacts

on:
workflow_call:
inputs:
artifact-glob:
description: Directory path containing NuGet packages to sign (e.g. ./sign or ./artifacts)
required: true
type: string
output-path:
description: Output directory for signed packages (e.g. ./artifacts or full path)
required: false
type: string
default: ${{ github.workspace }}
artifact-name:
description: Name for the uploaded artifacts
required: false
type: string
default: signed-nuget-artifacts
retention-days:
description: Retention days for the artifacts
required: false
type: number
default: 7
nuget-environment:
description: SSL.com environment name for NuGet signing
required: false
type: string
default: PROD
jvm-max-memory:
description: Maximum JVM memory for NuGet signing process
required: false
type: string
default: 1024M
malware-block:
description: Enable malware blocking during signing
required: false
type: boolean
default: false
override:
description: Override existing signatures
required: false
type: boolean
default: false
runs-on:
description: The runner to use for the build
required: false
type: string
default: ubuntu-latest
download-artifact-name:
description: Name of the artifact to download before signing (optional)
required: false
type: string
secrets:
ES_USERNAME:
description: SSL.com username for NuGet signing
required: true
ES_PASSWORD:
description: SSL.com password for NuGet signing
required: true
CREDENTIAL_ID:
description: SSL.com credential ID for NuGet signing
required: true
ES_TOTP_SECRET:
description: SSL.com TOTP secret for NuGet signing
required: true

permissions:
contents: read
packages: read

jobs:
sign-nuget:
runs-on: ${{ inputs.runs-on }}
steps:
- uses: actions/checkout@v4

- name: Download artifacts (if specified)
if: ${{ inputs.download-artifact-name != '' }}
uses: actions/download-artifact@v4
with:
name: ${{ inputs.download-artifact-name }}
path: ${{ inputs.artifact-glob }}

- name: Check for NuGet packages
run: |
echo "Checking for NuGet packages in: ${{ inputs.artifact-glob }}"
echo "Current working directory: $(pwd)"
echo "Workspace directory: ${{ github.workspace }}"

# Handle both relative and absolute paths
if [[ "${{ inputs.artifact-glob }}" == /* ]]; then
SEARCH_PATH="${{ inputs.artifact-glob }}"
else
SEARCH_PATH="${{ github.workspace }}/${{ inputs.artifact-glob }}"
fi

echo "Searching in: $SEARCH_PATH"
NUGET_PACKAGES=$(find "$SEARCH_PATH" -name "*.nupkg" -type f 2>/dev/null || echo "")
if [ -n "$NUGET_PACKAGES" ]; then
echo "Found NuGet packages:"
echo "$NUGET_PACKAGES"
else
echo "No NuGet packages found in $SEARCH_PATH"
echo "Directory contents:"
ls -la "$SEARCH_PATH" 2>/dev/null || echo "Directory does not exist"
exit 1
fi

- name: Sign NuGet Packages with SSL.com
uses: sslcom/esigner-codesign@a272724cb13abe0abc579c6c40f7899969b6942b
with:
command: batch_sign
username: ${{secrets.ES_USERNAME}}
password: ${{secrets.ES_PASSWORD}}
credential_id: ${{secrets.CREDENTIAL_ID}}
totp_secret: ${{secrets.ES_TOTP_SECRET}}
dir_path: ${{ inputs.artifact-glob }}
output_path: ${{ inputs.output-path == 'artifacts' && format('{0}/artifacts', github.workspace) || inputs.output-path || github.workspace }}
malware_block: ${{ inputs.malware-block || false }}
override: ${{ inputs.override || false }}

environment_name: ${{ inputs.nuget-environment }}
clean_logs: true
jvm_max_memory: ${{ inputs.jvm-max-memory }}
signing_method: v1

- name: Verify NuGet Packages
run: |
echo "Verifying signed NuGet packages..."
OUTPUT_DIR="${{ inputs.output-path == 'artifacts' && format('{0}/artifacts', github.workspace) || inputs.output-path || github.workspace }}"
if [ -d "$OUTPUT_DIR" ]; then
find "$OUTPUT_DIR" -name "*.nupkg" -type f | while read -r file; do
echo "Verifying: $file"
dotnet nuget verify "$file" --all || echo "Warning: Could not verify $file"
done
fi

- name: Upload Signed NuGet Artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.artifact-name }}
path: ${{ inputs.output-path == 'artifacts' && format('{0}/artifacts', github.workspace) || inputs.output-path || github.workspace }}
retention-days: ${{ inputs.retention-days }}
10 changes: 6 additions & 4 deletions .github/workflows/reusable_sign-artifacts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_call:
inputs:
artifact-glob:
description: Glob pattern to match artifacts to sign (e.g. dist/**/*.{jar,deb,rpm})
description: Glob pattern to match artifacts to sign (e.g. dist/**/*.{jar,deb,rpm,nupkg})
required: true
type: string
artifact-name:
Expand All @@ -16,7 +16,7 @@ on:
description: Retention days for the artifacts
required: false
type: number
default: 1
default: 7
artifactory-url:
required: false
description: JFrog Artifactory URL
Expand All @@ -37,17 +37,18 @@ on:
required: false
type: string
default: ubuntu-22.04

secrets:
gpg-private-key:
required: true
gpg-public-key:
required: true
gpg-key-pass:
required: true

permissions:
contents: read
packages: read

jobs:
sign:
runs-on: ${{ inputs.runs-on }}
Expand All @@ -65,10 +66,11 @@ jobs:
run: |
sudo apt-get update && sudo apt-get install dpkg-sig dpkg-dev -y

- name: Sign Artifacts
- name: Sign Artifacts with GPG
run: |
chmod +x ${{ github.workspace }}/.github/workflows/sign-artifacts/entrypoint.sh
${{ github.workspace }}/.github/workflows/sign-artifacts/entrypoint.sh "${{ inputs.artifact-glob }}" "${{ inputs.artifact-name }}"

- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/sign-artifacts/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ echo "Processing all files in target directory: $TARGET_DIR"
find "$TARGET_DIR" -type f | while read -r file; do
echo "Processing: $file"


# Skip signature and checksum files to prevent infinite loops
if [[ "$file" =~ \.(asc|sha256)$ ]]; then
continue
Expand Down Expand Up @@ -80,8 +79,13 @@ find "$TARGET_DIR" -type f | while read -r file; do
# SHA256 checksum for signature file
shasum -a 256 "$file.asc" > "$file.asc.sha256"

echo "Signed: $file"
echo "GPG Signed: $file"
echo " Signature: $file.asc"
echo " Checksum: $file.sha256"
echo " Sig Checksum: $file.asc.sha256"

# Note about NuGet packages
if [[ "$ext" == "nupkg" ]]; then
Copy link
Contributor

Choose a reason for hiding this comment

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

would it be better to change the logic of the script to only pick up files it could sign, aka, this bash script only signs rpms, and debs right? Or is this echo important?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i added the nuget signing to the reusable-sign artifacts file. so this just confirms if theres a nupkg to be signed if not it skips the signing

echo " Note: NuGet package detected - will be signed by SSL.com if enabled in workflow"
fi
done
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"yaml.schemas": {},
"cSpell.words": ["aerospike", "kennylong", "kennylong's"]
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like there is a war between formatters but please use the default trunk from this repository.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

"cSpell.words": ["aerospike", "kennylong", "kennylong's"],
"postman.settings.dotenv-detection-notification-visibility": false
}
Loading