Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .cargo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
### Optional: Faster compilation

You can add the following to your `.cargo/config.toml` to potentially speed up compilation on your local machine.

> **Note:** These flags are intentionally not set by default. The GitHub runners used to build the KMS Docker image have unpredictable CPU architectures, which causes error code 132 when running containers built with `target_cpu=native`. These flags are however passed explicitly in CI for macOS, Windows, Linux, and CentOS 7 builds via the `RUSTFLAGS` environment variable in `cargo_build.yml`.

```toml
[build]
# Speeds up Ristretto 25519 multiplication x 2
rustflags = [
"--cfg",
"curve25519_dalek_backend=\"simd\"",
"-C",
"target_cpu=native",
]

# Can increase link speed on systems that support mold
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=mold"]
```

### Optional: VS Code / rust-analyzer

Add the following to your `.vscode/settings.json` to prevent rust-analyzer from interfering with regular `cargo` builds, which also reduces overall compilation time:

```json
{
"rust-analyzer.cargo.extraEnv": {
"CARGO_TARGET_DIR": "target/rust-analyzer"
}
}
```
13 changes: 0 additions & 13 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,3 @@ deps = "udeps --workspace --all-targets --all-features --backend depinfo"
# Publish dry-run helpers (allow dirty tree during local checks)
publish-dry = "publish --dry-run --workspace --allow-dirty"
publish-dry-crate = "publish --dry-run --allow-dirty"

###
# This options have been commented out because the Github runners responsible to build the KMS docker image have unpredictable CPU architectures, resulting in an error code 132 when running the generated container.
# However, those flags are specifically given by CI in other builds (macos, windows, linux, centos7) in cargo_build.yml via the RUSTFLAGS environment variable.
###
# [build]
# # Speeds up Ristretto 25519 multiplication x 2
# rustflags = [
# "--cfg",
# "curve25519_dalek_backend=\"simd\"",
# "-C",
# "target_cpu=native",
# ]
61 changes: 61 additions & 0 deletions crate/server/src/config/command_line/azure_ekm_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use clap::Args;
use serde::{Deserialize, Serialize};

#[allow(clippy::trivially_copy_pass_by_ref)] // this is required by serde
fn is_false(b: &bool) -> bool {
!b
}
#[derive(Debug, Args, Deserialize, Serialize, Clone)]
#[serde(default)]
#[derive(Default)]
pub struct AzureEkmConfig {
/// This setting turns on/off the endpoints handling Azure EKM features
#[clap(long, env = "KMS_AZURE_EKM_ENABLE", default_value = "false")]
pub azure_ekm_enable: bool,

/// Optional path prefix set within Managed HSM during EKM configuration.
///
/// Enables multi-customer use or isolation of different MHSM pools using the same proxy.
/// Must be max 64 characters: letters (a-z, A-Z), numbers (0-9), slashes (/), dashes (-).
#[clap(long, env = "KMS_AZURE_EKM_PATH_PREFIX", verbatim_doc_comment)]
#[serde(skip_serializing_if = "Option::is_none")]
pub azure_ekm_path_prefix: Option<String>,

/// WARNING: This bypasses mTLS authentication entirely. Only use for testing!
#[clap(
long,
env = "KMS_AZURE_EKM_DISABLE_CLIENT_AUTH",
default_value = "false"
)]
// serde does not support skipping booleans out of the box so a custom function is used
#[serde(skip_serializing_if = "is_false")]
pub azure_ekm_disable_client_auth: bool,
Comment on lines +24 to +32
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this parameter really required?
If during testing, mTLS must be disabled, I would advise to disable this TLS configuration:

[tls]
# Your server certificate and private key (PKCS#12 format)
tls_p12_file = "/etc/cosmian/server-cert.p12"
tls_p12_password = "your-secure-password"

# The certificate downloaded in the previous section
# This validates the client certificate presented by Azure MHSM
clients_ca_cert_file = "/etc/cosmian/mhsm-root-ca.pem"

Isn't it enough?


/// Proxy vendor name to report in /info endpoint.
#[clap(long, env = "KMS_AZURE_EKM_PROXY_VENDOR", default_value = "Cosmian")]
#[serde(skip_serializing_if = "String::is_empty")]
pub azure_ekm_proxy_vendor: String,

/// Proxy name to report in /info endpoint.
#[clap(
long,
env = "KMS_AZURE_EKM_PROXY_NAME",
default_value_t = format!("EKM Proxy Service v{}", env!("CARGO_PKG_VERSION"))
)]
#[serde(skip_serializing_if = "String::is_empty")]
pub azure_ekm_proxy_name: String,

/// EKMS vendor name report in the /info endpoint.
#[clap(long, env = "KMS_AZURE_EKM_VENDOR", default_value = "Cosmian")]
#[serde(skip_serializing_if = "String::is_empty")]
pub azure_ekm_ekm_vendor: String, // double "ekm" is intentional

