Skip to content

Commit

Permalink
image-rs: Support simple signing with X-R-S-S
Browse files Browse the repository at this point in the history
Support getting simple signing signatures from
registry that supports X-R-S-S extension.

Refactor into separate tests for XRSS and others.

Fixes: confidential-containers#12

Signed-off-by: Matthew Arnold <mattarno@uk.ibm.com>
  • Loading branch information
mattarnoatibm committed Oct 11, 2023
1 parent f4f89da commit 43227e4
Show file tree
Hide file tree
Showing 10 changed files with 338 additions and 23 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/image_rs_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ jobs:
cargo clippy -p image-rs --all-targets --features=kata-cc-native-tls --no-default-features -- -D warnings
cargo clippy -p image-rs --all-targets --features=enclave-cc-eaakbc-native-tls --no-default-features -- -D warnings
cargo clippy -p image-rs --all-targets --features=enclave-cc-cckbc-native-tls --no-default-features -- -D warnings
cargo clippy -p image-rs --all-targets --features=kata-cc-native-tls,signature-simple-xrss --no-default-features -- -D warnings
- name: Run cargo build
uses: actions-rs/cargo@v1
Expand All @@ -100,3 +101,9 @@ jobs:
- name: Run cargo test - kata-cc (native-tls version) with keywrap-ttrpc (default) + keywrap-jwe
run: |
sudo -E PATH=$PATH -s cargo test -p image-rs --no-default-features --features=kata-cc-native-tls,keywrap-jwe
- name: Run cargo test - kata-cc (native-tls version) with keywrap-ttrpc (default) + keywrap-jwe and with signatures from XRSS registry extension
env:
AUTH_PASSWORD: ${{ secrets.SH_ICR_API_KEY }}
run: |
sudo -E PATH=$PATH -s cargo test -p image-rs --no-default-features --features=kata-cc-native-tls,keywrap-jwe,signature-simple-xrss
57 changes: 56 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions image-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ oci-spec = "0.6.2"
ocicrypt-rs = { path = "../ocicrypt-rs", default-features = false, features = ["async-io"], optional = true }
prost = { workspace = true, optional = true }
protobuf = { workspace = true, optional = true }
reqwest = { workspace = true, features = ["json"], optional = true }
sequoia-openpgp = { version = "1.7.0", default-features = false, features = ["compression", "crypto-rust", "allow-experimental-crypto", "allow-variable-time-crypto"], optional = true }
serde = { workspace = true, features = ["serde_derive", "rc"] }
serde_json.workspace = true
Expand Down Expand Up @@ -111,6 +112,7 @@ signature-cosign-native = ["signature-cosign", "sigstore/cosign-native-tls"]
oci-distribution-rustls = ["oci-distribution/rustls-tls"]
oci-distribution-native = ["oci-distribution/native-tls"]

signature-simple-xrss = ["signature-simple", "dep:reqwest"]
signature-simple = ["signature", "sequoia-openpgp", "serde_yaml"]

snapshot-overlayfs = ["nix"]
Expand Down
53 changes: 39 additions & 14 deletions image-rs/src/signature/mechanism/simple/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ use serde::*;
use strum_macros::Display;
use strum_macros::EnumString;

#[cfg(feature = "signature-simple")]
use base64::Engine;

#[cfg(feature = "signature-simple")]
mod sigstore;
#[cfg(feature = "signature-simple")]
mod verify;
#[cfg(feature = "signature-simple-xrss")]
mod xrss;

use crate::signature::{image::Image, mechanism::Paths, policy::ref_match::PolicyReqMatchType};

