1
0
forked from baron/baron-sso

웍스 드라이브 구조 변경

This commit is contained in:
2026-06-19 14:14:25 +09:00
parent 0062633bee
commit a1a4620d3e
13 changed files with 610 additions and 144 deletions

View File

@@ -29,7 +29,6 @@ require_env ADMINFRONT_URL
require_env DEVFRONT_URL
require_env ORGFRONT_URL
require_env VITE_OIDC_AUTHORITY
require_env HARBOR_HOSTNAME
if ! printf '%s' "$IMAGE_TAG" | grep -Eq '^v[0-9]+\.[0-9]{4}\.[0-9a-f]{4}$'; then
die "IMAGE_TAG must look like vX.YYMM.ab12 (got: $IMAGE_TAG)"
@@ -59,6 +58,10 @@ compose_template="${IMAGE_DEPLOY_COMPOSE_TEMPLATE:-$repo_root/deploy/templates/d
rm -rf "$bundle_dir"
TARGET_DIR="$bundle_dir" bash "$repo_root/deploy/create-instance.sh" "$instance_name" "$port_prefix"
cp "$compose_template" "$bundle_dir/docker-compose.yml"
mkdir -p "$bundle_dir/scripts/docker-image" "$bundle_dir/scripts/backup/lib"
cp "$repo_root/scripts/docker-image/download_works_drive.sh" "$bundle_dir/scripts/docker-image/download_works_drive.sh"
cp "$repo_root/scripts/backup/lib/common.sh" "$bundle_dir/scripts/backup/lib/common.sh"
chmod +x "$bundle_dir/scripts/docker-image/download_works_drive.sh"
sed "s/{{BACKEND_PORT}}/${IMAGE_DEPLOY_BACKEND_PORT}/g" \
"$repo_root/deploy/templates/gateway/nginx.conf" >"$bundle_dir/gateway/nginx.conf"

View File

