sigstore-cli 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sigstore/cli.rb +62 -13
  3. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 305e113d4f2f07e30e327a2c423bf03c7a218dd01a7e5a6f4ef2c9e93da36b5e
4
- data.tar.gz: 1039d75f4b0416388c74a3bad415487c022d8668addf6b852801e983efab38ae
3
+ metadata.gz: fb6ae7ecf2b8c666e2f15a7ae9170e2c5b3ed0dc3d17ddd368406b1ca9487503
4
+ data.tar.gz: fc4df628cb9b00abdee837864dfa982371e6deefa14908c14c33f01322112168
5
5
  SHA512:
6
- metadata.gz: 030bf7fe8360f9d57201f8de1fb3760d6403aae393ad0ddb69e0cb23fb0b711486584d5d30e60ae4451fdcb892cc1b977ee81e9b01762b5bae2e6e597b1eb237
7
- data.tar.gz: 4980ef8f0f6f05e8a9a526970d36f73285a72f779689b37a2d235844ebeb77e0c2b94bfbeee1fd60c8c63c67290421ea660b186203ee00f9e3cb468debeef1e3
6
+ metadata.gz: 99e28350dc70c09cf048160cfc415bd2c3ee694054dd8629ced2ba25403c06d2ca410ec949ce6ef66d4e2ec8da07f1c9cd2c99fc58d62bfa5695fbd1a1952d2a
7
+ data.tar.gz: 315e7240b1c2500c139c5e9346dba3415262c341c4386d21a31cb3794eb71681f308074a149f164a34425632634a846de273da2657d9be1d4cc0a38f6c0913ae
data/lib/sigstore/cli.rb CHANGED
@@ -48,21 +48,29 @@ module Sigstore
48
48
  option :certificate, type: :string, desc: "Path to the public certificate"
49
49
  option :certificate_identity, type: :string, desc: "The identity of the certificate"
50
50
  option :certificate_oidc_issuer, type: :string, desc: "The OIDC issuer of the certificate"
51
+ option :key, type: :string, desc: "Path to a PEM public key for managed-key (bring-your-own-key) verification"
51
52
  option :offline, type: :boolean, desc: "Do not fetch the latest timestamp from the Rekor server"
52
53
  option :bundle, type: :string, desc: "Path to the signed bundle"
53
54
  option :trusted_root, type: :string, desc: "Path to the trusted root"
54
55
  option :update_trusted_root, type: :boolean, desc: "Update the trusted root", default: true
55
56
  exclusive :bundle, :signature
56
57
  exclusive :bundle, :certificate
58
+ exclusive :key, :certificate
59
+ exclusive :key, :certificate_identity
57
60
  def verify(*files)
58
61
  verifier, files_with_materials = collect_verification_state(files)
59
- policy = Sigstore::Policy::Identity.new(
60
- identity: options[:certificate_identity],
61
- issuer: options[:certificate_oidc_issuer]
62
- )
62
+ key = load_verification_key
63
+ policy = if key
64
+ Sigstore::Policy::UnsafeNoOp.new
65
+ else
66
+ Sigstore::Policy::Identity.new(
67
+ identity: options[:certificate_identity],
68
+ issuer: options[:certificate_oidc_issuer]
69
+ )
70
+ end
63
71
 
64
72
  verified = files_with_materials.all? do |file, input|
65
- result = verifier.verify(input:, policy:, offline: options[:offline])
73
+ result = verifier.verify(input:, policy:, offline: options[:offline], key:)
66
74
 
67
75
  if result.verified?
68
76
  say "OK: #{file}"
@@ -84,8 +92,17 @@ module Sigstore
84
92
  option :signature, type: :string, desc: "Path to write the signature to"
85
93
  option :certificate, type: :string, desc: "Path to the public certificate"
86
94
  option :trusted_root, type: :string, desc: "Path to the trusted root"
95
+ option :signing_config, type: :string, desc: "Path to the signing config"
87
96
  option :update_trusted_root, type: :boolean, desc: "Update the trusted root", default: true
97
+ option :in_toto, type: :boolean, desc: "Sign the file as an in-toto statement in a DSSE envelope"
88
98
  def sign(file)
