Skip to content

Latest commit

 

History

History
262 lines (206 loc) · 11 KB

README.adoc

File metadata and controls

262 lines (206 loc) · 11 KB

ITE-7: Signing & Verification With X509

Abstract

This ITE proposes adding to the in-toto specification to support signing and verifying link metadata with key & X509 certificate pairs. This ITE details the required changes to the current layout and link specifications as well as the signing and verification processes.

Specification

This ITE proposes modifying the existing in-toto layout and link metadata specs to support verifying functionaries with a chain of trust to a known root certificate authority.

Modifications include the addition of a trustBundles key to the layout. This allows a layout creator to define a set of X509 roots and intermediates that we will use to verify leaf certificates as functionaries.

Additionally a certConstraints field is added to steps within a layout. This field allows the layout creator to authorize a functionary’s key by constraining some attributes of the key’s certificate, ensuring the key has a specific common name or URI for instance. The bundle id is also used within a cert constraint to ensure that a leaf certificate belongs to the expected trust bundle defined in trustBundles.

And finally a certificate field is added to signatures on a link metadata. This field will be a PEM encoded leaf certificate that belongs to the public key used to sign the link metadata.

[[Trust Bundles]] === Trust Bundles

A trustBundles field is added to the layout that describes a X509 root and any intermediates required to build a chain of trust back to roots in the bundle. The trustBundles object is indexed by an identifier for each bundle, defined as the bundle id. roots is an array of PEM encoded X509 root certificates. intermediates is an array of strings representing PEM encoded X509 intermediate certificates that are part of the trust bundle.

"trustBundles": {
  "<BUNDLEID>": {
    "bundleid": "<BUNDLEID>",
    "roots": ["-----BEGIN CERTIFICATE-----\nMIIBkjCCATegAwIBAgIBADAKBggqhkjOPQQDAjAdMQswCQYDVQQGEwJVUzEOMAwG\nA1UEChMFU1BJUkUwHhcNMjEwMzAzMTk0MjI0WhcNMjEwNDAyMTk0MjM0WjAdMQsw\nCQYDVQQGEwJVUzEOMAwGA1UEChMFU1BJUkUwWTATBgcqhkjOPQIBBggqhkjOPQMB\nBwNCAARbJaNMniz2ejaGwLAS5Kfl3modn0ceD6LXw+QltwIJKIqGO3C8Lh2KGmZ+\nBycxOHpDcHky8NMdM+0dIVawlIlVo2gwZjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T\nAQH/BAUwAwEB/zAdBgNVHQ4EFgQU0dLhyMLPbujKf9nW7j/7qUheP7IwJAYDVR0R\nBB0wG4YZc3BpZmZlOi8vc3BpcmUuYm94Ym9hdC5pbzAKBggqhkjOPQQDAgNJADBG\nAiEA4RYLyrSxwUbv3h1X8kpfyLQmOniCbbMZqvIS49GcWtMCIQD309bBx89ITsYx\nxskO9LGz7NM1QYeiETY3LgZ6joIdgg==\n-----END CERTIFICATE-----\n"],
    "intermediates": ["-----BEGIN CERTIFICATE-----\nMIIBkjCCATegAwIBAgIBADAKBggqhkjOPQQDAjAdMQswCQYDVQQGEwJVUzEOMAwG\nA1UEChMFU1BJUkUwHhcNMjEwMzAzMTk0MjI0WhcNMjEwNDAyMTk0MjM0WjAdMQsw\nCQYDVQQGEwJVUzEOMAwGA1UEChMFU1BJUkUwWTATBgcqhkjOPQIBBggqhkjOPQMB\nBwNCAARbJaNMniz2ejaGwLAS5Kfl3modn0ceD6LXw+QltwIJKIqGO3C8Lh2KGmZ+\nBycxOHpDcHky8NMdM+0dIVawlIlVo2gwZjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T\nAQH/BAUwAwEB/zAdBgNVHQ4EFgQU0dLhyMLPbujKf9nW7j/7qUheP7IwJAYDVR0R\nBB0wG4YZc3BpZmZlOi8vc3BpcmUuYm94Ym9hdC5pbzAKBggqhkjOPQQDAgNJADBG\nAiEA4RYLyrSxwUbv3h1X8kpfyLQmOniCbbMZqvIS49GcWtMCIQD309bBx89ITsYx\nxskO9LGz7NM1QYeiETY3LgZ6joIdgg==\n-----END CERTIFICATE-----\n"]
    }
}

During the verification process a functionary will be tested against the existing set of known keys as defined in the layout or whether a chain of trust can be built to the defined roots using the defined intermediates.

Additional intermediates could be supplied at time of verification though security concerns discussed below may deem this undesirable.

Certificate Constraints

The cert_constraints field of a step can be used to limit who can act as a valid functionary for each step. Wildcards may be used to specify that any value meets the constraint whereas an empty array means there should be no values for that attribute of the certificate. An example of a few constraints:

{
  "cert_constraints": [{
    "common_name": "*"
    "dns_names": ["*"],
    "emails": ["*"],
    "organizations": ["*"],
    "trustBundleIds": ["<TRUSTBUNDLEID>"],
    "uris": ["spiffe://example.com/Something"]
  }, {
    "common_name": "Bob",
    "dns_names": [],
    "emails": ["bob@corp.example"],
    "organizations": ["Example Corp"],
    "trustBundleIds": ["<TRUSTBUNDLEID>"],
    "uris": []
  }, {
    "common_name": "*",
    "dns_names": ["*"],
    "emails": ["*"],
    "organizations": ["*"],
    "trustBundleIds": ["*"],
    "uris": ["*"]
  }]
}

