예제 #1
0
def test_verify_signatures(image_config: ImageConfig):
    """Test signature verification for signed and unsigned configurations."""

    # Unsigned configurations should explicitly raise an exception.
    with pytest.raises(Exception) as e:
        image_config.verify_signatures()
    assert str(e.value) == "Image does not contain any signatures!"

    # Sign a previously unsigned configuration, so that only the new signature type is present.
    # Note: It is not trivial to embed "known" GPG / PKI signature types, as assumptions about the
    #       test environment are difficult to make.
    image_config.sign(FakeSigner())

    # An exception should be raised if the provider for a signature type is not known
    with pytest.raises(Exception) as e:
        image_config.verify_signatures()
    assert str(e.value) == "Unsupported signature type!"

    # Replace the class method for resolving signature providers ...
    original_method = Signer.for_signature
    Signer.for_signature = _signer_for_signature

    # The Signer's verify() method should be invoked.
    assert image_config.verify_signatures()["results"] == [{
        "type": "fake",
        "valid": True
    }]

    # Restore the original class method
    Signer.for_signature = original_method
예제 #2
0
def test_acceptance_sign_unsign_symmetry(image_config: ImageConfig,
                                         image_config_signed: ImageConfig):
    """Tests that sign and unsign are (mostly) symmetric operations."""

    config_digest = image_config.get_config_digest()

    # 1. Sign
    signer = FakeSigner()
    assert image_config.sign(signer) == signer.signature_value
    assert image_config_signed.sign(signer) == signer.signature_value

    # Previously unsigned configurations should now contain the new signature.
    assert b"BEGIN FAKE SIGNATURE" in image_config.get_config()

    # Previously signed configurations should now contain the original signature(s) and the new signature.
    assert b"BEGIN FAKE SIGNATURE" in image_config_signed.get_config()
    assert b"BEGIN PGP SIGNATURE" in image_config_signed.get_config()

    # 2. Unsign
    image_config.unsign()
    image_config_signed.unsign()

    # Configurations where we added the first signature should be reverted.
    assert b"BEGIN FAKE SIGNATURE" not in image_config.get_config()

    # Configurations where we appended a signature should now contain no signature(s).
    assert b"BEGIN FAKE SIGNATURE" not in image_config_signed.get_config()
    assert b"BEGIN PGP SIGNATURE" not in image_config_signed.get_config()

    assert image_config.get_config_digest() == config_digest
def test_sign_resign(
    image_config: ImageConfig,
    image_config_signed: ImageConfig,
    config_digest_canonical: str,
    config_digest_signed_canonical: str,
    signature: str,
):
    """Test configuration resigning for signed and unsigned configurations."""

    signer = FakeSigner()
    assert image_config.sign(signer,
                             SignatureTypes.RESIGN) == signer.signature_value
    assert (image_config_signed.sign(
        signer, SignatureTypes.RESIGN) == signer.signature_value)

    # Previously unsigned configurations should now contain the new signature.
    assert b"BEGIN FAKE SIGNATURE" in image_config.get_config()
    signatures = image_config.get_signature_list()
    assert len(signatures) == 1
    assert signatures[0]["digest"] == config_digest_canonical
    assert signatures[0]["signature"] == signer.signature_value

    # Previously signed configurations should now contain (only) the new signature.
    assert b"BEGIN FAKE SIGNATURE" in image_config_signed.get_config()
    assert b"BEGIN PGP SIGNATURE" not in image_config_signed.get_config()
    signatures_signed = image_config_signed.get_signature_list()
    assert len(signatures_signed) == 1
    assert signatures[0]["digest"] == config_digest_canonical
    assert signatures[0]["signature"] == signer.signature_value
