feat(cosmian_cli): Add support for Oracle Transparent Database Encryption (TDE) using Oracle Key Vault (#396)
* docs: add Oracle Key Vault integration * fix: align cosmian_findex version with client-repo version * fix: clean Cargo.lock * fix: update Cargo.lock * chore: upgrade some deps * chore: rebase with develop * test: add end-to-end test on cosmian_pkcs11 crate
This commit is contained in:
parent
e719da16bd
commit
788ad721ec
19 changed files with 858 additions and 748 deletions
13
.github/scripts/cargo_deny.sh
vendored
13
.github/scripts/cargo_deny.sh
vendored
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
# Install cargo deny if not already installed
|
||||
# cargo install --version 0.18.2 cargo-deny --locked
|
||||
|
||||
# Run cargo deny in each directory containing a Cargo.toml
|
||||
find . -name "Cargo.toml" -exec dirname {} \; | while read -r dir; do
|
||||
echo "Running cargo deny check in $dir"
|
||||
(cd "$dir" && cargo deny check advisories)
|
||||
done
|
18
.github/scripts/check_build.sh
vendored
Normal file
18
.github/scripts/check_build.sh
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
# Install cargo deny if not already installed
|
||||
# cargo install --version 0.18.2 cargo-deny --locked
|
||||
|
||||
find . -name "Cargo.toml" -not -path "./Cargo.toml" -not -path "./cli/Cargo.toml" -exec dirname {} \; | while read -r dir; do
|
||||
echo "Running cargo build in $dir"
|
||||
pushd "$dir"
|
||||
cargo build
|
||||
cargo test -- --nocapture --skip hsm --skip google_cse
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
cargo deny check advisories
|
||||
popd
|
||||
done
|
||||
|
||||
cargo hack build --all --feature-powerset
|
1
.github/workflows/main_base.yml
vendored
1
.github/workflows/main_base.yml
vendored
|
@ -81,6 +81,7 @@ jobs:
|
|||
- run: find .
|
||||
|
||||
- name: Creating zip to be attached to release
|
||||
shell: bash
|
||||
run: |
|
||||
set -xe
|
||||
apt update -y
|
||||
|
|
|
@ -20,7 +20,7 @@ repos:
|
|||
rev: v0.44.0
|
||||
hooks:
|
||||
- id: markdownlint-fix
|
||||
args: [--disable=MD013, --disable=MD041, --disable=MD046, --fix]
|
||||
args: [--disable=MD013, --disable=MD033, --disable=MD041, --disable=MD046, --fix]
|
||||
|
||||
- repo: https://github.com/tcort/markdown-link-check
|
||||
rev: v3.13.7
|
||||
|
|
1097
Cargo.lock
generated
1097
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
12
Cargo.toml
12
Cargo.toml
|
@ -24,7 +24,7 @@ resolver = "2"
|
|||
[workspace.package]
|
||||
version = "4.23.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.71.0"
|
||||
rust-version = "1.80.0"
|
||||
authors = [
|
||||
"Bruno Grieder <bruno.grieder@cosmian.com>",
|
||||
"Emmanuel Coste <emmanuel.coste@cosmian.com>",
|
||||
|
@ -55,10 +55,10 @@ opt-level = 0
|
|||
[workspace.dependencies]
|
||||
actix-rt = "2.10"
|
||||
actix-server = { version = "2.5", default-features = false }
|
||||
actix-web = { version = "4.9", default-features = false }
|
||||
actix-web = { version = "4.10", default-features = false }
|
||||
async-trait = "0.1"
|
||||
base64 = "0.22"
|
||||
bitflags = "2.8"
|
||||
bitflags = "2.9"
|
||||
chrono = "0.4"
|
||||
clap = { version = "4.5", default-features = false }
|
||||
cosmian_findex = { git = "https://github.com/Cosmian/findex", default-features = false, rev = "6329b6b2f2b64b033e40b05cd12ca1c9b5ee376f" }
|
||||
|
@ -66,7 +66,7 @@ cosmian_findex_server = { git = "https://www.github.com/Cosmian/findex-server",
|
|||
cosmian_findex_structs = { git = "https://www.github.com/Cosmian/findex-server", branch = "develop" }
|
||||
cosmian_config_utils = "0.1.1"
|
||||
cosmian_cover_crypt = "15.0"
|
||||
cosmian_crypto_core = { version = "10.0.1", default-features = false, features = [
|
||||
cosmian_crypto_core = { version = "10.1", default-features = false, features = [
|
||||
"ser",
|
||||
] }
|
||||
cosmian_http_client = "0.1.1"
|
||||
|
@ -101,8 +101,8 @@ strum = { version = "0.25", default-features = false }
|
|||
thiserror = "2.0"
|
||||
time = "0.3"
|
||||
tiny-keccak = "2.0"
|
||||
tempfile = "3.16"
|
||||
tokio = { version = "1.43", default-features = false }
|
||||
tempfile = "3.19"
|
||||
tokio = { version = "1.44", default-features = false }
|
||||
tracing-subscriber = { version = "0.3", default-features = false }
|
||||
tracing = "0.1"
|
||||
url = "2.5"
|
||||
|
|
2
cli
2
cli
|
@ -1 +1 @@
|
|||
Subproject commit 08f2b3ae53c860a2327c6256f1b0b53b038eb15c
|
||||
Subproject commit c9241a44f4e98d18dd9b7e25283d88ecab2f62c6
|
|
@ -137,7 +137,7 @@ pub fn kmip_public_key_to_openssl(public_key: &Object) -> Result<PKey<Public>, C
|
|||
),
|
||||
},
|
||||
f => crypto_bail!(
|
||||
"Unsupported key format type: {f:?}, for tr transforming a {} to openssl",
|
||||
"Unsupported key format type: {f:?}, for transforming a {} to openssl",
|
||||
public_key.object_type()
|
||||
),
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
This directory provides
|
||||
# Folder structure
|
||||
|
||||
- base Rust PKCS#11 bindings and traits that ccan be used to create a PKCS#11 client or a PPKCS#11 provider
|
||||
- base Rust PKCS#11 bindings and traits that can be used to create a PKCS#11 client or a PKCS#11 provider
|
||||
- a PKCS#11 library to interface the KMS (the `provider` crate) from a PKCS#11 compliant application such as LUKS
|
||||
|
||||
[PKCS##11 documentation](https://www.cryptsoft.com/pkcs11doc/STANDARD/pkcs-11.pdf)
|
||||
|
@ -9,13 +9,3 @@ This directory provides
|
|||
|
||||
The sys crate is generated from the cryptoki headers files using `bindgen` and provides Linux and Windows bindings for
|
||||
the PKCS#11 API.
|
||||
|
||||
2. `module` crate
|
||||
|
||||
The module crate exposes traits to create a PKCS#11 library. It is a modified fork of
|
||||
the `native_pkcs11` crate from Google. The `module` crate is used to build the `provider` PKCS#11 library.
|
||||
|
||||
3. `provider` crate
|
||||
|
||||
The provider crate is a PKCS#11 library that interfaces the KMS. It provides a PKCS#11 library that can be used by
|
||||
applications such as LUKS to interface the KMS. The `provider` crate is built from the `module` crate.
|
||||
|
|
|
@ -103,14 +103,14 @@ x509-parser = { workspace = true }
|
|||
zeroize = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-http = "3.6"
|
||||
actix-http = "3.10"
|
||||
cosmian_kms_client_utils = { workspace = true }
|
||||
cosmian_logger = { workspace = true }
|
||||
pem = { workspace = true }
|
||||
tempfile = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
actix-http = "3.6"
|
||||
actix-http = "3.10"
|
||||
time = { workspace = true, features = ["local-offset", "formatting"] }
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use cosmian_kmip::{
|
||||
KmipError,
|
||||
kmip_2_1::{
|
||||
KmipOperation,
|
||||
kmip_data_structures::{KeyBlock, KeyMaterial, KeyValue, KeyWrappingSpecification},
|
||||
kmip_objects::{Object, ObjectType},
|
||||
kmip_operations::{Export, ExportResponse},
|
||||
|
@ -9,9 +11,7 @@ use cosmian_kmip::{
|
|||
Attributes, CertificateType, CryptographicAlgorithm, CryptographicUsageMask,
|
||||
KeyFormatType, KeyWrapType, LinkType, StateEnumeration, UniqueIdentifier,
|
||||
},
|
||||
KmipOperation,
|
||||
},
|
||||
KmipError,
|
||||
};
|
||||
use cosmian_kms_crypto::openssl::{
|
||||
kmip_certificate_to_openssl, kmip_private_key_to_openssl, kmip_public_key_to_openssl,
|
||||
|
@ -26,16 +26,16 @@ use openssl::{
|
|||
stack::Stack,
|
||||
x509::X509,
|
||||
};
|
||||
use tracing::trace;
|
||||
use tracing::{debug, trace};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use crate::{
|
||||
core::{
|
||||
KMS,
|
||||
certificate::{retrieve_certificate_for_private_key, retrieve_private_key_for_certificate},
|
||||
operations::import::upsert_imported_links_in_attributes,
|
||||
retrieve_object_utils::retrieve_object_for_operation,
|
||||
wrapping::wrap_key,
|
||||
KMS,
|
||||
},
|
||||
error::KmsError,
|
||||
kms_bail,
|
||||
|
@ -228,6 +228,7 @@ async fn post_process_private_key(
|
|||
#[cfg(feature = "fips")]
|
||||
let is_pkcs12 = request.key_format_type == Some(KeyFormatType::PKCS12);
|
||||
// according to the KMIP specs the KeyMaterial is not returned if the object is destroyed
|
||||
trace!("post_process_private_key: operation type: {operation_type:?}");
|
||||
if (operation_type == KmipOperation::Export)
|
||||
&& (owm.state() == StateEnumeration::Destroyed
|
||||
|| owm.state() == StateEnumeration::Destroyed_Compromised)
|
||||
|
@ -273,6 +274,7 @@ async fn post_process_active_private_key(
|
|||
user: &str,
|
||||
params: Option<Arc<dyn SessionParams>>,
|
||||
) -> KResult<()> {
|
||||
trace!("post_process_active_private_key: key_format_type: {key_format_type:?}",);
|
||||
// First perform any necessary unwrapping to the expected type
|
||||
transform_to_key_wrap_type(
|
||||
object_with_metadata,
|
||||
|
@ -353,6 +355,10 @@ async fn post_process_active_private_key(
|
|||
|
||||
//No wrapping requested: export the private key to the requested format
|
||||
if let Some(key_format_type) = key_format_type {
|
||||
debug!(
|
||||
"export: exporting private key with format: {:?}",
|
||||
key_format_type
|
||||
);
|
||||
#[cfg(not(feature = "fips"))]
|
||||
let supported_formats = [
|
||||
KeyFormatType::PKCS1,
|
||||
|
|
|
@ -39,7 +39,7 @@ future) public
|
|||
key `ms_dke_pub_key`.
|
||||
|
||||
```bash
|
||||
cargo run --bin ckms -- rsa keys import -f pem -t dke_key -p ms_dke_pub_key \
|
||||
cargo run --bin cosmian -- kms rsa keys import -f pem -t dke_key -p ms_dke_pub_key \
|
||||
crate/server/src/tests/ms_dke/private_key.pkcs8.pem ms_dke_priv_key
|
||||
```
|
||||
|
||||
|
@ -47,18 +47,18 @@ Import the public key with the tag `dke_key`, with a name `ms_dke_pub_key` and a
|
|||
key `ms_dke_priv_key`
|
||||
|
||||
```bash
|
||||
cargo run --bin ckms -- rsa keys import -f pem -t dke_key -k ms_dke_priv_key \
|
||||
cargo run --bin cosmian -- kms rsa keys import -f pem -t dke_key -k ms_dke_priv_key \
|
||||
crate/server/src/tests/ms_dke/public_key.pkcs8.pem ms_dke_pub_key
|
||||
|
||||
```
|
||||
|
||||
Verify that you can export the keys using the `ckms` command line tool.
|
||||
Verify that you can export the keys using the `cosmian` command line tool.
|
||||
|
||||
```bash
|
||||
# public key
|
||||
cargo run --bin ckms -- rsa keys export -t dke_key -t _pk -f pkcs1-pem /tmp/pub_key.pkcs1.pem
|
||||
cargo run --bin cosmian -- kms rsa keys export -t dke_key -t _pk -f pkcs1-pem /tmp/pub_key.pkcs1.pem
|
||||
# private key
|
||||
cargo run --bin ckms -- rsa keys export -t dke_key -t _sk -f pkcs8-pem /tmp/priv_key.pkcs1.pem
|
||||
cargo run --bin cosmian -- kms rsa keys export -t dke_key -t _sk -f pkcs8-pem /tmp/priv_key.pkcs1.pem
|
||||
```
|
||||
|
||||
## Grant access to the keys
|
||||
|
@ -67,8 +67,8 @@ The calls to the `ms_dke` endpoint are unauthenticated and hence made under the
|
|||
you created the keys with a different user, you may have to grant accesses to `admin`:
|
||||
|
||||
```shell
|
||||
cargo run --bin ckms -- access-rights grant admin ms_dke_priv_key decrypt
|
||||
cargo run --bin ckms -- access-rights grant admin ms_dke_pub_key encrypt export get
|
||||
cargo run --bin cosmian -- kms access-rights grant admin ms_dke_priv_key decrypt
|
||||
cargo run --bin cosmian -- kms access-rights grant admin ms_dke_pub_key encrypt export get
|
||||
```
|
||||
|
||||
## Check
|
||||
|
|
|
@ -33,7 +33,7 @@ redis = { version = "0.23", features = [
|
|||
] }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
sqlx = { version = "0.8.2", default-features = false, features = [
|
||||
sqlx = { version = "0.8.5", default-features = false, features = [
|
||||
"json",
|
||||
"runtime-tokio-native-tls",
|
||||
"mysql",
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
use std::pin::Pin;
|
||||
|
||||
use futures::Future;
|
||||
use redis::{aio::ConnectionManager, cmd, pipe, Pipeline, RedisError, ToRedisArgs};
|
||||
|
||||
/// This function encapsulates the boilerplate required to establish a Redis transaction.
|
||||
/// Do not use it directly but use the `transaction_async!` macro instead.
|
||||
/// See the `transaction_async!` macro for more details.
|
||||
pub(crate) async fn transaction_async<
|
||||
T,
|
||||
E: From<RedisError>,
|
||||
K: ToRedisArgs,
|
||||
F: Fn(
|
||||
ConnectionManager,
|
||||
&mut Pipeline,
|
||||
CTX,
|
||||
) -> Pin<Box<dyn Future<Output = Result<Option<T>, E>> + Send>>,
|
||||
CTX: Clone,
|
||||
>(
|
||||
mut mgr: ConnectionManager,
|
||||
keys: &[K],
|
||||
context: CTX,
|
||||
func: F,
|
||||
) -> Result<T, E> {
|
||||
loop {
|
||||
cmd("WATCH").arg(keys).query_async(&mut mgr).await?;
|
||||
let mut p = pipe();
|
||||
let response: Option<T> = func(mgr.clone(), p.atomic(), context.clone()).await?;
|
||||
match response {
|
||||
None => continue,
|
||||
Some(response) => {
|
||||
// make sure no watch is left in the connection, even if
|
||||
// someone forgot to use the pipeline.
|
||||
cmd("UNWATCH").query_async(&mut mgr).await?;
|
||||
return Ok(response)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Asynchronous transaction macro for Redis operations.
|
||||
///
|
||||
/// This macro encapsulates the boilerplate required to establish a Redis transaction
|
||||
/// and apply a function to it. What it
|
||||
/// does is automatically watching keys and then going into a transaction
|
||||
/// loop util it succeeds. Once it goes through the results are
|
||||
/// returned.
|
||||
///
|
||||
/// To use the transaction two pieces of information are needed: a list
|
||||
/// of all the keys that need to be watched for modifications and a
|
||||
/// closure with the code that should be execute in the context of the
|
||||
/// transaction. The closure is invoked with a fresh pipeline in atomic
|
||||
/// mode. To use the transaction the function needs to return the result
|
||||
/// from querying the pipeline with the connection.
|
||||
///
|
||||
/// The end result of the transaction is then available as the return
|
||||
/// value from the function call.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `$mgr`: A cloned connection manager for Redis.
|
||||
/// - `$key`: A key (or array of keys) for the Redis operation.
|
||||
/// - `$context`: An optional cloneable context passed to the function.
|
||||
/// - `$func`: Either a path to a function or a lambda function. This function
|
||||
/// should have the signature `async fn(ConnectionManager, Pipeline) -> Result<Option<T>, RedisError>`
|
||||
/// where `T` is the expected return type.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns a `Result` containing the return value of the passed function, or an error.
|
||||
///
|
||||
/// Note: This macro is exported so it can be used in other modules.
|
||||
#[macro_export]
|
||||
macro_rules! transaction_async {
|
||||
($mgr:expr, $key:expr, $context:expr, $func:path) => {{
|
||||
$crate::database::redis::transaction_async(
|
||||
$mgr,
|
||||
$key,
|
||||
$context,
|
||||
|mgr, pipeline, context| {
|
||||
let pipeline = pipeline.clone();
|
||||
Box::pin(async move { $func(mgr, pipeline, context).await })
|
||||
},
|
||||
)
|
||||
.await
|
||||
}};
|
||||
($mgr:expr, $key:expr, $context:expr, $func:expr) => {{
|
||||
$crate::database::redis::transaction_async(
|
||||
$mgr,
|
||||
$key,
|
||||
$context,
|
||||
|mgr, pipeline, context| {
|
||||
let pipeline = pipeline.clone();
|
||||
Box::pin($func(mgr, pipeline, context))
|
||||
},
|
||||
)
|
||||
.await
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use redis::{aio::ConnectionManager, AsyncCommands, Pipeline, RedisError};
|
||||
use serial_test::serial;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::{log_init, result::KResult};
|
||||
|
||||
const REDIS_URL: &str = "redis://localhost:6379";
|
||||
|
||||
#[actix_web::test]
|
||||
#[serial]
|
||||
pub async fn test_async_transaction() -> KResult<()> {
|
||||
cosmian_logger::log_init(Some("test_permissions_db=info"));
|
||||
trace!("test_permissions_db");
|
||||
|
||||
let client = redis::Client::open(REDIS_URL)?;
|
||||
let mgr = ConnectionManager::new(client).await?;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Context {
|
||||
new_value: String,
|
||||
}
|
||||
|
||||
async fn return_blah(
|
||||
mut mgr: ConnectionManager,
|
||||
mut pipeline: Pipeline,
|
||||
context: Context,
|
||||
) -> KResult<Option<Vec<String>>> {
|
||||
let res = pipeline
|
||||
.set("key", context.new_value)
|
||||
.ignore()
|
||||
.get("key")
|
||||
.query_async(&mut mgr)
|
||||
.await?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
let res = transaction_async!(
|
||||
mgr.clone(),
|
||||
&["key"],
|
||||
Context {
|
||||
new_value: "blah".to_owned(),
|
||||
},
|
||||
return_blah
|
||||
)?;
|
||||
assert_eq!(res, vec!["blah".to_owned()]);
|
||||
|
||||
let res: Vec<String> = transaction_async!(
|
||||
mgr.clone(),
|
||||
&["key"],
|
||||
Context {
|
||||
new_value: "blah".to_owned(),
|
||||
},
|
||||
|mut mgr: ConnectionManager, mut pipeline: Pipeline, context: Context| async move {
|
||||
pipeline
|
||||
.set("key", context.new_value)
|
||||
.ignore()
|
||||
.get("key")
|
||||
.query_async(&mut mgr)
|
||||
.await
|
||||
}
|
||||
)?;
|
||||
assert_eq!(res, vec!["blah".to_owned()]);
|
||||
|
||||
// now insert a key/value and modify it in a transaction
|
||||
mgr.clone().set("key", "value").await?;
|
||||
async fn modify_key(
|
||||
mut mgr: ConnectionManager,
|
||||
mut pipeline: Pipeline,
|
||||
context: Context,
|
||||
) -> Result<Option<Vec<String>>, RedisError> {
|
||||
let value: String = mgr.get("key").await?;
|
||||
// do some dummy stuff
|
||||
let new_value = format!("{}->{}", value, context.new_value);
|
||||
pipeline
|
||||
.set("key", &new_value)
|
||||
.ignore()
|
||||
.get("key")
|
||||
.query_async(&mut mgr)
|
||||
.await
|
||||
}
|
||||
let new_value: Vec<String> = transaction_async!(
|
||||
mgr.clone(),
|
||||
&["key"],
|
||||
Context {
|
||||
new_value: "new".to_owned()
|
||||
},
|
||||
modify_key
|
||||
)?;
|
||||
let actual_value: String = mgr.clone().get("key").await?;
|
||||
assert_eq!(new_value[0], actual_value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
147
documentation/docs/oracle/tde.md
Normal file
147
documentation/docs/oracle/tde.md
Normal file
|
@ -0,0 +1,147 @@
|
|||
# Oracle Database Transparent Data Encryption (TDE)
|
||||
|
||||
**Oracle Database** [Transparent Data Encryption (TDE)](https://docs.oracle.com/en/database/oracle/oracle-database/23/dbtde/introduction-to-transparent-data-encryption.html) enables automatic encryption of data at rest in Oracle databases. Users can execute SQL queries normally while TDE handles encryption transparently in the background. Encryption keys are stored directly in the database but can be encrypted using **Oracle Key Vault**.
|
||||
|
||||
**Oracle Key Vault** centralizes encryption key management, offering secure storage and distribution for Oracle databases and enterprise applications. It uses `wallets` to the crucial TDE `master key` which acts as the `Key-Encryption-Key (KEK)` for TDE. The `master key` is stored in a `wallet` that is protected by a password. This `wallet` provides a secure and centralized location for managing encryption keys.
|
||||
|
||||
For enhanced security, **Hardware Security Modules (HSM)** can be integrated with Oracle Key Vault to provide additional protection for these `wallets`. This configuration establishes a [Root-of-Trust (RoT)](https://docs.oracle.com/en/database/oracle/key-vault/18.5/okvhm/getting-started-hsm.html#GUID-DADA7E20-82E2-40C9-A63A-4A159EBD5F09): when an HSM is deployed with Oracle Key Vault, the RoT remains in the HSM. The HSM RoT protects the Transparent Data Encryption (TDE) wallet password, which protects the TDE master key, which in turn protects all the encryption keys, certificates, and other security artifacts managed by the Oracle Key Vault server. Note that the HSM in this RoT usage scenario does not store any customer encryption keys. The customer keys are stored and managed directly by the Oracle Key Vault server.
|
||||
|
||||
Using HSM as a RoT is intended to mitigate attempts to recover keys from an Oracle Key Vault server which has been started in an unauthorized environment.
|
||||
Physical loss of an Oracle Key Vault server from a facility is one example of such a scenario.
|
||||
|
||||
When an **Oracle Key Vault server** is HSM-enabled, Oracle Key Vault contacts the HSM every five minutes (or whatever you have set the monitoring interval to) to ensure that the Root of Trust key is available and the TDE wallet password can be decrypted.
|
||||
|
||||
What Cosmian provides is:
|
||||
|
||||
- **a HSM client**: this is a PKCS#11 provider library that make the Oracle Key Vault a HSM client itself. **It enables the Root-of-Trust** by protecting the Oracle Key Vault wallets passwords. That library also provides a KMS client to communicate with the KMS server.
|
||||
- **a KMS server** that is interrogated by the KMS client. The KMS server can either front a HSM or act as a HSM but deployed in a secure environment.
|
||||
|
||||
<div align="center">
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph okv_client[Oracle Database]
|
||||
okvclient[okvclient.jar]
|
||||
dek[**Encryption Keys**
|
||||
encrypted by
|
||||
TDE Master Key]
|
||||
end
|
||||
okvclient -- OKV endpoint --> OKV[Oracle Key Vault]
|
||||
subgraph OKV[Oracle Key Vault]
|
||||
subgraph hsm_client[Cosmian **HSM** client]
|
||||
kms_client[Cosmian **KMS** client]
|
||||
end
|
||||
subgraph wallet[Wallet protected by HSM]
|
||||
tde[**TDE Master Key**]
|
||||
end
|
||||
tde --> hsm_client
|
||||
end
|
||||
kms_client -- REST API --> KMS[Cosmian **KMS** Server]
|
||||
KMS --> HSM[HSM]
|
||||
subgraph HSM[HSM]
|
||||
kek[**Wallet Encryption Key**]
|
||||
end
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Oracle Database](https://www.oracle.com/database/) installed and running
|
||||
- [Cosmian KMS server](https://docs.cosmian.com/key_management_system) installed and running
|
||||
- [Oracle Key Vault](https://docs.oracle.com/en/database/oracle/key-vault/21.10/okvig/oracle-key-vault-installation-and-upgrade-requirements.html#GUID-CBAC69C6-14DB-4AB9-8942-6FBF117770B0) installed and running
|
||||
|
||||
## Oracle Key Vault Configuration
|
||||
|
||||
Before configuring a HSM such as described in [Oracle Key Vault](https://docs.oracle.com/en/database/oracle/key-vault/21.10/okvhm/index.html), some steps are needed:
|
||||
|
||||
- Copy the PKCS#11 provider library to the Oracle Key Vault server to `/usr/local/okv/hsm/generic/libcosmian_pkcs11.so`
|
||||
- Copy the configuration of the PKCS#11 provider library to `/usr/local/okv/hsm/generic/cosmian.toml`
|
||||
- Override the OKV generic HSM configuration files:
|
||||
|
||||
- `/usr/local/okv/hsm/generic/okv_hsm_env`
|
||||
|
||||
```bash
|
||||
COSMIAN_PKCS11_LOGGING_LEVEL="trace"
|
||||
COSMIAN_CLI_CONF="/usr/local/okv/hsm/generic/cosmian.toml"
|
||||
COSMIAN_PKCS11_LOGGING_FOLDER="/var/okv/log/hsm"
|
||||
```
|
||||
|
||||
- `/usr/local/okv/hsm/generic/okv_hsm_conf`
|
||||
|
||||
```bash
|
||||
# Oracle Key Vault HSM vendor configuration file
|
||||
# Lines must be shorter than 4096 characters.
|
||||
|
||||
# The vendor name, to be displayed on the HSM page on the management console.
|
||||
VENDOR_NAME="cosmian"
|
||||
|
||||
# The location of the PKCS#11 library. This file must be preserved on upgrade.
|
||||
PKCS11_LIB_LOC="/usr/local/okv/hsm/generic/libcosmian_pkcs11.so"
|
||||
|
||||
# A colon-separated list of the full paths of files and directories that must
|
||||
# be preserved on upgrade. All of these files and directories should have been
|
||||
# created by the HSM client software setup; none should have existed on Oracle
|
||||
# Key Vault by default. These will be necessary when upgrading to a version
|
||||
# of Oracle Key Vault that is running on a higher major OS version.
|
||||
# Do not use wildcards.
|
||||
PRESERVED_FILES=""
|
||||
```
|
||||
|
||||
Then you can follow the official [HSM-Enabling in a Standalone Oracle Key Vault Deployment](https://docs.oracle.com/en/database/oracle/key-vault/21.10/okvhm/configuring-hsm-oracle-key-vault1.html#GUID-5645696A-3F19-4CF9-AE79-105569529182).
|
||||
|
||||
- At this point, a symmetric key labeled `OKV 18.1 HSM Root Key` has been create in KMS server
|
||||
- Create an endpoint with an associated `wallet`
|
||||
|
||||
## Oracle Database Configuration
|
||||
|
||||
For test purposes, we will use the official [Oracle docker container](https://container-registry.oracle.com/ords/f?p=113:4:106545702571334:::4:P4_REPOSITORY,AI_REPOSITORY,AI_REPOSITORY_NAME,P4_REPOSITORY_NAME,P4_EULA_ID,P4_BUSINESS_AREA_ID:1863,1863,Oracle%20Database%20Free,Oracle%20Database%20Free,1,0&cs=3Ti6PWKfgzS30ZJfMaoHY1WKna0Ss_mxMjkSQqTBI7AfugrE1tN9BilNn74Z9ynq_5THQFpwXGPfVnPbkILvCiw) image.
|
||||
|
||||
1. Configure TDE on Oracle Database: [United Mode](https://docs.oracle.com/en/database/oracle/oracle-database/23/dbtde/configuring-united-mode2.html#GUID-D3045557-FA85-4EA5-A85A-75EAE9D67E13)
|
||||
|
||||
```sql
|
||||
SQL> ALTER SYSTEM SET WALLET_ROOT='/etc/ORACLE/KEYSTORES/${ORACLE_SID}' SCOPE = SPFILE;
|
||||
SQL> SHUTDOWN IMMEDIATE
|
||||
SQL> STARTUP
|
||||
SQL> ALTER SYSTEM SET TDE_CONFIGURATION="KEYSTORE_CONFIGURATION=OKV" SCOPE=SPFILE SID='*';
|
||||
```
|
||||
|
||||
2. Follow the enrollment procedure for the `Oracle Database`: <https://docs.oracle.com/en/database/oracle/key-vault/21.4/okvag/okv_endpoints.html#GUID-5C1A6874-C7A9-41C6-859D-9FFD9010E13D>
|
||||
|
||||
3. Create and open a keystore and create the TDE `master key` open it:
|
||||
|
||||
```sql
|
||||
SQL> ADMINISTER KEY MANAGEMENT CREATE KEYSTORE IDENTIFIED BY <password>;
|
||||
SQL> ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY <password>;
|
||||
SQL> ADMINISTER KEY MANAGEMENT SET KEY IDENTIFIED BY <password> WITH BACKUP;
|
||||
# Check keystore status:
|
||||
SQL> SELECT STATUS FROM V$ENCRYPTION_WALLET;
|
||||
# Check encryption keys:
|
||||
SQL> select KEY_ID,KEYSTORE_TYPE,CREATOR_DBNAME,ACTIVATION_TIME,KEY_USE,ORIGIN from v$encryption_keys;
|
||||
```
|
||||
|
||||
## Example of encrypted table
|
||||
|
||||
Create a test database and a table:
|
||||
|
||||
```sql
|
||||
CONNECT SYS AS SYSDBA
|
||||
CREATE DATABASE test_db
|
||||
DATAFILE 'test_system' SIZE 10M
|
||||
LOGFILE GROUP 1 ('test_log1a', 'test_log1b') SIZE 500K,
|
||||
GROUP 2 ('test_log2a', 'test_log2b') SIZE 500K;
|
||||
|
||||
CREATE USER C##u1 IDENTIFIED BY pwd1 DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP QUOTA UNLIMITED ON USERS CONTAINER=ALL;
|
||||
GRANT CREATE SESSION to C##u1;
|
||||
GRANT CREATE TABLE TO C##u1;
|
||||
```
|
||||
|
||||
Connect as C##u1:
|
||||
|
||||
```sql
|
||||
connect test
|
||||
create table infos_employees (firstname varchar2(40), name varchar2(40),
|
||||
address varchar2(40) encrypt using 'AES256',
|
||||
zip_code number(6) encrypt using 'AES256');
|
||||
insert into infos_employees values ('John','Doe','55 rue de la Boétie, Paris','75008');
|
||||
```
|
|
@ -1,3 +1,5 @@
|
|||
# Prim'X CRYHOD
|
||||
|
||||
The Cosmian KMS can be used to unlock Prim'x CRYHOD partitions
|
||||
|
||||
## Configuring Prim'X CRYHOD
|
||||
|
@ -55,7 +57,7 @@ Click `next`
|
|||
## Adjusting the KMS location and authentication
|
||||
|
||||
The configuration file is located in the User home `.cosmian` sub-directory,
|
||||
in the `kms.json` file.
|
||||
in the `cosmian.toml` file.
|
||||
|
||||
See [Authenticating users to the KMS](../authentication.md#authenticating-using-tls-client-certificates) to learn
|
||||
how to configure the
|
||||
|
@ -65,12 +67,11 @@ also manage the machines certificates).
|
|||
Here is an example configuration file for the PKCS#11 provider library accessing the KMS using a
|
||||
PKCS#12 file for authentication.
|
||||
|
||||
```json
|
||||
{
|
||||
"server_url": "https://kms.acme.com:9999",
|
||||
"ssl_client_pkcs12_path": "./certificates/machine123.acme.p12",
|
||||
"ssl_client_pkcs12_password": "machine123_pkcs12_password"
|
||||
}
|
||||
```toml
|
||||
[kms_config.http_config]
|
||||
server_url = "https://kms.acme.com:9999"
|
||||
ssl_client_pkcs12_path = "./certificates/machine123.acme.p12"
|
||||
ssl_client_pkcs12_password = "machine123_pkcs12_password"
|
||||
```
|
||||
|
||||
## Viewing the logs
|
||||
|
|
|
@ -24,20 +24,20 @@ default-hierarchy=unified
|
|||
```
|
||||
|
||||
Unfortunately, Ubuntu 22.04 does not provide p11-kit support, however the setup works fine for
|
||||
Ubuntu 23.10.
|
||||
Ubuntu 24.04.
|
||||
|
||||
### 1. Install the `p11-kit` package
|
||||
|
||||
#### Ubuntu 23.10
|
||||
#### Ubuntu 24.04
|
||||
|
||||
```bash
|
||||
sudo apt install p11-kit
|
||||
sudo apt install p11-kit cryptsetup
|
||||
```
|
||||
|
||||
#### RHEL 9
|
||||
|
||||
```bash
|
||||
sudo dnf install p11-kit
|
||||
sudo dnf install p11-kit cryptsetup
|
||||
```
|
||||
|
||||
### 2. Create the PKCS#11 configuration and module directories
|
||||
|
@ -103,7 +103,7 @@ cosmian_pkcs11: /usr/local/lib/libcosmian_pkcs11.so
|
|||
The PKCS#11 module uses the same configuration file as
|
||||
the [CLI](../../cosmian_cli/index.md).
|
||||
Since it may be run as a system user, the configuration file should be made available
|
||||
in `/etc/cosmian/kms.json`.
|
||||
in `/etc/cosmian/cosmian.toml`.
|
||||
|
||||
See [Authenticating users to the KMS](../authentication.md) to learn
|
||||
how to configure the KMS to use Open ID connect or certificate authentication.
|
||||
|
@ -111,12 +111,11 @@ how to configure the KMS to use Open ID connect or certificate authentication.
|
|||
Here is an example configuration file for the PKCS#11 provider library accessing the KMS using a
|
||||
PKCS#12 file for authentication.
|
||||
|
||||
```json
|
||||
{
|
||||
"server_url": "https://kms.acme.com:9999",
|
||||
"ssl_client_pkcs12_path": "./certificates/machine123.acme.p12",
|
||||
"ssl_client_pkcs12_password": "machine123_pkcs12_password"
|
||||
}
|
||||
```toml
|
||||
[kms_config.http_config]
|
||||
server_url = "https://kms.acme.com:9999"
|
||||
ssl_client_pkcs12_path = "./certificates/machine123.acme.p12"
|
||||
ssl_client_pkcs12_password = "machine123_pkcs12_password"
|
||||
```
|
||||
|
||||
To use Open ID connect, install the [Cosmian CLI](../../cosmian_cli/index.md) from
|
||||
|
@ -149,7 +148,7 @@ openssl pkcs12 -export -out certificate.p12 -inkey private_key.pem -in cert.pem
|
|||
### 4. Import the PKCS12 file into the Cosmian KMS using a `disk-encryption` tag
|
||||
|
||||
```bash
|
||||
cosmian kms certificates import -f pkcs12 -t disk-encryption certificate.p12
|
||||
cosmian kms certificates import -f pkcs12 -t disk-encryption certificate.p12 disk-encryption
|
||||
|
||||
The private key in the PKCS12 file was imported with id: 6fc631...
|
||||
Tags:
|
||||
|
@ -212,6 +211,12 @@ The encrypted passphrase will be stored in the LUKS header in key slot 0.
|
|||
sudo cryptsetup luksFormat --type luks2 --key-slot 0 /dev/vda4
|
||||
```
|
||||
|
||||
or alternatively, if you created a file:
|
||||
|
||||
```bash
|
||||
sudo cryptsetup luksFormat --type luks2 --key-slot 0 /path/to/file
|
||||
```
|
||||
|
||||
Make sure to remember the passphrase, as it will be needed to unlock the partition
|
||||
during `cryptenroll` or when rotating the RSA keys.
|
||||
|
||||
|
@ -225,21 +230,12 @@ The RSA key pair is searched opn the KMS using a tag controlled by
|
|||
the `COSMIAN_PKCS11_DISK_ENCRYPTION_TAG` environment variable.
|
||||
When not set, the default tag searched is `disk-encryption`.
|
||||
|
||||
### 1. Verify that Cosmian-KMS token is available for the partition
|
||||
|
||||
```bash
|
||||
> sudo systemd-cryptenroll /dev/vda4 --pkcs11-token-uri=list
|
||||
|
||||
URI LABEL MANUFACTURER MODEL
|
||||
pkcs11:model=software;manufacturer=Cosmian;serial=x.y.z;token=Cosmian-KMS Cosmian-KMS Cosmian software
|
||||
```
|
||||
|
||||
### 2. Enroll the partition with the Cosmian KMS
|
||||
### 1. Enroll the partition with the Cosmian KMS
|
||||
|
||||
```bash
|
||||
# this is equivalent to
|
||||
# sudo COSMIAN_PKCS11_LOGGING_LEVEL=info COSMIAN_PKCS11_DISK_ENCRYPTION_TAG=disk-encryption systemd-cryptenroll /dev/vda4 --pkcs11-token-uri=pkcs11:token=Cosmian-KMS
|
||||
> sudo systemd-cryptenroll /dev/vda4 --pkcs11-token-uri=pkcs11:token=Cosmian-KMS
|
||||
> sudo systemd-cryptenroll --pkcs11-token-uri=pkcs11:token=Cosmian-KMS /dev/vda4
|
||||
|
||||
🔐 Please enter current passphrase for disk /dev/vda4: *************
|
||||
cosmian-pkcs11 module logging at INFO level to file /var/log/cosmian-pkcs11.log
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# Veracrypt integration with Cosmian KMS
|
||||
|
||||
The Cosmian KMS is integrated with [Veracrypt](https://www.veracrypt.fr/en/Home.html)
|
||||
disk encryption using the Cosmian KMS PKCS#11 provider library.
|
||||
|
||||
|
@ -8,7 +10,7 @@ formal security evaluation from BSI.
|
|||
Using the Cosmian KMS PKCS#11 provider library, Veracrypt can use keys stored in the KMS to
|
||||
encrypt and decrypt volumes.
|
||||
|
||||

|
||||

|
||||
|
||||
## Installing the PKCS#11 provider library on Veracrypt
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ nav:
|
|||
- Quick start: quick_start.md
|
||||
- Use cases and integrations:
|
||||
- Encrypting and decrypting at scale: encrypting_and_decrypting_at_scale.md
|
||||
- S/MIME Email encryption: pki/smime.md
|
||||
- Google workspace Client-Side Encryption (CSE):
|
||||
- Getting started: google_cse/index.md
|
||||
- Configuring the .well-known file: google_cse/configuring-the-well-known-file-and-server.md
|
||||
|
@ -77,7 +78,8 @@ nav:
|
|||
- Veracrypt: pkcs11/veracrypt.md
|
||||
- LUKS: pkcs11/luks.md
|
||||
- Cryhod: pkcs11/cryhod.md
|
||||
- S/MIME Email encryption: pki/smime.md
|
||||
- Oracle Database Transparent Data Encryption (TDE):
|
||||
- Integration: oracle/tde.md
|
||||
- API Endpoints: api.md
|
||||
- Installation:
|
||||
- Getting started: installation/installation_getting_started.md
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue