@supacloud/admin 0.7.4 → 0.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +59 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -25622,7 +25622,7 @@ SUPACLOUD_GITHUB_REPOSITORY="\${SUPACLOUD_GITHUB_REPOSITORY:-zuohuadong/supaclou
25622
25622
  SUPACLOUD_RELEASES_API="\${SUPACLOUD_RELEASES_API:-https://api.github.com/repos/\${SUPACLOUD_GITHUB_REPOSITORY}/releases}"
25623
25623
  SUPACLOUD_ATTESTATION_SIGNER_WORKFLOW="\${SUPACLOUD_ATTESTATION_SIGNER_WORKFLOW:-\${SUPACLOUD_GITHUB_REPOSITORY}/.github/workflows/release-please.yml}"
25624
25624
  SUPACLOUD_GH_VERSION="\${SUPACLOUD_GH_VERSION:-2.96.0}"
25625
- SUPACLOUD_GH_MIN_VERSION="\${SUPACLOUD_GH_MIN_VERSION:-2.51.0}"
25625
+ SUPACLOUD_GH_MIN_VERSION="\${SUPACLOUD_GH_MIN_VERSION:-2.68.0}"
25626
25626
  SUPACLOUD_GH_AMD64_SHA256="\${SUPACLOUD_GH_AMD64_SHA256:-83d5c2ccad5498f58bf6368acb1ab32588cf43ab3a4b1c301bf36328b1c8bd60}"
25627
25627
  SUPACLOUD_GH_ARM64_SHA256="\${SUPACLOUD_GH_ARM64_SHA256:-06f86ec7103d41993b76cd78072f43595c34aaa56506d971d9860e67140bf909}"
25628
25628
 
@@ -25951,13 +25951,49 @@ supacloud_record_integrity_mode() {
25951
25951
  chmod 600 "$record_file" 2>/dev/null || true
25952
25952
  }
25953
25953
 
25954
- supacloud_verify_attestation() {
25954
+ supacloud_fetch_attestation_bundle() {
25955
+ local artifact_file="$1"
25956
+ local bundle_file="$2"
25957
+ local digest response
25958
+ digest=$(sha256sum "$artifact_file" | awk '{print $1}') || return 1
25959
+ [[ "$digest" =~ ^[0-9a-fA-F]{64}$ ]] || {
25960
+ echo "Unable to calculate the artifact digest for attestation lookup" >&2
25961
+ return 1
25962
+ }
25963
+ digest=$(printf '%s' "$digest" | tr '[:upper:]' '[:lower:]')
25964
+ response=$(supacloud_fetch_release_json \\
25965
+ "https://api.github.com/repos/\${SUPACLOUD_GITHUB_REPOSITORY}/attestations/sha256:\${digest}") || {
25966
+ echo "Unable to download the public GitHub artifact attestation bundle" >&2
25967
+ return 1
25968
+ }
25969
+ if ! jq -ce '
25970
+ .attestations
25971
+ | if type != "array" or length == 0 or any(.[]; (.bundle | type) != "object")
25972
+ then error("no valid attestation bundles returned")
25973
+ else .[].bundle
25974
+ end
25975
+ ' <<< "$response" > "$bundle_file"; then
25976
+ echo "GitHub artifact attestation response did not contain a valid bundle" >&2
25977
+ return 1
25978
+ fi
25979
+ }
25980
+
25981
+ supacloud_verify_attestation() (
25955
25982
  local artifact_file="$1"
25956
25983
  if supacloud_attestation_verifier_available; then
25957
- local verification_output
25984
+ local verification_output bundle_dir bundle_file
25985
+ bundle_dir=$(mktemp -d "\${TMPDIR:-/tmp}/supacloud-attestation.XXXXXX") || return 1
25986
+ trap 'rm -rf -- "$bundle_dir"' EXIT
25987
+ trap 'trap - EXIT HUP INT TERM; rm -rf -- "$bundle_dir"; exit 1' HUP INT TERM
25988
+ bundle_file="\${bundle_dir}/bundle.jsonl"
25989
+ if ! supacloud_fetch_attestation_bundle "$artifact_file" "$bundle_file"; then
25990
+ return 1
25991
+ fi
25958
25992
  if ! verification_output=$(gh attestation verify "$artifact_file" \\
25993
+ --bundle "$bundle_file" \\
25959
25994
  --repo "$SUPACLOUD_GITHUB_REPOSITORY" \\
25960
- --signer-workflow "$SUPACLOUD_ATTESTATION_SIGNER_WORKFLOW" 2>&1); then
25995
+ --signer-workflow "$SUPACLOUD_ATTESTATION_SIGNER_WORKFLOW" \\
25996
+ --source-ref "refs/heads/main" 2>&1); then
25961
25997
  echo "GitHub artifact attestation verification failed: \${verification_output}" >&2
25962
25998
  return 1
25963
25999
  fi
@@ -25973,15 +26009,18 @@ supacloud_verify_attestation() {
25973
26009
 
25974
26010
  echo "Artifact attestation verification is required, but gh attestation verify is unavailable. Install GitHub CLI or explicitly set SUPACLOUD_ALLOW_UNVERIFIED_RELEASE=true for emergency break-glass use." >&2
25975
26011
  return 1
25976
- }
26012
+ )
25977
26013
 
