blockers 2
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-11-23 14:54:17 +02:00
parent f47d2d1377
commit cce96f3596
100 changed files with 2758 additions and 1912 deletions

View File

@@ -0,0 +1,147 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT=$(cd "$(dirname "$0")/../../.." && pwd)
OUT="$ROOT/out/mirror/thin"
STAGE="$OUT/stage-v1"
CREATED="2025-11-23T00:00:00Z"
mkdir -p "$STAGE/layers" "$STAGE/indexes"
# 1) Seed deterministic content
cat > "$STAGE/layers/observations.ndjson" <<'DATA'
{"id":"obs-001","purl":"pkg:nuget/Newtonsoft.Json@13.0.3","advisory":"CVE-2025-0001","severity":"medium","source":"vendor-a","timestamp":"2025-11-01T00:00:00Z"}
{"id":"obs-002","purl":"pkg:npm/lodash@4.17.21","advisory":"CVE-2024-9999","severity":"high","source":"vendor-b","timestamp":"2025-10-15T00:00:00Z"}
DATA
cat > "$STAGE/indexes/observations.index" <<'DATA'
obs-001 layers/observations.ndjson:1
obs-002 layers/observations.ndjson:2
DATA
# 2) Build manifest from staged files
python - <<'PY'
import json, hashlib, os, pathlib
root = pathlib.Path(os.environ['STAGE'])
created = os.environ['CREATED']
def digest(path: pathlib.Path) -> str:
h = hashlib.sha256()
with path.open('rb') as f:
for chunk in iter(lambda: f.read(8192), b''):
h.update(chunk)
return 'sha256:' + h.hexdigest()
def size(path: pathlib.Path) -> int:
return path.stat().st_size
layers = []
for path in sorted((root / 'layers').glob('*')):
layers.append({
'path': f"layers/{path.name}",
'size': size(path),
'digest': digest(path)
})
indexes = []
for path in sorted((root / 'indexes').glob('*')):
indexes.append({
'name': path.name,
'digest': digest(path)
})
manifest = {
'version': '1.0.0',
'created': created,
'layers': layers,
'indexes': indexes
}
manifest_path = root / 'manifest.json'
manifest_path.write_text(json.dumps(manifest, indent=2, sort_keys=True) + '\n', encoding='utf-8')
PY
# 3) Tarball with deterministic metadata
pushd "$OUT" >/dev/null
rm -f mirror-thin-v1.tar.gz mirror-thin-v1.tar.gz.sha256 mirror-thin-v1.manifest.json mirror-thin-v1.manifest.json.sha256
cp "$STAGE/manifest.json" mirror-thin-v1.manifest.json
export GZIP=-n
/usr/bin/tar --sort=name --owner=0 --group=0 --numeric-owner --mtime='1970-01-01' -czf mirror-thin-v1.tar.gz -C "$STAGE" .
popd >/dev/null
# 4) Checksums
pushd "$OUT" >/dev/null
sha256sum mirror-thin-v1.manifest.json > mirror-thin-v1.manifest.json.sha256
sha256sum mirror-thin-v1.tar.gz > mirror-thin-v1.tar.gz.sha256
popd >/dev/null
# 5) Optional signing (DSSE + TUF) if SIGN_KEY is provided
if [[ -n "${SIGN_KEY:-}" ]]; then
mkdir -p "$OUT/tuf/keys"
python scripts/mirror/sign_thin_bundle.py \
--key "$SIGN_KEY" \
--manifest "$OUT/mirror-thin-v1.manifest.json" \
--tar "$OUT/mirror-thin-v1.tar.gz" \
--tuf-dir "$OUT/tuf"
fi
# 6) Optional OCI archive (MIRROR-CRT-57-001)
if [[ "${OCI:-0}" == "1" ]]; then
OCI_DIR="$OUT/oci"
BLOBS="$OCI_DIR/blobs/sha256"
mkdir -p "$BLOBS"
# layer = thin tarball
LAYER_SHA=$(sha256sum "$OUT/mirror-thin-v1.tar.gz" | awk '{print $1}')
cp "$OUT/mirror-thin-v1.tar.gz" "$BLOBS/$LAYER_SHA"
LAYER_SIZE=$(stat -c%s "$OUT/mirror-thin-v1.tar.gz")
# config = minimal empty config
CONFIG_TMP=$(mktemp)
echo '{"architecture":"amd64","os":"linux"}' > "$CONFIG_TMP"
CONFIG_SHA=$(sha256sum "$CONFIG_TMP" | awk '{print $1}')
CONFIG_SIZE=$(stat -c%s "$CONFIG_TMP")
cp "$CONFIG_TMP" "$BLOBS/$CONFIG_SHA"
rm "$CONFIG_TMP"
mkdir -p "$OCI_DIR"
cat > "$OCI_DIR/oci-layout" <<'JSON'
{
"imageLayoutVersion": "1.0.0"
}
JSON
MANIFEST_FILE="$OCI_DIR/manifest.json"
cat > "$MANIFEST_FILE" <<JSON
{
"schemaVersion": 2,
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": $CONFIG_SIZE,
"digest": "sha256:$CONFIG_SHA"
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": $LAYER_SIZE,
"digest": "sha256:$LAYER_SHA",
"annotations": {"org.stellaops.bundle.type": "mirror-thin-v1"}
}
]
}
JSON
MANIFEST_SHA=$(sha256sum "$MANIFEST_FILE" | awk '{print $1}')
MANIFEST_SIZE=$(stat -c%s "$MANIFEST_FILE")
cat > "$OCI_DIR/index.json" <<JSON
{
"schemaVersion": 2,
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:$MANIFEST_SHA",
"size": $MANIFEST_SIZE,
"annotations": {"org.opencontainers.image.ref.name": "mirror-thin-v1"}
}
]
}
JSON
fi
# 7) Verification
python scripts/mirror/verify_thin_bundle.py "$OUT/mirror-thin-v1.manifest.json" "$OUT/mirror-thin-v1.tar.gz"
echo "mirror-thin-v1 built at $OUT"