Skip to content

Commit

Permalink
image-rs: fix integration test
Browse files Browse the repository at this point in the history
We used to request AA for image decryption keys and public keys, etc.
Now we are using CDH for these non-attestation APIs.

This patch brings a workaround that make the test environment look like
it is a "peer pod" environment, then the CDH will read aa_kbc_params
from a file rather than kernel cmdline.

In future, we will define a launch configuration file for CDH. After
that, this workaround can be depreciated.

Signed-off-by: Xynnn007 <[email protected]>
  • Loading branch information
Xynnn007 authored and jialez0 committed Jan 12, 2024
1 parent 85ad504 commit ee6306c
Show file tree
Hide file tree
Showing 13 changed files with 120 additions and 118 deletions.
2 changes: 1 addition & 1 deletion image-rs/protos/getresource.proto
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
syntax = "proto3";

package getresource;
package api;

message GetResourceRequest {
string ResourcePath = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@ set -o errexit
set -o nounset
set -o pipefail

parameters=("KBC=offline_fs_kbc")

[ -n "${BASH_VERSION:-}" ] && set -o errtrace
[ -n "${DEBUG:-}" ] && set -o xtrace
if [[ -n "${TTRPC:-}" ]]; then
parameters+=("ttrpc=true")
dest_dir_suffix="ttrpc"
else
dest_dir_suffix="grpc"
Expand All @@ -23,12 +20,12 @@ fi
source $HOME/.cargo/env

SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
AA_DIR=$SCRIPT_DIR/../../attestation-agent
CDH_DIR=$SCRIPT_DIR/../../confidential-data-hub

pushd $AA_DIR
pushd $CDH_DIR

make "${parameters[@]}"
make
make DESTDIR="${SCRIPT_DIR}/${dest_dir_suffix}" install

file "${SCRIPT_DIR}/${dest_dir_suffix}/attestation-agent"
file "${SCRIPT_DIR}/${dest_dir_suffix}/confidential-data-hub"
popd
10 changes: 9 additions & 1 deletion image-rs/scripts/install_offline_fs_kbc_files.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,19 @@ if [ "${1:-}" = "install" ]; then
sudo install --owner=root --group=root --mode=0640 "${test_resource_record}" "${target_resource_record_path}"
sudo install --owner=root --group=root --mode=0640 "${test_keys}" "${target_keys_path}"

# This is a workaround for CDH to read the aa_kbc_params from a
# file rather than kernel commandline. This makes a fake environment
# that CDH will recognize as it is in "peer pod", so aa_kbc param will
# be read from a file.
# TODO: when CDH has its own configuration launch file, we can
# promote this way.
mkdir -p /run/peerpod
touch /run/peerpod/daemon.json
echo "aa_kbc_params = \"offline_fs_kbc::null\"" > /etc/agent-config.toml
elif [ "${1:-}" = "clean" ]; then
sudo rm "${target_resource_record_path}"
sudo rm "${target_keys_path}"

else
echo >&2 "ERROR: Wrong or missing argument: '${1:-}'"

fi
2 changes: 1 addition & 1 deletion image-rs/src/resource/kbs/grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ mod get_resource {
#![allow(unknown_lints)]
#![allow(clippy::derive_partial_eq_without_eq)]
#![allow(clippy::redundant_async_block)]
tonic::include_proto!("getresource");
tonic::include_proto!("api");
}

/// Attestation Agent's GetResource gRPC address.
Expand Down
19 changes: 1 addition & 18 deletions image-rs/src/resource/kbs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,27 +119,10 @@ impl Protocol for SecureChannel {
return Ok(res);
}

// Related issue: https://github.com/confidential-containers/attestation-agent/issues/130
//
// Now we use `aa_kbc_params` to specify the KBC and KBS URI
// used in CoCo System. Different KBCs are initialized in AA lazily due
// to the kbs uri information included in a `download_confidential_resource` or
// `decrypt_image_layer_annotation`. The kbs uri input to the two APIs
// are from `aa_kbc_params` but not the kbs uri in a resource uri.
// Thus as a temporary solution, we need to overwrite the
// kbs uri field using the one included in `aa_kbc_params`, s.t.
// `kbs_uri` of [`SecureChannel`].
let resource_path = get_resource_path(resource_uri)?;

let res = self.client.get_resource(&resource_path).await?;
let res = self.client.get_resource(resource_uri).await?;

let path = self.get_filepath(resource_uri);
fs::write(path, &res).await?;
Ok(res)
}
}