@@ -15,25 +15,78 @@ require_env IMAGE_DEPLOY_BUNDLE_FILE
require_env DEPLOY_HOST
require_env DEPLOY_USER
require_env DEPLOY_PATH
require_env HARBOR_ENDPOINT
require_env HARBOR_ROBOT_ACCOUNT
require_env HARBOR_ROBOT_KEY
require_env WORKS_DRIVE_DOCKER_IMAGE_DRIVE_ID
[[ -f "$IMAGE_DEPLOY_BUNDLE_FILE" ]] || die "bundle file not found: $IMAGE_DEPLOY_BUNDLE_FILE"
resolve_works_drive_access_token() {
if [[ -n "${WORKS_DRIVE_ACCESS_TOKEN:-}" ]]; then
printf '%s\n' "$WORKS_DRIVE_ACCESS_TOKEN"
return
fi
if [[ -n "${WORKS_DRIVE_ACCESS_TOKEN_INPUT:-}" ]]; then
printf '%s\n' "$WORKS_DRIVE_ACCESS_TOKEN_INPUT"
return
fi
if [[ -n "${WORKS_DRIVE_ACCESS_TOKEN_FILE:-}" ]]; then
[[ -f "$WORKS_DRIVE_ACCESS_TOKEN_FILE" ]] || die "WORKS_DRIVE_ACCESS_TOKEN_FILE not found: $WORKS_DRIVE_ACCESS_TOKEN_FILE"
sed -n '1p' "$WORKS_DRIVE_ACCESS_TOKEN_FILE"
return
fi
if [[ -n "${WORKS_DRIVE_ACCESS_TOKEN_CMD:-}" ]]; then
sh -c "$WORKS_DRIVE_ACCESS_TOKEN_CMD"
return
fi
if [[ -n "${WORKS_DRIVE_OAUTH_REFRESH_TOKEN:-}" ]]; then
[[ -n "${WORKS_DRIVE_OAUTH_CLIENT_ID:-}" ]] || die "WORKS_DRIVE_OAUTH_CLIENT_ID is required when using WORKS_DRIVE_OAUTH_REFRESH_TOKEN."
[[ -n "${WORKS_DRIVE_OAUTH_CLIENT_SECRET:-}" ]] || die "WORKS_DRIVE_OAUTH_CLIENT_SECRET is required when using WORKS_DRIVE_OAUTH_REFRESH_TOKEN."
local token_url="${WORKS_DRIVE_OAUTH_TOKEN_URL:-https://auth.worksmobile.com/oauth2/v2.0/token}"
local response
local access_token
local rotated_refresh_token
response="$(curl -fsS -X POST "$token_url" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=refresh_token" \
--data-urlencode "refresh_token=${WORKS_DRIVE_OAUTH_REFRESH_TOKEN}" \
--data-urlencode "client_id=${WORKS_DRIVE_OAUTH_CLIENT_ID}" \
--data-urlencode "client_secret=${WORKS_DRIVE_OAUTH_CLIENT_SECRET}")"
access_token="$(jq -er '.access_token' <<<"$response")"
rotated_refresh_token="$(jq -r '.refresh_token // empty' <<<"$response")"
if [[ -n "$rotated_refresh_token" && "$rotated_refresh_token" != "$WORKS_DRIVE_OAUTH_REFRESH_TOKEN" ]]; then
printf 'WARNING: WORKS returned a rotated refresh token. Update WORKS_DRIVE_REFRESH_TOKEN before the old token ages out.\n' >&2
fi
printf '%s\n' "$access_token"
return
fi
die "Missing WORKS Drive access auth. Provide WORKS_DRIVE_ACCESS_TOKEN, WORKS_DRIVE_ACCESS_TOKEN_FILE, WORKS_DRIVE_ACCESS_TOKEN_CMD, or WORKS_DRIVE_OAUTH_REFRESH_TOKEN."
}
remote_bundle="/tmp/baron-sso-image-deploy-$(date -u '+%Y%m%d%H%M%S').tgz"
works_drive_access_token="$(resolve_works_drive_access_token)"
ssh-keyscan -H "$DEPLOY_HOST" >>~/.ssh/known_hosts
scp "$IMAGE_DEPLOY_BUNDLE_FILE" "${DEPLOY_USER}@${DEPLOY_HOST}:${remote_bundle}"
echo "$HARBOR_ROBOT_KEY" | ssh "${DEPLOY_USER}@${DEPLOY_HOST}" \
printf '%s\n' "$works_drive_access_token" | ssh "${DEPLOY_USER}@${DEPLOY_HOST}" \
"set -euo pipefail; \
read -r works_drive_access_token; \
mkdir -p '${DEPLOY_PATH}'; \
tar -xzf '${remote_bundle}' -C '${DEPLOY_PATH}'; \
cd '${DEPLOY_PATH}'; \
chmod 600 .env; \
docker network inspect traefik-public >/dev/null 2>&1 || docker network create traefik-public; \
docker login '${HARBOR_ENDPOINT}' -u '${HARBOR_ROBOT_ACCOUNT}' --password-stdin; \
docker compose --env-file .env -f docker-compose.yml pull; \
export WORKS_DRIVE_ACCESS_TOKEN=\"\${works_drive_access_token}\"; \
export WORKS_DRIVE_DOCKER_IMAGE_DRIVE_ID='${WORKS_DRIVE_DOCKER_IMAGE_DRIVE_ID}'; \
export WORKS_DRIVE_DOCKER_IMAGE_PARENT_FILE_ID='${WORKS_DRIVE_DOCKER_IMAGE_PARENT_FILE_ID:-}'; \
export WORKS_DRIVE_DOCKER_IMAGE_DIR='${WORKS_DRIVE_DOCKER_IMAGE_DIR:-baron-sso}'; \
export WORKS_ADMIN_API_BASE_URL='${WORKS_ADMIN_API_BASE_URL:-https://www.worksapis.com}'; \
scripts/docker-image/download_works_drive.sh; \
docker compose --env-file .env -f docker-compose.yml up -d --remove-orphans; \
docker compose --env-file .env -f docker-compose.yml ps"

