Skip to content

Commit

Permalink
Merge pull request #52 from larrydewey/clap-migration
Browse files Browse the repository at this point in the history
clap-migration: Moving from StructOpt to Clap
  • Loading branch information
DGonzalezVillal authored Apr 24, 2024
2 parents cc5f414 + 1fa85f9 commit c47fa28
Show file tree
Hide file tree
Showing 9 changed files with 367 additions and 453 deletions.
586 changes: 250 additions & 336 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ default = []
hyperv = ["tss-esapi"]

[dependencies]
structopt = "0.3"
clap = { version = "<4.5", features = [ "derive" ] }
env_logger = "0.10.0"
anyhow = "1.0.69"
sev = { version = "^3.1.1", default-features = false, features = ['openssl','snp']}
Expand Down
17 changes: 9 additions & 8 deletions src/certs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ pub struct CertPaths {
pub ask_path: PathBuf,
pub vek_path: PathBuf,
}
#[derive(StructOpt, Clone, Copy)]

#[derive(ValueEnum, Clone, Copy)]
pub enum CertFormat {
#[structopt(about = "Certificates are encoded in PEM format.")]
/// Certificates are encoded in PEM format.
Pem,

#[structopt(about = "Certificates are encoded in DER format.")]
/// Certificates are encoded in DER format.
Der,
}

Expand Down Expand Up @@ -164,14 +165,14 @@ pub fn write_cert(
Ok(())
}

#[derive(StructOpt)]
#[derive(Parser)]
pub struct CertificatesArgs {
#[structopt(help = "Specify encoding to use for certificates. [PEM | DER]")]
/// Specify encoding to use for certificates.
#[arg(value_name = "encoding", required = true)]
pub encoding: CertFormat,

#[structopt(
help = "Directory to store certificates in. Required if requesting an extended-report."
)]
/// Directory to store certificates in. Required if requesting an extended-report.
#[arg(value_name = "certs-dir", required = true)]
pub certs_dir: PathBuf,
}

Expand Down
16 changes: 9 additions & 7 deletions src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
use super::*;
use std::path::PathBuf;

#[derive(StructOpt)]
#[derive(Subcommand)]
pub enum DisplayCmd {
#[structopt(about = "Display an attestation report in console.")]
/// Display an attestation report in console.
Report(report_display::Args),

#[structopt(about = "Display the derived key in console.")]
/// Display the derived key in console.
Key(key_display::Args),
}

Expand All @@ -22,9 +22,10 @@ pub fn cmd(cmd: DisplayCmd, quiet: bool) -> Result<()> {
mod report_display {
use super::*;

#[derive(StructOpt)]
#[derive(Parser)]
pub struct Args {
#[structopt(help = "Path to attestation report to display.")]
/// Path to attestation report to display.
#[arg(value_name = "att-report-path", required = true)]
pub att_report_path: PathBuf,
}

Expand All @@ -44,9 +45,10 @@ mod report_display {
mod key_display {
use super::*;

#[derive(StructOpt)]
#[derive(Parser)]
pub struct Args {
#[structopt(help = "Path of key to be displayed.")]
/// Path of key to be displayed.
#[arg(value_name = "key-path", required = true)]
pub key_path: PathBuf,
}

Expand Down
57 changes: 33 additions & 24 deletions src/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@ use sev::firmware::host::CertType;

use certs::{write_cert, CertFormat};

#[derive(StructOpt)]
#[derive(Subcommand)]
pub enum FetchCmd {
#[structopt(about = "Fetch the certificate authority (ARK & ASK) from the KDS.")]
/// Fetch the certificate authority (ARK & ASK) from the KDS.
CA(cert_authority::Args),

#[structopt(about = "Fetch the VCEK from the KDS.")]
/// Fetch the VCEK from the KDS.
Vcek(vcek::Args),
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(ValueEnum, Debug, Clone, PartialEq, Eq)]
pub enum Endorsement {
/// Versioned Chip Endorsement Key
Vcek,

/// Versioned Loaded Endorsement Key
Vlek,
}

Expand All @@ -48,11 +51,18 @@ impl FromStr for Endorsement {
}
}
}
#[derive(Debug, Clone)]
#[derive(ValueEnum, Debug, Clone)]
pub enum ProcType {
/// 3rd Gen AMD EPYC Processor (Standard)
Milan,

/// 4th Gen AMD EPYC Processor (Standard)
Genoa,

/// 4th Gen AMD EPYC Processor (Performance)
Bergamo,

/// 4th Gen AMD EPYC Processor (Edge)
Siena,
}

Expand Down Expand Up @@ -102,25 +112,22 @@ mod cert_authority {
use openssl::x509::X509;
use reqwest::StatusCode;

#[derive(StructOpt)]
#[derive(Parser)]
pub struct Args {
#[structopt(help = "Specify encoding to use for certificates. [PEM | DER]")]
/// Specify encoding to use for certificates.
#[arg(value_name = "encoding", required = true)]
pub encoding: CertFormat,

#[structopt(
help = "Specify the processor model for the certificate chain. [Milan | Genoa]"
)]
/// Specify the processor model for the certificate chain.
#[arg(value_name = "processor-model", required = true)]
pub processor_model: ProcType,

#[structopt(help = "Directory to store the certificates in.")]
/// Directory to store the certificates in.
#[arg(value_name = "certs-dir", required = true)]
pub certs_dir: PathBuf,

#[structopt(
long,
short,
default_value = "vcek",
help = "Specify to pull the VLEK certificate chain instead of VCEK."
)]
/// Specify which endorsement certificate chain to pull, either VCEK or VLEK.
#[arg(short, long, value_name = "endorser", default_value_t = Endorsement::Vcek)]
pub endorser: Endorsement,
}

