Skip to content

Commit

Permalink
Sample Keyprovider: Add encrypt mod for CC KBC
Browse files Browse the repository at this point in the history
Signed-off-by: Jiale Zhang <[email protected]>
  • Loading branch information
jialez0 committed Feb 2, 2023
1 parent 410bd6a commit 338c9b7
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 0 deletions.
1 change: 1 addition & 0 deletions sample_keyprovider/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ shadow-rs = "0.5.25"
default = []
sample_enc = []
offline_fs_kbs = ["openssl"]
cc_kbc_enc = []
54 changes: 54 additions & 0 deletions sample_keyprovider/src/enc_mods/cc_kbc_enc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# CC-KBC Encryption module

This encryption module corresponds to the [CC KBC](../../../../src/kbc_modules/cc_kbc).
It wraps keys to be used by that KBC.
As this is done ahead of time rather than at the runtime of the KBC, it is not a broker _service_ in the stricter sense of the word.

## Usage

Generate a random encryption key first:

```shell
head -c32 < /dev/random > test_key_1
```

Then register this key to [KBS](https://github.com/confidential-containers/kbs) resource repository,
The resource path (`<repository>/<type>/<tag>`) of this key in KBS will be used as part of the key ID when encrypting the container image in the next step.

The sample keyprovider with CC-KBC encryption module can be run with e.g.:
```
cargo run --release --features cc_kbc_enc -- --keyprovider_sock 127.0.0.1:50000
```

### Encrypt Container Image

To correspond with the sample keyprovider as described above, an `ocicrypt.conf` like
```json
{
"key-providers": {
"attestation-agent": {
"grpc": "127.0.0.1:50000"
}
}
}
```

is required.
To encrypt e.g. `oci:busybox` with the key file path and key ID suggested above, run
```
OCICRYPT_KEYPROVIDER_CONFIG=ocicrypt.conf skopeo copy --encryption-key provider:attestation-agent:$(realpath test_key_1):<key_id> oci:busybox oci:busybox_encrypted
```

The `<key_id>` parameter format should be:
```
cc_kbc://<kbs-address>/<repository>/<type>/<tag>
```

Where:
- `<kbs-address>`: e.g: `127.0.0.1:8080`, `example.kbs.com` etc.
- `<repository>/<type>/<tag>`: As mentioned above, this is the resource path of the encryption key in KBS.

For example:
```
OCICRYPT_KEYPROVIDER_CONFIG=ocicrypt.conf skopeo copy --encryption-key provider:attestation-agent:$(realpath test_key_1):cc_kbc://127.0.0.1:8080/my_repo/test/test_key_1 oci:busybox oci:busybox_encrypted
```
49 changes: 49 additions & 0 deletions sample_keyprovider/src/enc_mods/cc_kbc_enc/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) 2023 Alibaba Cloud
//
// SPDX-License-Identifier: Apache-2.0
//

use aes_gcm::aead::{Aead, KeyInit};
use aes_gcm::{AeadCore, Aes256Gcm, Key};
use anyhow::*;
use rand::rngs::OsRng;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct AnnotationPacket {
// Key Resource ID (URL)
// Format:
// `cc_kbc://127.0.0.1:8080/test_repo/key/id_1`
pub kid: String,
// Encrypted key to unwrap (base64-encoded)
pub wrapped_data: String,
// Initialisation vector (base64-encoded)
pub iv: String,
// Wrap type to specify encryption algorithm and mode
pub wrap_type: String,
}

pub fn enc_optsdata_gen_anno(optsdata: &[u8], params: Vec<String>) -> Result<String> {
let (key_file_path, kid) = params[0].split_once(':').ok_or(anyhow!(
"Failed to parse parameters: {:?}, need key file path and key URL in KBS split by ':'",
params
))?;

let key = std::fs::read(key_file_path).map_err(|e| anyhow!("Read Key file failed: {}", e))?;
let aes_key = Key::<Aes256Gcm>::from_slice(&key);
let nonce = Aes256Gcm::generate_nonce(&mut OsRng);

let cipher = Aes256Gcm::new(aes_key);
let encrypt_optsdata = cipher
.encrypt(&nonce, optsdata)
.map_err(|e| anyhow!("Eecrypt failed: {:?}", e))?;

let annotation = AnnotationPacket {
kid: kid.to_string(),
wrapped_data: base64::encode(encrypt_optsdata),
iv: base64::encode(nonce.to_vec()),
wrap_type: "A256GCM".to_string(),
};

serde_json::to_string(&annotation).map_err(|_| anyhow!("Serialize annotation failed"))
}
4 changes: 4 additions & 0 deletions sample_keyprovider/src/enc_mods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ pub use sample_enc::enc_optsdata_gen_anno;
pub mod offline_fs_kbs;
#[cfg(feature = "offline_fs_kbs")]
pub use offline_fs_kbs::enc_optsdata_gen_anno;
#[cfg(feature = "cc_kbc_enc")]
pub mod cc_kbc_enc;
#[cfg(feature = "cc_kbc_enc")]
pub use cc_kbc_enc::enc_optsdata_gen_anno;

0 comments on commit 338c9b7

Please sign in to comment.