def test_get_tagged_image_digests_no_manifest_list(mock_quay_client, target_settings, repo_api_data, v2s2_manifest_data): hub = mock.MagicMock() mock_get_manifest = mock.MagicMock() mock_get_manifest.return_value = v2s2_manifest_data mock_quay_client.return_value.get_manifest = mock_get_manifest mock_get_manifest_digest = mock.MagicMock() mock_get_manifest_digest.return_value = ( "sha256:146ab6fa7ba3ab4d154b09c1c5522e4966ecd071bf23d1ba3df6c8b9fc33f8cb" ) mock_quay_client.return_value.get_manifest_digest = mock_get_manifest_digest sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings, "some-target") digests = sig_handler.get_tagged_image_digests( "registry.com/namespace/image:3", "application/vnd.docker.distribution.manifest.list.v2+json", ) assert digests == [ "sha256:146ab6fa7ba3ab4d154b09c1c5522e4966ecd071bf23d1ba3df6c8b9fc33f8cb" ] mock_get_manifest.assert_called_once_with( "registry.com/namespace/image:3", media_type="application/vnd.docker.distribution.manifest.list.v2+json", ) mock_get_manifest_digest.assert_called_once_with( "registry.com/namespace/image:3", media_type="application/vnd.docker.distribution.manifest.list.v2+json", )
def test_filter_claim_messages( mock_quay_client, mock_get_signatures, target_settings, claim_messages, existing_signatures, ): hub = mock.MagicMock() mock_get_signatures.return_value = existing_signatures sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings, "some-target") filtered_msgs = sig_handler.filter_claim_messages(claim_messages) mock_get_signatures.assert_called_once_with(manifest_digests=[ "sha256:a2a2a2a", "sha256:b3b3b3b", "sha256:d5d5d5d5", "sha256:f4f4f4f" ]) assert filtered_msgs == [{ "sig_key_id": "00000002", "claim_file": "some-encode", "pub_task_id": "1", "request_id": "id3", "manifest_digest": "sha256:b3b3b3b", "repo": "some-dest-repo", "image_name": "image", "docker_reference": "registry.com/image:2", "created": "2021-03-19T14:45:23.128632Z", }]
def test_get_tagged_image_digests_manifest_list(mock_quay_api_client, mock_quay_client, target_settings, repo_api_data, manifest_list_data): hub = mock.MagicMock() mock_get_repo_data = mock.MagicMock() mock_get_repo_data.return_value = repo_api_data mock_get_manifest = mock.MagicMock() mock_get_manifest.return_value = manifest_list_data mock_quay_api_client.return_value.get_repository_data = mock_get_repo_data mock_quay_client.return_value.get_manifest = mock_get_manifest sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings) digests = sig_handler.get_tagged_image_digests( "registry.com/namespace/image:1") assert digests == [ "sha256:2e8f38a0a8d2a450598430fa70c7f0b53aeec991e76c3e29c63add599b4ef7ee", "sha256:b3f9218fb5839763e62e52ee6567fe331aa1f3c644f9b6f232ff23959257acf9", "sha256:496fb0ff2057c79254c9dc6ba999608a98219c5c93142569a547277c679e532c", "sha256:146ab6fa7ba3ab4d154b09c1c5522e4966ecd071bf23d1ba3df6c8b9fc33f8cb", "sha256:bbef1f46572d1f33a92b53b0ba0ed5a1d09dab7ffe64be1ae3ae66e76275eabd", ] mock_get_repo_data.assert_called_once_with("namespace/image") mock_get_manifest.assert_called_once_with("registry.com/namespace/image:1", manifest_list=True)
def test_create_claim_message( mock_quay_api_client, mock_quay_client, mock_encode, mock_datetime, mock_uuid, target_settings ): hub = mock.MagicMock() mock_encode.return_value = b"some-encode" mock_uuid.return_value = "7ed1d8fb-77bc-4222-ad6a-89f508f02d75" mock_datetime.utcnow.return_value.isoformat.return_value = "2021-03-19T14:45:23.128632" sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings, "some-target") claim_msg = sig_handler.create_manifest_claim_message( "some-dest-repo", "key1", "sha256:f4f4f4f", "registry.com/image:1", "image", "1" ) mock_encode.assert_called_with( json.dumps( { "critical": { "type": "atomic container signature", "image": {"docker-manifest-digest": "sha256:f4f4f4f"}, "identity": {"docker-reference": "registry.com/image:1"}, }, "optional": {"creator": "Red Hat RCM Pub"}, } ).encode("latin1") ) assert claim_msg == { "sig_key_id": "key1", "claim_file": "some-encode", "pub_task_id": "1", "request_id": "7ed1d8fb-77bc-4222-ad6a-89f508f02d75", "manifest_digest": "sha256:f4f4f4f", "repo": "some-dest-repo", "image_name": "image", "docker_reference": "registry.com/image:1", "created": "2021-03-19T14:45:23.128632Z", }
def test_validate_radas_msgs( mock_quay_api_client, mock_quay_client, target_settings, claim_messages, error_signed_messages ): hub = mock.MagicMock() sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings, "some-target") with pytest.raises(exceptions.SigningError, match="Signing of 2/3 messages has failed"): sig_handler.validate_radas_messages(claim_messages, error_signed_messages)
def test_get_signatures_from_radas( mock_quay_api_client, mock_quay_client, mock_claim_handler, mock_proton, target_settings, claim_messages, ): hub = mock.MagicMock() sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings, "some-target") sig_handler.get_signatures_from_radas(claim_messages) assert mock_claim_handler.call_args[1]["umb_urls"] == ["some-url1", "some-url2"] radas_addr = "queue://Consumer.msg-producer-pub.1.VirtualTopic.eng.robosignatory.container.sign" assert mock_claim_handler.call_args[1]["radas_address"] == radas_addr assert mock_claim_handler.call_args[1]["claim_messages"] == [ { "sig_key_id": "key1", "claim_file": "some-encode", "pub_task_id": "1", "request_id": "id1", "manifest_digest": "sha256:f4f4f4f", "repo": "some-dest-repo", "image_name": "image", "docker_reference": "registry.com/image:1", "created": "2021-03-19T14:45:23.128632Z", }, { "sig_key_id": "key1", "claim_file": "some-encode", "pub_task_id": "1", "request_id": "id2", "manifest_digest": "sha256:a2a2a2a", "repo": "some-dest-repo", "image_name": "image", "docker_reference": "registry.com/image:1", "created": "2021-03-19T14:45:23.128632Z", }, { "sig_key_id": "key1", "claim_file": "some-encode", "pub_task_id": "1", "request_id": "id3", "manifest_digest": "sha256:b3b3b3b", "repo": "some-dest-repo", "image_name": "image", "docker_reference": "registry.com/image:2", "created": "2021-03-19T14:45:23.128632Z", }, ] assert mock_claim_handler.call_args[1]["pub_cert"] == "/etc/pub/umb-pub-cert-key.pem" assert mock_claim_handler.call_args[1]["ca_cert"] == "/etc/pki/tls/certs/ca-bundle.crt" assert mock_claim_handler.call_args[1]["timeout"] == 600 assert mock_claim_handler.call_args[1]["throttle"] == 100 assert mock_claim_handler.call_args[1]["retry"] == 3 assert len(mock_proton.mock_calls) == 2
def test_get_tagged_image_digests_no_manifest_list( mock_quay_api_client, mock_quay_client, target_settings, repo_api_data ): hub = mock.MagicMock() mock_get_repo_data = mock.MagicMock() mock_get_repo_data.return_value = repo_api_data mock_quay_api_client.return_value.get_repository_data = mock_get_repo_data sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings, "some-target") digests = sig_handler.get_tagged_image_digests("registry.com/namespace/image:3") assert digests == ["sha256:146ab6fa7ba3ab4d154b09c1c5522e4966ecd071bf23d1ba3df6c8b9fc33f8cb"] mock_get_repo_data.assert_called_once_with("namespace/image")
def test_init(mock_quay_api_client, mock_quay_client, target_settings): hub = mock.MagicMock() sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings, "some-target") assert sig_handler.hub == hub assert sig_handler.task_id == "1" assert sig_handler.dest_registries == ["some-registry1.com", "some-registry2.com"] assert sig_handler.target_settings == target_settings assert sig_handler.quay_host == "quay.io" mock_quay_client.assert_not_called() mock_quay_api_client.assert_not_called() assert sig_handler.quay_client == mock_quay_client.return_value assert sig_handler.quay_api_client == mock_quay_api_client.return_value mock_quay_client.assert_called_once_with("quay-user", "quay-pass", "quay.io") mock_quay_api_client.assert_called_once_with("quay-token", "quay.io")
def test_get_pyxis_signature( mock_quay_api_client, mock_quay_client, mock_run_entrypoint, target_settings ): hub = mock.MagicMock() expected_data1 = [{"some": "data"}, {"other": "data"}] expected_data2 = [{"some-other": "data"}] mock_run_entrypoint.side_effect = [iter(expected_data1), iter(expected_data2)] sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings, "some-target") sig_handler.MAX_MANIFEST_DIGESTS_PER_SEARCH_REQUEST = 2 sig_data = sig_handler.get_signatures_from_pyxis( ["sha256:a1a1a1a1a", "sha256:b2b2b2b2", "sha256:c3c3c3c3"], ) for i, data in enumerate(sig_data): assert data == (expected_data1 + expected_data2)[i] assert mock_run_entrypoint.call_count == 2 assert mock_run_entrypoint.mock_calls[0] == mock.call( ("pubtools-pyxis", "console_scripts", "pubtools-pyxis-get-signatures"), "pubtools-pyxis-get-signatures", [ "--pyxis-server", "pyxis-url.com", "--pyxis-krb-principal", "*****@*****.**", "--pyxis-krb-ktfile", "/etc/pub/some.keytab", "--manifest-digest", "sha256:a1a1a1a1a,sha256:b2b2b2b2", ], {}, ) assert mock_run_entrypoint.mock_calls[1] == mock.call( ("pubtools-pyxis", "console_scripts", "pubtools-pyxis-get-signatures"), "pubtools-pyxis-get-signatures", [ "--pyxis-server", "pyxis-url.com", "--pyxis-krb-principal", "*****@*****.**", "--pyxis-krb-ktfile", "/etc/pub/some.keytab", "--manifest-digest", "sha256:c3c3c3c3", ], {}, )
def test_upload_signatures_pyxis( mock_quay_client, mock_run_entrypoint, mock_tempfile, mock_json_dump, target_settings, claim_messages, signed_messages, fake_cert_key_paths, ): hub = mock.MagicMock() temp_filename = "/tmp/pubtools_quay_upload_signatures_ABC123" mock_tempfile.return_value.__enter__.return_value.name = temp_filename sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings, "some-target") sig_handler.upload_signatures_to_pyxis(claim_messages, signed_messages) signatures = [ { "manifest_digest": "sha256:f4f4f4f", "reference": "registry.com/image:1", "repository": "image", "sig_key_id": "00000000", "signature_data": "binary-data1", }, { "manifest_digest": "sha256:a2a2a2a", "reference": "registry.com/image:1", "repository": "image", "sig_key_id": "00000001", "signature_data": "binary-data2", }, { "manifest_digest": "sha256:b3b3b3b", "reference": "registry.com/image:2", "repository": "image", "sig_key_id": "00000002", "signature_data": "binary-data3", }, { "manifest_digest": "sha256:d5d5d5d5", "reference": "registry.com/image:1", "repository": "image", "sig_key_id": "1234567800000003", "signature_data": "binary-data4", }, ] mock_run_entrypoint.assert_called_once_with( ("pubtools-pyxis", "console_scripts", "pubtools-pyxis-upload-signatures"), "pubtools-pyxis-upload-signature", [ "--pyxis-server", "pyxis-url.com", "--pyxis-ssl-crtfile", "/path/to/file.crt", "--pyxis-ssl-keyfile", "/path/to/file.key", "--signatures", "@/tmp/pubtools_quay_upload_signatures_ABC123", ], {}, ) mock_json_dump.assert_called_once_with( signatures, mock_tempfile.return_value.__enter__.return_value)
def test_get_pyxis_signature( mock_quay_client, mock_run_entrypoint, mock_tempfile, mock_json_dump, target_settings, fake_cert_key_paths, ): hub = mock.MagicMock() temp_filename = "/tmp/pubtools_quay_get_signatures_ABC123" mock_tempfile.return_value.__enter__.return_value.name = temp_filename expected_data1 = [{"some": "data"}, {"other": "data"}] expected_data2 = [{"some-other": "data"}] mock_run_entrypoint.side_effect = [ iter(expected_data1), iter(expected_data2) ] sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings, "some-target") sig_handler.MAX_MANIFEST_DIGESTS_PER_SEARCH_REQUEST = 2 sig_data = sig_handler.get_signatures_from_pyxis([ "sha256:a1a1a1a1a", "sha256:b2b2b2b2", "sha256:c3c3c3c3", "sha256:c3c3c3c3" ]) for i, data in enumerate(sig_data): assert data == (expected_data1 + expected_data2)[i] assert mock_run_entrypoint.call_count == 2 assert mock_run_entrypoint.mock_calls[0] == mock.call( ("pubtools-pyxis", "console_scripts", "pubtools-pyxis-get-signatures"), "pubtools-pyxis-get-signatures", [ "--pyxis-server", "pyxis-url.com", "--pyxis-ssl-crtfile", "/path/to/file.crt", "--pyxis-ssl-keyfile", "/path/to/file.key", "--manifest-digest", "@/tmp/pubtools_quay_get_signatures_ABC123", ], {}, ) assert mock_run_entrypoint.mock_calls[1] == mock.call( ("pubtools-pyxis", "console_scripts", "pubtools-pyxis-get-signatures"), "pubtools-pyxis-get-signatures", [ "--pyxis-server", "pyxis-url.com", "--pyxis-ssl-crtfile", "/path/to/file.crt", "--pyxis-ssl-keyfile", "/path/to/file.key", "--manifest-digest", "@/tmp/pubtools_quay_get_signatures_ABC123", ], {}, ) assert mock_json_dump.call_count == 2 assert mock_json_dump.mock_calls[0][1][0] == [ "sha256:a1a1a1a1a", "sha256:b2b2b2b2" ] assert mock_json_dump.mock_calls[1][1][0] == ["sha256:c3c3c3c3"]
def test_upload_signatures_pyxis( mock_quay_api_client, mock_quay_client, mock_run_entrypoint, target_settings, claim_messages, signed_messages, ): hub = mock.MagicMock() sig_handler = signature_handler.SignatureHandler(hub, "1", target_settings, "some-target") sig_handler.upload_signatures_to_pyxis(claim_messages, signed_messages, 2) signatures = [ { "manifest_digest": "sha256:f4f4f4f", "reference": "registry.com/image:1", "repository": "image", "sig_key_id": "key1", "signature_data": "binary-data1", }, { "manifest_digest": "sha256:a2a2a2a", "reference": "registry.com/image:1", "repository": "image", "sig_key_id": "key1", "signature_data": "binary-data2", }, { "manifest_digest": "sha256:b3b3b3b", "reference": "registry.com/image:2", "repository": "image", "sig_key_id": "key1", "signature_data": "binary-data3", }, ] mock_run_entrypoint.call_count == 2 assert mock_run_entrypoint.mock_calls[0] == mock.call( ("pubtools-pyxis", "console_scripts", "pubtools-pyxis-upload-signatures"), "pubtools-pyxis-upload-signature", [ "--pyxis-server", "pyxis-url.com", "--pyxis-krb-principal", "*****@*****.**", "--pyxis-krb-ktfile", "/etc/pub/some.keytab", "--signatures", json.dumps(signatures[:2]), ], {}, ) assert mock_run_entrypoint.mock_calls[1] == mock.call( ("pubtools-pyxis", "console_scripts", "pubtools-pyxis-upload-signatures"), "pubtools-pyxis-upload-signature", [ "--pyxis-server", "pyxis-url.com", "--pyxis-krb-principal", "*****@*****.**", "--pyxis-krb-ktfile", "/etc/pub/some.keytab", "--signatures", json.dumps(signatures[2:]), ], {}, )