99
+ # A DSSE bundle carries an envelope, not a message signature, so the
100
+ # detached --signature/--certificate outputs of the message-signature flow
101
+ # do not apply.
102
+ if options[:in_toto] && (options[:signature] || options[:certificate])
103
+ raise Thor::InvocationError, "--in-toto cannot be combined with --signature or --certificate"
104
+ end
105
+
89
106
  self.options = options.merge(identity_token: IdToken.detect_credential).freeze if options[:identity_token].nil?
90
107
  unless options[:identity_token]
91
108
  raise Error::InvalidIdentityToken,
@@ -93,10 +110,12 @@ module Sigstore
93
110
  end
94
111
 
95
112
  contents = File.binread(file)
96
- bundle = Sigstore::Signer.new(
113
+ signer = Sigstore::Signer.new(
97
114
  jwt: options[:identity_token],
98
- trusted_root:
99
- ).sign(contents)
115
+ trusted_root:,
116
+ signing_config:
117
+ )
118
+ bundle = options[:in_toto] ? signer.sign_dsse(contents) : signer.sign(contents)
100
119
 
101
120
  File.binwrite(options[:bundle], bundle.to_json) if options[:bundle]
102
121
  if options[:signature]
@@ -114,7 +133,11 @@ module Sigstore
114
133
 
115
134
  say "--- Bundle #{file} ---"
116
135
  say "Media Type: #{bundle.media_type}"
117
- say bundle.leaf_certificate.to_text
136
+ if bundle.key_based?
137
+ say "Public Key (hint): #{bundle.signing_key_hint}"
138
+ else
139
+ say bundle.leaf_certificate.to_text
140
+ end
118
141
 
119
142
  case bundle.content
120
143
  when :message_signature
@@ -185,13 +208,39 @@ module Sigstore
185
208
  def trusted_root
186
209
  return Sigstore::TrustedRoot.from_file(options[:trusted_root]) if options[:trusted_root]
187
210
 
188
- if options[:staging]
189
- Sigstore::TrustedRoot.staging(offline: !options[:update_trusted_root])
190
- else
191
- Sigstore::TrustedRoot.production(offline: !options[:update_trusted_root])
211
+ Sigstore::TrustedRoot.from_tuf_updater(tuf_updater)
212
+ end
213
+
214
+ def signing_config
215
+ return Sigstore::SigningConfig.from_file(options[:signing_config]) if options[:signing_config]
216
+
217
+ # With no explicit config, fall back to the one the Sigstore instance
218
+ # publishes via TUF, so signing targets the current Rekor (v2 where the
219
+ # config selects it). Returns nil offline or when none is published, in
220
+ # which case the Signer uses the legacy v1 flow from the trusted root.
221
+ Sigstore::SigningConfig.from_tuf_updater(tuf_updater)
222
+ end
223
+
224
+ # One refreshed TUF updater per command invocation, shared by the trusted
225
+ # root and signing config so signing refreshes the repository only once.
226
+ def tuf_updater
227
+ @tuf_updater ||= begin
228
+ url = options[:staging] ? Sigstore::TUF::STAGING_TUF_URL : Sigstore::TUF::DEFAULT_TUF_URL
229
+ offline = !options[:update_trusted_root]
230
+ Sigstore::TUF::TrustUpdater.new(url, offline).tap { _1.refresh unless offline }
192
231
  end
193
232
  end
194
233
 
234
+ def load_verification_key
235
+ return unless options[:key]
236
+
237
+ raise Thor::InvocationError, "Key file not found: #{options[:key]}" unless File.exist?(options[:key])
238
+
239
+ OpenSSL::PKey.read(Gem.read_binary(options[:key]))
240
+ rescue OpenSSL::OpenSSLError => e
241
+ raise Error::InvalidKey, "could not parse verification key #{options[:key].inspect}: #{e.message}"
242
+ end
243
+
195
244
  def collect_verification_state(files)
196
245
  if (options[:certificate] || options[:signature] || options[:bundle]) && files.size > 1
197
246
  raise Thor::InvocationError, "Too many files specified: #{files.inspect}"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sigstore-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - The Sigstore Authors
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2026-03-10 00:00:00.000000000 Z
12
+ date: 2026-11-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sigstore
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - '='
19
19
  - !ruby/object:Gem::Version
20
- version: 0.2.3
20
+ version: 0.3.0
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - '='
26
26
  - !ruby/object:Gem::Version
27
- version: 0.2.3
27
+ version: 0.3.0
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: thor
30
30
  requirement: !ruby/object:Gem::Requirement