Skip to content

Commit

Permalink
cdh: add one-shot CDH
Browse files Browse the repository at this point in the history
One-shot CDH is a different version of CDH that will run and do the
operation one time then exit. This is useful in scenarios where CDH
cannot run as a long term daemon.

Signed-off-by: Xynnn007 <[email protected]>
  • Loading branch information
Xynnn007 committed Oct 29, 2024
1 parent 1a6bb93 commit 962d4c2
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 1 deletion.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ A tool for exercising CDH endpoints
[CDH Go Client](confidential-data-hub/golang)
A Go tool for exercising CDH endpoints

[CDH (One Shot)](confidential-data-hub/hub/src/bin/cdh-oneshot.rs)
One Shot version of CDH

[CoCo Keyprovider](attestation-agent/coco_keyprovider)
Keyprovider endpoint for encrypting images

Expand Down
8 changes: 7 additions & 1 deletion confidential-data-hub/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ $(info DEBIANOS is: $(DEBIANOS))
TARGET_DIR := ../target
BIN_NAME := confidential-data-hub

ONE_SHOT ?= false

SOURCE_ARCH := $(shell uname -m)
RPC ?= ttrpc
ARCH ?= $(shell uname -m)
Expand All @@ -27,7 +29,11 @@ features ?=

binary_name ?=

ifeq ($(RPC), ttrpc)
ifeq ($(ONE_SHOT), true)
binary = --bin cdh-oneshot
features += bin
binary_name = cdh-oneshot
else ifeq ($(RPC), ttrpc)
binary = --bin ttrpc-cdh
features += bin,ttrpc
binary_name = ttrpc-cdh
Expand Down
5 changes: 5 additions & 0 deletions confidential-data-hub/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ If you don't want to include any RESOURCE_PROVIDER(s):
make RESOURCE_PROVIDER=none
```

The default CDH runs as a service daemon. If you want to build CDH to an one-shot binary (run once and exit), use flag `ONE_SHOT=true`
```shell
make ONE_SHOT=true
```

Please refer to [Supported Features](#supported-features) for the options.

### Supported Features
Expand Down
4 changes: 4 additions & 0 deletions confidential-data-hub/hub/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ required-features = ["bin", "ttrpc"]
name = "grpc-cdh-tool"
required-features = ["bin", "grpc"]

[[bin]]
name = "cdh-oneshot"
required-features = ["bin"]

[dependencies]
anyhow = { workspace = true, optional = true }
async-trait.workspace = true
Expand Down
186 changes: 186 additions & 0 deletions confidential-data-hub/hub/src/bin/cdh-oneshot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Copyright (c) 2024 Alibaba Cloud
//
// SPDX-License-Identifier: Apache-2.0
//

//! This is a one-shot version of CDH

#![allow(non_snake_case)]

use base64::{engine::general_purpose::STANDARD, Engine};
use clap::{Args, Parser, Subcommand};
use confidential_data_hub::{hub::Hub, CdhConfig, DataHub};
use log::warn;
use storage::volume_type::Storage;

#[derive(Parser)]
#[command(name = "cdh_oneshot")]
#[command(bin_name = "cdh_oneshot")]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(subcommand)]
operation: Operation,

/// CDH's config path
#[arg(short, long)]
config: Option<String>,

/// Retries times
#[arg(short, long, default_value = "3")]
retry: u32,
}

#[derive(Subcommand)]
#[command(author, version, about, long_about = None)]
enum Operation {
/// Unseal the given sealed secret
UnsealSecret(UnsealSecretArgs),

/// Unwrap the image encryption key
UnwrapKey(UnwrapKeyArgs),

/// Get Resource from KBS
GetResource(GetResourceArgs),

/// Secure mount
SecureMount(SecureMountArgs),

/// Pull image
PullImage(PullImageArgs),
}

#[derive(Args)]
#[command(author, version, about, long_about = None)]
struct UnsealSecretArgs {
/// path to the file which contains the sealed secret
#[arg(short, long)]
secret_path: String,
}

#[derive(Args)]
#[command(author, version, about, long_about = None)]
struct UnwrapKeyArgs {
/// path to the file which contains the AnnotationPacket
#[arg(short, long)]
annotation_path: String,
}

#[derive(Args)]
#[command(author, version, about, long_about = None)]
struct GetResourceArgs {
/// KBS Resource URI to the target resource
#[arg(short, long)]
resource_uri: String,
}

#[derive(Args)]
#[command(author, version, about, long_about = None)]
struct SecureMountArgs {
/// path to the file which contains the Storage object.
#[arg(short, long)]
storage_path: String,
}

#[derive(Args)]
#[command(author, version, about, long_about = None)]
struct PullImageArgs {
/// URL of the image to be pulled
#[arg(short, long)]
image_url: String,

/// Path to store the bundle
#[arg(short, long)]
bundle_path: String,
}

#[tokio::main]
async fn main() {
let args = Cli::parse();
let config = CdhConfig::new(args.config).expect("failed to initialize cdh config");
config.set_configuration_envs();

let cdh = Hub::new(config).await.expect("failed to start CDH");

let mut tried = 1;
match args.operation {
Operation::UnsealSecret(op_args) => {
let secret = tokio::fs::read(op_args.secret_path)
.await
.expect("read secret file");
loop {
match cdh.unseal_secret(secret.clone()).await {
Ok(secret) => {
let res = STANDARD.encode(secret);
println!("{res}");
break;
}
Err(e) => {
if tried > args.retry {
let error = format!("failed to unseal secret, {:?}", e);
panic!("{error}");
}
warn!("Tried {tried} times... failed to unseal secret: {e}.");
tried += 1;
}
}
}
}
Operation::UnwrapKey(op_args) => {
let KeyProviderKeyWrapProtocolInput = tokio::fs::read(op_args.annotation_path)
.await
.expect("read annotation packet file");
loop {
match cdh.unwrap_key(&KeyProviderKeyWrapProtocolInput).await {
Ok(KeyProviderKeyWrapProtocolOutput) => {
let res = STANDARD.encode(KeyProviderKeyWrapProtocolOutput);
println!("{res}");
break;
}
Err(e) => {
if tried > args.retry {
panic!("failed to unwrap key");
}
warn!("Tried {tried} times... failed to unwrap key: {e}.");
tried += 1;
}
}
}
}
Operation::GetResource(op_args) => loop {
match cdh.get_resource(op_args.resource_uri.clone()).await {
Ok(resource) => {
let res = STANDARD.encode(resource);
println!("{res}");
break;
}
Err(e) => {
if tried > args.retry {
let error = format!("failed to get resource, {:?}", e);
panic!("{error}");
}
warn!("Tried {tried} times... failed to get resource: {e}.");
tried += 1;
}
}
},
Operation::SecureMount(op_args) => {
let storage_manifest = tokio::fs::read(op_args.storage_path)
.await
.expect("read file");
let storage: Storage =
serde_json::from_slice(&storage_manifest).expect("deserialize Storage");
let res = cdh
.secure_mount(storage)
.await
.expect("failed to secure mount");
println!("mount path: {res}");
}
Operation::PullImage(op_args) => {
let manifest_digest = cdh
.pull_image(&op_args.image_url, &op_args.bundle_path)
.await
.expect("failed to pull image");
println!("image digest: {manifest_digest}");
}
}
}

0 comments on commit 962d4c2

Please sign in to comment.