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)
Esempio n. 4
0
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",
    }
Esempio n. 5
0
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)
Esempio n. 6
0
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
Esempio n. 7
0
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")
Esempio n. 8
0
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")
Esempio n. 9
0
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"]
Esempio n. 12
0
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:]),
        ],
        {},
    )