Skip to content

Commit

Permalink
CDH/KMS/Aliyun: read credentials from env
Browse files Browse the repository at this point in the history
Related to confidential-containers#413. Before this commit, we will read credentials from local
filesystem for aliyun KMS plugin. This would make unexpected side
effects. We now read them from the env, which will not spread side
effects.

There are some envs that will be used.

If the `client_type` is `client_key`:
- `ALIYUN_CLIENT_KEY`: Aliyun KMS client key
- `ALIYUN_PASSWORD`: The password of Aliyun KMS client key
- `ALIYUN_KMS_INSTANCE_CERT`: The public key cert to KMS instance

if the `client_type` is `ecs_ram_role`
- `ALIYUN_ECS_RAM_ROLE`: The ECS RAM Role name on Aliyun
- `ALIYUN_REGION_ID`: ECS Instance region id

Signed-off-by: Xynnn007 <[email protected]>
  • Loading branch information
Xynnn007 committed Jan 19, 2024
1 parent 82c20c0 commit 3bd4841
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 140 deletions.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// SPDX-License-Identifier: Apache-2.0
//

use std::collections::BTreeMap;
use std::{collections::BTreeMap, env};

use async_trait::async_trait;
use base64::{engine::general_purpose::STANDARD, Engine};
Expand All @@ -14,7 +14,6 @@ use reqwest::{header::HeaderMap, Certificate, ClientBuilder};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use sha2::{Digest, Sha256};
use tokio::fs;

mod config;
mod credential;
Expand All @@ -23,7 +22,6 @@ use crate::{Annotations, Decrypter, Encrypter, Getter, ProviderSettings};
use crate::{Error, Result};

use super::super::annotations::*;
use super::ALIYUN_IN_GUEST_DEFAULT_KEY_PATH;
use config::*;
use credential::*;

Expand Down Expand Up @@ -82,34 +80,23 @@ impl ClientKeyClient {
}

