From 10954211577b6dbabb9bc5e822064b9ee9f5da2d Mon Sep 17 00:00:00 2001 From: Ben Hearsum Date: Tue, 14 Jan 2025 16:19:22 -0500 Subject: [PATCH] feat: avoid hardcoding widevine signing format --- iscript/src/iscript/autograph.py | 7 ++-- iscript/src/iscript/hardened_sign.py | 5 ++- iscript/src/iscript/mac.py | 5 ++- iscript/tests/test_autograph.py | 63 ++++++++++++++++++++++------ 4 files changed, 59 insertions(+), 21 deletions(-) diff --git a/iscript/src/iscript/autograph.py b/iscript/src/iscript/autograph.py index 60d883f09..5f8b7565b 100644 --- a/iscript/src/iscript/autograph.py +++ b/iscript/src/iscript/autograph.py @@ -65,7 +65,7 @@ # sign_widevine_dir {{{1 -async def sign_widevine_dir(config, sign_config, app_dir): +async def sign_widevine_dir(config, sign_config, app_dir, autograph_fmt): """Sign the internals of a tarfile with the widevine key. Extract the entire tarball, but only sign a handful of files (see @@ -98,7 +98,7 @@ async def sign_widevine_dir(config, sign_config, app_dir): to = _get_mac_sigpath(from_) log.debug("Adding %s to the sigfile paths...", to) makedirs(os.path.dirname(to)) - tasks.append(asyncio.ensure_future(sign_widevine_with_autograph(sign_config, from_, "blessed" in fmt, to=to))) + tasks.append(asyncio.ensure_future(sign_widevine_with_autograph(sign_config, from_, autograph_fmt, "blessed" in fmt, to=to))) all_files.append(to) await raise_future_exceptions(tasks) remove_extra_files(app_dir, all_files) @@ -439,7 +439,7 @@ async def merge_omnija_files(orig, signed, to): # sign_widevine_with_autograph {{{1 -async def sign_widevine_with_autograph(sign_config, from_, blessed, to=None): +async def sign_widevine_with_autograph(sign_config, from_, fmt, blessed, to=None): """Create a widevine signature using autograph as a backend. Args: @@ -462,7 +462,6 @@ async def sign_widevine_with_autograph(sign_config, from_, blessed, to=None): to = to or f"{from_}.sig" flags = 1 if blessed else 0 - fmt = "autograph_widevine" h = widevine.generate_widevine_hash(from_, flags) diff --git a/iscript/src/iscript/hardened_sign.py b/iscript/src/iscript/hardened_sign.py index f0077790b..5c2f309c8 100644 --- a/iscript/src/iscript/hardened_sign.py +++ b/iscript/src/iscript/hardened_sign.py @@ -184,8 +184,9 @@ async def sign_hardened_behavior(config, task, create_pkg=False, **kwargs): # sign widevine futures = [] for app in all_apps: - if {"autograph_widevine", "widevine"} & set(app.formats): - futures.append(asyncio.ensure_future(sign_widevine_dir(config, sign_config, app.app_path))) + fmt = next((f for f in app.formats if "widevine" in f), None) + if fmt: + futures.append(asyncio.ensure_future(sign_widevine_dir(config, sign_config, app.app_path, fmt))) await raise_future_exceptions(futures) await unlock_keychain(sign_config["signing_keychain"], sign_config["keychain_password"]) futures = [] diff --git a/iscript/src/iscript/mac.py b/iscript/src/iscript/mac.py index 67c962ebc..2d10488c1 100644 --- a/iscript/src/iscript/mac.py +++ b/iscript/src/iscript/mac.py @@ -648,8 +648,9 @@ async def sign_all_apps(config, sign_config, entitlements_path, all_paths, provi # sign widevine futures = [] for app in all_paths: - if {"autograph_widevine", "widevine"} & set(app.formats): - futures.append(asyncio.ensure_future(sign_widevine_dir(config, sign_config, app.app_path))) + fmt = next((f for f in app.formats if "widevine" in f), None) + if fmt: + futures.append(asyncio.ensure_future(sign_widevine_dir(config, sign_config, app.app_path, fmt))) await raise_future_exceptions(futures) await unlock_keychain(sign_config["signing_keychain"], sign_config["keychain_password"]) futures = [] diff --git a/iscript/tests/test_autograph.py b/iscript/tests/test_autograph.py index 402fe8509..76233eb44 100644 --- a/iscript/tests/test_autograph.py +++ b/iscript/tests/test_autograph.py @@ -31,6 +31,20 @@ def sign_config(): "langpack_url": "https://autograph-hsm.dev.mozaws.net/langpack", "langpack_user": "langpack_user", "langpack_pass": "langpack_pass", + "stage_widevine_url": "https://autograph-stage.dev.mozaws.net", + "stage_widevine_user": "widevine_user", + "stage_widevine_pass": "widevine_pass", + "stage_widevine_cert": "widevine_cert", + "stage_langpack_url": "https://autograph-stage.dev.mozaws.net/langpack", + "stage_langpack_user": "langpack_user", + "stage_langpack_pass": "langpack_pass", + "gcp_prod_widevine_url": "https://autograph-gcp.dev.mozaws.net", + "gcp_prod_widevine_user": "widevine_user", + "gcp_prod_widevine_pass": "widevine_pass", + "gcp_prod_widevine_cert": "widevine_cert", + "gcp_prod_langpack_url": "https://autograph-gcp.dev.mozaws.net/langpack", + "gcp_prod_langpack_user": "langpack_user", + "gcp_prod_langpack_pass": "langpack_pass", } @@ -42,8 +56,16 @@ def noop_sync(*args, **kwargs): ... # sign_file_with_autograph {{{1 @pytest.mark.asyncio -@pytest.mark.parametrize("to,expected,format,options", ((None, "from", "autograph_widevine", None), ("to", "to", "autograph_widevine", None))) -async def test_sign_file_with_autograph(sign_config, mocker, to, expected, format, options): +@pytest.mark.parametrize( + "to,expected,format,url", + ( + (None, "from", "autograph_widevine", "https://autograph-hsm.dev.mozaws.net"), + ("to", "to", "autograph_widevine", "https://autograph-hsm.dev.mozaws.net"), + ("to", "to", "stage_autograph_widevine", "https://autograph-stage.dev.mozaws.net"), + ("to", "to", "gcp_prod_autograph_widevine", "https://autograph-gcp.dev.mozaws.net"), + ), +) +async def test_sign_file_with_autograph(sign_config, mocker, to, expected, format, url): open_mock = mocker.mock_open(read_data=b"0xdeadbeef") mocker.patch("builtins.open", open_mock, create=True) @@ -58,9 +80,8 @@ async def test_sign_file_with_autograph(sign_config, mocker, to, expected, forma assert await autograph.sign_file_with_autograph(sign_config, "from", format, to=to) == expected open_mock.assert_called() kwargs = {"input": "MHhkZWFkYmVlZg=="} - if options: - kwargs["options"] = options - session_mock.post.assert_called_with("https://autograph-hsm.dev.mozaws.net/sign/file", auth=mocker.ANY, json=[kwargs]) + expected_url = f"{url}/sign/file" + session_mock.post.assert_called_with(expected_url, auth=mocker.ANY, json=[kwargs]) @pytest.mark.asyncio @@ -140,7 +161,7 @@ def fake_isfile(path): mocker.patch.object(os.path, "isfile", new=fake_isfile) mocker.patch.object(os, "walk", new=fake_walk) - await autograph.sign_widevine_dir(config, sign_config, filename) + await autograph.sign_widevine_dir(config, sign_config, filename, fmt) # _get_widevine_signing_files {{{1 @@ -240,13 +261,21 @@ async def test_bad_autograph_method(): @pytest.mark.asyncio -@pytest.mark.parametrize("blessed", (True, False)) -async def test_widevine_autograph(mocker, tmp_path, blessed, sign_config): +@pytest.mark.parametrize("blessed,fmt,expected_url", + ( + (True, "autograph_widevine", "https://autograph-hsm.dev.mozaws.net"), + (False, "autograph_widevine", "https://autograph-hsm.dev.mozaws.net"), + (False, "stage_autograph_widevine", "https://autograph-stage.dev.mozaws.net"), + (False, "gcp_prod_autograph_widevine", "https://autograph-gcp.dev.mozaws.net"), + ) +) +async def test_widevine_autograph(mocker, tmp_path, blessed, sign_config, fmt, expected_url): wv = mocker.patch("iscript.autograph.widevine") wv.generate_widevine_hash.return_value = b"hashhashash" wv.generate_widevine_signature.return_value = b"sigwidevinesig" - async def fake_call(*args, **kwargs): + async def fake_call(url, *args, **kwargs): + assert expected_url in url return [{"signature": base64.b64encode(b"sigwidevinesig")}] mocker.patch.object(autograph, "call_autograph", fake_call) @@ -256,21 +285,29 @@ async def fake_call(*args, **kwargs): sign_config["widevine_cert"] = cert to = tmp_path / "signed.sig" - to = await autograph.sign_widevine_with_autograph(sign_config, "from", blessed, to=to) + to = await autograph.sign_widevine_with_autograph(sign_config, "from", fmt, blessed, to=to) assert b"sigwidevinesig" == to.read_bytes() @pytest.mark.asyncio -async def test_no_widevine(mocker, tmp_path): - async def fake_call(*args, **kwargs): +@pytest.mark.parametrize("fmt,expected_url", + ( + ("autograph_widevine", "https://autograph-hsm.dev.mozaws.net"), + ("stage_autograph_widevine", "https://autograph-stage.dev.mozaws.net"), + ("gcp_prod_autograph_widevine", "https://autograph-gcp.dev.mozaws.net"), + ) +) +async def test_no_widevine(mocker, tmp_path, fmt, expected_url): + async def fake_call(url, *args, **kwargs): + assert expected_url in url return [{"signature": b"sigautographsig"}] mocker.patch.object(autograph, "call_autograph", fake_call) with pytest.raises(ImportError): to = tmp_path / "signed.sig" - to = await autograph.sign_widevine_with_autograph({}, "from", True, to=to) + to = await autograph.sign_widevine_with_autograph({}, "from", fmt, True, to=to) # omnija {{{1