Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

verifier: Fetch VCEK cert from KDS instead of bailing #555

Merged
merged 3 commits into from
Nov 19, 2024

Conversation

AdithyaKrishnan
Copy link
Contributor

Fetch the VCEK cert from the KDS if it is absent in the cert chain instead of just printing a bail statement stating that the VCEK is not found.

@AdithyaKrishnan AdithyaKrishnan requested a review from a team as a code owner November 4, 2024 18:17
Copy link

@cclaudio cclaudio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few minor comments.

// Function to request vcek from KDS. Return vcek in der format.
fn request_endorsement_key_kds(
att_report: AttestationReport,
) -> Result<Vec<CertTableEntry>, anyhow::Error> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function is specific to download the VCEK, so I think it could be rename to something more specific such as fetch_vcek_from_kds()

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, I think the function would be more self-contained if it returns Result<Vec<u8>>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed. If appropriate, please mark this comment as Resolved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, I think the function would be more self-contained if it returns Result<Vec<u8>>

Tried this and got a type mismatch error

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw I don't think you need anyhow::Error in in this return type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Member

@fitzthum fitzthum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice PR. Looks like this will address #456 which is actually a duplicate of #363

One thing to think about is that this could result in quite a few requests being made to the KDS. We should probably implement some kind of caching mechanism so that the verifier doesn't have to get the vcek for the same node again and again. We can probably do this in a follow-up.

Also, we might want to add vlek support at some point although I suspect this will require specifying a few more config params.

@@ -49,6 +49,7 @@ strum.workspace = true
veraison-apiclient = { git = "https://github.com/chendave/rust-apiclient", branch = "token", optional = true }
ear = { git = "https://github.com/veraison/rust-ear", rev = "43f7f480d09ea2ebc03137af8fbcd70fe3df3468", optional = true }
x509-parser = { version = "0.14.0", optional = true }
reqwest = { version="0.12.9", features = ["blocking"] }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I you are already specifying the needed version of reqwest in the global Cargo file, you can just say request = workspace.true here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed. If appropriate, please mark this comment as Resolved.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See Ding's suggestions about the Cargo file as well.

@@ -84,8 +85,10 @@ impl Verifier for Snp {
cert_chain,
} = serde_json::from_slice(evidence).context("Deserialize Quote failed.")?;

let Some(cert_chain) = cert_chain else {
bail!("Cert chain is unset");
let cert_chain = if let Some(chain) = cert_chain{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the cert chain is type Option<Vec<Cert>> or something. This accounts for cases where the option is none, but what if the option is there but the vector is empty?

Ideally we should get the vcek even if there is a non-empty cert chain as long as the vcek/vlek isn't part of it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be part of the future follow-up PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can leave check the cert types to a follow-up, but please add a case to this statement to catch an empty vector.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the empty vector check

deps/verifier/src/snp/mod.rs Outdated Show resolved Hide resolved
) -> Result<Vec<CertTableEntry>, anyhow::Error> {
// KDS URL parameters
const KDS_CERT_SITE: &str = "https://kdsintf.amd.com";
const KDS_VCEK: &str = "/vcek/v1";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be better to put these consts at the top of the file rather than inside this function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. If appropriate, please mark this comment as Resolved.

deps/verifier/src/snp/mod.rs Outdated Show resolved Hide resolved
Cargo.lock Outdated
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems your Cargo.lock has more changes than required. You may need to restore it and apply the request = worspace.true change that Tobin suggested

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If appropriate, please mark this comment as Resolved.

deps/verifier/src/snp/mod.rs Outdated Show resolved Hide resolved
Cargo.toml Outdated
@@ -36,7 +36,7 @@ jsonwebtoken = { version = "9", default-features = false }
log = "0.4.17"
prost = "0.12"
regorus = { version = "0.1.5", default-features = false, features = ["regex", "base64", "time"] }
reqwest = { version = "0.12", default-features = false, features = ["default-tls"] }
reqwest = { version = "0.12", default-features = false, features = ["default-tls", "blocking"] }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that the reqwest is used in fetch_vcek_from_kds. It is suggested to use reqwest::get (the async version) rather than blocking version, because the blocking version would hang on network I/O during which the process would wait.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm able to resolve most comments except this. Could we please have a conversation on slack?

deps/verifier/Cargo.toml Show resolved Hide resolved
let key = CertTableEntry { cert_type: CertType::VCEK, data: vcek_rsp_bytes };
Ok(vec![key])
}
status => Err(anyhow::anyhow!("Unable to fetch VCEK from URL: {status:?}")),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

anyhow::anyhow! -> anyhow!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@AdithyaKrishnan AdithyaKrishnan force-pushed the main branch 3 times, most recently from 8005c31 to 770fd0c Compare November 15, 2024 19:16
chain
}
} else {
fetch_vcek_from_kds(report)?
Copy link
Member

@fitzthum fitzthum Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can simplify this by doing something like

let cert_chain = match cert_chain {
    Some(chain) if !chain.is_empty() => chain,
    _ => fetch_vcek_from_kds(report)?
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

Fetch the VCEK cert from the KDS if it is absent in the cert chain instead of just printing a bail statement stating that the VCEK is not found.

Signed-off-by: Adithya Krishnan Kannan <[email protected]>
Copy link
Member

@Xynnn007 Xynnn007 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @AdithyaKrishnan ! LGTM. Please see @fitzthum and @cclaudio 's comments.

@@ -307,6 +313,41 @@ fn get_common_name(cert: &x509::X509) -> Result<String> {
Ok(e.data().as_utf8()?.to_string())
}

// Function to request vcek from KDS asynchronously. Return vcek in der format.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can change // to ///. This would automatically generate a document about the function when we publish the crate to crates.io.

Copy link
Contributor Author

@AdithyaKrishnan AdithyaKrishnan Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Further, would you like me to add descriptions to all the functions in mod.rs?

Per Ding's feedback, I'm testing the use of reqwest asynchronously with get instead of the earlier used blocking version.

Signed-off-by: Adithya Krishnan Kannan <[email protected]>
Per Ding's suggestion, I've added a description of each function as part of documenting the code.

Signed-off-by: Adithya Krishnan Kannan <[email protected]>
@AdithyaKrishnan
Copy link
Contributor Author

Thanks @AdithyaKrishnan ! LGTM. Please see @fitzthum and @cclaudio 's comments.

@fitzthum and @cclaudio - I believe I've fixed all your concerns. Please let me know if there are any more to be resolved. Further, per Ding's suggestion, I've added a third commit that adds on to the documentation by providing descriptions of all functions.
Hoping this PR can be approved and merged at the earliest.

Copy link
Member

@fitzthum fitzthum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link

@cclaudio cclaudio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks @AdithyaKrishnan

@fitzthum fitzthum merged commit 55668c9 into confidential-containers:main Nov 19, 2024
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants