Procedures
High Level steps for implementing Postgres TDE using Entrust KeyControl:
-
Check the prerequisites.
-
Create a certificate request (CSR) for the DSE Server.
-
Generate a KMIP client certificate for the DSE Server.
-
Test access to the KMIP Service.
-
Add a KMIP Host.
-
Encrypt Table Data.
Check Prerequisites
Before implementing Postgres TDE using Entrust KeyControl, complete the following tasks:
-
Check the Python 3 installation on the Cassandra DSE server:
$ python3 --version Python 3.11.9
-
Check the Java installation
$ java --version OpenJDK Runtime Environment (build 21.0.4+7-Ubuntu-1ubuntu224.04) OpenJDK 64-Bit Server VM (build 21.0.4+7-Ubuntu-1ubuntu224.04, mixed mode, sharing)
If you are using OpenJDK, the results should resemble the following output:
openjdk version "11.0.x" YYYY-MM-DD OpenJDK Runtime Environment 18.9 (build 11.0.x+xx) OpenJDK 64-Bit Server VM 18.9 (build 11.0.x+xx, mixed mode)
-
Check that the Cassandra (DSE) service is running
$ systemctl status dse.service ● dse.service - LSB: DataStax Enterprise Loaded: loaded (/etc/init.d/dse; generated) Active: active (running) since Fri 2024-09-06 21:32:21 UTC; 9s ago Docs: man:systemd-sysv-generator(8) Process: 864 ExecStart=/etc/init.d/dse start (code=exited, status=0/SUCCESS) Tasks: 377 (limit: 9519) Memory: 2.7G (peak: 2.7G) CPU: 47.372s CGroup: /system.slice/dse.service └─1720 /usr/lib/jvm/java-11-openjdk-amd64//bin/java -Ddse.server_process -Djdk.attach.allowAttachSelf=true --add-exports java.base/jdk.internal.misc=ALLUNNAMED --add-opens java.base/jdk.internal.module=ALL-UNNAMED --add-exports java.base/jdk.internal.ref=A>
-
Launch
cqlsh
$ /usr/bin/cqlsh Connected to Test Cluster at 127.0.0.1:9042. [cqlsh 6.8.0 | DSE 6.9.2 | CQL spec 3.4.5 | DSE protocol v2] Use HELP for help. cqlsh>
Create a certificate request (CSR) for the DSE server
-
Change your working directory to the
$home
$ cd ~
-
Create a new certificate request with a three-year duration:
$ openssl req -new -nodes -keyout dse-serv.key -out dse-serv.csr Generating a RSA private key ...................................................................................... ..+++++ ...................................................................................... +++++ writing new private key to 'dse-serv.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:UK State or Province Name (full name) []:England Locality Name (eg, city) [Default City]:London Organization Name (eg, company) [Default Company Ltd]:Entrust Organizational Unit Name (eg, section) []:DPS Common Name (eg, your name or your server's hostname) []:dse-serv Email Address []:<user_email_address> Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:<empty> An optional company name []:Entrust
-
Verify that the CSR has been generated:
$ ls dse-serv.csr dse-serv.key
-
Download the
csr
file to your local machine:$ scp user@<dse_hostname>:dse-serv.csr . dse-serv.csr
The generated file dse-serv.csr will be used in the next step to generate a KMIP client certificate.
Generate a KMIP Client Certificate for the DSE server
-
Sign into the KCaaS or KeyControl KMIP vault webGUI using an account with Security Admin privileges.
-
Navigate to Security > Client certificates.
-
Select the + button.
-
In the Create Client Certificate dialog box, specify the options you want to use.
-
Certificate Name:
dse-serv
-
Certificate Expiration: 3 years from today
-
Certificate Signing Request (CSR):
dse-serv.csr
-
Encrypt Certificate Bundle: No
-
-
Select Create.
A message is dispayed indicating that the certificate has been successfully generated. -
Select the check box next to the newly generated certificate.
-
Select Download Certificate. A zip file is downloaded by the browser.
The zip file contains a client certificate .pem
file and a CA certificate file calledcacert.pem
. -
Extract the zip file contents:
$ unzip dse-serv_2024-*.zip Archive: dse-serv_2023-12-15-16-54-42.zip inflating: dse-serv.pem inflating: cacert.pem
-
Upload the two
.pem
files to the DSE linux machine:$ scp dse-serv.pem user@<dse_hostname>:. $ scp cacert.pem user@<dse_hostname>:.
Test access the KMIP Service
-
Show information about the TLS certificate of the KMIP server (KMS):
$ echo | openssl s_client -servername <kmip_hostname> -connect <kmip_hostname>:5696 2>/dev/null | openssl x509 -noout -issuer -subject -dates -ext subjectAltName fingerprint issuer=C = US, O = HyTrust Inc., CN = HyTrust KeyControl Certificate Authority subject=C = US, O = HyTrust Inc., CN = ip-172-21-103-172.skynet.entrust.cloud notBefore=Jun 1 00:00:00 2011 GMT notAfter=Dec 31 23:59:59 2049 GMT X509v3 Subject Alternative Name: IP Address:172.21.103.172, DNS:ip-172-21-103-172, DNS:ip-172-21-103-172.skynet.entrust.cloud SHA1 Fingerprint=30:10:0E:9D:DA:2B:24:8C:B1:96:DE:1F:17:08:20:59:51:60:94:04
-
Test the CA certificate:
$ openssl s_client -CAfile cacert.pem -connect <kmip_hostname>:5696 Client Certificate Types: RSA sign, DSA sign, ECDSA sign Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+S HA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1 Shared Requested Signature Algorithms: RSA+SHA512:ECDSA+SHA512:RSA+SHA384:ECDSA+SHA384:RSA+SHA256:ECDSA+SHA256:RSA+SHA224:ECD SA+SHA224:RSA+SHA1:ECDSA+SHA1 Peer signing digest: SHA256 Peer signature type: RSA Server Temp Key: ECDH, P-256, 256 bits -- SSL handshake has read 2813 bytes and written 460 bytes Verification: OK -- New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: 2ABAF7C3DF81A077634ED5E8480DA23C4D9C1CD3A0C46982224F4DA38B93CE73 Session-ID-ctx: Master-Key: 20606FADDD52929948B0D754D19F412FA032ACB4859D7E5B0B689BFCCB2BE73D5566EA58F8EA5837E168210046FA5AE4 PSK identity: None PSK identity hint: None SRP azureusername: None TLS session ticket lifetime hint: 300 (seconds) TLS session ticket: 0000 - c2 d0 4a 51 b8 fb fe 66-4f e8 42 3c fe 85 66 3e ..JQ...fO.B<..f> 0010 - 8b 17 a0 f3 9b fa e8 e0-92 b9 98 87 f4 ca 8f 98 ................ 0020 - 7a 46 55 49 dd 7e 01 62-e9 1b cd 26 44 7f d3 10 zFUI.~.b...&D... 0030 - b7 77 f3 c9 bb 1b 4a be-82 c2 4f 43 d8 f2 8d 18 .w....J...OC.... 0040 - f1 62 5f 9a 55 02 ec e7-b6 76 17 41 46 7d d3 c8 .b_.U....v.AF}.. 0050 - e0 62 7b f2 7b ee ba 3d-49 1a 15 bb 76 ed 7a b0 .b{.{..=I...v.z. 0060 - 70 76 bc c0 20 b6 a9 83-86 f4 8d 16 e2 4e 58 7c pv.. ........NX| 0070 - 75 83 7c d6 67 e4 16 1f-d4 94 9d e9 b3 9c ba 96 u.|.g........... 0080 - 79 8c d5 52 3d 5d 04 72-61 aa c9 29 06 38 45 4f y..R=].ra..).8EO 0090 - d8 03 86 fc 5f 26 56 d8-c6 cf 74 88 77 2d 00 ab ...._&V...t.w-.. 00a0 - 7a 49 6b 21 97 c3 9d 54-fc 8f 76 d6 be fa 08 36 zIk!...T..v....6 00b0 - c2 57 c7 96 83 ff 54 c2-0c 70 b3 c6 c1 e5 00 a1 .W....T..p...... Start Time: 1563985354 Timeout : 7200 (sec) Verify return code: 0 (ok) Extended master secret: no -- closed
Add a KMIP host
-
Copy the certificate and CA
.pem
files to the home directory of the DSE server. -
Convert the key pair from PEM to a DSE compatible JKS format.
$ openssl pkcs12 -export -out dse-serv.p12 -inkey dse-serv.key -in dse-serv.pem Enter Export Password:<password> Verifying - Enter Export Password:<password>
-
Create a JKS keystore:
$ keytool -importkeystore -destkeystore dse-serv.jks -srcstoretype PKCS12 -srckeystore dse-serv.p12 Importing keystore dse-serv.p12 to dse-serv.jks... Enter destination keystore password:<password> Re-enter new password:<password> Enter source keystore password:<password> Entry for alias 1 successfully imported. Import command completed: 1 entries successfully imported, 0 entries failed or cancelled
-
Use openssl to extract the both the KMIP server certificate and the KMIP CA certificate:
$ openssl s_client -connect <kmip_hostname>:5696 -showcerts
This returns the entire certificate chain, including the KMIP server certificate and possibly the intermediate and CA certificates.
The KMIP Server Certificate is the server’s own certificate that the client (your JVM) is trying to validate.
The CA Certificate ensures that the JVM trusts authority that issued the server certificate, creating a valid certificate chain. Without the CA certificate, you may get errors related to an incomplete certification path.
-
Copy each certificate (from
-----BEGIN CERTIFICATE-----
to-----END CERTIFICATE-----
) and save them as separate.crt
files, for example:-
KMIP server certificate:
kmip-server-cert.crt
-
CA certificate, if available:
ca-cert.crt
-
-
Import the KMIP Server Certificate into the Truststore:
$ sudo keytool -import -alias kmip-server-cert -file kmip-server-cert.crt -keystore kmip_truststore.jks -storepass <password> Certificate was added to keystore
-
Verify that the KMIP server certificate has been added correctly:
$ keytool -list -v -keystore /etc/dse/conf/kmip_truststore.jks -storepass <password> | grep -A 1 kmip-server-cert Alias name: kmip-server-cert Creation date: Sep 6, 2024
-
Verify that the KMIP CA certificate has been added correctly:
$ keytool -list -v -keystore /etc/dse/conf/kmip_truststore.jks -storepass <password> | grep -A 1 kmip-server-cert Alias name: kmip-server-cert Creation date: Sep 6, 2024
-
Move the keystore and truststore to a directory accessible by DSE and change the file to allow the DSE account read/write access:
$ sudo mkdir /etc/dse/conf $ sudo chown cassandra:cassandra /etc/dse/conf/ $ sudo cp *.jks /etc/dse/conf $ sudo chown cassandra:cassandra /etc/dse/conf/*.*
-
Delete or secure the files used to create the keystore and truststore.
-
Add the host details to the
kmip_hosts
section of the/etc/dse/dse.yaml
:kmip_hosts: <kmip_group_name>: hosts: <kmip_hostname> keystore_path: /etc/dse/conf/dse-serv.jks keystore_type: jks keystore_password: <password> truststore_path: /etc/dse/conf/kmip_truststore.jks truststore_type: jks truststore_password: <password> key_cache_millis: 300000 timeout: 1000 protocol: <protocol> cipher_suites: <supported_cipher>
-
Restart DataStax Enterprise:
$ sudo service dse restart
-
Check that the DSE service is running:
$ systemctl status dse.service ● dse.service - LSB: DataStax Enterprise Loaded: loaded (/etc/init.d/dse; generated) Active: active (running) since Fri 2024-09-06 21:32:21 UTC; 9s ago Docs: man:systemd-sysv-generator(8) Process: 864 ExecStart=/etc/init.d/dse start (code=exited, status=0/SUCCESS) Tasks: 377 (limit: 9519) Memory: 2.7G (peak: 2.7G) CPU: 47.372s CGroup: /system.slice/dse.service └─1720 /usr/lib/jvm/java-11-openjdk-amd64//bin/java -Ddse.server_process -Djdk.attach.allowAttachSelf=true --add-exports java.base/jdk.internal.misc=ALLUNNAMED --add-opens java.base/jdk.internal.module=ALL-UNNAMED --add-exports java.base/jdk.internal.ref=A>
Encrypt table data
-
Back up the configuration files:
$ sudo cp /etc/dse/dse.yaml /etc/dse/dse.yaml.save $ sudo cp /etc/dse/cassandra/cassandra.yaml /etc/dse/cassandra/cassandra.yaml.save
-
Run
cqlsh
:$ /usr/bin/cqlsh Connected to Test Cluster at 127.0.0.1:9042. [cqlsh 6.8.0 | DSE 6.9.2 | CQL spec 3.4.5 | DSE protocol v2] Use HELP for help. cqlsh>
-
Create a keyspace for your application:
> CREATE KEYSPACE my_keyspace WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 3};
-
After creating your keyspace, you can use it with:
> USE my_keyspace;
-
Create an encrypted table:
> CREATE TABLE my_keyspace.customers ( customer_id UUID PRIMARY KEY, first_name text, last_name text, email text ) WITH COMPRESSION = { 'class': 'Encryptor', 'key_provider': 'KmipKeyProviderFactory', 'kmip_host': 'kmip.entrust.com', 'cipher_algorithm': 'AES/ECB/PKCS5Padding', 'secret_key_strength': 128 };
-
Describe the created database:
> USE my_keyspace; > DESCRIBE TABLE customers; CREATE TABLE my_keyspace.customers ( customer_id uuid PRIMARY KEY, email text, first_name text, last_name text ) WITH additional_write_policy = '99PERCENTILE' AND bloom_filter_fp_chance = 0.01 AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'} AND comment = '' AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'} AND compression = {'chunk_length_in_kb': '64', 'cipher_algorithm': 'AES/ECB/PKCS5Padding', 'class': 'org.apache.cassandra.io.compress.Encryptor', 'key_provider': 'KmipKeyProviderFactory', 'kmip_host': 'kmip.entrust.com', 'secret_key_strength': '128'} AND crc_check_chance = 1.0 AND default_time_to_live = 0 AND gc_grace_seconds = 864000 AND max_index_interval = 2048 AND memtable_flush_period_in_ms = 0 AND min_index_interval = 128 AND nodesync = {'enabled': 'true', 'incremental': 'true'} AND read_repair = 'BLOCKING' AND speculative_retry = '99PERCENTILE';
A new key has been created in the KMIP vault:
UUID: e9c264bd-c145-4ec1-a88a-67cf2c991631 Object Type: Symmetric Key State: ACTIVE Activation Date: Sep 7, 2024, 12:06:18 AM Cryptographic Usage Mask: Encrypt,Decrypt Key Format Type: Raw Cryptographic Algorithm: AES Cryptographic Length: 128 Encrypted with KEK: No Initial Date: Sep 7, 2024, 12:06:18 AM Last Status Changed Date: Sep 7, 2024, 12:06:18 AM x-dse-version: 6.9.2
-
Display table content.
cqlsh> SELECT * FROM my_keyspace.customers; customer_id | email | first_name | last_name ----------------------------------------+-----------------------+---------------+----------- 2056af70-0f0a-4d4d-a8a6-561883c523a0 | jane.doe@example.com | Jane | Doe dfcb3df4-4f26-4df9-98aa-a035f8149641 | john.doe@example.com | John | Doe