1. Introduction


CloudStack has used StandardPBEStringEncryptor from jasypt for more than 10 years. 

The encryptor use algorithm "PBEWithMD5AndDes", which is considered as Insecure, because it uses MD5 and DES which has only 56-bits key.

After investigation, we decided to replace it with an implementation of AES-GCM algorithm. The key length of AES-GCM is 256-bit. Please refer to https://github.com/google/tink


Main changes of this feature:


Community PR to main/4.18: https://github.com/apache/cloudstack/pull/7003

2. New encryptors

There are 4 new classes introduced in this feature:

3. cloudstack-setup-databases changes

"/usr/bin/cloudstack-setup-databases" is used to setup

it has been updated to support



Please note: com.cloud.utils.crypt.EncryptionCLI in /usr/share/cloudstack-common/lib/cloudstack-utils.jar is used to replace org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI


3.1 Usage


# cloudstack-setup-databases -h
Usage: cloudstack-setup-databases user:[password]@mysqlhost:[port] [--deploy-as=rootuser:[rootpassword]] [--auto=/path/to/server-setup.xml] [-e ENCRYPTIONTYPE] [-m MGMTSECRETKEY] [-k DBSECRETKEY] [–debug]


Options:
  -h, --help            show this help message and exit
  -v, --debug           If enabled, print the commands it will run as they run
  -d ROOTCREDS, --deploy-as=ROOTCREDS
                        Colon-separated user name and password of a MySQL user
                        with administrative privileges
  -s, --schema-only     Creates the db schema without having to pass root
                        credentials - Please note: The databases (cloud,
                        cloud_usage) and user (cloud) has to be configured
                        manually prior to running this script when using this
                        flag.
  -a SERVERSETUP, --auto=SERVERSETUP
                        Path to an XML file describing an automated unattended
                        cloud setup
  -e ENCRYPTIONTYPE, --encrypt-type=ENCRYPTIONTYPE
                        Encryption method used for db password encryption.
                        Valid values are file, web and env. Default is file.
  -m MGMTSECRETKEY, --managementserver-secretkey=MGMTSECRETKEY
                        Secret key used to encrypt confidential parameters in
                        db.properties. A string, default is password
  -k DBSECRETKEY, --database-secretkey=DBSECRETKEY
                        Secret key used to encrypt sensitive database values.
                        A string, default is password
  -i MSHOSTIP, --mshost=MSHOSTIP
                        Cluster management server host IP. A string, by
                        default it will try to detect a local IP
  -r REGIONID, --regionid=REGIONID
                        Region Id for the management server cluster
  -c DBCONFPATH, --db-conf-path=DBCONFPATH
                        The path to find db.properties which hold db
                        properties
  -f DBFILESPATH, --db-files-path=DBFILESPATH
                        The path to find sql files to create initial
                        database(s)
  -j ENCRYPTIONJARPATH, --encryption-jar-path=ENCRYPTIONJARPATH
                        The cloudstack jar to be used to encrypt the values in
                        db.properties
  -n ENCRYPTIONKEYFILE, --encryption-key-file=ENCRYPTIONKEYFILE
                        The name of the file in which encryption key to be
                        generated
  -g ENCRYPTORVERSION, --encryptor-version=ENCRYPTORVERSION
                        The encryptor version to be used to encrypt the values
                        in db.properties
  -b MYSQLBINPATH, --mysql-bin-path=MYSQLBINPATH
                        The mysql installed bin path

3.2 Examples


create /etc/cloudstack/management/key (content of the file is the management key = password)

create /etc/cloudstack/management/db.properties with default passwords (management key = password, db key = password)

in db.properties (1) db.cloud.encryptor.version is not set;  (2) db.cloud.encryption.type=file; (3) db.cloud.password, db.cloud.encrypt.secret, db.usage.password are encrypted by default encryptor (currently V2)


create /etc/cloudstack/management/key (content of the file is the management key = mgmtkey)

create /etc/cloudstack/management/db.properties with keys  (management key = mgmtkey, db key = dbkey)

in db.properties (1) db.cloud.encryptor.version=V1; (2) db.cloud.encryption.type=file; (3) db.cloud.password, db.cloud.encrypt.secret, db.usage.password are encrypted by encryptor V1.

recreate database using mysql user root:'Password'


create /etc/cloudstack/management/db.properties with keys  (management key = $CLOUD_SECRET_KEY, db key = password)

in db.properties (1) db.cloud.encryptor.version=V2;  (2) db.cloud.encryption.type=env; (3) db.cloud.password, db.cloud.encrypt.secret, db.usage.password are encrypted by encryptor V2;

recreate database using mysql user root:'Password'

4. New CloudStack startup process

5. cloudstack-migrate-databases changes

"/usr/bin/cloudstack-migrate-databases" are used to migrate the following with new keys/encryptor.

It has been updated to support

5.1 Usage

# cloudstack-migrate-databases -h
usage: cloudstack-migrate-databases -d <oldDBKey> -m <oldMSKey> [-e <newDBKey>] [-n <newMSKey>] [-v
       <version>] [-f] [-h] [-l] [-s]
Options:
 -d,--oldDBKey <oldDBKey>                (required) Current DB Secret Key
 -m,--oldMSKey <oldMSKey>                (required) Current Mgmt Secret Key
 -e,--newDBKey <newDBKey>                New DB Secret Key
 -n,--newMSKey <newMSKey>                New Mgmt Secret Key
 -v,--version <version>                  New DB Encryptor Version. Options are V1, V2.
 -f,--force-database-migration           Force database migration even if DB Secret key is not
                                         changed
 -h,--help                               Show help message
 -l,--load-new-management-key-from-env   Load new management key from environment variable
                                         CLOUD_SECRET_KEY_NEW
 -s,--skip-database-migration            Skip database migration even if DB Secret key is changed