Expand Down Expand Up @@ -194,20 +201,22 @@ mod vcek {

use super::*;

#[derive(StructOpt)]
#[derive(Parser)]
pub struct Args {
#[structopt(help = "Specify encoding to use for certificates. [PEM | DER]")]
/// Specify encoding to use for certificates.
#[arg(value_name = "encoding", required = true)]
pub encoding: CertFormat,

#[structopt(
help = "Specify the processor model for the certificate chain. [Milan | Genoa]"
)]
/// Specify the processor model for the certificate chain.
#[arg(value_name = "processor-model", required = true)]
pub processor_model: ProcType,

#[structopt(help = "Directory to store the certificates in.")]
/// Directory to store the certificates in.
#[arg(value_name = "certs-dir", required = true)]
pub certs_dir: PathBuf,

#[structopt(help = "Path to attestation report to use to request VCEK.")]
/// Path to attestation report to use to request VCEK.
#[arg(value_name = "att-report-path", required = true)]
pub att_report_path: PathBuf,
}

Expand Down
40 changes: 14 additions & 26 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,31 @@ use sev::firmware::guest::{DerivedKey, Firmware, GuestFieldSelect};
use std::io::Read;
use std::{fs, path::PathBuf};

#[derive(StructOpt)]
#[derive(Parser)]
pub struct KeyArgs {
#[structopt(help = "This is the path where the derived key will be saved")]
/// This is the path where the derived key will be saved.
#[arg(value_name = "key-path", required = true)]
pub key_path: PathBuf,

#[structopt(
help = "This is the root key from which to derive the key. Input either VCEK or VMRK."
)]
/// This is the root key from which to derive the key. Input either VCEK or VMRK.
#[arg(value_name = "root-key-select", required = true)]
pub root_key_select: String,

#[structopt(
long = "vmpl",
short,
help = "Specify VMPL level the Guest is running on. Defaults to 1."
)]
/// Specify an integer VMPL level between 0 and 3 that the Guest is running on.
#[arg(short, long, value_name = "vmpl", default_value = "1")]
pub vmpl: Option<u32>,

#[structopt(
long = "guest_field_select",
short = "g",
help = "Specify which Guest Field Select bits to enable. It is a 6 digit binary string. For each bit, 0 denotes off and 1 denotes on.
The least significant (rightmost) bit is Guest Policy followed by Image ID, Family ID, Measurement, SVN, TCB Version which is the most significant (leftmost) bit. "
)]
/// Specify which Guest Field Select bits to enable. It is a 6 digit binary string. For each bit, 0 denotes off and 1 denotes on.
/// The least significant (rightmost) bit is Guest Policy followed by Image ID, Family ID, Measurement, SVN, TCB Version which is the most significant (leftmost) bit.
#[arg(short, long = "guest_file_select", value_name = "######")]
pub gfs: Option<String>,

#[structopt(
long = "guest_svn",
short = "s",
help = "Specify the guest SVN to mix into the key. Must not exceed the guest SVN provided at launch in the ID block."
)]
/// Specify the guest SVN to mix into the key. Must not exceed the guest SVN provided at launch in the ID block.
#[arg(short = 's', long = "guest_svn")]
pub gsvn: Option<u32>,