def test_sign_endorse(
    image_config: ImageConfig,
    image_config_signed: ImageConfig,
    config_digest_canonical: str,
    config_digest_signed_canonical: str,
    signature: str,
):
    """Test configuration endorsement for signed and unsigned configurations."""

    signer = FakeSigner()
    assert image_config.sign(signer,
                             SignatureTypes.ENDORSE) == signer.signature_value
    assert (image_config_signed.sign(
        signer, SignatureTypes.ENDORSE) == signer.signature_value)

    # Previously unsigned configurations should now contain the new signature.
    assert b"BEGIN FAKE SIGNATURE" in image_config.get_config()
    signatures = image_config.get_signature_list()
    assert len(signatures) == 1
    assert signatures[0]["digest"] == config_digest_canonical
    assert signatures[0]["signature"] == signer.signature_value

    # Previously signed configurations should now contain the original signature(s) and the new signature.
    assert b"BEGIN FAKE SIGNATURE" in image_config_signed.get_config()
    assert b"BEGIN PGP SIGNATURE" in image_config_signed.get_config()
    signatures_signed = image_config_signed.get_signature_list()
    assert len(signatures_signed) == 2
    assert signatures_signed[0]["digest"] == config_digest_canonical
    assert signatures_signed[0]["signature"] == signature
    assert signatures_signed[1]["digest"] == config_digest_signed_canonical
    assert signatures_signed[1]["signature"] == signer.signature_value
 def append_new_image_config(config: ImageConfig,
                             endorse: bool = False,
                             iteration=i):
     signer = FakeSigner("<<< {0} {1}: {2} >>>".format(
         iteration,
         "Endorsing" if endorse else "Signing",
         config.get_config_digest_canonical(),
     ))
     config.sign(signer, endorse)
     stack.append(config)
예제 #6
0
def test_sign(image_config: ImageConfig, image_config_signed: ImageConfig):
    """Test configuration signing for signed and unsigned configurations."""

    signer = FakeSigner()
    assert image_config.sign(signer) == signer.signature_value
    assert image_config_signed.sign(signer) == signer.signature_value

    # Previously unsigned configurations should now contain the new signature.
    assert b"BEGIN FAKE SIGNATURE" in image_config.get_config()

    # Previously signed configurations should now contain the original signature(s) and the new signature.
    assert b"BEGIN FAKE SIGNATURE" in image_config_signed.get_config()
    assert b"BEGIN PGP SIGNATURE" in image_config_signed.get_config()
 def append_new_image_config(
     config: ImageConfig,
     signature_type: SignatureTypes = SignatureTypes.SIGN,
     iteration=i,
 ):
     signer = FakeSigner("<<< {0} {1}: {2} >>>".format(
         iteration,
         "Endorsing"
         if signature_type == SignatureTypes.ENDORSE else "Signing",
         config.get_config_digest_canonical(),
     ))
     config.sign(signer, signature_type)
     stack.append(config)
def test_verify_signatures_manipulated_signatures(image_config: ImageConfig):
    """Test that signature verification detects manipulated signatures."""

    # Add a single signature ...
    signer = FakeSigner()
    assert image_config.sign(signer) == signer.signature_value

    # Replace the class method for resolving signature providers ...
    original_method = Signer.for_signature
    Signer.for_signature = _signer_for_signature

    # Sanity check
    assert image_config.verify_signatures()["results"][0]["valid"] is True

    # Modify the digest value of the (first) signature ...
    signatures = image_config.get_signature_list()
    temp = copy.deepcopy(signatures)
    temp[0]["digest"] = "tampertampertamper"
    image_config.set_signature_list(temp)

    # An exception should be raised if digest value from the signature does not match the canonical digest of the image
    # configuration (without any signatures).
    with pytest.raises(Exception) as exception:
        image_config.verify_signatures()
    assert str(
        exception.value).startswith("Image config canonical digest mismatch:")

    # Restore the unmodified signature and endorse ...
    image_config.set_signature_list(signatures)
    assert image_config.sign(signer,
                             SignatureTypes.ENDORSE) == signer.signature_value

    # Sanity check
    assert image_config.verify_signatures()["results"][0]["valid"] is True

    # Modify the digest value of the second signature ...
    signatures = image_config.get_signature_list()
    temp = copy.deepcopy(signatures)
    temp[1]["digest"] = "tampertampertamper"
    image_config.set_signature_list(temp)

    # An exception should be raised if digest value from the signature does not match the canonical digest of the image
    # configuration (including the first signature).
    with pytest.raises(Exception) as exception:
        image_config.verify_signatures()
    assert str(
        exception.value).startswith("Image config canonical digest mismatch:")

    # Restore the original class method
    Signer.for_signature = original_method
def test_minimal():
    """Test minimal image configuration (for non-conformant labels)k."""

    # Note: At a minimum, [Cc]onfig key must exist with non-null value
    image_config = ImageConfig(b'{"Config":{}}')
    config_digest_canonical = image_config.get_config_digest_canonical()
    signer = FakeSigner()
    assert image_config.sign(signer) == signer.signature_value

    # A signature should always be able to be added ...
    assert b"BEGIN FAKE SIGNATURE" in image_config.get_config()
    signatures = image_config.get_signature_list()
    assert len(signatures) == 1
    assert signatures[0]["digest"] == config_digest_canonical
    assert signatures[0]["signature"] == signer.signature_value