From 01c94523ab382e7ee9f5bc9eb0ca7a974c46114f Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 19 Jan 2024 17:01:10 +0800 Subject: [PATCH] CDH/KMS/eHSM: read credentials from env Related to #413. Before this commit, we will read credentials from local filesystem for eHSM KMS plugin. This would make unexpected side effects. We now read them from the env, which will not spread side effects. There are two envs that will be used: - EHSM_API_KEY: API key of the eHSM instance - EHSM_APP_ID: Application Id to the eHSM instance - EHSM_ENDPOINT: HTTP/HTTPS address to the eHSM service Signed-off-by: Xynnn007 --- .../kms/src/plugins/ehsm/README.md | 5 +- .../kms/src/plugins/ehsm/annotations.rs | 13 --- .../kms/src/plugins/ehsm/client.rs | 98 +++++++------------ .../kms/src/plugins/ehsm/credential.rs | 16 --- .../credential.4eb1____.json | 4 - .../kms/src/plugins/ehsm/mod.rs | 2 - 6 files changed, 38 insertions(+), 100 deletions(-) delete mode 100644 confidential-data-hub/kms/src/plugins/ehsm/annotations.rs delete mode 100644 confidential-data-hub/kms/src/plugins/ehsm/credential.rs delete mode 100644 confidential-data-hub/kms/src/plugins/ehsm/example_credential/credential.4eb1____.json diff --git a/confidential-data-hub/kms/src/plugins/ehsm/README.md b/confidential-data-hub/kms/src/plugins/ehsm/README.md index 128c63076..3afa463f3 100644 --- a/confidential-data-hub/kms/src/plugins/ehsm/README.md +++ b/confidential-data-hub/kms/src/plugins/ehsm/README.md @@ -108,7 +108,10 @@ Congratulations! eHSM-KMS service should be ready by now. # eHSM-KMS Client -eHSM-KMS client requires a credential file to run. The file name of the credential file is `credential.{your_app_id}.json`. The credential file need to be placed in `/run/confidential-containers/cdh/kms-credential/ehsm/`. And the structure of the credential file is shown in `ehsm/example_credential/` folder. +eHSM-KMS client requires credentials to run. In the eHSM plugin, the credentials are delievered by environment variable +- `EHSM_API_KEY`: API key of the eHSM instance +- `EHSM_APP_ID`: Application Id to the eHSM instance +- `EHSM_ENDPOINT`: HTTP/HTTPS address to the eHSM service To test eHSM-KMS client, run ```bash diff --git a/confidential-data-hub/kms/src/plugins/ehsm/annotations.rs b/confidential-data-hub/kms/src/plugins/ehsm/annotations.rs deleted file mode 100644 index 41de08109..000000000 --- a/confidential-data-hub/kms/src/plugins/ehsm/annotations.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2023 Alibaba Cloud -// -// SPDX-License-Identifier: Apache-2.0 -// - -use serde::{Deserialize, Serialize}; - -/// Serialized [`crate::ProviderSettings`] -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EhsmProviderSettings { - pub app_id: String, - pub endpoint: String, -} diff --git a/confidential-data-hub/kms/src/plugins/ehsm/client.rs b/confidential-data-hub/kms/src/plugins/ehsm/client.rs index 339b63bd7..7560b43ba 100644 --- a/confidential-data-hub/kms/src/plugins/ehsm/client.rs +++ b/confidential-data-hub/kms/src/plugins/ehsm/client.rs @@ -3,28 +3,21 @@ // SPDX-License-Identifier: Apache-2.0 // +use std::env; + use ehsm_client::{api::KMS, client::EHSMClient}; use async_trait::async_trait; use base64::engine::general_purpose::STANDARD; use base64::Engine; -use const_format::concatcp; -use serde_json::Value; -use tokio::fs; -use crate::plugins::_IN_GUEST_DEFAULT_KEY_PATH; use crate::{Annotations, Decrypter, Encrypter, ProviderSettings}; use crate::{Error, Result}; -use super::annotations::EhsmProviderSettings; -use super::credential::Credential; - pub struct EhsmKmsClient { client: EHSMClient, } -const EHSM_IN_GUEST_DEFAULT_KEY_PATH: &str = concatcp!(_IN_GUEST_DEFAULT_KEY_PATH, "/ehsm"); - impl EhsmKmsClient { pub fn new(app_id: &str, api_key: &str, endpoint: &str) -> Result { Ok(Self { @@ -43,51 +36,28 @@ impl EhsmKmsClient { }) } - /// This new function is used by a in-pod client. The side-effect is to read the - /// [`EHSM_IN_GUEST_DEFAULT_KEY_PATH`] which is the by default path where the credential - /// to access kms is saved. - pub async fn from_provider_settings(provider_settings: &ProviderSettings) -> Result { - let provider_settings: EhsmProviderSettings = - serde_json::from_value(Value::Object(provider_settings.clone())) - .map_err(|e| Error::EhsmKmsError(format!("parse provider setting failed: {e}")))?; - - let credential_path = format!( - "{EHSM_IN_GUEST_DEFAULT_KEY_PATH}/credential_{}.json", - provider_settings.app_id - ); - - let api_key = { - let cred = fs::read_to_string(credential_path) - .await - .map_err(|e| Error::EhsmKmsError(format!("read credential failed: {e}")))?; - let cred: Credential = serde_json::from_str(&cred) - .map_err(|e| Error::EhsmKmsError(format!("serialize credential failed: {e}")))?; - cred.api_key - }; - - Self::new( - &provider_settings.app_id, - &api_key, - &provider_settings.endpoint, - ) + /// This new function is used by a in-pod client. It will read environment variables + /// to create the client. The envs are + /// + /// - `EHSM_ENDPOINT`: The endpoint of the eHSM instance + /// - `EHSM_API_KEY`: The API key to connect to eHSM + /// - `EHSM_APP_ID`: Application id + pub async fn from_provider_settings(_provider_settings: &ProviderSettings) -> Result { + let endpoint = env::var("EHSM_ENDPOINT") + .map_err(|_| Error::EhsmKmsError("EHSM_ENDPOINT not set in env".to_string()))?; + let api_key = env::var("EHSM_API_KEY") + .map_err(|_| Error::EhsmKmsError("EHSM_API_KEY not set in env".to_string()))?; + let app_id = env::var("EHSM_APP_ID") + .map_err(|_| Error::EhsmKmsError("EHSM_APP_ID not set in env".to_string()))?; + + Self::new(&app_id, &api_key, &endpoint) } /// Export the [`ProviderSettings`] of the current client. This function is to be used /// in the encryptor side. The [`ProviderSettings`] will be used to initial a client /// in the decryptor side. - pub fn export_provider_settings(&self) -> Result { - let provider_settings = EhsmProviderSettings { - app_id: self.client.appid.clone(), - endpoint: self.client.base_url.clone(), - }; - - let provider_settings = serde_json::to_value(provider_settings) - .map_err(|e| Error::EhsmKmsError(format!("serialize ProviderSettings failed: {e}")))? - .as_object() - .expect("must be an object") - .to_owned(); - - Ok(provider_settings) + pub fn export_provider_settings(&self) -> ProviderSettings { + ProviderSettings::default() } } @@ -149,8 +119,10 @@ impl EhsmKmsClient { #[cfg(test)] mod tests { + use std::env; + use rstest::rstest; - use serde_json::json; + use serde_json::Map; use crate::{plugins::ehsm::client::EhsmKmsClient, Decrypter, Encrypter}; @@ -158,14 +130,13 @@ mod tests { #[tokio::test] async fn test_create_key() { let key_spec = "EH_AES_GCM_256"; - let provider_settings = json!({ - "app_id": "86f0e9fe-****-a224ddee1233", - "endpoint": "https://172.0.0.1:9000", - }); + + env::set_var("EHSM_ENDPOINT", "https://172.0.0.1:9000"); + env::set_var("EHSM_APP_ID", "86f0e9fe-****-a224ddee1233"); + env::set_var("EHSM_API_KEY", "xxx"); // init client at user side - let provider_settings = provider_settings.as_object().unwrap().to_owned(); - let mut client = EhsmKmsClient::from_provider_settings(&provider_settings) + let mut client = EhsmKmsClient::from_provider_settings(&Map::new()) .await .unwrap(); @@ -183,21 +154,20 @@ mod tests { #[tokio::test] async fn key_lifetime(#[case] plaintext: &[u8]) { let key_spec = "EH_AES_GCM_256"; - let provider_settings = json!({ - "app_id": "86f0e9fe-7f05-4110-9f65-a224ddee1233", - "endpoint": "https://172.16.1.1:9002", - }); + + env::set_var("EHSM_ENDPOINT", "https://172.16.1.1:9002"); + env::set_var("EHSM_APP_ID", "86f0e9fe-****-a224ddee1233"); + env::set_var("EHSM_API_KEY", "xxx"); // init client at user side - let provider_settings = provider_settings.as_object().unwrap().to_owned(); - let mut client = EhsmKmsClient::from_provider_settings(&provider_settings) + let mut client = EhsmKmsClient::from_provider_settings(&Map::new()) .await .unwrap(); // create key let key_id = client.create_key(key_spec).await.unwrap(); - let mut encryptor = EhsmKmsClient::from_provider_settings(&provider_settings) + let mut encryptor = EhsmKmsClient::from_provider_settings(&Map::new()) .await .unwrap(); @@ -208,7 +178,7 @@ mod tests { .encrypt(plaintext, &key_id) .await .expect("encrypt"); - let provider_settings = encryptor.export_provider_settings().unwrap(); + let provider_settings = encryptor.export_provider_settings(); // init decrypter in a guest let mut decryptor = EhsmKmsClient::from_provider_settings(&provider_settings) diff --git a/confidential-data-hub/kms/src/plugins/ehsm/credential.rs b/confidential-data-hub/kms/src/plugins/ehsm/credential.rs deleted file mode 100644 index 707df1cc4..000000000 --- a/confidential-data-hub/kms/src/plugins/ehsm/credential.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2023 Alibaba Cloud -// -// SPDX-License-Identifier: Apache-2.0 -// - -//! Credentials to access eHSM-KMS - -// use anyhow::*; -use serde::Deserialize; - -#[derive(Deserialize)] -#[serde(rename_all = "PascalCase")] -pub(crate) struct Credential { - pub _app_id: String, - pub api_key: String, -} diff --git a/confidential-data-hub/kms/src/plugins/ehsm/example_credential/credential.4eb1____.json b/confidential-data-hub/kms/src/plugins/ehsm/example_credential/credential.4eb1____.json deleted file mode 100644 index 355b8f638..000000000 --- a/confidential-data-hub/kms/src/plugins/ehsm/example_credential/credential.4eb1____.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "AppId": "4eb1****", - "ApiKey": "2LkL****" -} \ No newline at end of file diff --git a/confidential-data-hub/kms/src/plugins/ehsm/mod.rs b/confidential-data-hub/kms/src/plugins/ehsm/mod.rs index 2e85599ce..e22152af5 100644 --- a/confidential-data-hub/kms/src/plugins/ehsm/mod.rs +++ b/confidential-data-hub/kms/src/plugins/ehsm/mod.rs @@ -8,8 +8,6 @@ //! eHSM KMS uses eHSM-KMS to support all functions. //! The project detail can be found here: . -mod annotations; mod client; -mod credential; pub use client::EhsmKmsClient;