fix: qualify mobile Cloud viewer and companion downloads
This commit is contained in:
@@ -71,15 +71,22 @@ echo "publish-companion-apk: zipalign + sign (v1+v2+v3)…" >&2
|
||||
"$SIGNED"
|
||||
|
||||
# 4. Verify all three schemes (min-sdk 21 forces the v1 path to be exercised).
|
||||
VERIFY="$("$APKSIGNER" verify -v --min-sdk-version 21 "$SIGNED" 2>&1)"
|
||||
VERIFY="$("$APKSIGNER" verify -v --min-sdk-version 21 --print-certs "$SIGNED" 2>&1)"
|
||||
for scheme in "v1 scheme" "v2 scheme" "v3 scheme"; do
|
||||
if ! printf '%s\n' "$VERIFY" | grep -iq "$scheme.*: true"; then
|
||||
if ! grep -iq "$scheme.*: true" <<< "$VERIFY"; then
|
||||
echo "publish-companion-apk: ERROR — $scheme NOT present after signing. Aborting." >&2
|
||||
printf '%s\n' "$VERIFY" | grep -iE "scheme" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "publish-companion-apk: verified v1 + v2 + v3 signatures." >&2
|
||||
# The existing shared companion identity must survive updates. Verifying a new
|
||||
# certificate's mathematical validity alone does not establish upgrade compatibility.
|
||||
EXPECTED_SIGNER_SHA256="d622e07e7f474246e8e2bcee828ca9bf6c6cdf9434c065c58fe89bb4eec2664d"
|
||||
if ! grep -iq "Signer #1 certificate SHA-256 digest: $EXPECTED_SIGNER_SHA256" <<< "$VERIFY"; then
|
||||
echo "publish-companion-apk: ERROR — signing identity differs from the existing companion. Aborting." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "publish-companion-apk: verified v1 + v2 + v3 signatures and existing signer." >&2
|
||||
|
||||
# 5. Publish.
|
||||
mkdir -p "$(dirname "$DEST")"
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
"""Run the publisher's actual verifier block, including noisy apksigner output."""
|
||||
import os
|
||||
import pathlib
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
ROOT = pathlib.Path(__file__).resolve().parents[2]
|
||||
SCRIPT = (ROOT / 'scripts/publish-companion-apk.sh').read_text()
|
||||
BLOCK = SCRIPT[SCRIPT.index('# 4. Verify'):SCRIPT.index('# 5. Publish')]
|
||||
CERT = 'd622e07e7f474246e8e2bcee828ca9bf6c6cdf9434c065c58fe89bb4eec2664d'
|
||||
GOOD = '\n'.join(f'Verified using {v} scheme (test): true' for v in ['v1', 'v2', 'v3']) + '\nSigner #1 certificate SHA-256 digest: ' + CERT
|
||||
|
||||
class VerificationTests(unittest.TestCase):
|
||||
def check(self, output, code=0):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root = pathlib.Path(tmp)
|
||||
verifier = root / 'apksigner'
|
||||
verifier.write_text('#!/bin/sh\ncat "$TEST_VERIFY_OUTPUT"\nexit "$TEST_VERIFY_CODE"\n')
|
||||
verifier.chmod(0o700)
|
||||
(root / 'output').write_text(output)
|
||||
env = dict(os.environ, APKSIGNER=str(verifier), SIGNED=str(root / 'test.apk'),
|
||||
TEST_VERIFY_OUTPUT=str(root / 'output'), TEST_VERIFY_CODE=str(code))
|
||||
return subprocess.run(['bash', '-c', 'set -euo pipefail\n' + BLOCK], env=env, capture_output=True, text=True).returncode
|
||||
|
||||
def test_noisy_valid_apk_does_not_fail_from_grep_sigpipe(self):
|
||||
# Reproduces pipefail+grep -q exit141 after an otherwise valid APK.
|
||||
self.assertEqual(self.check(GOOD + '\n' + 'WARNING: compatible signature algorithm\n' * 4000), 0)
|
||||
|
||||
def test_all_three_schemes_are_required(self):
|
||||
for version in ['v1', 'v2', 'v3']:
|
||||
with self.subTest(version=version):
|
||||
self.assertNotEqual(self.check(GOOD.replace(f'{version} scheme (test): true', f'{version} scheme (test): false')), 0)
|
||||
|
||||
def test_wrong_signing_identity_fails(self):
|
||||
self.assertNotEqual(self.check(GOOD.replace(CERT, '0' * 64)), 0)
|
||||
|
||||
def test_verifier_failure_is_never_accepted(self):
|
||||
self.assertNotEqual(self.check(GOOD, 1), 0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user