Skip to content

Commit d21316a

Browse files
authored
Improve error handling (#153)
1 parent 8e289fc commit d21316a

File tree

5 files changed

+55
-9
lines changed

5 files changed

+55
-9
lines changed

bin/sigstore-ruby

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ module Sigstore
239239
b64_sig = Gem.read_binary(inputs[:sig])
240240
signature = b64_sig.unpack1("m")
241241

242-
verification_input.bundle = Sigstore::SBundle.for_cert_bytes_and_signature(cert_pem, signature)
242+
verification_input.bundle = Sigstore::SBundle.for_cert_bytes_and_signature(cert_pem, signature).__getobj__
243243
end
244244

245245
say "Verifying #{file}..."

lib/sigstore/internal/x509.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ def initialize(x509_certificate)
3838

3939
def self.read(certificate_bytes)
4040
new(OpenSSL::X509::Certificate.new(certificate_bytes))
41+
rescue OpenSSL::X509::CertificateError => e
42+
raise Error::InvalidCertificate, e.message
4143
end
4244

4345
def tbs_certificate_der
@@ -104,7 +106,7 @@ def leaf?
104106

105107
key_usage = extension(Extension::KeyUsage) ||
106108
raise(Error::InvalidCertificate,
107-
"no keyUsage in #{@x509_certificate.extensions.map(&:to_h)}")
109+
"no keyUsage in #{openssl.extensions.map(&:to_h)}")
108110

109111
unless key_usage.digital_signature
110112
raise Error::InvalidCertificate,

lib/sigstore/models.rb

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ class VerificationInput < DelegateClass(Verification::V1::Input)
8080

8181
def initialize(*)
8282
super
83+
84+
unless bundle.is_a?(Bundle::V1::Bundle)
85+
raise ArgumentError,
86+
"bundle must be a #{Bundle::V1::Bundle}, is #{bundle.class}"
87+
end
88+
8389
@trusted_root = TrustedRoot.new(artifact_trust_root)
8490
@sbundle = SBundle.new(bundle)
8591
if sbundle.message_signature? && !artifact
@@ -138,13 +144,19 @@ def expected_tlog_entry(hashed_input)
138144
expected_hashed_rekord_tlog_entry(hashed_input)
139145
when :dsse_envelope
140146
rekor_entry = verification_material.tlog_entries.first
141-
case JSON.parse(rekor_entry.canonicalized_body).values_at("kind", "apiVersion")
147+
canonicalized_body = begin
148+
JSON.parse(rekor_entry.canonicalized_body)
149+
rescue JSON::ParserError
150+
raise Error::InvalidBundle, "expected canonicalized_body to be JSON"
151+
end
152+
153+
case kind_version = canonicalized_body.values_at("kind", "apiVersion")
142154
when %w[dsse 0.0.1]
143155
expected_dsse_0_0_1_tlog_entry
144156
when %w[intoto 0.0.2]
145157
expected_intoto_0_0_2_tlog_entry
146158
else
147-
raise Error::InvalidRekorEntry, "Unhandled rekor entry kind/version: #{t.inspect}"
159+
raise Error::InvalidRekorEntry, "Unhandled rekor entry kind/version: #{kind_version.inspect}"
148160
end
149161
else
150162
raise Error::InvalidBundle, "expected either message_signature or dsse_envelope"
@@ -154,6 +166,8 @@ def expected_tlog_entry(hashed_input)
154166
private
155167

