trelent-hyok 0.1.12

A Rust library implementing Hold Your Own Key (HYOK) encryption patterns with support for multiple cloud providers
Documentation
//! Azure Key Vault integration for key management.
//!
//! This module provides integration with Azure Key Vault for cryptographic
//! operations. It supports:
//!
//! - Key encryption/decryption
//! - Multiple encryption algorithms
//! - Azure Key Vault key management
//! - Error handling for Azure operations

#![cfg(feature = "azure")]

use std::sync::Arc;

use async_trait::async_trait;
use azure_security_keyvault::{
    prelude::{CryptographParamtersEncryption, DecryptParameters, EncryptParameters},
    KeyvaultClient,
};

use crate::cmk::CMKTrait;
use crate::error::cmk::CMKError;

/// Azure Customer Managed Key implementation using Azure Key Vault.
///
/// This CMK implementation:
/// - Uses Azure Key Vault for cryptographic operations
/// - Supports multiple encryption algorithms
/// - Handles key identifiers
/// - Provides proper error handling
///
/// # Security
///
/// This implementation:
/// - Uses Azure Key Vault for key protection
/// - Supports key rotation
/// - Provides audit logging
/// - Enables Azure RBAC
///
/// # Authentication
///
/// Supports multiple authentication methods:
/// - Service principals
/// - Managed identities
/// - User credentials
/// - Connection strings
///
/// # Example
/// ```no_run
/// use std::sync::Arc;
/// use azure_security_keyvault::{KeyvaultClient, prelude::CryptographParamtersEncryption};
/// use hyokashi::AzureCMK;
///
/// async {
///     let client = Arc::new(KeyvaultClient::new(/* ... */));
///     let cmk = AzureCMK::new(
///         client,
///         "my-key".to_string(),
///         CryptographParamtersEncryption::RsaOaep256,
///     );
///
///     // Encrypt some data
///     let data = vec![1, 2, 3];
///     let encrypted = cmk.encrypt(data).await?;
///
///     // Decrypt the data
///     let decrypted = cmk.decrypt(encrypted).await?;
///     # Ok::<(), Box<dyn std::error::Error>>(())
/// };
/// ```
#[derive(Debug, Clone)]
/// Azure Customer Managed Key, enabling encryption and decryption
/// through Azure Key Vault.
///
/// # Example
/// ```no_run
/// // Let's say you have a KeyvaultClient:
/// // let client = Arc::new(KeyvaultClient::new(/* ... */));
/// // let azure_cmk = AzureCMK::new(
/// //     client,
/// //     "my_key".to_string(),
/// //     CryptographParamtersEncryption::RsaOaep256,
/// // );
/// // let encrypted_data = azure_cmk.encrypt(vec![1, 2, 3]).await.unwrap();
/// // let decrypted_data = azure_cmk.decrypt(encrypted_data).await.unwrap();
/// ```
pub struct AzureCMK {
    pub(crate) client: Arc<KeyvaultClient>,
    pub(crate) key_name: String,
    pub(crate) params: CryptographParamtersEncryption,
}

impl AzureCMK {
    /// Creates a new `AzureCMK` from an Azure KeyvaultClient instance, a key name, and encryption parameters.
    ///
    /// # Arguments
    ///
    /// * `client` - An `Arc` wrapping the Azure KeyvaultClient for API calls.
    /// * `key_name` - The name (or identifier) of the key within Key Vault.
    /// * `params` - Encryption parameters describing the algorithm to be used.
    ///
    /// # Returns
    ///
    /// A new `AzureCMK` that allows encrypting and decrypting with Azure Key Vault.
    pub fn new(
        client: Arc<KeyvaultClient>,
        key_name: String,
        params: CryptographParamtersEncryption
    ) -> AzureCMK {
        AzureCMK {
            client,
            key_name,
            params,
        }
    }
}

#[async_trait]
impl CMKTrait for AzureCMK {
    /// Encrypts the specified plaintext data using Azure Key Vault.
    ///
    /// # Arguments
    ///
    /// * `plaintext` - The plaintext bytes to be encrypted.
    ///
    /// # Errors
    ///
    /// Returns a `CMKError` if encryption in Azure Key Vault fails.
    ///
    /// # Example
    /// ```no_run
    /// // let azure_cmk = AzureCMK::new(/* ... */);
    /// // let encrypted = azure_cmk.encrypt(vec![0xab, 0xcd]).await?;
    /// ```
    async fn encrypt(&self, plaintext: Vec<u8>) -> Result<Vec<u8>, CMKError> {
        let key_client = self.client.key_client();
        let encrypt_params = EncryptParameters {
            plaintext: plaintext,
            encrypt_parameters_encryption: self.params.clone(),
        };
        key_client
            .encrypt(self.key_name.clone(), encrypt_params).await
            .map(|result| result.result)
            .map_err(|e| CMKError(format!("Error encrypting using azure keyvault, Error: {:?}", e)))
    }

    /// Decrypts the specified ciphertext data using Azure Key Vault.
    ///
    /// # Arguments
    ///
    /// * `ciphertext` - The ciphertext bytes to be decrypted.
    ///
    /// # Errors
    ///
    /// Returns a `CMKError` if decryption in Azure Key Vault fails.
    ///
    /// # Example
    /// ```no_run
    /// // let azure_cmk = AzureCMK::new(/* ... */);
    /// // let decrypted = azure_cmk.decrypt(encrypted_data).await?;
    /// ```
    async fn decrypt(&self, ciphertext: Vec<u8>) -> Result<Vec<u8>, CMKError> {
        let key_client = self.client.key_client();
        let decrypt_params = DecryptParameters {
            ciphertext: ciphertext,
            decrypt_parameters_encryption: self.params.clone(),
        };
        key_client
            .decrypt(self.key_name.clone(), decrypt_params).await
            .map(|result| result.result)
            .map_err(|e| CMKError(format!("Error encrypting using azure keyvault, Error: {:?}", e)))
    }
}