/// This new function is used by a in-pod client. The side-effect is to read the
/// [`ALIYUN_IN_GUEST_DEFAULT_KEY_PATH`] which is the by default path where the credential
/// to access kms is saved.
/// environment variable to get parameters, s.t.
/// - `ALIYUN_CLIENT_KEY`: Aliyun KMS client key
/// - `ALIYUN_PASSWORD`: The password of Aliyun KMS client key
/// - `ALIYUN_KMS_INSTANCE_CERT`: The public key cert to KMS instance
pub async fn from_provider_settings(provider_settings: &ProviderSettings) -> Result<Self> {
let provider_settings: AliClientKeyProviderSettings =
serde_json::from_value(Value::Object(provider_settings.clone())).map_err(|e| {
Error::AliyunKmsError(format!("parse client_key provider setting failed: {e}"))
})?;

let cert_path = format!(
"{ALIYUN_IN_GUEST_DEFAULT_KEY_PATH}/PrivateKmsCA_{}.pem",
provider_settings.kms_instance_id
);
let pswd_path = format!(
"{ALIYUN_IN_GUEST_DEFAULT_KEY_PATH}/password_{}.json",
provider_settings.client_key_id
);
let client_key_path = format!(
"{ALIYUN_IN_GUEST_DEFAULT_KEY_PATH}/clientKey_{}.json",
provider_settings.client_key_id
);
let cert_pem = fs::read_to_string(cert_path).await.map_err(|e| {
Error::AliyunKmsError(format!("read kms instance pem cert failed: {e}"))
})?;
let pswd = fs::read_to_string(pswd_path).await.map_err(|e| {
Error::AliyunKmsError(format!("read password of the credential failed: {e}"))
let client_key = env::var("ALIYUN_CLIENT_KEY")
.map_err(|_| Error::AliyunKmsError("ALIYUN_CLIENT_KEY not set in env".to_string()))?;
let pswd = env::var("ALIYUN_PASSWORD").map_err(|_| {
Error::AliyunKmsError("ALIYUN_CLIENT_KEY_PASSWORD not set in env".to_string())
})?;
let client_key = fs::read_to_string(client_key_path).await.map_err(|e| {
Error::AliyunKmsError(format!("read client key of the credential failed: {e}"))
let cert_pem = env::var("ALIYUN_KMS_INSTANCE_CERT").map_err(|_| {
Error::AliyunKmsError("ALIYUN_KMS_INSTANCE_CERT not set in env".to_string())
})?;

Self::new(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use std::{
collections::{BTreeMap, HashMap},
env,
fmt::Write,
};

Expand All @@ -14,7 +15,6 @@ use log::error;
use rand::{distributions::Alphanumeric, Rng};
use reqwest::{header::HeaderMap, ClientBuilder};
use serde_json::Value;
use tokio::fs;

mod config;
mod credential;
Expand All @@ -23,7 +23,6 @@ use crate::{Annotations, Getter, ProviderSettings};
use crate::{Error, Result};

use super::super::annotations::*;
use super::ALIYUN_IN_GUEST_DEFAULT_KEY_PATH;
use config::*;
use credential::*;

Expand Down Expand Up @@ -55,54 +54,16 @@ impl EcsRamRoleClient {
}

/// This new function is used by a in-pod client. The side-effect is to read the
/// [`ALIYUN_IN_GUEST_DEFAULT_KEY_PATH`] which is the by default path where the credential
/// to access kms is saved.
/// environment variable to get parameters, s.t.
/// - `ALIYUN_ECS_RAM_ROLE`: The ECS RAM Role name on Aliyun
/// - `ALIYUN_REGION_ID`: ECS Instance region id
pub async fn from_provider_settings(_provider_settings: &ProviderSettings) -> Result<Self> {
let ecs_ram_role_path = format!("{ALIYUN_IN_GUEST_DEFAULT_KEY_PATH}/ecsRamRole.json");
let ecs_ram_role_name = env::var("ALIYUN_ECS_RAM_ROLE")
.map_err(|_| Error::AliyunKmsError("ALIYUN_ECS_RAM_ROLE not set in env".to_string()))?;
let region_id = env::var("ALIYUN_REGION_ID")
.map_err(|_| Error::AliyunKmsError("ALIYUN_REGION_ID not set in env".to_string()))?;

let ecs_ram_role_str = fs::read_to_string(ecs_ram_role_path).await.map_err(|e| {
Error::AliyunKmsError(format!(
"read ecs_ram_role with `fs::read_to_string()` failed: {e}"
))
})?;

let ecs_ram_role_json: serde_json::Value = serde_json::from_str(&ecs_ram_role_str)
.map_err(|e| {
Error::AliyunKmsError(format!(
"read ecs_ram_role with `serde_json::from_str()` failed: {e}"
))
})?;

let ecs_ram_role_name =
if let Some(ecs_ram_role_name_value) = ecs_ram_role_json.get("ecs_ram_role_name") {
match ecs_ram_role_name_value.as_str() {
Some(ecs_ram_role_name) => ecs_ram_role_name,
None => {
return Err(Error::AliyunKmsError(
"ecs ram role name value is not str.".to_string(),
))
}
}
} else {
return Err(Error::AliyunKmsError(
"ecs ram role name not exist.".to_string(),
));
};

let region_id = if let Some(region_id_value) = ecs_ram_role_json.get("region_id") {
match region_id_value.as_str() {
Some(region_id) => region_id,
None => {
return Err(Error::AliyunKmsError(
"region id value is not str.".to_string(),
))
}
}
} else {
return Err(Error::AliyunKmsError("region id not exist.".to_string()));
};

Self::new(ecs_ram_role_name, region_id)
Self::new(&ecs_ram_role_name, &region_id)
}

/// Export the [`ProviderSettings`] of the current client. This function is to be used
Expand Down
29 changes: 17 additions & 12 deletions confidential-data-hub/kms/src/plugins/aliyun/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
//

use async_trait::async_trait;
use const_format::concatcp;
use serde_json::json;

mod client_key_client;
mod ecs_ram_role_client;

use crate::plugins::_IN_GUEST_DEFAULT_KEY_PATH;
use crate::{Annotations, Decrypter, Encrypter, Getter, ProviderSettings};
use crate::{Error, Result};

Expand All @@ -31,8 +29,6 @@ pub struct AliyunKmsClient {
inner_client: Client,
}

const ALIYUN_IN_GUEST_DEFAULT_KEY_PATH: &str = concatcp!(_IN_GUEST_DEFAULT_KEY_PATH, "/aliyun");

impl AliyunKmsClient {
pub fn new(
client_key: &str,
Expand Down Expand Up @@ -70,8 +66,15 @@ impl AliyunKmsClient {
}

/// This new function is used by a in-pod client. The side-effect is to read the
/// [`ALIYUN_IN_GUEST_DEFAULT_KEY_PATH`] which is the by default path where the credential
/// to access kms is saved.
/// environment variable to get parameters. If the `client_type` is `client_key`,
/// will read the following env keys
/// - `ALIYUN_CLIENT_KEY`: Aliyun KMS client key
/// - `ALIYUN_PASSWORD`: The password of Aliyun KMS client key
/// - `ALIYUN_KMS_INSTANCE_CERT`: The public key cert to KMS instance
///
/// if the `client_type` is `ecs_ram_role`, will read the following env keys
/// - `ALIYUN_ECS_RAM_ROLE`: The ECS RAM Role name on Aliyun
/// - `ALIYUN_REGION_ID`: ECS Instance region id
pub async fn from_provider_settings(provider_settings: &ProviderSettings) -> Result<Self> {
let client_type = if let Some(client_type_value) = provider_settings.get("client_type") {
match client_type_value.as_str() {
Expand Down Expand Up @@ -209,10 +212,11 @@ mod tests {
#[tokio::test]
async fn key_lifetime(#[case] plaintext: &[u8]) {
let kid = "alias/test_key_id";
std::env::set_var("ALIYUN_CLIENT_KEY", "KAAP.f4c8****");
std::env::set_var("ALIYUN_KMS_INSTANCE_CERT", "kst-shh6****");
std::env::set_var("ALIYUN_PASSWORD", "xxx");
let provider_settings = json!({
"client_type": "client_key",
"client_key_id": "KAAP.f4c8****",
"kms_instance_id": "kst-shh6****",
"client_type": "client_key"
});
// init encrypter at user side
let provider_settings = provider_settings.as_object().unwrap().to_owned();
Expand Down Expand Up @@ -247,10 +251,11 @@ mod tests {
#[tokio::test]
async fn get_secret(#[case] client_type: &str) {
let secret_name = "test_secret";
std::env::set_var("ALIYUN_CLIENT_KEY", "KAAP.f4c8****");
std::env::set_var("ALIYUN_KMS_INSTANCE_CERT", "kst-shh6****");
std::env::set_var("ALIYUN_PASSWORD", "xxx");
let provider_settings = json!({
"client_type": client_type,
"client_key_id": "KAAP.f4c8****",
"kms_instance_id": "kst-shh6****",
"client_type": client_type
});
// init getter at user side
let provider_settings = provider_settings.as_object().unwrap().to_owned();
Expand Down

0 comments on commit 3bd4841

Please sign in to comment.