View File

@@ -0,0 +1,185 @@
#!/usr/bin/env bash
set -euo pipefail
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "$script_dir/../.." && pwd)"
source "$repo_root/scripts/backup/lib/common.sh"
dotenv_value() {
local key="$1"
local env_file="${WORKS_DOCKER_IMAGE_ENV_FILE:-.env}"
[[ -f "$env_file" ]] || return 0
sed -n "s/^${key}=//p" "$env_file" | tail -n 1
}
urlencode_path() {
jq -nr --arg value "$1" '$value|@uri'
}
split_curl_response() {
local response="$1"
local __body_var="$2"
local __status_var="$3"
local status
local body
status="$(tail -n 1 <<<"$response")"
if [[ "$status" =~ ^[0-9][0-9][0-9]$ ]]; then
body="$(sed '$d' <<<"$response")"
else
status="200"
body="$response"
fi
printf -v "$__body_var" '%s' "$body"
printf -v "$__status_var" '%s' "$status"
}
redact_for_log() {
sed -E 's/("(access_token|refresh_token|assertion|client_secret|Authorization)"[[:space:]]*:[[:space:]]*)"[^"]*"/\1"REDACTED"/Ig'
}
resolve_files_endpoint() {
local parent_file_id="${1:-}"
local encoded_drive_id
encoded_drive_id="$(urlencode_path "$drive_id")"
if [[ -n "$parent_file_id" ]]; then
printf '%s/v1.0/sharedrives/%s/files/%s\n' "$api_base_url" "$encoded_drive_id" "$(urlencode_path "$parent_file_id")"
else
printf '%s/v1.0/sharedrives/%s/files\n' "$api_base_url" "$encoded_drive_id"
fi
}
list_children() {
local parent_file_id="${1:-}"
local endpoint
local response
local response_body
local http_status
endpoint="$(resolve_files_endpoint "$parent_file_id")/children"
response="$("$curl_bin" -sS -w $'\n%{http_code}' \
-H "Authorization: Bearer $access_token" \
"$endpoint")"
split_curl_response "$response" response_body http_status
if [[ "$http_status" -lt 200 || "$http_status" -ge 300 ]]; then
backup_die "WORKS folder list request failed (HTTP $http_status): $(printf '%s' "$response_body" | redact_for_log)"
fi
printf '%s\n' "$response_body"
}
find_child_id() {
local parent_file_id="$1"
local child_name="$2"
local expected_type="${3:-}"
local children_json
children_json="$(list_children "$parent_file_id")"
jq -er --arg name "$child_name" --arg expectedType "$expected_type" '
[
(.files // .children // .items // [])[]
| select((.fileName // .name) == $name)
| select(
$expectedType == ""
or (((.fileType // .type // "") | ascii_downcase) == ($expectedType | ascii_downcase))
)
| .fileId // .id
][0] // empty
' <<<"$children_json" 2>/dev/null || true
}
resolve_folder_path() {
local path="$1"
local parent_file_id="${WORKS_DRIVE_DOCKER_IMAGE_PARENT_FILE_ID:-}"
local component
local folder_id
IFS='/' read -r -a components <<<"$path"
for component in "${components[@]}"; do
[[ -n "$component" ]] || continue
folder_id="$(find_child_id "$parent_file_id" "$component" "folder")"
[[ -n "$folder_id" ]] || backup_die "WORKS Drive folder not found: ${path}"
parent_file_id="$folder_id"
done
printf '%s\n' "$parent_file_id"
}
download_file() {
local file_id="$1"
local output_file="$2"
local endpoint
endpoint="$(resolve_files_endpoint "$file_id")/download"
"$curl_bin" -fL -sS \
--location-trusted \
-H "Authorization: Bearer $access_token" \
-o "$output_file" \
"$endpoint"
}
load_image_archive() {
local archive_file="$1"
backup_log "Loading Docker image archive: $(basename "$archive_file")"
zstd -dc "$archive_file" | docker load >/dev/null
}
image_tag="${IMAGE_TAG:-$(dotenv_value IMAGE_TAG)}"
drive_id="${WORKS_DRIVE_DOCKER_IMAGE_DRIVE_ID:-${WORKS_DRIVE_SHARED_DRIVE_ID:-}}"
access_token="${WORKS_DRIVE_ACCESS_TOKEN:-}"
api_base_url="${WORKS_ADMIN_API_BASE_URL:-https://www.worksapis.com}"
curl_bin="${WORKS_DRIVE_CURL_BIN:-curl}"
image_root_dir="${WORKS_DRIVE_DOCKER_IMAGE_DIR:-${WORKS_SHAREDRIVE_DOCKER_IMAGE_DIR:-baron-sso}}"
download_root="${WORKS_DOCKER_IMAGE_DOWNLOAD_DIR:-/tmp/baron-sso-docker-image-download}"
image_list="${WORKS_DOCKER_IMAGE_NAMES:-backend userfront adminfront devfront orgfront}"
[[ -n "$image_tag" ]] || backup_die "IMAGE_TAG is required."
[[ -n "$drive_id" ]] || backup_die "WORKS_DRIVE_DOCKER_IMAGE_DRIVE_ID is required."
[[ -n "$access_token" ]] || backup_die "WORKS_DRIVE_ACCESS_TOKEN is required."
backup_require_command jq
backup_require_command sha256sum
backup_require_command zstd
backup_require_command docker
backup_require_command "$curl_bin"
# Normalized remote path: baron-sso/${IMAGE_TAG}/${image}.${IMAGE_TAG}.tar.zst
remote_path="${image_root_dir}/${image_tag}"
target_folder_id="$(resolve_folder_path "$remote_path")"
artifact_dir="${download_root}/${remote_path}"
mkdir -p "$artifact_dir"
for image in $image_list; do
archive_name="${image}.${image_tag}.tar.zst"
checksum_name="${image}.${image_tag}.sha256"
manifest_name="manifest.${image_tag}.json"
archive_id="$(find_child_id "$target_folder_id" "$archive_name")"
checksum_id="$(find_child_id "$target_folder_id" "$checksum_name")"
manifest_id="$(find_child_id "$target_folder_id" "$manifest_name")"
[[ -n "$archive_id" ]] || backup_die "WORKS Drive image archive not found: ${remote_path}/${archive_name}"
[[ -n "$checksum_id" ]] || backup_die "WORKS Drive image checksum not found: ${remote_path}/${checksum_name}"
[[ -n "$manifest_id" ]] || backup_die "WORKS Drive image manifest not found: ${remote_path}/${manifest_name}"
download_file "$archive_id" "$artifact_dir/$archive_name"
download_file "$checksum_id" "$artifact_dir/$checksum_name"
download_file "$manifest_id" "$artifact_dir/$manifest_name"
(
cd "$artifact_dir"
sha256sum -c "$checksum_name" >/dev/null
)
manifest_sha256="$(jq -er --arg image "$image" '.images[$image].archive.sha256 // .archive.sha256' "$artifact_dir/$manifest_name")"
actual_sha256="$(sha256sum "$artifact_dir/$archive_name" | awk '{print $1}')"
[[ "$manifest_sha256" == "$actual_sha256" ]] || backup_die "manifest sha256 mismatch for $archive_name"
load_image_archive "$artifact_dir/$archive_name"
done
backup_log "Loaded WORKS Drive Docker image archives from ${remote_path}"

View File

@@ -68,7 +68,7 @@ image_ref="${DOCKER_IMAGE_REF:-${IMAGE_REF:-}}"
commit_container="${WORKS_DOCKER_COMMIT_CONTAINER:-${DOCKER_COMMIT_CONTAINER:-}}"
archive_root="${WORKS_DOCKER_IMAGE_ARCHIVE_DIR:-/tmp/baron-sso-docker-image-upload}"
image_root_dir="${WORKS_SHAREDRIVE_DOCKER_IMAGE_DIR:-docker-build-image}"
image_root_dir="${WORKS_DRIVE_DOCKER_IMAGE_DIR:-${WORKS_SHAREDRIVE_DOCKER_IMAGE_DIR:-baron-sso}}"
dry_run="${WORKS_DRIVE_DRY_RUN:-false}"
target="${WORKS_DRIVE_TARGET:-sharedrive}"
api_base_url="${WORKS_ADMIN_API_BASE_URL:-https://www.worksapis.com}"
@@ -504,14 +504,16 @@ derive_repository_and_tag() {
derive_repository_and_tag "$image_ref"
remote_path="${image_root_dir}/${image_repository}/${image_tag}"
artifact_dir="${archive_root}/${image_repository}/${image_tag}"
image_name="${image_repository##*/}"
release_repository="${image_root_dir}"
remote_path="${release_repository}/${image_tag}"
artifact_dir="${archive_root}/${release_repository}/${image_tag}"
mkdir -p "$artifact_dir"
tar_file="$artifact_dir/image.tar"
archive_file="$artifact_dir/image.tar.zst"
checksum_file="$artifact_dir/image.tar.zst.sha256"
manifest_file="$artifact_dir/manifest.json"
tar_file="$artifact_dir/${image_name}.${image_tag}.tar"
archive_file="$artifact_dir/${image_name}.${image_tag}.tar.zst"
checksum_file="$artifact_dir/${image_name}.${image_tag}.sha256"
manifest_file="$artifact_dir/manifest.${image_tag}.json"
upload_report_file="$artifact_dir/works-upload.json"
rm -f "$tar_file" "$archive_file" "$checksum_file" "$manifest_file" "$upload_report_file"
@@ -535,36 +537,77 @@ image_id="$(docker image inspect "$image_ref" --format '{{.Id}}' 2>/dev/null ||
archive_size="$(stat -c '%s' "$archive_file")"
git_commit="$(backup_git_commit "$repo_root")"
jq -n \
--arg createdAt "$(backup_utc_now)" \
--arg imageRef "$image_ref" \
--arg repository "$image_repository" \
--arg tag "$image_tag" \
--arg sourceContainer "$commit_container" \
--arg imageId "$image_id" \
--arg gitCommit "$git_commit" \
--arg remotePath "$remote_path" \
--arg archiveFile "$(basename "$archive_file")" \
--arg archiveSha256 "$archive_sha256" \
--argjson archiveSize "$archive_size" \
'{
schema_version: 1,
format: "docker-save-zstd",
created_at: $createdAt,
manifest_tmp_file="${manifest_file}.tmp"
manifest_jq_filter='
def image_entry: {
image_ref: $imageRef,
repository: $repository,
tag: $tag,
image_name: $imageName,
source_container: $sourceContainer,
docker_image_id: $imageId,
git_commit: $gitCommit,
remote_path: $remotePath,
restore_command: ("zstd -d -c " + $archiveFile + " | docker load"),
archive: {
file_name: $archiveFile,
size_bytes: $archiveSize,
sha256: $archiveSha256
},
restore_command: ("zstd -d -c " + $archiveFile + " | docker load")
};
.schema_version = 1
| .format = "docker-save-zstd"
| .created_at = (.created_at // $createdAt)
| .updated_at = $createdAt
| .image_ref = $imageRef
| .repository = $repository
| .release_repository = $releaseRepository
| .image_name = $imageName
| .tag = $tag
| .source_container = $sourceContainer
| .docker_image_id = $imageId
| .git_commit = $gitCommit
| .remote_path = $remotePath
| .restore_command = ("zstd -d -c " + $archiveFile + " | docker load")
| .archive = {
file_name: $archiveFile,
size_bytes: $archiveSize,
sha256: $archiveSha256
}
}' >"$manifest_file"
| .images = ((.images // {}) + {($imageName): image_entry})
'
if [[ -f "$manifest_file" ]]; then
jq \
--arg createdAt "$(backup_utc_now)" \
--arg imageRef "$image_ref" \
--arg repository "$image_repository" \
--arg releaseRepository "$release_repository" \
--arg imageName "$image_name" \
--arg tag "$image_tag" \
--arg sourceContainer "$commit_container" \
--arg imageId "$image_id" \
--arg gitCommit "$git_commit" \
--arg remotePath "$remote_path" \
--arg archiveFile "$(basename "$archive_file")" \
--arg archiveSha256 "$archive_sha256" \
--argjson archiveSize "$archive_size" \
"$manifest_jq_filter" "$manifest_file" >"$manifest_tmp_file"
else
jq -n \
--arg createdAt "$(backup_utc_now)" \
--arg imageRef "$image_ref" \
--arg repository "$image_repository" \
--arg releaseRepository "$release_repository" \
--arg imageName "$image_name" \
--arg tag "$image_tag" \
--arg sourceContainer "$commit_container" \
--arg imageId "$image_id" \
--arg gitCommit "$git_commit" \
--arg remotePath "$remote_path" \
--arg archiveFile "$(basename "$archive_file")" \
--arg archiveSha256 "$archive_sha256" \
--argjson archiveSize "$archive_size" \
"$manifest_jq_filter" >"$manifest_tmp_file"
fi
mv "$manifest_tmp_file" "$manifest_file"
upload_files=("$archive_file" "$checksum_file" "$manifest_file")

View File

@@ -17,6 +17,11 @@ backup_require_command stat
backup_require_command zstd
manifest_file="$archive_dir/manifest.json"
mapfile -t versioned_manifest_files < <(find "$archive_dir" -maxdepth 1 -type f -name 'manifest.*.json' | sort)
if [[ "${#versioned_manifest_files[@]}" -gt 0 ]]; then
[[ "${#versioned_manifest_files[@]}" -eq 1 ]] || backup_die "archive directory must contain exactly one manifest.*.json file."
manifest_file="${versioned_manifest_files[0]}"
fi
backup_require_path "$manifest_file"
schema_version="$(jq -er '.schema_version' "$manifest_file")"
@@ -33,6 +38,9 @@ manifest_size="$(jq -er '.archive.size_bytes' "$manifest_file")"
archive_file="$archive_dir/$archive_name"
checksum_file="$archive_dir/${archive_name}.sha256"
if [[ ! -f "$checksum_file" && "$archive_name" == *.tar.zst ]]; then
checksum_file="$archive_dir/${archive_name%.tar.zst}.sha256"
fi
backup_require_path "$archive_file"
backup_require_path "$checksum_file"

View File

@@ -28,19 +28,19 @@ require_command jq
require_command sha256sum
require_command zstd
artifact_dir="$tmp_root/baron_sso/backend/v1.2606.ab12"
artifact_dir="$tmp_root/baron-sso/v1.2606.ab12"
mkdir -p "$artifact_dir"
printf 'docker image archive smoke\n' >"$artifact_dir/image.tar"
zstd -q -f -o "$artifact_dir/image.tar.zst" "$artifact_dir/image.tar"
rm -f "$artifact_dir/image.tar"
printf 'docker image archive smoke\n' >"$artifact_dir/backend.v1.2606.ab12.tar"
zstd -q -f -o "$artifact_dir/backend.v1.2606.ab12.tar.zst" "$artifact_dir/backend.v1.2606.ab12.tar"
rm -f "$artifact_dir/backend.v1.2606.ab12.tar"
archive_sha256="$(sha256sum "$artifact_dir/image.tar.zst" | awk '{print $1}')"
archive_size="$(wc -c <"$artifact_dir/image.tar.zst" | tr -d ' ')"
printf '%s image.tar.zst\n' "$archive_sha256" >"$artifact_dir/image.tar.zst.sha256"
archive_sha256="$(sha256sum "$artifact_dir/backend.v1.2606.ab12.tar.zst" | awk '{print $1}')"
archive_size="$(wc -c <"$artifact_dir/backend.v1.2606.ab12.tar.zst" | tr -d ' ')"
printf '%s backend.v1.2606.ab12.tar.zst\n' "$archive_sha256" >"$artifact_dir/backend.v1.2606.ab12.sha256"
jq -n \
--arg remotePath "docker-build-image/baron_sso/backend/v1.2606.ab12" \
--arg remotePath "baron-sso/v1.2606.ab12" \
--arg archiveSha256 "$archive_sha256" \
--argjson archiveSize "$archive_size" \
'{
@@ -48,33 +48,35 @@ jq -n \
format: "docker-save-zstd",
image_ref: "reg.hmac.kr/baron_sso/backend:v1.2606.ab12",
repository: "baron_sso/backend",
release_repository: "baron-sso",
image_name: "backend",
tag: "v1.2606.ab12",
remote_path: $remotePath,
archive: {
file_name: "image.tar.zst",
file_name: "backend.v1.2606.ab12.tar.zst",
size_bytes: $archiveSize,
sha256: $archiveSha256
}
}' >"$artifact_dir/manifest.json"
}' >"$artifact_dir/manifest.v1.2606.ab12.json"
"$verify_script" "$artifact_dir" >/dev/null
bad_checksum_dir="$tmp_root/bad-checksum"
cp -R "$artifact_dir" "$bad_checksum_dir"
printf '0000000000000000000000000000000000000000000000000000000000000000 image.tar.zst\n' >"$bad_checksum_dir/image.tar.zst.sha256"
printf '0000000000000000000000000000000000000000000000000000000000000000 backend.v1.2606.ab12.tar.zst\n' >"$bad_checksum_dir/backend.v1.2606.ab12.sha256"
assert_fails "$verify_script" "$bad_checksum_dir"
bad_manifest_dir="$tmp_root/bad-manifest"
cp -R "$artifact_dir" "$bad_manifest_dir"
jq '.archive.sha256 = "1111111111111111111111111111111111111111111111111111111111111111"' \
"$bad_manifest_dir/manifest.json" >"$bad_manifest_dir/manifest.json.tmp"
mv "$bad_manifest_dir/manifest.json.tmp" "$bad_manifest_dir/manifest.json"
"$bad_manifest_dir/manifest.v1.2606.ab12.json" >"$bad_manifest_dir/manifest.v1.2606.ab12.json.tmp"
mv "$bad_manifest_dir/manifest.v1.2606.ab12.json.tmp" "$bad_manifest_dir/manifest.v1.2606.ab12.json"
assert_fails "$verify_script" "$bad_manifest_dir"
bad_archive_dir="$tmp_root/bad-archive"
cp -R "$artifact_dir" "$bad_archive_dir"
printf 'not a zstd stream\n' >"$bad_archive_dir/image.tar.zst"
sha256sum "$bad_archive_dir/image.tar.zst" | awk '{print $1 " image.tar.zst"}' >"$bad_archive_dir/image.tar.zst.sha256"
printf 'not a zstd stream\n' >"$bad_archive_dir/backend.v1.2606.ab12.tar.zst"
sha256sum "$bad_archive_dir/backend.v1.2606.ab12.tar.zst" | awk '{print $1 " backend.v1.2606.ab12.tar.zst"}' >"$bad_archive_dir/backend.v1.2606.ab12.sha256"
assert_fails "$verify_script" "$bad_archive_dir"
echo "docker image archive verification checks passed"