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 copy_bom | ||||
| 	@$(MAKE) --no-print-directory -C init | ||||
| 	@$(MAKE) --no-print-directory -C init_grpc_ratls | ||||
| 
 | ||||
| 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 copy_bom 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