Expand Down Expand Up @@ -71,9 +76,16 @@ impl SignScheme for SimpleParameters {
async fn init(&mut self, config: &Paths) -> Result<()> {
prepare_runtime_dirs(crate::config::SIG_STORE_CONFIG_DIR).await?;
self.initialize_sigstore_config().await?;
let sig_store_config_file = crate::resource::get_resource(&config.sigstore_config).await?;
let sig_store_config_file = crate::resource::get_resource(&config.sigstore_config).await;

#[cfg(feature = "signature-simple-xrss")]
if sig_store_config_file.is_err() {
// When using xrss extension a sigstore config file is optional
return Ok(());
}

let sig_store_config_file =
serde_yaml::from_slice::<sigstore::SigstoreConfig>(&sig_store_config_file)?;
serde_yaml::from_slice::<sigstore::SigstoreConfig>(&sig_store_config_file?)?;
self.sig_store_config_file
.update_self(sig_store_config_file)?;
Ok(())
Expand All @@ -86,7 +98,6 @@ impl SignScheme for SimpleParameters {

#[cfg(feature = "signature-simple")]
async fn allows_image(&self, image: &mut Image, _auth: &RegistryAuth) -> Result<()> {
use base64::Engine;
// FIXME: only support "GPGKeys" type now.
//
// refer to https://github.com/confidential-containers/image-rs/issues/14
Expand All @@ -108,7 +119,7 @@ impl SignScheme for SimpleParameters {
}
};

let sigs = self.get_signatures(image).await?;
let sigs = self.get_signatures(image, _auth).await?;
let mut reject_reasons: Vec<anyhow::Error> = Vec::new();

for sig in sigs.iter() {
Expand Down Expand Up @@ -182,22 +193,19 @@ impl SimpleParameters {
/// Set the content of sigstore config with files in
/// [`crate::config::SIG_STORE_CONFIG_DIR`]
pub async fn initialize_sigstore_config(&mut self) -> Result<()> {
// If the registry support `X-Registry-Supports-Signatures` API extension,
// try to get signatures from the registry first.
// Else, get signatures from "sigstore" according to the sigstore config file.
// (https://github.com/containers/image/issues/384)
//
// TODO: Add get signatures from registry X-R-S-S API extension.
//
// issue: https://github.com/confidential-containers/image-rs/issues/12
let sigstore_config =
sigstore::SigstoreConfig::new_from_configs(crate::config::SIG_STORE_CONFIG_DIR).await?;
self.sig_store_config_file.update_self(sigstore_config)?;

Ok(())
}

pub async fn get_signatures(&self, image: &Image) -> Result<Vec<Vec<u8>>> {
pub async fn get_signatures(
&self,
image: &Image,
_auth: &RegistryAuth,
) -> Result<Vec<Vec<u8>>> {
let mut sigs: Vec<Vec<u8>> = Vec::new();
// Get image digest (manifest digest)
let image_digest = if !image.manifest_digest.is_empty() {
image.manifest_digest.clone()
Expand All @@ -207,6 +215,22 @@ impl SimpleParameters {
bail!("Missing image digest");
};

#[cfg(feature = "signature-simple-xrss")]
{
let registry_client = xrss::RegistryClient::new();
let mut registry_sigs = registry_client
.get_signatures_from_registry(image, &image_digest, _auth)
.await?;
sigs.append(&mut registry_sigs);
if self.sig_store_config_file == sigstore::SigstoreConfig::default() {
if sigs.is_empty() {
bail!("Missing sigstore config file and no signatures in registry");
}

return Ok(sigs);
}
}

// Format the sigstore name: `image-repository@digest-algorithm=digest-value`.
let sigstore_name = sigstore::format_sigstore_name(&image.reference, image_digest);

Expand All @@ -219,7 +243,8 @@ impl SimpleParameters {
let sigstore_uri = url::Url::parse(&sigstore)
.map_err(|e| anyhow!("Failed to parse sigstore_uri: {:?}", e))?;

let sigs = sigstore::get_sigs_from_specific_sigstore(sigstore_uri).await?;
let mut sigstore_sigs = sigstore::get_sigs_from_specific_sigstore(sigstore_uri).await?;
sigs.append(&mut sigstore_sigs);

Ok(sigs)
}
Expand Down
Loading

0 comments on commit 43227e4

Please sign in to comment.