25978
26014
  supacloud_attestation_verifier_available() {
25979
- local version
26015
+ local version help
25980
26016
  command -v gh >/dev/null 2>&1 || return 1
25981
26017
  version=$(supacloud_gh_version)
25982
26018
  [[ -n "$version" ]] || return 1
25983
26019
  supacloud_version_at_least "$version" "$SUPACLOUD_GH_MIN_VERSION" || return 1
25984
- gh attestation verify --help 2>&1 | grep -q -- '--signer-workflow'
26020
+ help=$(gh attestation verify --help 2>&1) || return 1
26021
+ grep -Eq -- '(^|[[:space:]])--bundle([=[:space:]]|$)' <<< "$help" || return 1
26022
+ grep -Eq -- '(^|[[:space:]])--signer-workflow([=[:space:]]|$)' <<< "$help" || return 1
26023
+ grep -Eq -- '(^|[[:space:]])--source-ref([=[:space:]]|$)' <<< "$help"
25985
26024
  }
25986
26025
 
25987
26026
  supacloud_download_release_asset() (
@@ -26136,6 +26175,12 @@ function componentPreflightCommands(request) {
26136
26175
  `test "$EDGE_RUNTIME_MODE_VALUE" = external || { echo 'Edge Runtime component upgrade supports persisted external mode only' >&2; exit 1; }`
26137
26176
  ] : [];
26138
26177
  }
26178
+ function signalSafeCleanupTraps(cleanupCommand) {
26179
+ return [
26180
+ `trap '${cleanupCommand}' EXIT`,
26181
+ `trap 'trap - EXIT HUP INT TERM; ${cleanupCommand}; exit 1' HUP INT TERM`
26182
+ ];
26183
+ }
26139
26184
  function buildRootUpgradeScript(request) {
26140
26185
  const envAssignments = upgradeEnvAssignments(request);
26141
26186
  return [
@@ -26144,12 +26189,12 @@ function buildRootUpgradeScript(request) {
26144
26189
  "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
26145
26190
  "export PATH",
26146
26191
  "unset SUPACLOUD_ALLOW_UNVERIFIED_RELEASE SUPACLOUD_GITHUB_REPOSITORY SUPACLOUD_RELEASES_API SUPACLOUD_ATTESTATION_SIGNER_WORKFLOW SUPACLOUD_GH_VERSION SUPACLOUD_GH_MIN_VERSION SUPACLOUD_GH_AMD64_SHA256 SUPACLOUD_GH_ARM64_SHA256 GH_PROXY",
26147
- request.githubProxy ? `export SUPACLOUD_GITHUB_PROXY=${quoteEnvValue(request.githubProxy)}` : "unset SUPACLOUD_GITHUB_PROXY",
26192
+ request.githubProxy ? `export SUPACLOUD_GITHUB_PROXY=${quoteEnvValue(request.githubProxy)}` : "unset SUPACLOUD_GITHUB_PROXY SUPACLOUD_GITHUB_PROXIES",
26148
26193
  'for tool in curl jq file sha256sum tar; do command -v "$tool" >/dev/null 2>&1 || { echo "Required upgrade tool is missing: $tool" >&2; exit 127; }; done',
26149
26194
  "test -x /usr/local/bin/supacloud || { echo 'SupaCloud binary not found at /usr/local/bin/supacloud; run ssh install first.' >&2; exit 127; }",
26150
26195
  ...componentPreflightCommands(request),
26151
26196
  "STAGED_MANAGEMENT=''",
26152
- `trap 'test -z "$STAGED_MANAGEMENT" || rm -f "$STAGED_MANAGEMENT"' EXIT HUP INT TERM`,
26197
+ ...signalSafeCleanupTraps('test -z "$STAGED_MANAGEMENT" || rm -f "$STAGED_MANAGEMENT"'),
26153
26198
  `source ${quoteEnvValue(request.helperPath)}`,
26154
26199
  "if ! supacloud_attestation_verifier_available; then supacloud_install_pinned_gh /usr/local/bin/gh; fi",
26155
26200
  "supacloud_attestation_verifier_available || { echo 'Pinned GitHub attestation verifier is unavailable' >&2; exit 1; }",
@@ -26160,7 +26205,11 @@ function buildRootUpgradeScript(request) {
26160
26205
  }
26161
26206
  function buildOfficialUpgradeCommand(request) {
26162
26207
  const rootScript = buildRootUpgradeScript(request);
26163
- return `set -e; trap 'rm -f ${request.helperPath}' EXIT HUP INT TERM; ` + 'if [ "$(id -u)" -eq 0 ]; then ' + `bash -c ${quoteEnvValue(rootScript)}; ` + "else sudo -n true; " + `sudo -n bash -c ${quoteEnvValue(rootScript)}; fi`;
26208
+ return [
26209
+ "set -e",
26210
+ ...signalSafeCleanupTraps(`rm -f ${request.helperPath}`),
26211
+ 'if [ "$(id -u)" -eq 0 ]; then ' + `bash -c ${quoteEnvValue(rootScript)}; ` + "else sudo -n true; " + `sudo -n bash -c ${quoteEnvValue(rootScript)}; fi`
26212
+ ].join("; ");
26164
26213
  }
26165
26214
  async function removeRemoteUpgradeHelper(ssh, helperPath) {
26166
26215
  const cleanup = await ssh.exec(`rm -f ${quoteEnvValue(helperPath)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supacloud/admin",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "description": "Platform administration CLI for SupaCloud operators",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",