fn get_resource_path(uri: &str) -> Result<String> {
let path = url::Url::parse(uri)?;
Ok(path.path().to_string())
}
22 changes: 11 additions & 11 deletions image-rs/src/resource/kbs/ttrpc_proto/getresource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@
/// of protobuf runtime.
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_3_0;

// @@protoc_insertion_point(message:getresource.GetResourceRequest)
// @@protoc_insertion_point(message:api.GetResourceRequest)
#[derive(PartialEq,Clone,Default,Debug)]
pub struct GetResourceRequest {
// message fields
// @@protoc_insertion_point(field:getresource.GetResourceRequest.ResourcePath)
// @@protoc_insertion_point(field:api.GetResourceRequest.ResourcePath)
pub ResourcePath: ::std::string::String,
// special fields
// @@protoc_insertion_point(special_field:getresource.GetResourceRequest.special_fields)
// @@protoc_insertion_point(special_field:api.GetResourceRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}

Expand Down Expand Up @@ -147,14 +147,14 @@ impl ::protobuf::reflect::ProtobufValue for GetResourceRequest {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}

// @@protoc_insertion_point(message:getresource.GetResourceResponse)
// @@protoc_insertion_point(message:api.GetResourceResponse)
#[derive(PartialEq,Clone,Default,Debug)]
pub struct GetResourceResponse {
// message fields
// @@protoc_insertion_point(field:getresource.GetResourceResponse.Resource)
// @@protoc_insertion_point(field:api.GetResourceResponse.Resource)
pub Resource: ::std::vec::Vec<u8>,
// special fields
// @@protoc_insertion_point(special_field:getresource.GetResourceResponse.special_fields)
// @@protoc_insertion_point(special_field:api.GetResourceResponse.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}

Expand Down Expand Up @@ -270,11 +270,11 @@ impl ::protobuf::reflect::ProtobufValue for GetResourceResponse {
}

static file_descriptor_proto_data: &'static [u8] = b"\
\n\x11getresource.proto\x12\x0bgetresource\"8\n\x12GetResourceRequest\
\x12\"\n\x0cResourcePath\x18\x01\x20\x01(\tR\x0cResourcePath\"1\n\x13Get\
ResourceResponse\x12\x1a\n\x08Resource\x18\x01\x20\x01(\x0cR\x08Resource\
2f\n\x12GetResourceService\x12P\n\x0bGetResource\x12\x1f.getresource.Get\
ResourceRequest\x1a\x20.getresource.GetResourceResponseb\x06proto3\
\n\x11getresource.proto\x12\x03api\"8\n\x12GetResourceRequest\x12\"\n\
\x0cResourcePath\x18\x01\x20\x01(\tR\x0cResourcePath\"1\n\x13GetResource\
Response\x12\x1a\n\x08Resource\x18\x01\x20\x01(\x0cR\x08Resource2V\n\x12\
GetResourceService\x12@\n\x0bGetResource\x12\x17.api.GetResourceRequest\
\x1a\x18.api.GetResourceResponseb\x06proto3\
";

/// `FileDescriptorProto` object which was a source for this generated file
Expand Down
6 changes: 3 additions & 3 deletions image-rs/src/resource/kbs/ttrpc_proto/getresource_ttrpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl GetResourceServiceClient {

pub async fn get_resource(&self, ctx: ttrpc::context::Context, req: &super::getresource::GetResourceRequest) -> ::ttrpc::Result<super::getresource::GetResourceResponse> {
let mut cres = super::getresource::GetResourceResponse::new();
::ttrpc::async_client_request!(self, ctx, req, "getresource.GetResourceService", "GetResource", cres);
::ttrpc::async_client_request!(self, ctx, req, "api.GetResourceService", "GetResource", cres);
}
}

Expand All @@ -52,7 +52,7 @@ impl ::ttrpc::r#async::MethodHandler for GetResourceMethod {
#[async_trait]
pub trait GetResourceService: Sync {
async fn get_resource(&self, _ctx: &::ttrpc::r#async::TtrpcContext, _: super::getresource::GetResourceRequest) -> ::ttrpc::Result<super::getresource::GetResourceResponse> {
Err(::ttrpc::Error::RpcStatus(::ttrpc::get_status(::ttrpc::Code::NOT_FOUND, "/getresource.GetResourceService/GetResource is not supported".to_string())))
Err(::ttrpc::Error::RpcStatus(::ttrpc::get_status(::ttrpc::Code::NOT_FOUND, "/api.GetResourceService/GetResource is not supported".to_string())))
}
}

Expand All @@ -64,6 +64,6 @@ pub fn create_get_resource_service(service: Arc<Box<dyn GetResourceService + Sen
methods.insert("GetResource".to_string(),
Box::new(GetResourceMethod{service: service.clone()}) as Box<dyn ::ttrpc::r#async::MethodHandler + Send + Sync>);

ret.insert("getresource.GetResourceService".to_string(), ::ttrpc::r#async::Service{ methods, streams });
ret.insert("api.GetResourceService".to_string(), ::ttrpc::r#async::Service{ methods, streams });
ret
}
2 changes: 1 addition & 1 deletion image-rs/test_data/ocicrypt_keyprovider_ttrpc.conf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"key-providers": {
"attestation-agent": {
"ttrpc": "unix:///run/confidential-containers/attestation-agent/keyprovider.sock"
"ttrpc": "unix:///run/confidential-containers/cdh.sock"
}
}
}
59 changes: 25 additions & 34 deletions image-rs/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const OFFLINE_FS_KBC_RESOURCE_SCRIPT: &str = "scripts/install_offline_fs_kbc_fil
pub const AA_PARAMETER: &str = "provider:attestation-agent:offline_fs_kbc::null";

/// Attestation Agent Offline Filesystem KBC resources file for general tests that use images stored in the quay.io registry
pub const AA_OFFLINE_FS_KBC_RESOURCES_FILE: &str = "aa-offline_fs_kbc-resources.json";
pub const OFFLINE_FS_KBC_RESOURCES_FILE: &str = "aa-offline_fs_kbc-resources.json";

/// Attestation Agent Offline Filesystem KBC resources file for XRSS tests
#[cfg(feature = "signature-simple-xrss")]
Expand Down Expand Up @@ -62,70 +62,61 @@ pub async fn clean() {
.expect("Clean GPG signature file failed.");
}

pub async fn start_attestation_agent() -> Result<Child> {
pub async fn start_confidential_data_hub() -> Result<Child> {
let script_dir = format!("{}/{}", std::env!("CARGO_MANIFEST_DIR"), "scripts");
cfg_if::cfg_if! {
if #[cfg(feature = "keywrap-ttrpc")] {
let aa_path = format!("{}/ttrpc/{}", script_dir, "attestation-agent");
let cdh_path = format!("{}/ttrpc/{}", script_dir, "confidential-data-hub");
} else {
let aa_path = format!("{}/grpc/{}", script_dir, "attestation-agent");
let cdh_path = format!("{}/grpc/{}", script_dir, "confidential-data-hub");
}
};
println!("aa_path: {}", aa_path);
println!("cdh_path: {}", cdh_path);
println!("script_dir: {}", script_dir);

if !Path::new(&aa_path).exists() {
let script_path = format!("{}/{}", script_dir, "build_attestation_agent.sh");
if !Path::new(&cdh_path).exists() {
let script_path = format!("{}/{}", script_dir, "build_confidential_data_hub.sh");
cfg_if::cfg_if! {
if #[cfg(feature = "keywrap-ttrpc")] {
let output = Command::new(script_path)
.env("TTRPC", "1")
.output()
.await
.expect("Failed to build attestation-agent");
println!("build ttrpc attestation-agent: {:?}", output);
.expect("Failed to build confidential-data-hub");
println!("build ttrpc confidential-data-hub: {:?}", output);
} else {
let output = Command::new(script_path)
.output()
.await
.expect("Failed to build attestation-agent");
println!("build grpc attestation-agent: {:?}", output);
.expect("Failed to build confidential-data-hub");
println!("build grpc confidential-data-hub: {:?}", output);
}
}
}

cfg_if::cfg_if! {
if #[cfg(feature = "keywrap-ttrpc")] {
let mut aa = Command::new(aa_path)
.kill_on_drop(true)
.args([
"--keyprovider_sock",
"unix:///run/confidential-containers/attestation-agent/keyprovider.sock",
"--getresource_sock",
"unix:///run/confidential-containers/attestation-agent/getresource.sock"
])
.spawn()
.expect("Failed to start ttrpc attestation-agent");
let mut cdh = Command::new(cdh_path)
.kill_on_drop(true)
.args(["-s", "unix:///run/confidential-containers/cdh.sock"])
.spawn()
.expect("Failed to start confidential-data-hub");
} else {
let mut aa = Command::new(aa_path)
.kill_on_drop(true)
.args([
"--keyprovider_sock",
"127.0.0.1:50000",
"--getresource_sock",
"127.0.0.1:50001"
])
.spawn()
.expect("Failed to start grpc attestation-agent");
// TODO: implement this after CDH supports gRPC
let mut cdh = Command::new(cdh_path)
.kill_on_drop(true)
.args(["-s", "unix:///run/confidential-containers/cdh.sock"])
.spawn()
.expect("Failed to start confidential-data-hub");
}
};

// Leave some time to let fork-ed AA process to be ready
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
if (aa.try_wait()?).is_some() {
panic!("Attestation Agent failed to start");
if (cdh.try_wait()?).is_some() {
panic!("Confidential Data Hub failed to start");
}
Ok(aa)
Ok(cdh)
}

pub fn umount_bundle(bundle_dir: &tempfile::TempDir) {
Expand Down
27 changes: 15 additions & 12 deletions image-rs/tests/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,29 @@
// SPDX-License-Identifier: Apache-2.0
//

#[cfg(feature = "getresource")]
#[cfg(all(feature = "getresource", feature = "keywrap-ttrpc"))]
use image_rs::image::ImageClient;
#[cfg(feature = "getresource")]
#[cfg(all(feature = "getresource", feature = "keywrap-ttrpc"))]
use rstest::rstest;
#[cfg(feature = "getresource")]
#[cfg(all(feature = "getresource", feature = "keywrap-ttrpc"))]
use serial_test::serial;

pub mod common;

#[cfg(feature = "getresource")]
// TODO: add `keywrap-grpc` integration test after CDH supports grpc mode
#[cfg(all(feature = "getresource", feature = "keywrap-ttrpc"))]
#[rstest]
#[case("liudalibj/private-busy-box", "kbs:///default/credential/test")]
#[case("quay.io/liudalibj/private-busy-box", "kbs:///default/credential/test")]
#[tokio::test]
#[serial]
async fn test_use_credential(#[case] image_ref: &str, #[case] auth_file_uri: &str) {
common::prepare_test(common::AA_OFFLINE_FS_KBC_RESOURCES_FILE).await;
common::prepare_test(common::OFFLINE_FS_KBC_RESOURCES_FILE).await;

// Init AA
let _aa = common::start_attestation_agent()
// // Init CDH
let _cdh = common::start_confidential_data_hub()
.await
.expect("Failed to start attestation agent!");

// AA parameter
let aa_parameters = common::AA_PARAMETER;
.expect("Failed to start confidential data hub!");

// clean former test files, which is needed to prevent
// lint from warning dead code.
Expand All @@ -50,7 +48,12 @@ async fn test_use_credential(#[case] image_ref: &str, #[case] auth_file_uri: &st
let bundle_dir = tempfile::tempdir().unwrap();

let res = image_client
.pull_image(image_ref, bundle_dir.path(), &None, &Some(aa_parameters))
.pull_image(
image_ref,
bundle_dir.path(),
&None,
&Some(common::AA_PARAMETER),
)
.await;
if cfg!(all(feature = "snapshot-overlayfs",)) {
assert!(res.is_ok(), "{:?}", res);
Expand Down
Loading

0 comments on commit ee6306c

Please sign in to comment.