Skip to content

Commit

Permalink
KMS signing support
Browse files Browse the repository at this point in the history
Signed-off-by: Eugene Koira <[email protected]>
  • Loading branch information
eugkoira committed Apr 15, 2024
1 parent d8bb682 commit 3499f4b
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 121 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ vsock = "0.3"
vmm-sys-util = "0.12.1"
sha2 = "0.9.5"
hex = "0.4"
aws-config = "0.55"
tokio = { version = "1.20", features = ["rt-multi-thread"] }
aws-types = "0.55"

lazy_static = "1.4.0"

Expand Down
27 changes: 11 additions & 16 deletions enclave_build/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// Copyright 2019-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#![allow(clippy::too_many_arguments)]

Expand All @@ -12,7 +12,7 @@ mod yaml_generator;

use aws_nitro_enclaves_image_format::defs::{EifBuildInfo, EifIdentityInfo, EIF_HDR_ARCH_ARM64};
use aws_nitro_enclaves_image_format::utils::identity::parse_custom_metadata;
use aws_nitro_enclaves_image_format::utils::{EifBuilder, SignEnclaveInfo};
use aws_nitro_enclaves_image_format::utils::{EifBuilder, SignKeyDataInfo, SignKeyData};
use docker::DockerUtil;
use serde_json::json;
use sha2::Digest;
Expand All @@ -31,7 +31,7 @@ pub struct Docker2Eif<'a> {
linuxkit_path: String,
artifacts_prefix: String,
output: &'a mut File,
sign_info: Option<SignEnclaveInfo>,
sign_info: Option<SignKeyDataInfo>,
img_name: Option<String>,
img_version: Option<String>,
metadata_path: Option<String>,
Expand Down Expand Up @@ -68,8 +68,7 @@ impl<'a> Docker2Eif<'a> {
linuxkit_path: String,
output: &'a mut File,
artifacts_prefix: String,
certificate_path: &Option<String>,
key_path: &Option<String>,
sign_info: &Option<SignKeyDataInfo>,
img_name: Option<String>,
img_version: Option<String>,
metadata_path: Option<String>,
Expand Down Expand Up @@ -98,15 +97,6 @@ impl<'a> Docker2Eif<'a> {
}
}

let sign_info = match (certificate_path, key_path) {
(None, None) => None,
(Some(cert_path), Some(key_path)) => Some(
SignEnclaveInfo::new(cert_path, key_path)
.map_err(|err| Docker2EifError::SignImageError(format!("{err:?}")))?,
),
_ => return Err(Docker2EifError::SignArgsError),
};

