Add cosign key import to ProvenancePublisher
What does this MR do and why?
This MR adds ProvenancePublisher#cosign_import_key_pair, a private method that imports a leaf private key into cosign's encrypted key format. It is written next to cosign_attest_blob, in the same style.
ADR 007 LOCAL_CA signing signs each attestation with a fresh leaf key from the project's root CA (RootCaDriver#generate_leaf_certificate). cosign signs with a key file in its own encrypted format, so the leaf private key has to be imported into that format first.
Behaviour:
- Runs
cosign import-key-pair --yes --key /dev/stdin --output-key-prefix <dir>/cosign. The leaf private key PEM goes over stdin, so the plaintext key never touches disk. - A random password (
SecureRandom.hex(32)) is passed only in theCOSIGN_PASSWORDenvironment variable, never on the command line. - cosign writes an encrypted
cosign.key(andcosign.pub) intodir. The method returns{ key_path:, password: }, wherekey_pathis<dir>/cosign.key. diris validated before cosign runs by a newvalidate_key_dir!, in the same style asvalidate_blob_name!: it checks for path traversal, requires an absolute path (so it cannot be read as a cosign option), and requires an existing directory.- An invalid
dirraisesInvalidInput, and a cosign failure raises the newKeyImportFailurewith the duration and cosign's stderr, the same wayAttestationFailureworks incosign_attest_blob. --yeslets cosign overwrite an existing key pair indirinstead of prompting.
This MR replaces the earlier approach in !258964 (closed) and !260612 (closed), which added separate SupplyChain::Cosign::* classes. After discussion, the import lives in ProvenancePublisher instead, to reuse the existing, AppSec-approved cosign_attest_blob pattern.
Not in this MR: the method is not called yet. https://gitlab.com/gitlab-org/gitlab/-/work_items/603913 will call it from cosign_attest_blob when signing with LOCAL_CA, and owns the temp dir (Dir.mktmpdir), leaf generation with SupplyChain::PostgresCaDriver, and cleanup. Option B verification (https://gitlab.com/gitlab-org/gitlab/-/work_items/630121) also needs a trusted root and an offline signing config, which come in later issues.
No database, API, UI or documentation changes.
Tests: spec/lib/supply_chain/provenance_publisher_spec.rb (8 new examples), using the existing 'with mocked cosign execution' shared context so CI does not need cosign. 100% line and branch coverage of provenance_publisher.rb.
References
- Closes https://gitlab.com/gitlab-org/gitlab/-/work_items/603914
- Wiring issue: https://gitlab.com/gitlab-org/gitlab/-/work_items/603913
- Verification approach decision: https://gitlab.com/gitlab-org/gitlab/-/work_items/630121
- Epic: https://gitlab.com/groups/gitlab-org/-/work_items/22313
- ADR 007: https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/slsa_level_3/decisions/007_attestations_private_dedicated_self_hosted/
- Replaces: !258964 (closed)
- Replaces: !260612 (closed)
Screenshots or screen recordings
Not applicable. This is a backend-only change with no UI.
How to set up and validate locally
In a Rails console, with cosign installed:
-
Import a key and inspect the result:
You would need to have
cosigninstalled locallybrew install cosign # if you want to test this locallybuild = Ci::Build.last publisher = SupplyChain::ProvenancePublisher.new(build) dir = Dir.mktmpdir key = OpenSSL::PKey::EC.generate('prime256v1') imported = publisher.send(:cosign_import_key_pair, key: key, dir: dir) Dir.children(dir) # ["cosign.key", "cosign.pub"] File.readlines(imported[:key_path]).first # "-----BEGIN ENCRYPTED SIGSTORE PRIVATE KEY-----\n" -
From a shell, confirm the imported key matches the original:
COSIGN_PASSWORD=<imported[:password]> cosign public-key --key <imported[:key_path]>prints the public key, which matcheskey.public_to_pem. -
Show validation:
publisher.send(:cosign_import_key_pair, key: key, dir: 'relative/dir')raisesSupplyChain::ProvenancePublisher::InvalidInputwithout running cosign. -
Run the specs:
bin/rspec spec/lib/supply_chain/provenance_publisher_spec.rb
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.