From 493ef2f244199a7403ea476d9996b9a2cc876dc2 Mon Sep 17 00:00:00 2001 From: rmlibre Date: Sun, 11 Aug 2024 14:57:55 -0400 Subject: [PATCH] v0.23.13: build: improve package signing with better logic & git file tree --- CHANGES.rst | 2 +- SIGNATURE.txt | 23 +++++++++++++++++------ pyproject.toml | 3 +++ sign_package_build.py | 33 ++++++++++++++++++++++----------- 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index ae5b97a..b06cbfb 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -12,7 +12,7 @@ Changes for version 0.23.13 Major Changes ^^^^^^^^^^^^^ -- None +- build: improve package signing with better logic & git file tree Minor Changes diff --git a/SIGNATURE.txt b/SIGNATURE.txt index 514e840..f7f24a5 100644 --- a/SIGNATURE.txt +++ b/SIGNATURE.txt @@ -1,8 +1,18 @@ { - "checksum": "5201c13d06d787ec1a9fdcd0a3b5f8e80acbd360ebc7563ec0ec06a83729241b2dfe3a158324c0d3db8e8bebe00359b5", + "checksum": "b79db7591144626753f40c3e637515f3452db828e4811f267732ef6efaf24121ab75ffd452f790aed7a74d2589b74f66", "checksums": { + ".github/ISSUE_TEMPLATE/bug-report.yml": "35b0ab3c57c6f08c6e08f5432217e2f3a5c2ffb7cbf102e3c1b719324b80bdc2797ba173cba97adb66f4b8e8dc3a5964", + ".github/workflows/linux-pypi-release-tests.yml": "8391a79d347dd43ac01fc856a8262c24391d3aafc4959a20e8ee626f93aaa4af1d276325d408691d31afd311d88623a5", + ".github/workflows/linux-pypi-release.yml": "e92e772eea5f3f2e0a82836ae3275998cbbe3071ec7673ea46a4a2e700f699f07888f31f541950808b5b60881ca3a876", + ".github/workflows/linux-python-app.yml": "88e3398adcd350c44d63bb51c747db760bf61939db4848a1bb6e9ee1ad47b1fbb0611b759eff8f93048172251ebcd831", + ".github/workflows/macos-pypi-release-tests.yml": "4f277dd0928f122f17aa9eaf186f544cc8d3cef502a39689a3a3ab186417faeeb76ff171ed1ef3c9a0bb7e09916385ce", + ".github/workflows/macos-pypi-release.yml": "978e94f107c232a454b50a86abc0bca08958958cd7b39d45b95150065ee188657c5b14e2526cc4bbf871792a26cb0cf9", + ".github/workflows/macos-python-app.yml": "3650ddf92d9ba3f8724d2f7ed8e03edbe7452afa93b439acfb4b0644821e07a5d7a1adc7068314e80481ef7fcdf538c8", + ".github/workflows/windows-pypi-release-tests.yml": "2222a4c4e354d74672cab0da0843e0f204283d039f3d39c62ebab84e20bd0a2a84d095948a0ceb682a6d2dc0432259e8", + ".github/workflows/windows-pypi-release.yml": "a1ceb5d9b37be6fc24bfe47f129283705b60f173821c6228835cd4faf8cd9db5e77e32f4b93c2054bacd95d4e34dc288", + ".github/workflows/windows-python-app.yml": "212109a917bf97f26ed5b61d8d0d28051d9f53b01a8f11ac2df50613b76ba8999e5e855e808d2cead808704f3dcfd037", ".gitignore": "12deb1309e7f3d7c571d7831e99afc0e4f9fbf9c495c91574ffeb4b873d97bb83cb4d81941a7df8f19ec2293ca276ea0", - "CHANGES.rst": "73fb488f4d0a0714db5afe17ffe820a95b84bb3512609526889021ee455dba73fa68738ea6250a5ddf3f13424f1f5553", + "CHANGES.rst": "fa1bfbcb1b4622aeb01049c807c8d70a06b360febfa215c76bc7494a11b73ef1daed581f985187c96bdec7d96b63d99f", "CODE_OF_CONDUCT.md": "1999f7d9791b3e79aac666c7286c71bcf1910a8b3adfb6699d29981c146b85479eece9e9ba6d877b888f6b7082707c34", "CONTRIBUTING.md": "6bd90aab16a531bf13652544b22400532cb13f9d89386955065f398a4fcfb065f60bbee2e28d9ae59146b70878236079", "FAQ.rst": "cad5af23d070117d3f1398ab979048ead7884b546ea9f2fe36f0f67b337ee93675a64ab84fe2a52f62dc66dd82d7c2c4", @@ -128,10 +138,10 @@ "licenses/pytest-asyncio_LICENSE.txt": "c7eade567a30b0dd5c3b56ebd500733d48a28d92897e69d2dc3130773a3a560e5ff470ae6d5af5b627a204fdaefc4b5c", "licenses/pytest_LICENSE.txt": "a8144a38e953dca1ffe5cc0e7dbacdb56bbabf012aba9adf2f65b51ed823f78e7333d82ec9c18cc88b4daba95b7f6330", "logo.png": "7cd769aaddcb3a2d14324f9ef325d42f7024d3e5351b49facef79c4f7ab8c050a39d41c31db2b6a786cd684115c05389", - "pyproject.toml": "482e4b6f0e4982ecdcbdcd2f2e7287ed98cfacde97d99ea4335e06f9ffa850d3401f5e738c4d78607a3c6a8af1e37a23", + "pyproject.toml": "9e00c0b991968d92588a04e131b38c1e94d8a74b5d5f6d72c85329960d60d06363ba706dc2c5f5cfd17126cccd31b388", "setup.cfg": "09cbcaf58f29823537e017ceaa6077b80f0d1136560c8b705ee9446c57479ef6f29733e540b24fa5cf57cec6f69f8465", "setup.py": "adf70ba11864f435b1bbb476c0c8818199b6d945b4ff4fa4a8819b160c8e5ed12abcf58240a7121fd6663be3ccd38b3a", - "sign_package_build.py": "5e355bba462f8067b0d88666d8e9d1d551c18e28dbd2100edc90e873dedf92e91e11c206c1e119d8ee0cf34f33723aa2", + "sign_package_build.py": "37b574f6f9b62896a46532977c75e11dd2bff81b0ce2543c981119ab7ea00227c0c86d2c09709339cf44c0f4857728aa", "tests/conftest.py": "eb991a9464363bdce93a7fc7938770569ef4884e0c70d8537f7f660501b1fa554cd0be1f21c2313135967a5cf67266e7", "tests/test_ByteIO.py": "00082a2677f0df1eaf1b355d2c5e9aed6c38f954ea0d5defeada1ad9870c1254efdc6263779188137567e2db62d0767f", "tests/test_Clock.py": "5a80bb4b478d5bd6fee4c46235cbe5240f52c3e072b1e8faf374d804d7dca87cd98cabdd9c2877a3812341663b4316af", @@ -179,13 +189,14 @@ }, "scope": { "author": "rmlibre@riseup.net", - "build_number": "1", + "build_number": "2", "date": 19946, "description": "a high-level async cryptographic anonymity library to scale, simplify, & automate privacy best practices for secure data & identity processing, communication, & storage.", + "git_branch": "main", "license": "AGPLv3", "package": "aiootp", "version": "0.23.13" }, "signing_key": "70d1740f2a439da98243c43a4d7ef1cf993b87a75f3bb0851ae79de675af5b3b", - "signature": "1ae6a85f434f99808311a394eb82225de4c8094a9834907477a56dfd37d716b77947af0fd164ebf5f00bf854eb9ef0ab332c95a8eaa9af7785c0046a6f230604" + "signature": "898f87b56492ce86eb6bfa91b4898b43b2e090f91f0b73f172d542bddf2eeeb53e9f2a53dd2ed003ecc2b03da4217dc6c3147d5673feb345fe18e96b15440c08" } \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index d9791c2..7c8376e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -385,6 +385,9 @@ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" "{issue_reporting,setup,sign_package_build}.py" = [ "T201", # legit print use in CLI ] +"sign_package_build.py" = [ + "S603", # legit shell use to get git file tree to sign +] "**/_typing/*" = [ "A002", # no control if mirrored interfaces reuse built-in names "FBT001", # no control over positional boolean params here diff --git a/sign_package_build.py b/sign_package_build.py index d7b18e8..6f2711f 100755 --- a/sign_package_build.py +++ b/sign_package_build.py @@ -18,6 +18,8 @@ import json from pathlib import Path from getpass import getpass +from shlex import quote, split +from subprocess import check_output from aiootp import ( __doc__, @@ -25,24 +27,34 @@ __package__, __version__, __author__, + __PUBLIC_ED25519_KEY__ as aiootp_signing_key, ) from aiootp import PackageSigner, PackageVerifier -if __name__ == "__main__" and getpass( - "sign package? (y/N) " -).lower().strip().startswith("y"): +if __name__ != "__main__": + pass +elif getpass("sign package? (y/N) ").lower().strip().startswith("y"): with Path("SIGNATURE.txt").open("r") as sig: scope = json.loads(sig.read())[PackageSigner._SCOPE] print("current version:", __version__) print(f"current build: {scope['build_number']}\n") + git_branch = next( + line.strip().split()[-1] + for line in check_output(split("git branch")).decode().split("\n") + if line.startswith("*") + ) + if f"* {git_branch}" not in check_output(split("git branch")).decode(): + raise ValueError(f"The value {git_branch=} is invalid.") + signer = PackageSigner( package=__package__, version=__version__, author=__author__, license=__license__, description=__doc__, + git_branch=git_branch, build_number=getpass("build number: "), ) signer.connect_to_secure_database( @@ -72,20 +84,19 @@ **{getpass("name: ").strip(): getpass("value: ")} ) - with Path("MANIFEST.in").open("r") as manifest: - filename_sheet = manifest.read().strip().split("\n") - - for line in filename_sheet: - line = line.strip() - if "SIGNATURE" in line or not line.startswith("include"): + git_branch_tree = check_output( + split(f"git ls-tree --full-tree -r {quote(git_branch)}") + ) + for line in git_branch_tree.decode().strip().split("\n"): + filename = line.strip().split("\t")[-1].strip() + if not filename or "SIGNATURE" in filename: continue - filename = line.split(" ")[-1] with Path(filename).open("rb") as source_file: signer.add_file(filename, source_file.read()) signer.sign_package() summary = signer.summarize() - verifier = PackageVerifier(signer.signing_key.public_bytes, path="") + verifier = PackageVerifier(bytes.fromhex(aiootp_signing_key), path="") verifier.verify_summary(summary) with Path("SIGNATURE.txt").open("w+") as attestation: attestation.write(json.dumps(summary, indent=4))