5.2 Examples





Return codes:
  0 - Succeed to change keys and/or migrate databases
  1 - Fail to parse the command line arguments
  2 - Fail to validate parameters
  3 - Fail to migrate database

5.3 Table and Column changes during migration

The following tables and columns will be migrated during database migration.

TableCoiumnColumn type

Conditions

Note

configuration

value

varchar(8191)

category IN ('Hidden', 'Secure')







host_details

value

varchar(255)

name = "password"


cluster_details

value

varchar(255)

name = "password"


storage_pool_details

value

varchar(255)

name in ("password",

"powerflex.gw.username",

"powerflex.gw.password")

ScaleIO

image_store_details

value

varchar(255)

name in ("key", "secretkey")


user_vm_details

value

varchar(5120)

name = "password"







user_vm_deploy_as_is_details

value

varchar(255)

(1) get OVFPropertyTO from

template_deploy_as_is_details by detail name

(2) migrate value if property is password.


storage_pool

path

varchar(255)

pool_type = 'SMB'


image_store

urlvarchar(2048)

protocol = 'cifs'







vpn_users

password

varchar(255)



sslcerts

password

varchar(255)



sslcerts

key

text

account_details

value

varchar(255)


if https://github.com/apache/cloudstack/pull/6812 is merged, extra methods need to be added to cloudstack-migrate-databases to migrate the values

(1) in account_details and domain_details

(2) the configs are Hidden/Secure global configurations.

domain_details

value

varchar(255)



s2s_customer_gateway

ipsec_psk

varchar(256)



virtual_supervisor_module

password

varchar(255)

ucs_manager

passwordvarchar(255)

vm_instance

vnc_password

varchar(255)

keystore

key

text

passphrase

passphrase

varchar(64)


Need test: volume encryption

Modify to varchar(255)

external_stratosphere_ssp_credentials

passwordvarchar(255)

vmware_data_center

password

varchar(255)

storage_pool

user_info

varchar(255)

remote_access_vpn

ipsec_psk

varchar(256)

user

secret_key

varchar(255)

oobm

password

varchar(255)

6. EncryptionCLI in cloudstack-utils.jar

A standalone jar package cloudstack-utils.jar is shipped with cloudstack-common. It will be placed as /usr/share/cloudstack-common/lib/cloudstack-utils.jar.

with the jar, we can encrypt and decrypt values using cloudstack encryptors.

6.1 Usage

# java -classpath /usr/share/cloudstack-common/lib/cloudstack-utils.jar com.cloud.utils.crypt.EncryptionCLI
Missing required options: i, p
usage: Usage:
 -d,--decrypt                               Decrypt instead of encrypt
 -e,--encryptorversion <encryptorversion>   The encryptor version
 -i,--input <input>                         The input string to process
 -p,--password <password>                   The encryption password
 -v,--verbose                               Verbose output

6.2 Examples


# java -classpath /usr/share/cloudstack-common/lib/cloudstack-utils.jar com.cloud.utils.crypt.EncryptionCLI -p mgmtkey -i dbkey

+X4wvxJcDzp2DhD8tUyyJa+4Ije5VAELOYC75QfEQBGI


# java -classpath /usr/share/cloudstack-common/lib/cloudstack-utils.jar com.cloud.utils.crypt.EncryptionCLI -p mgmtkey -i +X4wvxJcDzp2DhD8tUyyJa+4Ije5VAELOYC75QfEQBGI -d

dbkey


# java -classpath /usr/share/cloudstack-common/lib/cloudstack-utils.jar com.cloud.utils.crypt.EncryptionCLI -p mgmtkey -i dbkey -e V1

sjlu6z6CSYCKitpVqgG0rw==


# java -classpath /usr/share/cloudstack-common/lib/cloudstack-utils.jar com.cloud.utils.crypt.EncryptionCLI -p mgmtkey -i sjlu6z6CSYCKitpVqgG0rw== -d -e V2

Exception in thread "main" com.cloud.utils.exception.CloudRuntimeException: Error decrypting value: sjlu6*****
    at com.cloud.utils.crypt.CloudStackEncryptor.decrypt(CloudStackEncryptor.java:107)
    at com.cloud.utils.crypt.EncryptionCLI.main(EncryptionCLI.java:50)
Caused by: com.cloud.utils.crypt.EncryptionException: Failed to decrypt sjlu6z6CSYCKitpVqgG0rw==. Error: ciphertext too short
    at com.cloud.utils.crypt.AeadBase64Encryptor.decrypt(AeadBase64Encryptor.java:40)
    at com.cloud.utils.crypt.CloudStackEncryptor.decrypt(CloudStackEncryptor.java:105)
    ... 1 more


# java -classpath /usr/share/cloudstack-common/lib/cloudstack-utils.jar com.cloud.utils.crypt.EncryptionCLI -p mgmtkey -i sjlu6z6CSYCKitpVqgG0rw== -d

dbkey

# java -classpath /usr/share/cloudstack-common/lib/cloudstack-utils.jar com.cloud.utils.crypt.EncryptionCLI -p mgmtkey -i sjlu6z6CSYCKitpVqgG0rw== -d -e V1

dbkey


7. References