For a key to be used as a valid functionary it must meet at least one of the defined constraints as well as establish a chain of trust back to one of the roots in the layout.

When testing a constraint a certificate must meet each of the constraint’s rules. For instance to satisfy the first constraint in the example above a functionary must have a certificate that is under the trust bundle with ID <TRUSTBUNDLEID> and have a URI of spiffe://example.com/Something. Any values in the other attributes are acceptable.

To satisfy the second constraint a certificate must have a common name of Bob with an email of bob@corp.example, organization of Example Corp, no URIs, no DNS names, and belong to the root with ID ROOTKEYID.

The third constraint will match any certificate belonging to any root specified in the layout.

Metadata Signatures

To support verification using a key’s certificate the certificate must be supplied to the in-toto-run command and will be embedded into the signature block in the link metadata. An example looks like:

"signatures": [
  {
    "keyid": "434f5f16788e49f4e405b63556cf5e7772c8fdc438ee381736c90804f648b304",
    "sig": "304402206e012377e2a661df4be391b4731c5cf92cb9b642509f441d284a15279bf3f8500220027697136b944aeba64578a4ed74af549358b5527a64e500f775b3bdbddfa3ce",
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIB7TCCAZSgAwIBAgIQZqgm6hMgv9qbQPkt+owbhDAKBggqhkjOPQQDAjAdMQsw\nCQYDVQQGEwJVUzEOMAwGA1UEChMFU1BJUkUwHhcNMjEwMzAzMTk0NzU5WhcNMjEw\nNDAyMTk0MjM0WjAdMQswCQYDVQQGEwJVUzEOMAwGA1UEChMFU1BJUkUwWTATBgcq\nhkjOPQIBBggqhkjOPQMBBwNCAASlOE5J2ARBjwQfM255aSPQ7p85qRyrGnuTVbhl\n0zX0P+Bswl8xPOLdIZq93ejAM2nEWv29u1I0f2n0ImU6FNnjo4G1MIGyMA4GA1Ud\nDwEB/wQEAwIDqDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0T\nAQH/BAIwADAdBgNVHQ4EFgQUe1TrPdjzCB7Qxq5vexEAlXOoCMYwHwYDVR0jBBgw\nFoAU0dLhyMLPbujKf9nW7j/7qUheP7IwMwYDVR0RBCwwKoYoc3BpZmZlOi8vc3Bp\ncmUuYm94Ym9hdC5pby9pbnRvdG8tYnVpbGRlcjAKBggqhkjOPQQDAgNHADBEAiB0\nuAsAE9W2xh2OclRFkf8MWaZvcoyeEGM1ppX7hMi7CgIgcXOBpm9jxGkFPUgJpwIU\nrGtQoIwPHAEtmC4hS5z3VFc=\n-----END CERTIFICATE-----\n"
  }
]

This ensures the necessary information to verify the signature remains alongside the metadata.

Motivation

Use Case 1: Usage of existing PKI

Some groups have existing public key infrastructure to issue and maintain their group’s keys. Being able to leverage this existing infrastructure would be a boon to these groups as opposed to potentially altering/creating new practices to support in-toto functionary keys.

Additionally in workflows where humans may be required to run commands with in-toto-run may suffer scaling issues when onboarding and offboarding authorized users in in-toto’s current model.

Use Case 2: Short lived functionary keys

The prototype implementation of this ITE currently integrates with SPIFFE/SPIRE to acquire short lived keys during build pipelines. Being able to limit the life of a functionary’s key help limit the blast radius of compromised signing keys. This ITE is the first step to supporting this model of functionary keys.

Another use case could be using certificates from a Fulcio instance to sign in-toto link metadata. A trust bundle of Sigstore’s root certificate can be added to the layout and a cert constraint added to ensure the email on the certificate is someone trusted to be a functionary.

Reasoning

The addition of trust bundles to the layout support the need to verify that a signing key’s certificate links back to a trusted root of trust as defined by the owner of the layout.

Adding the certificate that belongs to the signing key as part of the signature simplifies the verification process by only requiring the signed metadata file to be passed from functionary to verifier.

Certificate constraints support the ability to restrict who can act as a functionary for each step. Constraints may require functionary’s to possess a key and certificate from a specific root or the certificate to be issued to a specific email. This enables a functionary’s key to be rotated without the need to modify and re-sign the layout.

Backwards Compatibility

Implementing changes to the layout and the link metadata structures carries some complications around verifying older versions due to canonical JSON. Depending on the in-toto implementation verification of signatures of previous versions may break.

A solution to this may be to add a version field to in-toto documents to ensure no unexpected fields appear when re-calculating hashes to verify signatures.

Security

If a functionary’s end-entity private key is leaked an attacker will be able to forge signatures. This is the same risk that exists today with a functionary’s key being compromised and doesn’t pose any more risk.

If an intermediate or root key is compromised an attacker may be able to craft keys and certificates that satisfy constraints of potentially multiple steps. This could be an elevated risk compared to compromising a single functionaries key depending on how the layout is created.

As mentioned in the Specification section there may be cases where intermediates need to be passed into in-toto-verify at time of verification instead of embedded into the layout. This could carry the same increased risk noted above if an attacker manages compromise an intermediate or root and craft their own intermediate. An option to allow additional intermediates to be supplied at time of verification could be added to the layout to alleviate this concern.

Infrastructure Requirements

Currently the only additional infrastructure being used in support of this ITE are test SPIRE servers being started during the testing pipeline.

Testing

Currently tests exist within in-toto-golang that start a test SPIRE server and use short lived certificates to sign link metadata and use the signed metadata to verify an in-toto layout.

Prototype Implementation

A prototype implementation of this ITE was merged into the main branch of in-toto-golang as part of Pull Request 119

References