156168
def validate_version!
169+
raise Error::InvalidBundle, "bundle requires verification material" unless verification_material
170+
157171
case bundle_type
158172
when BundleType::BUNDLE_0_1
159173
unless verification_material.tlog_entries.all?(&:inclusion_promise)
@@ -169,7 +183,7 @@ def validate_version!
169183
raise Error::InvalidBundle,
170184
"must contain an inclusion proof"
171185
end
172-
unless verification_material.tlog_entries.all? { |t| t.inclusion_proof.checkpoint.envelope }
186+
unless verification_material.tlog_entries.all? { |t| t.inclusion_proof.checkpoint&.envelope }
173187
raise Error::InvalidBundle,
174188
"inclusion proof must contain a checkpoint"
175189
end
@@ -192,9 +206,9 @@ def validate_version!
192206
when :certificate
193207
@leaf_certificate = Internal::X509::Certificate.read(verification_material.certificate.raw_bytes)
194208
else
195-
raise Error::InvalidBundle, "Unsupported bundle content: #{content}"
209+
raise Error::InvalidBundle, "Unsupported bundle content: #{content.inspect}"
196210
end
197-
raise Error::InvalidBundle, "Expected leaf certificate" unless @leaf_certificate.leaf?
211+
raise Error::InvalidBundle, "expected certificate to be leaf" unless @leaf_certificate.leaf?
198212
end
199213

200214
def expected_hashed_rekord_tlog_entry(hashed_input)

lib/sigstore/verifier.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,12 @@ def verify(input:, policy:, offline:)
183183

184184
case bundle.dsse_envelope.payloadType
185185
when "application/vnd.in-toto+json"
186-
verify_in_toto(input, JSON.parse(bundle.dsse_envelope.payload))
186+
in_toto = begin
187+
JSON.parse(bundle.dsse_envelope.payload)
188+
rescue JSON::ParserError
189+
raise Error::InvalidBundle, "invalid JSON for in-toto statement in DSSE payload"
190+
end
191+
verify_in_toto(input, in_toto)
187192
else
188193
raise Sigstore::Error::Unimplemented,
189194
"unsupported DSSE payload type: #{bundle.dsse_envelope.payloadType.inspect}"
@@ -432,7 +437,11 @@ def find_rekor_entry(bundle, hashed_input, offline:)
432437

433438
logger.debug { "Found rekor entry: #{entry}" }
434439

435-
actual_body = JSON.parse(entry.canonicalized_body)
440+
actual_body = begin
441+
JSON.parse(entry.canonicalized_body)
442+
rescue JSON::ParserError
443+
raise Error::InvalidRekorEntry, "invalid JSON in rekor entry canonicalized_body"
444+
end
436445
if bundle.dsse_envelope?
437446
# since the hash is over the uncanonicalized envelope, we need to remove it
438447
#

test/sigstore/models_test.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,25 @@ def test_from_media_type
1717
Sigstore::BundleType.from_media_type("application/vnd.dev.sigstore.bundle+json;version=0.0")
1818
end
1919
end
20+
21+
def test_verification_input_no_bundle
22+
verification_input = Sigstore::Verification::V1::Input.new
23+
e = assert_raise(ArgumentError) { Sigstore::VerificationInput.new(verification_input) }
24+
assert_equal("bundle must be a Sigstore::Bundle::V1::Bundle, is NilClass", e.message)
25+
end
26+
27+
def test_verification_input_bundle_missing_media_type
28+
verification_input = Sigstore::Verification::V1::Input.new
29+
verification_input.bundle = Sigstore::Bundle::V1::Bundle.new
30+
e = assert_raise(Sigstore::Error::InvalidBundle) { Sigstore::VerificationInput.new(verification_input) }
31+
assert_equal("Unsupported bundle format: \"\"", e.message)
32+
end
33+
34+
def test_verification_input_bundle_missing_verification_material
35+
verification_input = Sigstore::Verification::V1::Input.new
36+
verification_input.bundle = Sigstore::Bundle::V1::Bundle.new
37+
verification_input.bundle.media_type = Sigstore::BundleType::BUNDLE_0_3.media_type
38+
e = assert_raise(Sigstore::Error::InvalidBundle) { Sigstore::VerificationInput.new(verification_input) }
39+
assert_equal("bundle requires verification material", e.message)
40+
end
2041
end

0 commit comments

Comments
 (0)