ci: sign macOS release artifacts with Azure Key Vault (#26252)

## Why

The public Codex release workflow needs to sign and notarize macOS
binaries and DMGs without placing the Developer ID private key in
GitHub. This moves the private-key operation behind the protected
`codesigning` environment and uses GitHub OIDC with Azure Key Vault
PKCS#11, while preserving the existing external `build_unsigned` /
`promote_signed` fallback.

## What changed

- Add a reusable AKV PKCS11 setup action that authenticates to Azure
with OIDC, downloads pinned signing tools, verifies their SHA-256
digests, and loads the public signing certificate from Key Vault.
- Replace the legacy macOS signing action with scripts that support
AKV-backed `rcodesign`, notarize signed binaries and DMGs, and staple
DMG notarization tickets.
- Restructure `rust-release.yml` so macOS builds produce unsigned
artifacts first, protected jobs perform signing and notarization, macOS
runners package and verify the results, and release publishing waits for
verified artifacts.
- Preserve the manual external-signing handoff flow and make manual-mode
conditions explicit.
- Move the Codex entitlements file alongside the signing scripts and
update CODEOWNERS for the new signing surfaces.

## Verification

- [Live protected signing workflow
run](https://github.com/openai/codex/actions/runs/26903610631) completed
successfully for both macOS architectures, including binary
signing/notarization, DMG signing/notarization, and final artifact
verification.
- Downloaded both signed DMGs and independently verified their checksums
and strict signatures.
- Confirmed `xcrun stapler validate` succeeds and Gatekeeper accepts
both DMGs as `Notarized Developer ID`.
- Mounted both DMGs and confirmed the contained `codex` and
`codex-responses-api-proxy` binaries have valid Developer ID signatures
for the expected architectures.

---------

Co-authored-by: shijie-openai <shijie.rao@openai.com>
This commit is contained in:
Eric Burke
2026-06-03 23:34:51 -04:00
committed by GitHub
Unverified
parent c143a86de8
commit ad2012d645
9 changed files with 1464 additions and 388 deletions
-259
View File
@@ -1,259 +0,0 @@
name: macos-code-sign
description: Configure, sign, notarize, and clean up macOS code signing artifacts.
inputs:
target:
description: Rust compilation target triple (e.g. aarch64-apple-darwin).
required: true
binaries:
description: Space-delimited binary basenames to sign and notarize.
default: "codex codex-responses-api-proxy"
sign-binaries:
description: Whether to sign and notarize the macOS binaries.
required: false
default: "true"
sign-dmg:
description: Whether to sign and notarize the macOS dmg.
required: false
default: "true"
apple-certificate:
description: Base64-encoded Apple signing certificate (P12).
required: true
apple-certificate-password:
description: Password for the signing certificate.
required: true
apple-notarization-key-p8:
description: Base64-encoded Apple notarization key (P8).
required: true
apple-notarization-key-id:
description: Apple notarization key ID.
required: true
apple-notarization-issuer-id:
description: Apple notarization issuer ID.
required: true
runs:
using: composite
steps:
- name: Configure Apple code signing
shell: bash
env:
KEYCHAIN_PASSWORD: actions
APPLE_CERTIFICATE: ${{ inputs.apple-certificate }}
APPLE_CERTIFICATE_PASSWORD: ${{ inputs.apple-certificate-password }}
run: |
set -euo pipefail
if [[ -z "${APPLE_CERTIFICATE:-}" ]]; then
echo "APPLE_CERTIFICATE is required for macOS signing"
exit 1
fi
if [[ -z "${APPLE_CERTIFICATE_PASSWORD:-}" ]]; then
echo "APPLE_CERTIFICATE_PASSWORD is required for macOS signing"
exit 1
fi
cert_path="${RUNNER_TEMP}/apple_signing_certificate.p12"
echo "$APPLE_CERTIFICATE" | base64 -d > "$cert_path"
keychain_path="${RUNNER_TEMP}/codex-signing.keychain-db"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$keychain_path"
security set-keychain-settings -lut 21600 "$keychain_path"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$keychain_path"
keychain_args=()
cleanup_keychain() {
if ((${#keychain_args[@]} > 0)); then
security list-keychains -s "${keychain_args[@]}" || true
security default-keychain -s "${keychain_args[0]}" || true
else
security list-keychains -s || true
fi
if [[ -f "$keychain_path" ]]; then
security delete-keychain "$keychain_path" || true
fi
}
while IFS= read -r keychain; do
[[ -n "$keychain" ]] && keychain_args+=("$keychain")
done < <(security list-keychains | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/"//g')
if ((${#keychain_args[@]} > 0)); then
security list-keychains -s "$keychain_path" "${keychain_args[@]}"
else
security list-keychains -s "$keychain_path"
fi
security default-keychain -s "$keychain_path"
security import "$cert_path" -k "$keychain_path" -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$keychain_path" > /dev/null
codesign_hashes=()
while IFS= read -r hash; do
[[ -n "$hash" ]] && codesign_hashes+=("$hash")
done < <(security find-identity -v -p codesigning "$keychain_path" \
| sed -n 's/.*\([0-9A-F]\{40\}\).*/\1/p' \
| sort -u)
if ((${#codesign_hashes[@]} == 0)); then
echo "No signing identities found in $keychain_path"
cleanup_keychain
rm -f "$cert_path"
exit 1
fi
if ((${#codesign_hashes[@]} > 1)); then
echo "Multiple signing identities found in $keychain_path:"
printf ' %s\n' "${codesign_hashes[@]}"
cleanup_keychain
rm -f "$cert_path"
exit 1
fi
APPLE_CODESIGN_IDENTITY="${codesign_hashes[0]}"
rm -f "$cert_path"
echo "APPLE_CODESIGN_IDENTITY=$APPLE_CODESIGN_IDENTITY" >> "$GITHUB_ENV"
echo "APPLE_CODESIGN_KEYCHAIN=$keychain_path" >> "$GITHUB_ENV"
echo "::add-mask::$APPLE_CODESIGN_IDENTITY"
- name: Sign macOS binaries
if: ${{ inputs.sign-binaries == 'true' }}
shell: bash
env:
TARGET: ${{ inputs.target }}
BINARIES: ${{ inputs.binaries }}
run: |
set -euo pipefail
if [[ -z "${APPLE_CODESIGN_IDENTITY:-}" ]]; then
echo "APPLE_CODESIGN_IDENTITY is required for macOS signing"
exit 1
fi
keychain_args=()
if [[ -n "${APPLE_CODESIGN_KEYCHAIN:-}" && -f "${APPLE_CODESIGN_KEYCHAIN}" ]]; then
keychain_args+=(--keychain "${APPLE_CODESIGN_KEYCHAIN}")
fi
entitlements_path="$GITHUB_ACTION_PATH/codex.entitlements.plist"
for binary in ${BINARIES}; do
path="codex-rs/target/${TARGET}/release/${binary}"
codesign --force --options runtime --timestamp --entitlements "$entitlements_path" --sign "$APPLE_CODESIGN_IDENTITY" "${keychain_args[@]}" "$path"
done
- name: Notarize macOS binaries
if: ${{ inputs.sign-binaries == 'true' }}
shell: bash
env:
TARGET: ${{ inputs.target }}
BINARIES: ${{ inputs.binaries }}
APPLE_NOTARIZATION_KEY_P8: ${{ inputs.apple-notarization-key-p8 }}
APPLE_NOTARIZATION_KEY_ID: ${{ inputs.apple-notarization-key-id }}
APPLE_NOTARIZATION_ISSUER_ID: ${{ inputs.apple-notarization-issuer-id }}
run: |
set -euo pipefail
for var in APPLE_NOTARIZATION_KEY_P8 APPLE_NOTARIZATION_KEY_ID APPLE_NOTARIZATION_ISSUER_ID; do
if [[ -z "${!var:-}" ]]; then
echo "$var is required for notarization"
exit 1
fi
done
notary_key_path="${RUNNER_TEMP}/notarytool.key.p8"
echo "$APPLE_NOTARIZATION_KEY_P8" | base64 -d > "$notary_key_path"
cleanup_notary() {
rm -f "$notary_key_path"
}
trap cleanup_notary EXIT
source "$GITHUB_ACTION_PATH/notary_helpers.sh"
notarize_binary() {
local binary="$1"
local source_path="codex-rs/target/${TARGET}/release/${binary}"
local archive_path="${RUNNER_TEMP}/${binary}.zip"
if [[ ! -f "$source_path" ]]; then
echo "Binary $source_path not found"
exit 1
fi
rm -f "$archive_path"
ditto -c -k --keepParent "$source_path" "$archive_path"
notarize_submission "$binary" "$archive_path" "$notary_key_path"
}
for binary in ${BINARIES}; do
notarize_binary "${binary}"
done
- name: Sign and notarize macOS dmg
if: ${{ inputs.sign-dmg == 'true' }}
shell: bash
env:
TARGET: ${{ inputs.target }}
APPLE_NOTARIZATION_KEY_P8: ${{ inputs.apple-notarization-key-p8 }}
APPLE_NOTARIZATION_KEY_ID: ${{ inputs.apple-notarization-key-id }}
APPLE_NOTARIZATION_ISSUER_ID: ${{ inputs.apple-notarization-issuer-id }}
run: |
set -euo pipefail
for var in APPLE_CODESIGN_IDENTITY APPLE_NOTARIZATION_KEY_P8 APPLE_NOTARIZATION_KEY_ID APPLE_NOTARIZATION_ISSUER_ID; do
if [[ -z "${!var:-}" ]]; then
echo "$var is required"
exit 1
fi
done
notary_key_path="${RUNNER_TEMP}/notarytool.key.p8"
echo "$APPLE_NOTARIZATION_KEY_P8" | base64 -d > "$notary_key_path"
cleanup_notary() {
rm -f "$notary_key_path"
}
trap cleanup_notary EXIT
source "$GITHUB_ACTION_PATH/notary_helpers.sh"
dmg_name="codex-${TARGET}.dmg"
dmg_path="codex-rs/target/${TARGET}/release/${dmg_name}"
if [[ ! -f "$dmg_path" ]]; then
echo "dmg $dmg_path not found"
exit 1
fi
keychain_args=()
if [[ -n "${APPLE_CODESIGN_KEYCHAIN:-}" && -f "${APPLE_CODESIGN_KEYCHAIN}" ]]; then
keychain_args+=(--keychain "${APPLE_CODESIGN_KEYCHAIN}")
fi
codesign --force --timestamp --sign "$APPLE_CODESIGN_IDENTITY" "${keychain_args[@]}" "$dmg_path"
notarize_submission "$dmg_name" "$dmg_path" "$notary_key_path"
xcrun stapler staple "$dmg_path"
- name: Remove signing keychain
if: ${{ always() }}
shell: bash
env:
APPLE_CODESIGN_KEYCHAIN: ${{ env.APPLE_CODESIGN_KEYCHAIN }}
run: |
set -euo pipefail
if [[ -n "${APPLE_CODESIGN_KEYCHAIN:-}" ]]; then
keychain_args=()
while IFS= read -r keychain; do
[[ "$keychain" == "$APPLE_CODESIGN_KEYCHAIN" ]] && continue
[[ -n "$keychain" ]] && keychain_args+=("$keychain")
done < <(security list-keychains | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/"//g')
if ((${#keychain_args[@]} > 0)); then
security list-keychains -s "${keychain_args[@]}"
security default-keychain -s "${keychain_args[0]}"
fi
if [[ -f "$APPLE_CODESIGN_KEYCHAIN" ]]; then
security delete-keychain "$APPLE_CODESIGN_KEYCHAIN"
fi
fi
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
</dict>
</plist>
@@ -1,46 +0,0 @@
#!/usr/bin/env bash
notarize_submission() {
local label="$1"
local path="$2"
local notary_key_path="$3"
if [[ -z "${APPLE_NOTARIZATION_KEY_ID:-}" || -z "${APPLE_NOTARIZATION_ISSUER_ID:-}" ]]; then
echo "APPLE_NOTARIZATION_KEY_ID and APPLE_NOTARIZATION_ISSUER_ID are required for notarization"
exit 1
fi
if [[ -z "$notary_key_path" || ! -f "$notary_key_path" ]]; then
echo "Notary key file $notary_key_path not found"
exit 1
fi
if [[ ! -f "$path" ]]; then
echo "Notarization payload $path not found"
exit 1
fi
local submission_json
submission_json=$(xcrun notarytool submit "$path" \
--key "$notary_key_path" \
--key-id "$APPLE_NOTARIZATION_KEY_ID" \
--issuer "$APPLE_NOTARIZATION_ISSUER_ID" \
--output-format json \
--wait)
local status submission_id
status=$(printf '%s\n' "$submission_json" | jq -r '.status // "Unknown"')
submission_id=$(printf '%s\n' "$submission_json" | jq -r '.id // ""')
if [[ -z "$submission_id" ]]; then
echo "Failed to retrieve submission ID for $label"
exit 1
fi
echo "::notice title=Notarization::$label submission ${submission_id} completed with status ${status}"
if [[ "$status" != "Accepted" ]]; then
echo "Notarization failed for ${label} (submission ${submission_id}, status ${status})"
exit 1
fi
}
@@ -0,0 +1,349 @@
name: Set up AKV PKCS11 code signing
description: Download prebuilt rcodesign and Azure Key Vault PKCS11 provider artifacts, then export macOS signing environment.
inputs:
setup-mode:
description: signing configures Azure and exports signing env vars; tools-only only downloads signing tools.
required: false
default: signing
rcodesign-blob-uri:
description: Azure Blob URI for the prebuilt Linux/amd64 rcodesign binary.
required: true
rcodesign-sha256:
description: Expected SHA-256 digest for the prebuilt rcodesign binary.
required: true
akv-pkcs11-library-blob-uri:
description: Azure Blob URI for the prebuilt Linux/amd64 AKV PKCS11 provider library.
required: true
akv-pkcs11-library-sha256:
description: Expected SHA-256 digest for the prebuilt AKV PKCS11 provider library.
required: true
azure-client-id:
description: GitHub OIDC client ID for the Azure signer application.
required: true
azure-tenant-id:
description: Azure tenant ID for the signer application.
required: true
azure-subscription-id:
description: Azure subscription ID that owns the signing vault.
required: true
key-vault-name:
description: Azure Key Vault name containing the certificate-backed signing key.
required: true
key-name:
description: Key Vault certificate/key name used as the PKCS11 key label.
required: true
key-version:
description: Optional Key Vault key version to pin while signing.
required: false
default: ""
certificate-sha256:
description: Optional expected SHA-256 fingerprint for the downloaded public certificate.
required: false
default: ""
outputs:
pkcs11-library:
description: Path to the downloaded AKV PKCS11 provider library.
value: ${{ steps.paths.outputs.pkcs11_library }}
signing-certificate-pem:
description: Path to the downloaded public signing certificate.
value: ${{ steps.paths.outputs.signing_certificate_pem }}
rcodesign:
description: Path to the downloaded rcodesign binary.
value: ${{ steps.paths.outputs.rcodesign }}
runs:
using: composite
steps:
- name: Validate pinned signing artifacts
shell: bash
env:
SETUP_MODE: ${{ inputs.setup-mode }}
RCODESIGN_BLOB_URI: ${{ inputs.rcodesign-blob-uri }}
RCODESIGN_SHA256: ${{ inputs.rcodesign-sha256 }}
AKV_PKCS11_LIBRARY_BLOB_URI: ${{ inputs.akv-pkcs11-library-blob-uri }}
AKV_PKCS11_LIBRARY_SHA256: ${{ inputs.akv-pkcs11-library-sha256 }}
KEY_VAULT_NAME: ${{ inputs.key-vault-name }}
KEY_NAME: ${{ inputs.key-name }}
run: |
set -euo pipefail
case "$SETUP_MODE" in
signing|tools-only)
;;
*)
echo "setup-mode must be 'signing' or 'tools-only', got '$SETUP_MODE'." >&2
exit 1
;;
esac
for variable_name in RCODESIGN_SHA256 AKV_PKCS11_LIBRARY_SHA256; do
value="${!variable_name}"
if [[ ! "$value" =~ ^[0-9a-f]{64}$ ]]; then
echo "$variable_name must be a lowercase SHA-256 digest." >&2
exit 1
fi
done
for variable_name in RCODESIGN_BLOB_URI AKV_PKCS11_LIBRARY_BLOB_URI; do
value="${!variable_name}"
if [[ ! "$value" =~ ^az://[^/]+/[^/]+/.+ ]]; then
echo "$variable_name must use az://<account>/<container>/<blob>." >&2
exit 1
fi
done
if [[ "$SETUP_MODE" == "signing" ]]; then
for variable_name in \
KEY_VAULT_NAME \
KEY_NAME; do
if [[ -z "${!variable_name}" ]]; then
echo "$variable_name is required for AKV PKCS11 signing." >&2
exit 1
fi
done
fi
- name: Resolve signing tool paths
id: paths
shell: bash
run: |
set -euo pipefail
if [[ "${RUNNER_OS}" != "Linux" ]]; then
echo "Prebuilt AKV PKCS11 signing tools are only vendored for Linux runners, got ${RUNNER_OS}." >&2
exit 1
fi
if [[ "${RUNNER_ARCH}" != "X64" && "${RUNNER_ARCH}" != "AMD64" ]]; then
echo "Prebuilt AKV PKCS11 signing tools are only vendored for amd64 runners, got ${RUNNER_ARCH}." >&2
exit 1
fi
provider_root="${RUNNER_TEMP}/akv-pkcs11-provider"
rcodesign_root="${RUNNER_TEMP}/rcodesign-root"
signing_certificate_pem="${RUNNER_TEMP}/akv-signing-cert.pem"
library_name="libakv_pkcs_11.so"
mkdir -p "$provider_root" "$rcodesign_root/bin"
{
echo "pkcs11_library=$provider_root/$library_name"
echo "pkcs11_manifest=$provider_root/akv-pkcs11-provider.manifest"
echo "rcodesign_root=$rcodesign_root"
echo "rcodesign=$rcodesign_root/bin/rcodesign"
echo "signing_certificate_pem=$signing_certificate_pem"
} >> "$GITHUB_OUTPUT"
- name: Validate Azure credentials for private signing artifacts
shell: bash
env:
AZURE_CLIENT_ID: ${{ inputs.azure-client-id }}
AZURE_TENANT_ID: ${{ inputs.azure-tenant-id }}
AZURE_SUBSCRIPTION_ID: ${{ inputs.azure-subscription-id }}
run: |
set -euo pipefail
for variable_name in AZURE_CLIENT_ID AZURE_TENANT_ID AZURE_SUBSCRIPTION_ID; do
if [[ -z "${!variable_name}" ]]; then
echo "$variable_name is required for private AKV PKCS11 signing artifacts." >&2
exit 1
fi
done
- name: Log in to Azure with GitHub OIDC
uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0
with:
client-id: ${{ inputs.azure-client-id }}
tenant-id: ${{ inputs.azure-tenant-id }}
subscription-id: ${{ inputs.azure-subscription-id }}
- name: Install prebuilt signing tools
shell: bash
env:
RCODESIGN_BLOB_URI: ${{ inputs.rcodesign-blob-uri }}
RCODESIGN_SHA256: ${{ inputs.rcodesign-sha256 }}
RCODESIGN: ${{ steps.paths.outputs.rcodesign }}
AKV_PKCS11_LIBRARY_BLOB_URI: ${{ inputs.akv-pkcs11-library-blob-uri }}
AKV_PKCS11_LIBRARY_SHA256: ${{ inputs.akv-pkcs11-library-sha256 }}
PKCS11_LIBRARY: ${{ steps.paths.outputs.pkcs11_library }}
PKCS11_MANIFEST: ${{ steps.paths.outputs.pkcs11_manifest }}
run: |
set -euo pipefail
download_az_blob_uri() {
local uri="$1"
local destination="$2"
local rest account container blob
rest="${uri#az://}"
account="${rest%%/*}"
rest="${rest#*/}"
container="${rest%%/*}"
blob="${rest#*/}"
if [[ -z "$account" || -z "$container" || -z "$blob" || "$blob" == "$rest" ]]; then
echo "Invalid Azure Blob URI. Expected az://<account>/<container>/<blob>." >&2
exit 1
fi
mkdir -p "$(dirname "$destination")"
rm -f "$destination"
if ! az storage blob download \
--account-name "$account" \
--container-name "$container" \
--name "$blob" \
--file "$destination" \
--auth-mode login \
--only-show-errors \
>/dev/null 2>&1; then
echo "Failed to download a private signing artifact from Azure Blob Storage." >&2
exit 1
fi
}
verify_sha256() {
local path="$1"
local expected="$2"
local actual
actual="$(shasum -a 256 "$path" | awk '{ print $1 }')"
if [[ "$actual" != "$expected" ]]; then
echo "SHA-256 verification failed for '$path'." >&2
exit 1
fi
}
echo "Downloading prebuilt rcodesign."
download_az_blob_uri "$RCODESIGN_BLOB_URI" "$RCODESIGN"
verify_sha256 "$RCODESIGN" "$RCODESIGN_SHA256"
chmod 0755 "$RCODESIGN"
echo "Downloading prebuilt AKV PKCS11 provider."
download_az_blob_uri "$AKV_PKCS11_LIBRARY_BLOB_URI" "$PKCS11_LIBRARY"
verify_sha256 "$PKCS11_LIBRARY" "$AKV_PKCS11_LIBRARY_SHA256"
chmod 0644 "$PKCS11_LIBRARY"
{
echo "runner_os=$RUNNER_OS"
echo "runner_arch=$RUNNER_ARCH"
echo "library_name=$(basename "$PKCS11_LIBRARY")"
} > "$PKCS11_MANIFEST"
- name: Verify downloaded signing tools
shell: bash
env:
RCODESIGN: ${{ steps.paths.outputs.rcodesign }}
RCODESIGN_SHA256: ${{ inputs.rcodesign-sha256 }}
PKCS11_LIBRARY: ${{ steps.paths.outputs.pkcs11_library }}
AKV_PKCS11_LIBRARY_SHA256: ${{ inputs.akv-pkcs11-library-sha256 }}
PKCS11_MANIFEST: ${{ steps.paths.outputs.pkcs11_manifest }}
run: |
set -euo pipefail
verify_sha256() {
local path="$1"
local expected="$2"
local actual
actual="$(shasum -a 256 "$path" | awk '{ print $1 }')"
if [[ "$actual" != "$expected" ]]; then
echo "SHA-256 verification failed for '$path'." >&2
exit 1
fi
}
if [[ ! -x "$RCODESIGN" ]]; then
echo "rcodesign is missing or not executable at '$RCODESIGN'." >&2
exit 1
fi
if [[ ! -f "$PKCS11_LIBRARY" ]]; then
echo "AKV PKCS11 provider library is missing at '$PKCS11_LIBRARY'." >&2
exit 1
fi
verify_sha256 "$RCODESIGN" "$RCODESIGN_SHA256"
verify_sha256 "$PKCS11_LIBRARY" "$AKV_PKCS11_LIBRARY_SHA256"
"$RCODESIGN" --version
"$RCODESIGN" notarize --help > /dev/null
if [[ -f "$PKCS11_MANIFEST" ]]; then
echo "AKV PKCS11 provider artifact manifest is present."
else
echo "AKV PKCS11 provider artifact manifest is absent." >&2
exit 1
fi
- name: Download signing certificate from Key Vault
if: ${{ inputs.setup-mode == 'signing' }}
shell: bash
env:
KEY_VAULT_NAME: ${{ inputs.key-vault-name }}
KEY_NAME: ${{ inputs.key-name }}
KEY_VERSION: ${{ inputs.key-version }}
CERTIFICATE_SHA256: ${{ inputs.certificate-sha256 }}
SIGNING_CERTIFICATE_PEM: ${{ steps.paths.outputs.signing_certificate_pem }}
run: |
set -euo pipefail
certificate_version_args=()
if [[ -n "$KEY_VERSION" ]]; then
certificate_version_args+=(--version "$KEY_VERSION")
fi
if ! az keyvault certificate download \
--vault-name "$KEY_VAULT_NAME" \
--name "$KEY_NAME" \
"${certificate_version_args[@]}" \
--file "$SIGNING_CERTIFICATE_PEM" \
--encoding PEM \
--only-show-errors \
>/dev/null 2>&1; then
echo "Failed to download the public signing certificate from Azure Key Vault." >&2
exit 1
fi
if [[ -n "$CERTIFICATE_SHA256" ]]; then
actual_sha256="$(
openssl x509 -in "$SIGNING_CERTIFICATE_PEM" -noout -fingerprint -sha256 |
awk -F= '{ print toupper($2) }' |
tr -d ':\r\n'
)"
expected_sha256="$(printf '%s' "$CERTIFICATE_SHA256" | tr '[:lower:]' '[:upper:]' | tr -d ':\r\n ')"
if [[ "$actual_sha256" != "$expected_sha256" ]]; then
echo "Downloaded signing certificate SHA-256 did not match the expected fingerprint." >&2
exit 1
fi
fi
- name: Export AKV PKCS11 signing environment
if: ${{ inputs.setup-mode == 'signing' }}
shell: bash
env:
RCODESIGN_ROOT: ${{ steps.paths.outputs.rcodesign_root }}
PKCS11_LIBRARY: ${{ steps.paths.outputs.pkcs11_library }}
SIGNING_CERTIFICATE_PEM: ${{ steps.paths.outputs.signing_certificate_pem }}
KEY_VAULT_NAME: ${{ inputs.key-vault-name }}
KEY_NAME: ${{ inputs.key-name }}
KEY_VERSION: ${{ inputs.key-version }}
run: |
set -euo pipefail
{
echo "$RCODESIGN_ROOT/bin"
} >> "$GITHUB_PATH"
{
echo "OAI_CODESIGN_BACKEND=akv-pkcs11"
echo "OAI_AKV_PKCS11_LIBRARY=$PKCS11_LIBRARY"
echo "OAI_AKV_SIGNING_CERTIFICATE_PEM=$SIGNING_CERTIFICATE_PEM"
echo "OAI_AKV_KEY_LABEL=$KEY_NAME"
echo "AZURE_CREDENTIAL_KIND=azurecli"
echo "AZURE_KEYVAULT_NAME=$KEY_VAULT_NAME"
if [[ -n "$KEY_VERSION" ]]; then
echo "AZURE_KEYVAULT_KEY_VERSION=$KEY_VERSION"
fi
} >> "$GITHUB_ENV"