Skip to content

Commit

Permalink
clap-migration: Moving from StructOpt to Clap
Browse files Browse the repository at this point in the history
As StructOpt is deprecated and no longer
maintained, we need to switch to clap.

Signed-off-by: Larry Dewey <larry.dewey@amd.com>
  • Loading branch information
larrydewey committed Apr 23, 2024
1 parent cc5f414 commit 285836c
Show file tree
Hide file tree
Showing 9 changed files with 362 additions and 451 deletions.
582 changes: 248 additions & 334 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
54 changes: 30 additions & 24 deletions src/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ 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 {
Vcek,
Vlek,
Expand All @@ -48,11 +48,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 +109,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 to pull the VLEK certificate chain instead of VCEK.
#[arg(short, long, default_value_t = Endorsement::Vcek)]
pub endorser: Endorsement,
}

Expand Down Expand Up @@ -194,20 +198,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(short, long, value_name = "FILE", 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(short, long, value_name = "ROOT_KEY", 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 = "INTEGER", default_value = "Some(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")]
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(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 = "INTEGER")]
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 285836c

Please sign in to comment.