/// Product Name and Version of the EKMS to report in the /info endpoint.
#[clap(
long,
env = "KMS_AZURE_EKM_PRODUCT",
default_value_t = format!("Cosmian KMS v{}", env!("CARGO_PKG_VERSION"))
)]
#[serde(skip_serializing_if = "String::is_empty")]
pub azure_ekm_ekm_product: String, // again, double "ekm" is intentional
}
35 changes: 34 additions & 1 deletion crate/server/src/config/command_line/clap_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::{
WorkspaceConfig, logging::LoggingConfig, ui_config::UiConfig,
};
use crate::{
config::{ProxyConfig, SocketServerConfig, TlsConfig},
config::{AzureEkmConfig, ProxyConfig, SocketServerConfig, TlsConfig},
error::KmsError,
result::KResult,
};
Expand Down Expand Up @@ -60,6 +60,7 @@ impl Default for ClapConfig {
non_revocable_key_id: None,
privileged_users: None,
kmip_policy: KmipPolicyConfig::default(),
azure_ekm_config: AzureEkmConfig::default(),
}
}
}
Expand Down Expand Up @@ -149,6 +150,9 @@ pub struct ClapConfig {
#[clap(flatten)]
pub google_cse_config: GoogleCseConfig,

#[clap(flatten)]
pub azure_ekm_config: AzureEkmConfig,

#[clap(flatten)]
pub workspace: WorkspaceConfig,

Expand Down Expand Up @@ -333,6 +337,35 @@ impl fmt::Debug for ClapConfig {
&self.google_cse_config.google_cse_enable,
)
};
let x = if self.azure_ekm_config.azure_ekm_enable {
x.field("azure_ekm_enable", &self.azure_ekm_config.azure_ekm_enable)
.field(
"azure_ekm_path_prefix",
&self.azure_ekm_config.azure_ekm_path_prefix,
)
.field(
"azure_ekm_disable_client_auth",
&self.azure_ekm_config.azure_ekm_disable_client_auth,
)
.field(
"azure_ekm_proxy_vendor",
&self.azure_ekm_config.azure_ekm_proxy_vendor,
)
.field(
"azure_ekm_proxy_name",
&self.azure_ekm_config.azure_ekm_proxy_name,
)
.field(
"azure_ekm_ekm_vendor",
&self.azure_ekm_config.azure_ekm_ekm_vendor,
)
.field(
"azure_ekm_ekm_product",
&self.azure_ekm_config.azure_ekm_ekm_product,
)
} else {
x.field("azure_ekm_enable", &self.azure_ekm_config.azure_ekm_enable)
};
let x = x.field(
"Microsoft Double Key Encryption URL",
&self.ms_dke_service_url,
Expand Down
2 changes: 2 additions & 0 deletions crate/server/src/config/command_line/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod azure_ekm_config;
mod clap_config;
mod db;
mod google_cse_config;
Expand All @@ -12,6 +13,7 @@ mod tls_config;
mod ui_config;
mod workspace;

pub use azure_ekm_config::AzureEkmConfig;
pub use clap_config::ClapConfig;
pub use db::{DEFAULT_SQLITE_PATH, MainDBConfig};
pub use google_cse_config::GoogleCseConfig;
Expand Down
31 changes: 30 additions & 1 deletion crate/server/src/config/params/server_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use cosmian_logger::{debug, warn};
use super::{KmipPolicyParams, TlsParams};
use crate::{
config::{
ClapConfig, GoogleCseConfig, IdpConfig, OidcConfig,
AzureEkmConfig, ClapConfig, GoogleCseConfig, IdpConfig, OidcConfig,
params::{
OpenTelemetryConfig, kmip_policy_params::KmipAllowlistsParams,
proxy_params::ProxyParams,
Expand Down Expand Up @@ -127,6 +127,8 @@ pub struct ServerParams {

/// KMIP algorithm policy.
pub kmip_policy: KmipPolicyParams,

pub azure_ekm: AzureEkmConfig,
}

/// Represents the server parameters.
Expand Down Expand Up @@ -336,6 +338,7 @@ impl ServerParams {
aes_key_sizes: kmip_allowlists.aes_key_sizes,
},
},
azure_ekm: conf.azure_ekm_config,
};
debug!("{res:#?}");

Expand Down Expand Up @@ -444,6 +447,32 @@ impl fmt::Debug for ServerParams {
debug_struct.field("google_cse_enable", &self.google_cse.google_cse_enable);
}

// Azure EKM configuration
if self.azure_ekm.azure_ekm_enable {
debug_struct
.field("azure_ekm_enable", &self.azure_ekm.azure_ekm_enable)
.field(
"azure_ekm_path_prefix",
&self.azure_ekm.azure_ekm_path_prefix,
)
.field(
"azure_ekm_disable_client_auth",
&self.azure_ekm.azure_ekm_disable_client_auth,
)
.field(
"azure_ekm_proxy_vendor",
&self.azure_ekm.azure_ekm_proxy_vendor,
)
.field("azure_ekm_proxy_name", &self.azure_ekm.azure_ekm_proxy_name)
.field("azure_ekm_ekm_vendor", &self.azure_ekm.azure_ekm_ekm_vendor)
.field(
"azure_ekm_ekm_product",
&self.azure_ekm.azure_ekm_ekm_product,
);
} else {
debug_struct.field("azure_ekm_enable", &self.azure_ekm.azure_ekm_enable);
}

if self.hsm_model.is_some() {
debug_struct
.field("hsm_admin", &self.hsm_admin)
Expand Down
7 changes: 6 additions & 1 deletion crate/server/src/core/operations/decrypt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ fn decrypt_single(
server_params: &crate::config::ServerParams,
request: &Decrypt,
) -> KResult<DecryptResponse> {
trace!("entering");
trace!("Extracting key block for decryption to identify key format type...");
let key_block = owm.object().key_block()?;
match &key_block.key_format_type {
#[cfg(feature = "non-fips")]
Expand Down Expand Up @@ -451,6 +451,11 @@ fn decrypt_single_with_symmetric_key(
)
})?;
let (key_bytes, aead) = get_aead_and_key(owm, request)?;
trace!(
"got key bytes of length: {}, aead: {:?}. Proceeding to get the nonce...",
key_bytes.len(),
aead
);
// For modes with nonce_size()==0 (e.g. ECB) we do not expect / require an IV.
// For modes with nonce_size()>0 we require an IV. Some KMIP vectors supply an empty
// IVCounterNonce element to indicate an all-zero IV (e.g. CBC test cases). Treat a
Expand Down
2 changes: 1 addition & 1 deletion crate/server/src/core/operations/encrypt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ fn get_key_and_cipher(
request: &Encrypt,
owm: &ObjectWithMetadata,
) -> KResult<(Zeroizing<Vec<u8>>, SymCipher)> {
trace!("entering");
trace!("Entering get_key_and_cipher");
// Make sure that the key used to encrypt can be used to encrypt.
if !owm
.object()
Expand Down
23 changes: 18 additions & 5 deletions crate/server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,12 @@ async fn run() -> KResult<()> {
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::unwrap_in_result)]
mod tests {
use std::path::PathBuf;

use cosmian_kms_server::config::{
ClapConfig, GoogleCseConfig, HttpConfig, IdpAuthConfig, KmipPolicyConfig, LoggingConfig,
MainDBConfig, OidcConfig, ProxyConfig, SocketServerConfig, TlsConfig, UiConfig,
WorkspaceConfig,
AzureEkmConfig, ClapConfig, GoogleCseConfig, HttpConfig, IdpAuthConfig, KmipPolicyConfig,
LoggingConfig, MainDBConfig, OidcConfig, ProxyConfig, SocketServerConfig, TlsConfig,
UiConfig, WorkspaceConfig,
};
use std::path::PathBuf;

#[cfg(feature = "non-fips")]
#[test]
Expand Down Expand Up @@ -216,6 +215,15 @@ mod tests {
]),
google_cse_migration_key: None,
},
azure_ekm_config: AzureEkmConfig {
azure_ekm_enable: false,
azure_ekm_path_prefix: None,
azure_ekm_disable_client_auth: false,
azure_ekm_proxy_vendor: String::new(),
azure_ekm_proxy_name: String::new(),
azure_ekm_ekm_vendor: String::new(),
azure_ekm_ekm_product: String::new(),
},
kms_public_url: Some("[kms_public_url]".to_owned()),
workspace: WorkspaceConfig {
root_data_path: PathBuf::from("[root data path]"),
Expand Down Expand Up @@ -308,6 +316,9 @@ google_cse_enable = false
google_cse_disable_tokens_validation = false
google_cse_incoming_url_whitelist = ["[kacls_url_1]", "[kacls_url_2]"]

[azure_ekm_config]
azure_ekm_enable = false

[workspace]
root_data_path = "[root data path]"
tmp_path = "[tmp path]"
Expand All @@ -322,6 +333,8 @@ rolling_log_name = "kms_log"
enable_metering = false
environment = "development"
ansi_colors = false

[kmip.allowlists]
"#;

assert_eq!(toml_string.trim(), toml::to_string(&config).unwrap().trim());
Expand Down
8 changes: 8 additions & 0 deletions crate/server/src/routes/azure_ekm/contributing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## About future versions

- Add future-ly supported version numbers in `SUPPORTED_API_VERSIONS` in `crate/server/src/routes/azure_ekm/mod.rs`
- Take into account that each version *might* support error status codes that were not previously supported, refer to `error.rs`.

## Development guidelines

- Separate handlers to `handlers.rs` to ease out testing the API.
Loading
Loading