If you are planning to use client-side field level encryption with a KMIP compliant key store in MongoDB, you can use PyKMIP. These steps outline the configuration required to setup your dev KMIP server.
Prerequisites
- MongoDB Enterprise Edition(either standalone or a single node replica set)
- Compass
- OpenSSL
- Self-signed Certificates(CA Cert, Client Cert & Server Certs)
- Python
- Client code for testing: clone the repo https://github.com/mongodb-university/docs-in-use-encryption-examples.git
Generate the Certificates
At a Powershell prompt
cd /
mkdir -p csfle/certs
cd csfle/certs
Save all the commands below in a file named create_certs.ps1 and run it from the Powershell prompt ./create_certs.ps1
# Define file paths
$caKeyPath = "ca-key.pem"
$caCertPath = "ca-cert.pem"
$serverKeyPath = "server-key.pem"
$serverCertPath = "server-cert.pem"
$clientKeyPath = "client-key.pem"
$clientCertPath = "client-cert.pem"
$mergedClientPath = "client-key-cert.pem"
# Step 1: Generate CA key and certificate
openssl req -new -x509 -days 365 -nodes -out $caCertPath -keyout $caKeyPath -subj "/CN=MyCA"
# Step 2: Generate server key and certificate signed by the CA
openssl genpkey -algorithm RSA -out $serverKeyPath
openssl req -new -key $serverKeyPath -out server.csr -subj "/CN=localhost"
openssl x509 -req -in server.csr -CA $caCertPath -CAkey $caKeyPath -CAcreateserial -out $serverCertPath -days 365
Remove-Item server.csr
# Step 3: Generate client key and certificate signed by the CA with SAN
openssl genpkey -algorithm RSA -out $clientKeyPath
openssl req -new -key $clientKeyPath -out client.csr -subj "/CN=Client" -addext "subjectAltName=DNS:localhost"
openssl x509 -req -in client.csr -CA $caCertPath -CAkey $caKeyPath -CAcreateserial -out $clientCertPath -days 365
Remove-Item client.csr
# Step 4: Merge client key and certificate into a single file
Get-Content $clientKeyPath, $clientCertPath | Set-Content $mergedClientPath
# Display success message
Write-Host "Certificates and keys generated successfully:"
Write-Host "CA Certificate: $caCertPath"
Write-Host "Server Certificate: $serverCertPath"
Write-Host "Client Certificate: $clientCertPath"
Write-Host "Merged Client Key and Certificate: $mergedClientPath"
#Create a local database to hold the CMKs
cd c:/csfle
New-Item -ItemType File pykmip.sqlite
Install PyKMIP
Run the following commands
pip install cryptography
pip install pykmip
pip install sqlalchemy
Create the PyKMIP configuration
In the folder c:\csfle\ create a configuration file create_server_conf.ps1 and add the code below. Save and run the file
$configFile = "kmip-server.conf"
Remove-Item $configFile
New-Item -ItemType File -Path $configFile
New-Item -ItemType File -Path server.log
$config= "[server]
hostname=127.0.0.1
port=5696
certificate_path=C:\csfle\certs\server-cert.pem
key_path=C:\csfle\certs\server-key.pem
ca_path=C:\csfle\certs\ca-cert.pem
auth_suite=TLS1.2
policy_path=
enable_tls_client_auth=False
tls_cipher_suites=
logging_level=DEBUG
database_path=C:\cfsfle\pykmip.sqlite
[client]
host=127.0.0.1
port=5696
certfile=C:\csfle\certs\client-cert.pem
keyfile=C:\csfle\certs\client-key.pem
ca_certs=C:\csfle\certs\ca-cert.pem
ssl_version=PROTOCOL_TLSv1_2
Add-Content -Path $configFile -Value $config
Start the Server
From the c:\csfle directory run the following at a prompt:
pykmip-server -f kmip-server.conf -l server.log
Test the Installation
Create a script kmip_client.py and add the the following code:
from kmip.pie import client
from kmip.core import enums
CONFIG_FILE ="C:\csfle\kmip-server.conf"
ALGORITHM=enums.CryptographicAlgorithm.CAST5
with client.ProxyKmipClient(config_file=CONFIG_FILE) as c:
uid = c.create(algorithm=ALGORITHM,
length=128,
)
symmetric_key = c.get(uid)
print(f"Symmetric Key Value: {symmetric_key.value}")
print(f"Created {ALGORITHM} key with ID: {uid}")
Check the Server Logs
2024-02-05 12:00:29,148 - kmip.server - INFO - Server successfully bound socket handler to 127.0.0.1:5696
2024-02-05 12:00:29,148 - kmip.server - INFO - Starting connection service...
2024-02-05 12:03:00,198 - kmip.server - INFO - Receiving incoming connection from: 127.0.0.1:51297
2024-02-05 12:03:00,199 - kmip.server - INFO - Dedicating session 00000001 to 127.0.0.1:51297
2024-02-05 12:03:00,202 - kmip.server.session.00000001 - INFO - Starting session: 00000001
2024-02-05 12:03:00,208 - kmip.server.session.00000001 - DEBUG - Request encoding: b'4200780100000120'
2024-02-05 12:03:00,209 - kmip.server.session.00000001 - DEBUG - Request encoding: b'4200770100000038420069010000002042006a0200000004000000010000000042006b0200000004000000020000000042000d0200000004000000010000000042000f01000000d842005c0500000004000000010000000042007901000000c04200570500000004000000020000000042009101000000a8420008010000003042000a070000001743727970746f6772617068696320416c676f726974686d0042000b05000000040000001200000000420008010000003042000a070000001443727970746f67726170686963204c656e6774680000000042000b02000000040000008000000000420008010000003042000a070000001843727970746f67726170686963205573616765204d61736b42000b02000000040000000c00000000'
2024-02-05 12:03:00,210 - kmip.server.session.00000001 - DEBUG - Possible session ciphers: 15
2024-02-05 12:03:00,210 - kmip.server.session.00000001 - DEBUG - ('TLS_AES_256_GCM_SHA384', 'TLSv1.3', 256)
2024-02-05 12:03:00,211 - kmip.server.session.00000001 - DEBUG - ('TLS_CHACHA20_POLY1305_SHA256', 'TLSv1.3', 256)
2024-02-05 12:03:00,211 - kmip.server.session.00000001 - DEBUG - ('TLS_AES_128_GCM_SHA256', 'TLSv1.3', 128)
2024-02-05 12:03:00,212 - kmip.server.session.00000001 - DEBUG - ('AES128-SHA256', 'TLSv1.2', 128)
2024-02-05 12:03:00,212 - kmip.server.session.00000001 - DEBUG - ('AES256-SHA256', 'TLSv1.2', 256)
2024-02-05 12:03:00,213 - kmip.server.session.00000001 - DEBUG - ('DHE-DSS-AES128-SHA256', 'TLSv1.2', 128)