#[structopt(
long = "tcb_version",
short,
help = "Specify the TCB version to mix into the derived key. Must not exceed CommittedTcb"
)]
/// Specify the TCB version to mix into the derived key. Must not exceed CommittedTcb.
#[arg(short, long = "tcb_version")]
pub tcbv: Option<u64>,
}

Expand Down
37 changes: 20 additions & 17 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,50 +20,53 @@ use report::ReportArgs;
use verify::VerifyCmd;

use anyhow::{Context, Result};
use structopt::StructOpt;
use clap::{arg, Parser, Subcommand, ValueEnum};

const VERSION: &str = env!("CARGO_PKG_VERSION");
const AUTHORS: &str = env!("CARGO_PKG_AUTHORS");

#[derive(StructOpt)]
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct SnpGuest {
#[structopt(subcommand)]
#[command(subcommand)]
pub cmd: SnpGuestCmd,

#[structopt(short, long, help = "Don't print anything to the console")]
/// Don't print anything to the console
#[arg(short, long, default_value_t = false)]
pub quiet: bool,
}

#[allow(clippy::large_enum_variant)]
#[derive(StructOpt)]
#[structopt(author = AUTHORS, version = VERSION, about = "Utilities for managing the SNP Guest environment")]
/// Utilities for managing the SNP Guest environment
#[derive(Subcommand)]
enum SnpGuestCmd {
#[structopt(about = "Report command to request an attestation report.")]
/// Report command to request an attestation report.
Report(ReportArgs),

#[structopt(about = "Certificates command to request cached certificates from the AMD PSP")]
/// Certificates command to request cached certificates from the AMD PSP.
Certificates(CertificatesArgs),

#[structopt(about = "Fetch command to request certificates.")]
/// Fetch command to request certificates.
#[command(subcommand)]
Fetch(FetchCmd),

#[structopt(about = "Verify command to verify certificates and attestation report.")]
/// Verify command to verify certificates and attestation report.
#[command(subcommand)]
Verify(VerifyCmd),

#[structopt(about = "Display command to display files in human readable form.")]
/// Display command to display files in human readable form.
#[command(subcommand)]
Display(DisplayCmd),

#[structopt(about = "Key command to generate derived key.")]
/// Key command to generate derived key.
Key(KeyArgs),

#[structopt(about = "Probe system for SEV-SNP support")]
/// Probe system for SEV-SNP support.
#[command(subcommand)]
Ok,
}

fn main() -> Result<()> {
env_logger::init();

let snpguest = SnpGuest::from_args();
let snpguest = SnpGuest::parse();

#[cfg(feature = "hyperv")]
let hv = hyperv::present();
Expand Down
36 changes: 16 additions & 20 deletions src/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,31 @@ pub fn create_random_request() -> [u8; 64] {
data
}

#[derive(StructOpt)]
/// Report command to request an attestation report.
#[derive(Parser)]
pub struct ReportArgs {
#[structopt(help = "File to write the attestation report to.")]
/// File to write the attestation report to.
#[arg(value_name = "att-report-path", required = true)]
pub att_report_path: PathBuf,

#[structopt(
long = "random",
short,
help = "Use random data for attestation report request. Writes data to ./random-request-file.txt by default, use --request to specify where to write data."
)]
/// Use random data for attestation report request. Writes data
/// to ./random-request-file.txt by default, use --request to specify
/// where to write data.
#[arg(short, long, default_value_t = false, conflicts_with = "platform")]
pub random: bool,

#[structopt(
long = "vmpl",
short,
help = "Specify VMPL level the Guest is running on. Defaults to 1."
)]
/// Specify an integer VMPL level between 0 and 3 that the Guest is running on.
#[arg(short, long, default_value = "1", value_name = "vmpl")]
pub vmpl: Option<u32>,

#[structopt(
help = "Provide file with data for attestation-report request. If provided with random flag, then the random data will be written in the provided path."
)]
/// Provide file with data for attestation-report request. If provided
/// with random flag, then the random data will be written in the
/// provided path.
#[arg(value_name = "request-file", required = true)]
pub request_file: PathBuf,

#[structopt(
long,
short,
help = "Expect that the 64-byte report data will already be provided by the platform provider."
)]
/// Expect that the 64-byte report data will already be provided by the platform provider.
#[arg(short, long, conflicts_with = "random")]
pub platform: bool,
}

Expand Down
Loading

0 comments on commit c47fa28

Please sign in to comment.