Add init with grpc_ratls kms client support
This commit is contained in:
parent
0541852659
commit
435ae8b68d
27
etc/template/init_grpc_ratls.json
Normal file
27
etc/template/init_grpc_ratls.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"kms_server": "localhost:50051",
|
||||||
|
"kms_keys": [
|
||||||
|
{
|
||||||
|
"key": "demo_key",
|
||||||
|
"path": "/etc/demo_key"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ra_config": {
|
||||||
|
"verify_mr_enclave" : "off",
|
||||||
|
"verify_mr_signer" : "off",
|
||||||
|
"verify_isv_prod_id" : "off",
|
||||||
|
"verify_isv_svn" : "off",
|
||||||
|
"verify_config_svn" : "off",
|
||||||
|
"verify_enclave_debuggable" : "off",
|
||||||
|
"sgx_mrs": [
|
||||||
|
{
|
||||||
|
"mr_enclave" : "",
|
||||||
|
"mr_signer" : "",
|
||||||
|
"isv_prod_id" : 0,
|
||||||
|
"isv_svn" : 0,
|
||||||
|
"config_svn" : 0,
|
||||||
|
"debuggable" : true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,7 @@ all:
|
|||||||
@$(MAKE) --no-print-directory -C gen_internal_conf
|
@$(MAKE) --no-print-directory -C gen_internal_conf
|
||||||
@$(MAKE) --no-print-directory -C copy_bom
|
@$(MAKE) --no-print-directory -C copy_bom
|
||||||
@$(MAKE) --no-print-directory -C init
|
@$(MAKE) --no-print-directory -C init
|
||||||
|
@$(MAKE) --no-print-directory -C init_grpc_ratls
|
||||||
|
|
||||||
format:
|
format:
|
||||||
@$(MAKE) --no-print-directory -C protect-integrity format
|
@$(MAKE) --no-print-directory -C protect-integrity format
|
||||||
@ -24,3 +25,4 @@ clean:
|
|||||||
@$(MAKE) --no-print-directory -C gen_internal_conf clean
|
@$(MAKE) --no-print-directory -C gen_internal_conf clean
|
||||||
@$(MAKE) --no-print-directory -C copy_bom clean
|
@$(MAKE) --no-print-directory -C copy_bom clean
|
||||||
@$(MAKE) --no-print-directory -C init clean
|
@$(MAKE) --no-print-directory -C init clean
|
||||||
|
@$(MAKE) --no-print-directory -C init_grpc_ratls clean
|
||||||
|
119
tools/init_grpc_ratls/Cargo.lock
generated
Normal file
119
tools/init_grpc_ratls/Cargo.lock
generated
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"safemem",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "init_grpc_ratls"
|
||||||
|
version = "0.0.2"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"libc",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.84"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "safemem"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.123"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.123"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.62"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.60"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
12
tools/init_grpc_ratls/Cargo.toml
Normal file
12
tools/init_grpc_ratls/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "init_grpc_ratls"
|
||||||
|
version = "0.0.2"
|
||||||
|
build = "build.rs"
|
||||||
|
authors = ["Zheng Qi huaiqing.zq@antgroup.com"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = "0.2.84"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
|
base64 = "0.9"
|
16
tools/init_grpc_ratls/Makefile
Normal file
16
tools/init_grpc_ratls/Makefile
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
include ../../src/sgxenv.mk
|
||||||
|
|
||||||
|
SRC_FILES := $(shell find . -type f -name '*.rs') Cargo.toml
|
||||||
|
RUST_TARGET_DIR := $(BUILD_DIR)/internal/tools/init_grpc_ratls/cargo-target
|
||||||
|
RUST_OUT_DIR := $(BUILD_DIR)/bin
|
||||||
|
TARGET_BINARY := $(RUST_OUT_DIR)/init_grpc_ratls
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
all: $(SRC_FILES)
|
||||||
|
@RUSTC_BOOTSTRAP=1 occlum-cargo build --release --target-dir=$(RUST_TARGET_DIR) -Z unstable-options --out-dir=$(RUST_OUT_DIR)
|
||||||
|
@echo "CARGO (release) => init_grpc_ratls"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@occlum-cargo clean --target-dir=$(RUST_TARGET_DIR)
|
||||||
|
@-$(RM) -f $(TARGET_BINARY)
|
7
tools/init_grpc_ratls/build.rs
Normal file
7
tools/init_grpc_ratls/build.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("cargo:rustc-link-search=native=/opt/occlum/toolchains/dcap_lib/musl");
|
||||||
|
println!("cargo:rustc-link-search=native=/opt/occlum/toolchains/grpc_ratls/musl");
|
||||||
|
println!("cargo:rustc-link-lib=dylib=grpc_ratls_client");
|
||||||
|
println!("cargo:rustc-link-lib=dylib=hw_grpc_proto");
|
||||||
|
println!("cargo:rustc-link-lib=dylib=occlum_dcap");
|
||||||
|
}
|
231
tools/init_grpc_ratls/src/main.rs
Normal file
231
tools/init_grpc_ratls/src/main.rs
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
extern crate libc;
|
||||||
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
|
use libc::syscall;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fs;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{ErrorKind, Read};
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::os::raw::{c_int, c_char};
|
||||||
|
|
||||||
|
#[link(name = "grpc_ratls_client")]
|
||||||
|
extern "C" {
|
||||||
|
fn grpc_ratls_get_secret(
|
||||||
|
server_addr: *const c_char, // grpc server address+port, such as "localhost:50051"
|
||||||
|
config_json: *const c_char, // ratls handshake config json file
|
||||||
|
name: *const c_char, // secret name to be requested
|
||||||
|
secret_file: *const c_char // secret file to be saved
|
||||||
|
) -> c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
#[warn(dead_code)]
|
||||||
|
struct MRsValue {
|
||||||
|
pub mr_enclave: String,
|
||||||
|
pub mr_signer: String,
|
||||||
|
pub isv_prod_id: u32,
|
||||||
|
pub isv_svn: u32,
|
||||||
|
pub config_svn: u32,
|
||||||
|
pub debuggable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
#[warn(dead_code)]
|
||||||
|
struct RAConfig {
|
||||||
|
verify_mr_enclave: String,
|
||||||
|
verify_mr_signer: String,
|
||||||
|
verify_isv_prod_id: String,
|
||||||
|
verify_isv_svn: String,
|
||||||
|
verify_config_svn: String,
|
||||||
|
verify_enclave_debuggable: String,
|
||||||
|
sgx_mrs: Vec<MRsValue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
|
#[warn(dead_code)]
|
||||||
|
struct KmsKeys {
|
||||||
|
key: String,
|
||||||
|
path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
#[warn(dead_code)]
|
||||||
|
struct InitRAConfig {
|
||||||
|
kms_server: String,
|
||||||
|
kms_keys: Vec<KmsKeys>,
|
||||||
|
ra_config: RAConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_ra_config(ra_conf_path: &str) -> Result<InitRAConfig, Box<dyn Error>> {
|
||||||
|
let mut ra_conf_file = File::open(ra_conf_path)?;
|
||||||
|
let ra_conf = {
|
||||||
|
let mut ra_conf = String::new();
|
||||||
|
ra_conf_file.read_to_string(&mut ra_conf)?;
|
||||||
|
ra_conf
|
||||||
|
};
|
||||||
|
let config: InitRAConfig = serde_json::from_str(&ra_conf)?;
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
// Load the configuration from initfs
|
||||||
|
const IMAGE_CONFIG_FILE: &str = "/etc/image_config.json";
|
||||||
|
const INIT_RA_CONF: &str = "/etc/init_ra_conf.json";
|
||||||
|
let image_config = load_config(IMAGE_CONFIG_FILE)?;
|
||||||
|
|
||||||
|
// Get the MAC of Occlum.json.protected file
|
||||||
|
let occlum_json_mac = {
|
||||||
|
let mut mac: sgx_aes_gcm_128bit_tag_t = Default::default();
|
||||||
|
parse_str_to_bytes(&image_config.occlum_json_mac, &mut mac)?;
|
||||||
|
mac
|
||||||
|
};
|
||||||
|
let occlum_json_mac_ptr = &occlum_json_mac as *const sgx_aes_gcm_128bit_tag_t;
|
||||||
|
|
||||||
|
// Do parse to get Init RA information
|
||||||
|
let init_ra_conf = load_ra_config(INIT_RA_CONF)?;
|
||||||
|
// Extract RA config part
|
||||||
|
let ra_conf_string = serde_json::to_string_pretty(&init_ra_conf.ra_config).unwrap();
|
||||||
|
fs::write("ra_config.json", ra_conf_string.clone().into_bytes())?;
|
||||||
|
let config_json = CString::new("ra_config.json").unwrap();
|
||||||
|
let server_addr = CString::new(init_ra_conf.kms_server).unwrap();
|
||||||
|
|
||||||
|
// Get the key of FS image if needed
|
||||||
|
let key = match &image_config.image_type[..] {
|
||||||
|
"encrypted" => {
|
||||||
|
// Get the image encrypted key through RA
|
||||||
|
let secret = CString::new("image_key").unwrap();
|
||||||
|
let filename = CString::new("/etc/image_key").unwrap();
|
||||||
|
|
||||||
|
let ret = unsafe {
|
||||||
|
grpc_ratls_get_secret(
|
||||||
|
server_addr.as_ptr(),
|
||||||
|
config_json.as_ptr(),
|
||||||
|
secret.as_ptr(),
|
||||||
|
filename.as_ptr())
|
||||||
|
};
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
println!("grpc_ratls_get_secret failed return {}", ret);
|
||||||
|
return Err(Box::new(std::io::Error::last_os_error()));
|
||||||
|
}
|
||||||
|
|
||||||
|
const IMAGE_KEY_FILE: &str = "/etc/image_key";
|
||||||
|
let key_str = load_key(IMAGE_KEY_FILE)?;
|
||||||
|
// Remove key file which is not needed any more
|
||||||
|
fs::remove_file(IMAGE_KEY_FILE)?;
|
||||||
|
let mut key: sgx_key_128bit_t = Default::default();
|
||||||
|
parse_str_to_bytes(&key_str, &mut key)?;
|
||||||
|
Some(key)
|
||||||
|
}
|
||||||
|
"integrity-only" => None,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let key_ptr = key
|
||||||
|
.as_ref()
|
||||||
|
.map(|key| key as *const sgx_key_128bit_t)
|
||||||
|
.unwrap_or(std::ptr::null());
|
||||||
|
|
||||||
|
// Do one time key acquire to force all necessary libraries got loaded to memory.
|
||||||
|
// Thus after mount rootfs, the API could run successfully.
|
||||||
|
// The key got this time will be dropped.
|
||||||
|
unsafe {
|
||||||
|
let kms_key = init_ra_conf.kms_keys[0].clone();
|
||||||
|
let key = CString::new(kms_key.key).unwrap();
|
||||||
|
let file = CString::new(kms_key.path).unwrap();
|
||||||
|
|
||||||
|
grpc_ratls_get_secret(
|
||||||
|
server_addr.as_ptr(),
|
||||||
|
config_json.as_ptr(),
|
||||||
|
key.as_ptr(),
|
||||||
|
file.as_ptr());
|
||||||
|
// Remove key file which is not needed any more
|
||||||
|
fs::remove_file(file.into_string().unwrap())?;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mount the image
|
||||||
|
const SYS_MOUNT_FS: i64 = 363;
|
||||||
|
let ret = unsafe { syscall(SYS_MOUNT_FS, key_ptr, occlum_json_mac_ptr) };
|
||||||
|
if ret < 0 {
|
||||||
|
return Err(Box::new(std::io::Error::last_os_error()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rewrite ra_config to rootfs
|
||||||
|
fs::write("ra_config.json", ra_conf_string.into_bytes())?;
|
||||||
|
let config_json = CString::new("ra_config.json").unwrap();
|
||||||
|
|
||||||
|
// Get keys and save to path
|
||||||
|
for keys in init_ra_conf.kms_keys {
|
||||||
|
let key = CString::new(keys.key).unwrap();
|
||||||
|
let file = CString::new(keys.path).unwrap();
|
||||||
|
|
||||||
|
let ret = unsafe {
|
||||||
|
grpc_ratls_get_secret(
|
||||||
|
server_addr.as_ptr(),
|
||||||
|
config_json.as_ptr(),
|
||||||
|
key.as_ptr(),
|
||||||
|
file.as_ptr())
|
||||||
|
};
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
println!("Failed to get key {:?}, return {}", key, ret);
|
||||||
|
// return Err(Box::new(std::io::Error::last_os_error()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
type sgx_key_128bit_t = [u8; 16];
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
type sgx_aes_gcm_128bit_tag_t = [u8; 16];
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct ImageConfig {
|
||||||
|
occlum_json_mac: String,
|
||||||
|
image_type: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_config(config_path: &str) -> Result<ImageConfig, Box<dyn Error>> {
|
||||||
|
let mut config_file = File::open(config_path)?;
|
||||||
|
let config_json = {
|
||||||
|
let mut config_json = String::new();
|
||||||
|
config_file.read_to_string(&mut config_json)?;
|
||||||
|
config_json
|
||||||
|
};
|
||||||
|
let config: ImageConfig = serde_json::from_str(&config_json)?;
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_key(key_path: &str) -> Result<String, Box<dyn Error>> {
|
||||||
|
let mut key_file = File::open(key_path)?;
|
||||||
|
let mut key = String::new();
|
||||||
|
key_file.read_to_string(&mut key)?;
|
||||||
|
Ok(key.trim_end_matches(|c| c == '\r' || c == '\n').to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_str_to_bytes(arg_str: &str, bytes: &mut [u8]) -> Result<(), Box<dyn Error>> {
|
||||||
|
let bytes_str_vec = {
|
||||||
|
let bytes_str_vec: Vec<&str> = arg_str.split('-').collect();
|
||||||
|
if bytes_str_vec.len() != bytes.len() {
|
||||||
|
return Err(Box::new(std::io::Error::new(
|
||||||
|
ErrorKind::InvalidData,
|
||||||
|
"The length or format of Key/MAC string is invalid",
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
bytes_str_vec
|
||||||
|
};
|
||||||
|
|
||||||
|
for (byte_i, byte_str) in bytes_str_vec.iter().enumerate() {
|
||||||
|
bytes[byte_i] = u8::from_str_radix(byte_str, 16)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user