Skip to content

Commit

Permalink
attestation-agent: Extend ResourceUri to support query string
Browse files Browse the repository at this point in the history
With this change, the kbs-client is able to send a get-resource request that
includes the query string provided e.g.:

kbs-client --url http://127.0.0.1:8080 \
           get-resource \
           --path 'plugin/nebula/credential?ip[ip]=10.11.12.13&ip[netbits]=21&name=pod1'

This is required by the KBS repository plugin interface.

Signed-off-by: Claudio Carvalho <cclaudio@linux.ibm.com>
  • Loading branch information
cclaudio committed Jul 31, 2024
1 parent 51e9670 commit 08e3ca6
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 45 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions attestation-agent/deps/resource_uri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ authors = ["The Attestation Agent Authors"]
publish = false
edition = "2021"

[dev-dependencies]
rstest.workspace = true

[dependencies]
anyhow.workspace = true
serde.workspace = true
Expand Down
102 changes: 59 additions & 43 deletions attestation-agent/deps/resource_uri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct ResourceUri {
pub repository: String,
pub r#type: String,
pub tag: String,
pub query: Option<String>,
}

impl TryFrom<&str> for ResourceUri {
Expand Down Expand Up @@ -62,6 +63,7 @@ impl TryFrom<url::Url> for ResourceUri {
repository: values[0].into(),
r#type: values[1].into(),
tag: values[2].into(),
query: value.query().map(|s| s.to_string()),
})
} else {
Err(RESOURCE_ID_ERROR_INFO)
Expand Down Expand Up @@ -103,6 +105,7 @@ impl ResourceUri {
repository: values[1].into(),
r#type: values[2].into(),
tag: values[3].into(),
query: None,
})
} else {
bail!(
Expand All @@ -112,10 +115,14 @@ impl ResourceUri {
}

pub fn whole_uri(&self) -> String {
format!(
let uri = format!(
"{SCHEME}://{}/{}/{}/{}",
self.kbs_addr, self.repository, self.r#type, self.tag
)
);
match &self.query {
Some(q) => format!("{uri}?{q}"),
None => uri,
}
}

/// Only return the resource path. This function is used
Expand Down Expand Up @@ -148,49 +155,58 @@ impl<'de> Deserialize<'de> for ResourceUri {
#[cfg(test)]
mod tests {
use super::ResourceUri;

const TEST_URL: &str = "kbs:///alice/cosign-key/213";

#[test]
fn deserialize() {
let resource: ResourceUri =
serde_json::from_str(&format!("\"{TEST_URL}\"")).expect("deserialize failed");
let expected = ResourceUri {
kbs_addr: "".into(),
repository: "alice".into(),
r#type: "cosign-key".into(),
tag: "213".into(),
};
assert_eq!(expected, resource);
}

#[test]
fn serialize() {
let rid = ResourceUri {
use rstest::rstest;

#[rstest]
#[case(
"kbs:///alice/cosign-key/213",
"alice",
"cosign-key",
"213",
None,
)]
#[case(
"kbs:///plugin/plugname/resourcename?param1=value1&param2=value2",
"plugin",
"plugname",
"resourcename",
Some("param1=value1&param2=value2"),
)]
fn test_resource_uri_serialization_conversion(
#[case] url: &str,
#[case] repository: &str,
#[case] r#type: &str,
#[case] tag: &str,
#[case] query: Option<&str>,
) {
let resource = ResourceUri {
kbs_addr: "".into(),
repository: "alice".into(),
r#type: "cosign-key".into(),
tag: "213".into(),
repository: repository.into(),
r#type: r#type.into(),
tag: tag.into(),
query: query.map(|s| s.to_string()),
};

let res = serde_json::to_string(&rid).expect("serialize failed");
assert_eq!(res, format!("\"{TEST_URL}\""));
}

#[test]
fn conversions() {
let rid = ResourceUri {
kbs_addr: "".into(),
repository: "alice".into(),
r#type: "cosign-key".into(),
tag: "213".into(),
};

let url = url::Url::try_from(TEST_URL).expect("failed to parse url");
let try_into: url::Url = rid.clone().try_into().expect("failed to try into url");
assert_eq!(url, try_into);

let rid_try_from = ResourceUri::try_from(url).expect("failed to try from url");
assert_eq!(rid, rid_try_from);
// Deserialization
let deserialized: ResourceUri =
serde_json::from_str(&format!("\"{url}\"")).expect("deserialize failed");
assert_eq!(deserialized, resource);

// Serialization
let serialized =
serde_json::to_string(&resource).expect("deserialize failed");
assert_eq!(serialized, format!("\"{url}\""));

// Conversion to Url
let url_from_string =
url::Url::try_from(url).expect("failed to parse url");
let url_from_resource: url::Url =
resource.clone().try_into().expect("failed to try into url");
assert_eq!(url_from_string, url_from_resource);

// Conversion to ResourceUri
let resource_from_url =
ResourceUri::try_from(url_from_string).expect("failed to try from url");
assert_eq!(resource_from_url, resource);
}
}
5 changes: 4 additions & 1 deletion attestation-agent/kbs_protocol/src/client/rcar_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,13 @@ impl KbsClient<Box<dyn EvidenceProvider>> {
#[async_trait]
impl KbsClientCapabilities for KbsClient<Box<dyn EvidenceProvider>> {
async fn get_resource(&mut self, resource_uri: ResourceUri) -> Result<Vec<u8>> {
let remote_url = format!(
let mut remote_url = format!(
"{}/{KBS_PREFIX}/resource/{}/{}/{}",
self.kbs_host_url, resource_uri.repository, resource_uri.r#type, resource_uri.tag
);
if let Some(ref q) = resource_uri.query {
remote_url = format!("{}?{}", remote_url, q);
}

for attempt in 1..=KBS_GET_RESOURCE_MAX_ATTEMPT {
debug!("KBS client: trying to request KBS, attempt {attempt}");
Expand Down
6 changes: 5 additions & 1 deletion attestation-agent/kbs_protocol/src/client/token_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ impl KbsClient<Box<dyn TokenProvider>> {
#[async_trait]
impl KbsClientCapabilities for KbsClient<Box<dyn TokenProvider>> {
async fn get_resource(&mut self, resource_uri: ResourceUri) -> Result<Vec<u8>> {
let remote_url = format!(
let mut remote_url = format!(
"{}/{KBS_PREFIX}/resource/{}/{}/{}",
self.kbs_host_url, resource_uri.repository, resource_uri.r#type, resource_uri.tag
);
if let Some(ref q) = resource_uri.query {
remote_url = format!("{}?{}", remote_url, q);
}

for attempt in 1..=KBS_GET_RESOURCE_MAX_ATTEMPT {
debug!("KBS client: trying to request KBS, attempt {attempt}");
if self.token.is_none() {
Expand Down

0 comments on commit 08e3ca6

Please sign in to comment.