Skip to content

Commit d48480c

Browse files
committed
Adding oidc_urls to signingConfig
Signed-off-by: SequeI <asiek@redhat.com>
1 parent 8183b8c commit d48480c

File tree

6 files changed

+187
-5
lines changed

6 files changed

+187
-5
lines changed

.github/workflows/trust-root-test.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,13 @@ jobs:
3636
./rhtas/tuf-repo-init.sh --export-keys file:///tmp/exported-keys \
3737
--fulcio-cert ./rhtas/test/fulcio-cert \
3838
--fulcio-uri "https://fulcio.rhtas" \
39+
--oidc-uri "https://oauth2.rhtas/auth" \
3940
--tsa-cert ./rhtas/test/tsa-chain \
4041
--tsa-uri "https://tsa.rhtas" \
4142
--ctlog-key ./rhtas/test/ctfe-pubkey \
42-
--fulcio-uri "https://ctlog.rhtas" \
43+
--ctlog-uri "https://ctlog.rhtas" \
4344
--rekor-key ./rhtas/test/rekor-pubkey \
44-
--fulcio-uri "https://rekor.rhtas" \
45+
--rekor-uri "https://rekor.rhtas" \
4546
/tmp/testrepo
4647
- run: curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64" && mv cosign-linux-amd64 ${HOME}/.local/bin/cosign && sudo chmod +x ${HOME}/.local/bin/cosign
4748
- run: cosign -d initialize --mirror=file:///tmp/testrepo --root=/tmp/testrepo/root.json

rhtas/tuf-repo-init.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ Options:
2121
--fulcio-uri
2222
Fulcio base URI
2323

24+
--oidc-uri
25+
OIDC provider URI (used with Fulcio for authentication)
26+
2427
--tsa-cert
2528
TSA certificate chain file
2629

@@ -51,6 +54,7 @@ export TSA_CERT=""
5154
export CTLOG_KEY=""
5255
export REKOR_KEY=""
5356
export FULCIO_URI=""
57+
export OIDC_URI=""
5458
export TSA_URI=""
5559
export CTLOG_URI=""
5660
export REKOR_URI=""
@@ -78,6 +82,11 @@ while [[ $# -gt 0 ]]; do
7882
shift
7983
shift
8084
;;
85+
--oidc-uri)
86+
OIDC_URI="$2"
87+
shift
88+
shift
89+
;;
8190
--tsa-cert)
8291
TSA_CERT="$2"
8392
shift
@@ -206,6 +215,7 @@ if [ -n "${FULCIO_CERT}" ]; then
206215
--key "${KEYDIR}/timestamp.pem" \
207216
--set-fulcio-target "${FULCIO_CERT}" \
208217
--fulcio-uri "${FULCIO_URI}" \
218+
--oidc-uri "${OIDC_URI}" \
209219
--targets-expires "${METADATA_EXPIRATION}" \
210220
--targets-version 1 \
211221
--snapshot-expires "${METADATA_EXPIRATION}" \
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIBRDCB6qADAgECAhQ48IquFOZo09saJlDbzTkhWk3fcDAKBggqhkjOPQQDAjAA
3+
MB4XDTI1MDYxODEzNDYyNVoXDTI3MDYxODEzNDYyNVowADBZMBMGByqGSM49AgEG
4+
CCqGSM49AwEHA0IABILV+1eMc2UU102fXxj3ubL05xYUknHAEe9aJ3uvIbns4oRW
5+
En4QNTUzmXMZvEuo9BgyhEFEDfTLLF0VDmHNs9SjQjBAMA8GA1UdEwEB/wQFMAMB
6+
Af8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSJKgcj+N/QRxcjctUUAs4xO83J
7+
0jAKBggqhkjOPQQDAgNJADBGAiEAl9hqgYh+9eqcbuzV0XWQ8G2a/n/+E/PTItMT
8+
Evbue8ICIQDffR5DqWh19Rfx37PqFoRIDfjOhvQPvE7rMWjDOu4cXQ==
9+
-----END CERTIFICATE-----

tuftool/src/rhtas.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ pub(crate) struct RhtasArgs {
109109
#[arg(long)]
110110
fulcio_uri: Option<String>,
111111

112+
/// URI for the OIDC provider (used with Fulcio).
113+
/// Example: <https://oauth2.sigstore.dev/auth>
114+
#[arg(long)]
115+
oidc_uri: Option<String>,
116+
112117
/// Path to the new Ctlog target file
113118
#[arg(long = "set-ctlog-target")]
114119
ctlog_target: Option<PathBuf>,
@@ -677,6 +682,11 @@ impl RhtasArgs {
677682
start = None;
678683
}
679684

685+
let valid_for = Some(TimeRange {
686+
start: start.clone(),
687+
end: end.clone(),
688+
});
689+
680690
let mut certificates: Vec<X509Certificate> = Vec::new();
681691
for item in certificate_raw_bytes_vec {
682692
certificates.push(X509Certificate { raw_bytes: item });
@@ -689,7 +699,7 @@ impl RhtasArgs {
689699
}),
690700
uri: self.fulcio_uri.clone().unwrap(),
691701
cert_chain: Some(X509CertificateChain { certificates }),
692-
valid_for: Some(TimeRange { start, end }),
702+
valid_for: valid_for.clone(),
693703
operator: String::new(),
694704
};
695705