Ok(Docker2Eif {
docker_image,
docker,
Expand All @@ -117,7 +107,7 @@ impl<'a> Docker2Eif<'a> {
linuxkit_path,
output,
artifacts_prefix,
sign_info,
sign_info: sign_info.clone(),
img_name,
img_version,
metadata_path,
Expand Down Expand Up @@ -275,10 +265,15 @@ impl<'a> Docker2Eif<'a> {
_ => return Err(Docker2EifError::UnsupportedArchError),
};

let sign_data = self.sign_info.as_ref().map(
|info| SignKeyData::new(info))
.transpose()
.map_err(|err| Docker2EifError::SignImageError(format!("{:?}", err)))?;

let mut build = EifBuilder::new(
Path::new(&self.kernel_img_path),
self.cmdline.clone(),
self.sign_info.clone(),
sign_data,
sha2::Sha384::new(),
flags,
self.generate_identity_info()?,
Expand Down
42 changes: 37 additions & 5 deletions enclave_build/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// Copyright 2019-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use clap::{App, AppSettings, Arg};
use std::fs::OpenOptions;

use aws_nitro_enclaves_image_format::generate_build_info;
use aws_nitro_enclaves_image_format::utils::{ SignKeyDataInfo, SignKeyInfo };
use enclave_build::Docker2Eif;

fn main() {
Expand Down Expand Up @@ -86,6 +87,18 @@ fn main() {
.help("Specify the path to the private-key")
.takes_value(true),
)
.arg(
Arg::with_name("kms-key-id")
.long("kms-key-id")
.help("Specify id of the KMS key")
.takes_value(true),
)
.arg(
Arg::with_name("kms-key-region")
.long("kms-key-region")
.help("Specify region in which the KMS key resides")
.takes_value(true),
)
.arg(
Arg::with_name("build")
.short('b')
Expand Down Expand Up @@ -133,9 +146,29 @@ fn main() {
let signing_certificate = matches
.value_of("signing_certificate")
.map(|val| val.to_string());
let private_key = matches
.value_of("private_certificate")
let kms_key_id = matches.value_of("kms-key-id");
let kms_key_region = matches.value_of("kms-key-region");
let private_key_path = matches
.value_of("private_key")
.map(|val| val.to_string());

let sign_key_info = match (signing_certificate, kms_key_id, private_key_path) {
(None, None, None) => None,
(Some(cert_path), None, Some(key_path)) =>
Some(SignKeyDataInfo {
cert_path: cert_path.to_string(),
key_info: SignKeyInfo::LocalPrivateKeyInfo { path: key_path.to_string() }
}),
(Some(cert_path), Some(key_id), None) =>
Some(SignKeyDataInfo {
cert_path: cert_path.to_string(),
key_info: SignKeyInfo::KmsKeyInfo { id: key_id.to_string(), region: kms_key_region.map(str::to_string) }
}),
(Some(_), None, None) => panic!("signing-certificate can be used only together with kms-key-id or private-key parameters"),
(None, Some(_), None) => panic!("signing-certificate is required together with kms-key-id parameters"),
(None, None, Some(_)) => panic!("signing-certificate is required together with private-key parameters"),
(_, Some(_), Some(_)) => panic!("kms-key-id and private-key parameters are mutually exclusive")
};
let img_name = matches.value_of("image_name").map(|val| val.to_string());
let img_version = matches.value_of("image_version").map(|val| val.to_string());
let metadata = matches.value_of("metadata").map(|val| val.to_string());
Expand All @@ -157,8 +190,7 @@ fn main() {
linuxkit_path.to_string(),
&mut output,
".".to_string(),
&signing_certificate,
&private_key,
&sign_key_info,
img_name,
img_version,
metadata,
Expand Down
65 changes: 47 additions & 18 deletions src/common/commands_parser.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// Copyright 2019-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#![deny(missing_docs)]
#![deny(warnings)]

use aws_nitro_enclaves_image_format::utils::{SignKeyInfo, SignKeyDataInfo};
use clap::ArgMatches;
use libc::VMADDR_CID_HOST;
#[cfg(test)]
Expand Down Expand Up @@ -104,10 +105,8 @@ pub struct BuildEnclavesArgs {
pub docker_dir: Option<String>,
/// The path where the enclave image file will be written to.
pub output: String,
/// The path to the signing certificate for signed enclaves.
pub signing_certificate: Option<String>,
/// The path to the private key for signed enclaves.
pub private_key: Option<String>,
/// Details of key and certificate used for signing the EIF
pub sign_info: Option<SignKeyDataInfo>,
/// The name of the enclave image.
pub img_name: Option<String>,
/// The version of the enclave image.
Expand All @@ -121,23 +120,46 @@ impl BuildEnclavesArgs {
pub fn new_with(args: &ArgMatches) -> NitroCliResult<Self> {
let signing_certificate = parse_signing_certificate(args);
let private_key = parse_private_key(args);

match (&signing_certificate, &private_key) {
(Some(_), None) => {
let kms_key_id = parse_kms_key_id(args);
let kms_key_region = parse_kms_key_region(args);

let sign_info = match (signing_certificate, kms_key_id, private_key) {
(None, None, None) => None,
(Some(cert_path), None, Some(key_path)) =>
Some(SignKeyDataInfo {
cert_path: cert_path.to_string(),
key_info: SignKeyInfo::LocalPrivateKeyInfo { path: key_path.to_string() }
}),
(Some(cert_path), Some(key_id), None) =>
Some(SignKeyDataInfo {
cert_path: cert_path.to_string(),
key_info: SignKeyInfo::KmsKeyInfo {
id: key_id.to_string(),
region: kms_key_region
}
}),
(Some(_), None, None) =>
return Err(new_nitro_cli_failure!(
"`private-key` or `kms-key-id` argument not found",
NitroCliErrorEnum::MissingArgument
)),
(None, Some(_), None) =>
return Err(new_nitro_cli_failure!(
"`private-key` argument not found",
"`signing-certificate` argument not found while `kms-key-id` is provided",
NitroCliErrorEnum::MissingArgument
)
.add_info(vec!["private-key"]))
}
(None, Some(_)) => {
.add_info(vec!["signing-certificate"])),
(None, None, Some(_)) =>
return Err(new_nitro_cli_failure!(
"`signing-certificate` argument not found",
"`signing-certificate` argument not found while `private-key` is provided",
NitroCliErrorEnum::MissingArgument
)
.add_info(vec!["signing-certificate"]))
}
_ => (),
.add_info(vec!["signing-certificate"])),
(_, Some(_), Some(_)) =>
return Err(new_nitro_cli_failure!(
"`kms-key-id` and `private-key` parameters are mutually exclusive",
NitroCliErrorEnum::ConflictingArgument
))
};

Ok(BuildEnclavesArgs {
Expand All @@ -156,8 +178,7 @@ impl BuildEnclavesArgs {
)
.add_info(vec!["output"])
})?,
signing_certificate,
private_key,
sign_info,
img_name: parse_image_name(args),
img_version: parse_image_version(args),
metadata: parse_metadata(args),
Expand Down Expand Up @@ -572,6 +593,14 @@ fn parse_error_code_str(args: &ArgMatches) -> NitroCliResult<String> {
Ok(error_code_str.to_string())
}

fn parse_kms_key_region(args: &ArgMatches) -> Option<String> {
args.value_of("kms-key-region").map(|val| val.to_string())
}

fn parse_kms_key_id(args: &ArgMatches) -> Option<String> {
args.value_of("kms-key-id").map(|val| val.to_string())
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
44 changes: 30 additions & 14 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// Copyright 2019-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#![deny(missing_docs)]
#![deny(warnings)]
Expand All @@ -17,6 +17,7 @@ pub mod utils;

use aws_nitro_enclaves_image_format::defs::eif_hasher::EifHasher;
use aws_nitro_enclaves_image_format::utils::eif_reader::EifReader;
use aws_nitro_enclaves_image_format::utils::SignKeyDataInfo;
use aws_nitro_enclaves_image_format::{generate_build_info, utils::get_pcrs};
use log::{debug, info};
use sha2::{Digest, Sha384};
Expand Down Expand Up @@ -56,8 +57,7 @@ pub fn build_enclaves(args: BuildEnclavesArgs) -> NitroCliResult<()> {
&args.docker_uri,
&args.docker_dir,
&args.output,
&args.signing_certificate,
&args.private_key,
&args.sign_info,
&args.img_name,
&args.img_version,
&args.metadata,
Expand All @@ -71,8 +71,7 @@ pub fn build_from_docker(
docker_uri: &str,
docker_dir: &Option<String>,
output_path: &str,
signing_certificate: &Option<String>,
private_key: &Option<String>,
sign_info: &Option<SignKeyDataInfo>,
img_name: &Option<String>,
img_version: &Option<String>,
metadata_path: &Option<String>,
Expand Down Expand Up @@ -134,8 +133,7 @@ pub fn build_from_docker(
format!("{}/linuxkit", blobs_path),
&mut file_output,
artifacts_path()?,
signing_certificate,
private_key,
sign_info,
img_name.clone(),
img_version.clone(),
metadata_path.clone(),
Expand Down Expand Up @@ -736,12 +734,6 @@ macro_rules! create_app {
.help("Local path to developer's X509 signing certificate.")
.takes_value(true),
)
.arg(
Arg::with_name("private-key")
.long("private-key")
.help("Local path to developer's Eliptic Curve private key.")
.takes_value(true),
)
.arg(
Arg::with_name("image_name")
.long("name")
Expand All @@ -759,6 +751,30 @@ macro_rules! create_app {
.long("metadata")
.help("Path to JSON containing the custom metadata provided by the user.")
.takes_value(true),
)
.arg(
Arg::with_name("private-key")
.long("private-key")
.help("Local path to developer's Eliptic Curve private key.")
.takes_value(true)
.conflicts_with("kms-key-id")
.conflicts_with("kms-key-region"),
)
.arg(
Arg::with_name("kms-key-region")
.long("kms-key-region")
.help("The region in which the KMS key resides.")
.takes_value(true)
.required(false)
.conflicts_with("private-key"),
)
.arg(
Arg::with_name("kms-key-id")
.long("kms-key-id")
.help("The KMS key ID")
.takes_value(true)
.required(false)
.conflicts_with("private-key"),
),
)
.subcommand(
Expand Down Expand Up @@ -839,5 +855,5 @@ macro_rules! create_app {
.required(true),
),
)
};
};
}
Loading

0 comments on commit 3499f4b

Please sign in to comment.