Use Keyfactor EJBCA to generate ephemeral signing certificates
Summary
Chainloop Evidence Store can be configured to generate signing certs by using EJBCA as the certificate authority, when signing in "key-less" mode: EJBCA is a popular open source PKI, check it out at https://www.ejbca.org/.
Prerequisites:
If your organization doesn't have it already, you can follow these tutorials for a basic setup of EJBCA PKI solution.
Requirements:
- EJBCA is deployed following the Quick Start Guide - Start EJBCA Container with Client Certificate Authenticated Access
- EJBCA is configured for issuing signing certificates. Check the Step 2 at Tutorial - SignServer Container Signing with Cosign
- EJBCA Certificate Management APIs are enabled.
Configure Chainloop to use EJBCA as CA
Check ejbca_cA
section in Chainloop configuration options. In particular, set these values in your config.yaml (these values are also mapped to the chart values.yaml file):
certificate_authority:
ejbca_ca:
# Where EJBCA service is located
server_url: "https://localhost/ejbca"
# Cert and private key for Client cert authentication against EJBCA
key_path: "../../devel/devkeys/superadmin.key"
cert_path: "../../devel/devkeys/superadmin.pem"
# Certificate chain
root_ca_path: "../../devel/devkeys/ManagementCA.pem"
# EJBCA profile, end entity and CA names
certificate_profile_name: "PlainSigner"
end_entity_profile_name: "PlainSigner"
certificate_authority_name: "ManagementCA"
Signing Chainloop attestations with EJBCA issued certificates
Using the following command (note that no key
is provided), the following sequence of events will happen:
- Chainloop CLI creates a certificate request, and sends it to Chainloop
- Chainloop forwards the request to EJBCA's
v1/certificate/pkcs10enroll
API, which generates a new short-lived certificate for signing - Chainloop CLI signs the In-toto payload, and sends the statement to Chainloop for storage.
> chainloop attestation push --bundle bundle.json
Full example
Crafting and signing an attestation.
> chainloop att init --workflow mywf --project myproject
INF Attestation initialized! now you can check its status or add materials to it
┌───────────────────┬──────────────────────────────────────┐
│ Initialized At │ 25 Jun 24 10:49 UTC │
├───────────────────┼──────────────────────────────────────┤
│ Attestation ID │ 966b2426-e5a6-4805-91ff-e4ea1e95c5ea │
│ Name │ mywf │
│ Team │ │
│ Project │ myproject │
│ Contract Revision │ 1 │
└───────────────────┴──────────────────────────────────────┘
> chainloop att add --value evidence.txt
INF material kind detected kind=ARTIFACT
INF material added to attestation
> chainloop --debug att push --bundle bundle-with-ejbca.json
INF generating Sigstore bundle bundle-with-ejbca.json
INF push completed
┌───────────────────┬──────────────────────────────────────┐
│ Initialized At │ 25 Jun 24 10:49 UTC │
├───────────────────┼──────────────────────────────────────┤
│ Attestation ID │ 966b2426-e5a6-4805-91ff-e4ea1e95c5ea │
│ Name │ mywf │
│ Team │ │
│ Project │ myproject │
│ Contract Revision │ 1 │
└───────────────────┴────────────────────────── ────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│ Materials │
├──────────┬─────────────────────────────────────────────────────────────────────────┤
│ Name │ material-1719312595918293000 │
│ Type │ ARTIFACT │
│ Set │ Yes │
│ Required │ No │
│ Value │ evidence.txt │
│ Digest │ sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 │
└──────────┴─────────────────────────────────────────────────────────────────────────┘
Attestation Digest: sha256:bafaffc629d5ffe4c3b6519b740459db6883a55c6092c438426ded7ec328f135
Storing and inspecting the generated certificate:
> cat bundle-with-ejbca.json | jq -r ".verificationMaterial.x509CertificateChain.certificates.[].rawBytes" | base64 --decode | openssl x509 -inform DER -outform PEM > signingcert.pem
> cat signingcert.pem | openssl x509 -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
6f:42:e2:ec:6d:b3:25:41:97:6d:66:3b:73:fc:dc:d2:cc:67:c7:ce
Signature Algorithm: sha256WithRSAEncryption
Issuer: UID=c-0kxd0tu03vo9bdv86, CN=ManagementCA, O=EJBCA Container Quickstart
Validity
Not Before: Jun 25 10:49:04 2024 GMT
Not After : Jun 25 10:49:03 2025 GMT
Subject: CN=fce05d49-b633-4862-be1d-3345081ecaea
...
Verifying the attestation
Verifying the attestation requires the signing cert extracted from the bundle and the root CA (provided by your organization out-of-band):
> chainloop wf run describe --digest sha256:bafaffc629d5ffe4c3b6519b740459db6883a55c6092c438426ded7ec328f135 --verify true --cert signingcert.pem --cert-chain ../keyfactor/ManagementCA.pem
WRN Both user credentials and $CHAINLOOP_TOKEN set. Ignoring $CHAINLOOP_TOKEN.
┌──────────────────────────────────────────────────────────────────────────────────────────┐
│ Workflow │
├────────────────┬─────────────────────────────────────────────────────────────────────────┤
│ ID │ eb7b4633-96e2-4efe-b23f-f667f3f7acdc │
│ Name │ mywf │
│ Team │ │
│ Project │ myproject │
├────────────────┼─────────────────────────────────────────────────────────────────────────┤
│ Workflow Run │ │
├────────────────┼─────────────────────────────────────────────────────────────────────────┤
│ ID │ 966b2426-e5a6-4805-91ff-e4ea1e95c5ea │
│ Initialized At │ 25 Jun 24 10:49 UTC │
│ Finished At │ 25 Jun 24 10:59 UTC │
│ State │ success │
│ Runner Link │ │
├────────────────┼─────────────────────────────────────────────────────────────────────────┤
│ Statement │ │
├────────────────┼ ─────────────────────────────────────────────────────────────────────────┤
│ Payload Type │ application/vnd.in-toto+json │
│ Digest │ sha256:bafaffc629d5ffe4c3b6519b740459db6883a55c6092c438426ded7ec328f135 │
│ Verified │ true │
└────────────────┴─────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│ Materials │
├──────────┬───────────────────────────────────────────────────── ────────────────────┤
│ Name │ material-1719312595918293000 │
│ Type │ ARTIFACT │
│ Filename │ evidence.txt │
│ Digest │ sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 │
└──────────┴─────────────────────────────────────────────────────────────────────────┘