@@ -701,6 +711,17 @@ impl RhtasArgs {
701711
eprintln!("Failed to set target: {e:?} in trust_bundle");
702712
}
703713
}
714+
715+
// Add OIDC URL to SigningConfig (OIDC is used with Fulcio for authentication)
716+
if let Some(ref oidc_uri) = self.oidc_uri {
717+
if let Err(e) = trust_bundle.add_oidc_url_to_signing_config(
718+
oidc_uri.clone(),
719+
valid_for,
720+
"sigstore.dev".to_string(),
721+
) {
722+
eprintln!("Failed to add OIDC URL to signing_config: {e:?}");
723+
}
724+
}
704725
}
705726
Ok(())
706727
}
@@ -1089,14 +1110,15 @@ impl RhtasArgs {
10891110
|| self.tsa_status.is_some())
10901111
{
10911112
return error::InvalidArgumentCombinationSnafu {
1092-
msg: "--set-fulcio-target only accepts --fulcio-uri and --fulcio-status."
1113+
msg: "--set-fulcio-target only accepts --fulcio-uri, --fulcio-status, and --oidc-uri."
10931114
.to_string(),
10941115
}
10951116
.fail();
10961117
}
10971118

10981119
if self.ctlog_target.is_some()
10991120
&& (self.fulcio_uri.is_some()
1121+
|| self.oidc_uri.is_some()
11001122
|| self.rekor_uri.is_some()
11011123
|| self.tsa_uri.is_some()
11021124
|| self.fulcio_status.is_some()
@@ -1111,6 +1133,7 @@ impl RhtasArgs {
11111133

11121134
if self.rekor_target.is_some()
11131135
&& (self.fulcio_uri.is_some()
1136+
|| self.oidc_uri.is_some()
11141137
|| self.ctlog_uri.is_some()
11151138
|| self.tsa_uri.is_some()
11161139
|| self.fulcio_status.is_some()
@@ -1125,6 +1148,7 @@ impl RhtasArgs {
11251148

11261149
if self.tsa_target.is_some()
11271150
&& (self.fulcio_uri.is_some()
1151+
|| self.oidc_uri.is_some()
11281152
|| self.ctlog_uri.is_some()
11291153
|| self.rekor_uri.is_some()
11301154
|| self.fulcio_status.is_some()
@@ -1144,6 +1168,9 @@ impl RhtasArgs {
11441168
if self.fulcio_status.is_none() {
11451169
self.fulcio_status = Some(String::from("Active"));
11461170
}
1171+
if self.oidc_uri.is_none() {
1172+
self.oidc_uri = Some(String::from("https://oauth2.sigstore.dev/auth"));
1173+
}
11471174
}
11481175
if self.ctlog_target.is_some() {
11491176
if self.ctlog_uri.is_none() {

tuftool/src/sigstore_trust/trust/sigstore/mod.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,38 @@ impl SigstoreTrustBundle {
213213
std::fs::write(file_path, json).map_err(SigstoreError::from)
214214
}
215215

216+
/// Add an OIDC URL to the `SigningConfig` (used with Fulcio).
217+
/// The `SigningConfig` must already exist (it is created when adding the Fulcio CA target).
218+
pub fn add_oidc_url_to_signing_config(
219+
&mut self,
220+
url: String,
221+
valid_for: Option<TimeRange>,
222+
operator: String,
223+
) -> Result<()> {
224+
let Some(signing_config) = &mut self.signing_config else {
225+
return Err(SigstoreError::UnexpectedError(
226+
"Cannot add OIDC URL: signing_config does not exist (add Fulcio target first)"
227+
.to_string(),
228+
));
229+
};
230+
231+
let operator = if operator.is_empty() {
232+
"sigstore.dev".to_string()
233+
} else {
234+
operator
235+
};
236+
signing_config
237+
.oidc_urls
238+
.retain(|service| service.url != url);
239+
signing_config.oidc_urls.push(Service {
240+
url,
241+
major_api_version: 1,
242+
valid_for,
243+
operator,
244+
});
245+
Ok(())
246+
}
247+
216248
/// Save the signing config to a file
217249
pub fn save_signing_config_to_file(&self, file_path: &Path) -> Result<()> {
218250
if let Some(signing_config) = &self.signing_config {
@@ -712,6 +744,7 @@ impl SigstoreTrustBundle {
712744
match target_type {
713745
Target::CertificateAuthority => {
714746
signing_config.ca_urls.retain(|svc| svc.url != uri);
747+
signing_config.oidc_urls.retain(|svc| svc.url != uri);
715748
}
716749
Target::Tlog => {
717750
signing_config.rekor_tlog_urls.retain(|svc| svc.url != uri);

tuftool/tests/rhtas_command.rs

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ async fn rhtas_command_argument_validation() {
385385
.join("ctfe.pub");
386386
let metadata_base_url = &dir_url(&repo_dir);
387387

388-
// Update the repo we just created
388+
// Update the repo we just created - fulcio-uri with ctlog-target should fail
389389
Command::cargo_bin("tuftool")
390390
.unwrap()
391391
.args([
@@ -405,6 +405,27 @@ async fn rhtas_command_argument_validation() {
405405
])
406406
.assert()
407407
.failure();
408+
409+
// oidc-uri with ctlog-target should also fail (oidc is only valid with fulcio-target)
410+
Command::cargo_bin("tuftool")
411+
.unwrap()
412+
.args([
413+
"rhtas",
414+
"-o",
415+
repo_dir.to_str().unwrap(),
416+
"-k",
417+
root_key.to_str().unwrap(),
418+
"--root",
419+
root_json.to_str().unwrap(),
420+
"--set-ctlog-target",
421+
new_targets_input_dir.to_str().unwrap(),
422+
"--oidc-uri",
423+
"https://oauth2.sigstore.dev/auth",
424+
"--metadata-url",
425+
metadata_base_url.as_str(),
426+
])
427+
.assert()
428+
.failure();
408429
}
409430

410431
#[tokio::test]
@@ -480,3 +501,84 @@ async fn rhtas_command_force_metadata_version() {
480501
assert_eq!(repo.timestamp().signed.expires, new_timestamp_expiration);
481502
assert_eq!(repo.timestamp().signed.version.get(), new_timestamp_version);
482503
}
504+
505+
#[tokio::test]
506+
#[serial]
507+
async fn rhtas_command_fulcio_oidc_signing_config() {
508+
let root_json = test_utils::test_data().join("simple-rsa").join("root.json");
509+
let root_key = test_utils::test_data().join("snakeoil.pem");
510+
let repo_dir = test_utils::test_data().join("rhtas_tmp");
511+
512+
let _cleanup = TestRepoCleanup::new(repo_dir.clone());
513+
514+
create_repo(repo_dir.clone());
515+
516+
let fulcio_cert = test_utils::test_data()
517+
.join("rhtas-targets")
518+
.join("fulcio-cert");
519+
let metadata_base_url = &dir_url(&repo_dir);
520+
521+
// Add Fulcio target with OIDC URI - this should populate signing_config with oidcUrls
522+
Command::cargo_bin("tuftool")
523+
.unwrap()
524+
.args([
525+
"rhtas",
526+
"-o",
527+
repo_dir.to_str().unwrap(),
528+
"-k",
529+
root_key.to_str().unwrap(),
530+
"--root",
531+
root_json.to_str().unwrap(),
532+
"--set-fulcio-target",
533+
fulcio_cert.to_str().unwrap(),
534+
"--fulcio-uri",
535+
"https://fulcio.test.example",
536+
"--oidc-uri",
537+
"https://oauth2.test.example/auth",
538+
"--metadata-url",
539+
metadata_base_url.as_str(),
540+
])
541+
.assert()
542+
.success();
543+
544+
// Load the repo and verify signing_config contains oidcUrls
545+
let repo = RepositoryLoader::new(
546+
&tokio::fs::read(root_json.clone()).await.unwrap(),
547+
dir_url(&repo_dir),
548+
dir_url(repo_dir.join("targets")),
549+
)
550+
.load()
551+
.await
552+
.unwrap();
553+
554+
// Find signing_config target (may be hashed or direct)
555+
let signing_config_name = repo
556+
.targets()
557+
.signed
558+
.targets
559+
.keys()
560+
.find(|k| k.raw().contains("signing_config"))
561+
.expect("signing_config target should exist");
562+
563+
let signing_config_data = test_utils::read_to_end(
564+
repo.read_target(signing_config_name)
565+
.await
566+
.unwrap()
567+
.unwrap(),
568+
)
569+
.await;
570+
let signing_config: serde_json::Value =
571+
serde_json::from_slice(&signing_config_data).expect("signing_config should be valid JSON");
572+
573+
let oidc_urls = signing_config
574+
.get("oidcUrls")
575+
.expect("signing_config should contain oidcUrls");
576+
let oidc_urls = oidc_urls.as_array().expect("oidcUrls should be an array");
577+
assert!(!oidc_urls.is_empty(), "oidcUrls should not be empty");
578+
let first_oidc = &oidc_urls[0];
579+
assert_eq!(
580+
first_oidc.get("url").and_then(|v| v.as_str()),
581+
Some("https://oauth2.test.example/auth"),
582+
"OIDC URL should match"
583+
);
584+
}

0 commit comments

Comments
 (0)