Skip to content

Commit 497695f

Browse files
committed
TUF conformance
1 parent 53db690 commit 497695f

13 files changed

+137
-62
lines changed

.gitleaksignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
data/_store/staging/root.json:generic-api-key:20
2+
data/_store/staging/root.json:generic-api-key:24
3+
data/_store/staging/root.json:generic-api-key:28
4+
data/_store/staging/root.json:generic-api-key:32

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/gitleaks/gitleaks
3-
rev: v8.18.2
3+
rev: v8.18.4
44
hooks:
55
- id: gitleaks
66
- repo: https://github.com/jumanjihouse/pre-commit-hooks

Rakefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ task test: %w[sigstore_conformance]
5252

5353
desc "Update the vendored data files"
5454
task :update_data do
55+
require "sigstore"
5556
require "sigstore/trusted_root"
5657
{
5758
prod: Sigstore::TUF::DEFAULT_TUF_URL,
@@ -128,8 +129,8 @@ end
128129

129130
GitRepo.define_task(:tuf_conformance).tap do |task|
130131
task.path = "test/tuf-conformance"
131-
task.url = "https://github.com/jku/tuf-conformance.git"
132-
task.commit = "b938daaea0e3a9b4cc5c5d743954be6a6ae32893"
132+
task.url = "https://github.com/theupdateframework/tuf-conformance.git"
133+
task.commit = "eefca0f5834b2bbc2f06ba319f06d52c0c18ee40"
133134
end
134135

135136
namespace :tuf_conformance do

bin/tuf-conformance-entrypoint

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@ OptionParser.new do |parser|
2828
parser.on("--target-base-url U") do |v|
2929
args << "--target-base-url" << v
3030
end
31+
parser.on("--days-in-future N") do |v|
32+
args << "--days-in-future" << v
33+
end
34+
parser.on("--max-root-rotations N") do |v|
35+
args << "--max-root-rotations" << v
36+
end
37+
parser.on("--target-base-url U") do |v|
38+
args << "--target-base-url" << v
39+
end
40+
parser.on("--target-name N") do |v|
41+
args << v
42+
end
3143
end.parse!
3244

3345
require "simplecov"
@@ -39,4 +51,5 @@ load File.expand_path("../.simplecov", __dir__)
3951
command = ARGV.shift
4052

4153
ARGV.unshift "sigstore_tuf_#{command.tr("-", "_")}", *args
54+
pp ARGV
4255
Gem::GemRunner.new.run ARGV.clone

data/_store/staging/root.json

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,105 +2,121 @@
22
"signatures": [
33
{
44
"keyid": "762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93",
5-
"sig": "3044022031a0b4c5fbdb12c26b06929adf6a9ee5fa68bc682fcb0cccc86f12018cfa1750022007a46dd475e80c13395ebadca48c5f3be4636c319a4479ef88f12502bf0a2255"
5+
"sig": "3046022100832dd6a362dc4f4c67733195265c80ab15751b5d5af732ec283478984ed6fecc0221008b111861fd98165ad6b932942111674c160a01945853c0802ed5c27bea416790"
66
},
77
{
88
"keyid": "d7d2d47a3f644fc3a685bac7b39c81ed9f9cee48ff861b44fbd86b91e34e7829",
9-
"sig": "304502200fff879af7a141a69d4c23636618410fac34e069e404d9790295c02bdcac958f022100e1c78d23d55fecae50703189060394b5177c1a220ba4ea574ef6a0434483af7b"
9+
"sig": "304602210091c4b0cc63517859a4678d420d0a857c9eec42041007253ef1aa10488c70850b022100a2a610ca6541d79a3dac2b8d45869945b9e9aa20cc3ae1e17fcf793c84de48bd"
1010
},
1111
{
1212
"keyid": "b78c9e4ff9048a1d9876a20f97fa1b3cb03223a0c520c7de730cfa9f5c7b77e5",
13-
"sig": "3045022100af6ea5521e208394bd2c72708ebc87acf6e630f39e5da46bcb45838ad3115b6802203eedccf4cb3c514228dd4e3f89c8bffbd15d329a4f1dbaaaa8728efd74bea840"
13+
"sig": "3045022100ce8bbdfb14f87c5183429d50c5a4173f2c49f218068a34e3c0e490acc5a913b702203bdee6b17ae378c36918efc01952cdd99eeb2172cedbb414fb110cfe8e87889f"
1414
},
1515
{
1616
"keyid": "afd6a6ebad62a0dd091db368c1806eeb172c893c80bece1098fed116e985ba35",
17-
"sig": "304402205f3a27995a075c9c89475e51e5159931b7a77e434d149126aba571c1afe8926f022030b1cad5d70fa25daa395ff11b0af7b55d431adad7e3f61d84d7d010168a5901"
17+
"sig": ""
18+
},
19+
{
20+
"keyid": "aa61e09f6af7662ac686cf0c6364079f63d3e7a86836684eeced93eace3acd81",
21+
"sig": "3046022100cedfe81229c20cc747420690c0660b8c6aefd0f2df0f232fe4265ee50416c174022100c064ebba2bdb8dec8b13d5519ae63ba9d4200b3790a8ef27adcfae1d487da772"
22+
},
23+
{
24+
"keyid": "61f9609d2655b346fcebccd66b509d5828168d5e447110e261f0bcc8553624bc",
25+
"sig": "30450221008a5319c88e134ab58e5a9bcb5e5722bd10504fa8a7fd24375aad875f71b341b502205b9888ba63fe7e9081801ccf8e2a4713b8725676923cd4deb29383fd78263ca5"
26+
},
27+
{
28+
"keyid": "9471fbda95411d10109e467ad526082d15f14a38de54ea2ada9687ab39d8e237",
29+
"sig": "3046022100b76041dabeca2f0dd88e33a0623a343b79e0c9e93dd6d7668d42798a9b7678fa022100ea1d416457e7837a6939930b6611ddcd023a5519ac6de83705bafe7879711c18"
30+
},
31+
{
32+
"keyid": "0374a9e18a20a2103736cb4277e2fdd7f8453642c7d9eaf4ad8aee9cf2d47bb5",
33+
"sig": ""
1834
}
1935
],
2036
"signed": {
2137
"_type": "root",
2238
"consistent_snapshot": true,
23-
"expires": "2024-08-21T13:23:32Z",
39+
"expires": "2024-09-30T11:42:30Z",
2440
"keys": {
25-
"5416a7a35ef827abc651e200ac11f3d23e9db74ef890b1fedb69fb2a152ebac5": {
41+
"0374a9e18a20a2103736cb4277e2fdd7f8453642c7d9eaf4ad8aee9cf2d47bb5": {
2642
"keytype": "ecdsa",
2743
"keyval": {
28-
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExxmEtmhF5U+i+v/6he4BcSLzCgMx\n/0qSrvDg6bUWwUrkSKS2vDpcJrhGy5fmmhRrGawjPp1ALpC3y1kqFTpXDg==\n-----END PUBLIC KEY-----\n"
44+
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoxkvDOmtGEknB3M+ZkPts8joDM0X\nIH5JZwPlgC2CXs/eqOuNF8AcEWwGYRiDhV/IMlQw5bg8PLICQcgsbrDiKg==\n-----END PUBLIC KEY-----\n"
2945
},
3046
"scheme": "ecdsa-sha2-nistp256",
31-
"x-tuf-on-ci-online-uri": "gcpkms:projects/projectsigstore-staging/locations/global/keyRings/tuf-keyring/cryptoKeys/tuf-key/cryptoKeyVersions/2"
47+
"x-tuf-on-ci-keyowner": "@mnm678"
3248
},
33-
"762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93": {
49+
"61f9609d2655b346fcebccd66b509d5828168d5e447110e261f0bcc8553624bc": {
3450
"keytype": "ecdsa",
3551
"keyval": {
36-
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEohqIdE+yTl4OxpX8ZxNUPrg3SL9H\nBDnhZuceKkxy2oMhUOxhWweZeG3bfM1T4ZLnJimC6CAYVU5+F5jZCoftRw==\n-----END PUBLIC KEY-----\n"
52+
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE++Wv+DcLRk+mfkmlpCwl1GUi9EMh\npBUTz8K0fH7bE4mQuViGSyWA/eyMc0HvzZi6Xr0diHw0/lUPBvok214YQw==\n-----END PUBLIC KEY-----\n"
3753
},
3854
"scheme": "ecdsa-sha2-nistp256",
39-
"x-tuf-on-ci-keyowner": "@jku"
55+
"x-tuf-on-ci-keyowner": "@kommendorkapten"
4056
},
41-
"afd6a6ebad62a0dd091db368c1806eeb172c893c80bece1098fed116e985ba35": {
57+
"9471fbda95411d10109e467ad526082d15f14a38de54ea2ada9687ab39d8e237": {
4258
"keytype": "ecdsa",
4359
"keyval": {
44-
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoxkvDOmtGEknB3M+ZkPts8joDM0X\nIH5JZwPlgC2CXs/eqOuNF8AcEWwGYRiDhV/IMlQw5bg8PLICQcgsbrDiKg==\n-----END PUBLIC KEY-----\n"
60+
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFHDb85JH+JYR1LQmxiz4UMokVMnP\nxKoWpaEnFCKXH8W4Fc/DfIxMnkpjCuvWUBdJXkO0aDIxwsij8TOFh2R7dw==\n-----END PUBLIC KEY-----\n"
4561
},
4662
"scheme": "ecdsa-sha2-nistp256",
47-
"x-tuf-on-ci-keyowner": "@mnm678"
63+
"x-tuf-on-ci-keyowner": "@joshuagl"
4864
},
49-
"b78c9e4ff9048a1d9876a20f97fa1b3cb03223a0c520c7de730cfa9f5c7b77e5": {
65+
"aa61e09f6af7662ac686cf0c6364079f63d3e7a86836684eeced93eace3acd81": {
5066
"keytype": "ecdsa",
5167
"keyval": {
52-
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFHDb85JH+JYR1LQmxiz4UMokVMnP\nxKoWpaEnFCKXH8W4Fc/DfIxMnkpjCuvWUBdJXkO0aDIxwsij8TOFh2R7dw==\n-----END PUBLIC KEY-----\n"
68+
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEohqIdE+yTl4OxpX8ZxNUPrg3SL9H\nBDnhZuceKkxy2oMhUOxhWweZeG3bfM1T4ZLnJimC6CAYVU5+F5jZCoftRw==\n-----END PUBLIC KEY-----\n"
5369
},
5470
"scheme": "ecdsa-sha2-nistp256",
55-
"x-tuf-on-ci-keyowner": "@joshuagl"
71+
"x-tuf-on-ci-keyowner": "@jku"
5672
},
57-
"d7d2d47a3f644fc3a685bac7b39c81ed9f9cee48ff861b44fbd86b91e34e7829": {
73+
"c3479007e861445ce5dc109d9661ed77b35bbc0e3f161852c46114266fc2daa4": {
5874
"keytype": "ecdsa",
5975
"keyval": {
60-
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE++Wv+DcLRk+mfkmlpCwl1GUi9EMh\npBUTz8K0fH7bE4mQuViGSyWA/eyMc0HvzZi6Xr0diHw0/lUPBvok214YQw==\n-----END PUBLIC KEY-----\n"
76+
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExxmEtmhF5U+i+v/6he4BcSLzCgMx\n/0qSrvDg6bUWwUrkSKS2vDpcJrhGy5fmmhRrGawjPp1ALpC3y1kqFTpXDg==\n-----END PUBLIC KEY-----\n"
6177
},
6278
"scheme": "ecdsa-sha2-nistp256",
63-
"x-tuf-on-ci-keyowner": "@kommendorkapten"
79+
"x-tuf-on-ci-online-uri": "gcpkms:projects/projectsigstore-staging/locations/global/keyRings/tuf-keyring/cryptoKeys/tuf-key/cryptoKeyVersions/2"
6480
}
6581
},
6682
"roles": {
6783
"root": {
6884
"keyids": [
69-
"762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93",
70-
"d7d2d47a3f644fc3a685bac7b39c81ed9f9cee48ff861b44fbd86b91e34e7829",
71-
"b78c9e4ff9048a1d9876a20f97fa1b3cb03223a0c520c7de730cfa9f5c7b77e5",
72-
"afd6a6ebad62a0dd091db368c1806eeb172c893c80bece1098fed116e985ba35"
85+
"aa61e09f6af7662ac686cf0c6364079f63d3e7a86836684eeced93eace3acd81",
86+
"61f9609d2655b346fcebccd66b509d5828168d5e447110e261f0bcc8553624bc",
87+
"9471fbda95411d10109e467ad526082d15f14a38de54ea2ada9687ab39d8e237",
88+
"0374a9e18a20a2103736cb4277e2fdd7f8453642c7d9eaf4ad8aee9cf2d47bb5"
7389
],
7490
"threshold": 2
7591
},
7692
"snapshot": {
7793
"keyids": [
78-
"5416a7a35ef827abc651e200ac11f3d23e9db74ef890b1fedb69fb2a152ebac5"
94+
"c3479007e861445ce5dc109d9661ed77b35bbc0e3f161852c46114266fc2daa4"
7995
],
8096
"threshold": 1,
8197
"x-tuf-on-ci-expiry-period": 3650,
8298
"x-tuf-on-ci-signing-period": 365
8399
},
84100
"targets": {
85101
"keyids": [
86-
"762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93",
87-
"d7d2d47a3f644fc3a685bac7b39c81ed9f9cee48ff861b44fbd86b91e34e7829",
88-
"b78c9e4ff9048a1d9876a20f97fa1b3cb03223a0c520c7de730cfa9f5c7b77e5",
89-
"afd6a6ebad62a0dd091db368c1806eeb172c893c80bece1098fed116e985ba35"
102+
"aa61e09f6af7662ac686cf0c6364079f63d3e7a86836684eeced93eace3acd81",
103+
"61f9609d2655b346fcebccd66b509d5828168d5e447110e261f0bcc8553624bc",
104+
"9471fbda95411d10109e467ad526082d15f14a38de54ea2ada9687ab39d8e237",
105+
"0374a9e18a20a2103736cb4277e2fdd7f8453642c7d9eaf4ad8aee9cf2d47bb5"
90106
],
91107
"threshold": 1
92108
},
93109
"timestamp": {
94110
"keyids": [
95-
"5416a7a35ef827abc651e200ac11f3d23e9db74ef890b1fedb69fb2a152ebac5"
111+
"c3479007e861445ce5dc109d9661ed77b35bbc0e3f161852c46114266fc2daa4"
96112
],
97113
"threshold": 1,
98114
"x-tuf-on-ci-expiry-period": 7,
99115
"x-tuf-on-ci-signing-period": 4
100116
}
101117
},
102118
"spec_version": "1.0",
103-
"version": 8,
119+
"version": 9,
104120
"x-tuf-on-ci-expiry-period": 91,
105121
"x-tuf-on-ci-signing-period": 35
106122
}

lib/rubygems/commands/sigstore_tuf_download_target_command.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# limitations under the License.
1616

1717
require "rubygems/command"
18+
require_relative "../../sigstore"
1819
require_relative "../../sigstore/tuf"
1920

2021
module Gem
@@ -49,8 +50,10 @@ def execute
4950

5051
kwargs = {}
5152
kwargs[:target_base_url] = @target_base_url if @target_base_url
52-
trust_updater = Sigstore::TUF::TrustUpdater.new(@metadata_url, false, metadata_dir: @metadata_dir,
53-
targets_dir: @targets_dir, **kwargs)
53+
trust_updater = Sigstore::TUF::TrustUpdater.new(
54+
@metadata_url, false,
55+
metadata_dir: @metadata_dir, targets_dir: @targets_dir, target_base_url: @target_base_url, **kwargs
56+
)
5457

5558
options[:args].each do |target|
5659
target_info = trust_updater.updater.get_targetinfo(target)

lib/rubygems/commands/sigstore_tuf_init_command.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ def initialize
3333
end
3434

3535
def execute
36-
raise Gem::CommandLineError, "--metadata-url is required" unless @metadata_url
3736
raise Gem::CommandLineError, "--metadata-dir is required" unless @metadata_dir
3837

3938
unless options[:args].size == 1 && File.exist?(options[:args].first)

lib/rubygems/commands/sigstore_tuf_refresh_command.rb

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,38 @@ def initialize
3131
add_option("--metadata-dir dir", String) do |dir|
3232
@metadata_dir = dir
3333
end
34+
35+
add_option("--days-in-future days", Integer) do |days|
36+
@days_in_future = days
37+
end
38+
39+
add_option("--max-root-rotations rotations", Integer) do |rotations|
40+
@max_root_rotations = rotations
41+
end
3442
end
3543

3644
def execute
45+
time_provider =
46+
if @days_in_future&.positive?
47+
-> { Time.now + (@days_in_future * 86_400) }
48+
else
49+
Time.method(:now)
50+
end
3751
raise Gem::CommandLineError, "metadata-url is required" unless @metadata_url
3852
raise Gem::CommandLineError, "metadata-dir is required" unless @metadata_dir
3953
raise Gem::CommandLineError, "no args accepted" unless options[:args].empty?
4054

41-
Sigstore::TUF::TrustUpdater.new(@metadata_url, false, metadata_dir: @metadata_dir)
55+
Sigstore::TUF::TrustUpdater.new(
56+
@metadata_url, false,
57+
metadata_dir: @metadata_dir,
58+
config: Sigstore::TUF::UpdaterConfig.new(
59+
max_root_rotations: @max_root_rotations
60+
),
61+
time_provider: time_provider
62+
)
63+
rescue Sigstore::Error => e
64+
alert_error "Error: #{e.full_message}"
65+
terminate_interaction 1
4266
end
4367
end
4468
end

lib/sigstore/tuf.rb

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class TrustUpdater
2929

3030
attr_reader :updater
3131

32-
def initialize(metadata_url, offline, metadata_dir: nil, targets_dir: nil, target_base_url: nil)
32+
def initialize(metadata_url, offline, metadata_dir: nil, targets_dir: nil, target_base_url: nil,
33+
config: UpdaterConfig.new, time_provider: Time.method(:now))
3334
@repo_url = metadata_url
3435

3536
default_metadata_dir, default_targets_dir = get_dirs(metadata_url) unless metadata_dir && targets_dir
@@ -80,14 +81,12 @@ def initialize(metadata_url, offline, metadata_dir: nil, targets_dir: nil, targe
8081
target_base_url: (target_base_url && URI.parse(target_base_url)) ||
8182
URI.join("#{@repo_url.to_s.chomp("/")}/", "targets/"),
8283
target_dir: @targets_dir,
83-
fetcher: Net::HTTP.new(repo_url.host, repo_url.port).tap { _1.use_ssl = true if repo_url.scheme != "http" }
84+
fetcher: Net::HTTP.new(repo_url.host, repo_url.port).tap { _1.use_ssl = true if repo_url.scheme != "http" },
85+
config: config,
86+
time_provider: time_provider
8487
)
8588

86-
begin
87-
@updater.refresh
88-
rescue StandardError => e
89-
raise "Failed to refresh TUF metadata: #{e.class} #{e.full_message}"
90-
end
89+
@updater.refresh
9190
end
9291

9392
def get_dirs(url)

lib/sigstore/tuf/error.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,8 @@ class ExpiredMetadata < Error; end
2323
class EqualVersionNumber < Error; end
2424
class BadVersionNumber < Error; end
2525
class BadUpdateOrder < Error; end
26+
class TooFewSignatures < Error; end
27+
class MetaVersionLower < Error; end
28+
class MetaVersionHigher < Error; end
2629
end
2730
end

0 commit comments

Comments
 (0)