Bootstrapping System Certificates and Secrets - Private Cloud(3.3)
Prior to installation, the system must be bootstrapped with certain system credentials and certificates. There are a few alternative ways to perform this task. The system credentials can be provided to the system in the following ways: These options are explained in the following sections. Necessary system credentials for Secret or Helm, respectively, are listed in the table. These credentials for database and system level API need to be provided before installation can complete: jdbcPassword mzownerPassword postgresqlPassword oraclePassword tlsKeystorePassword tlsKeyPassword Credentials can be written into a Secret object named env-secrets prior to installation. Example - Secret object Credentials can also be provided through values to Helm, by providing them in values.yaml or by passing them on the command line. Example - Helm credentials Note! Be aware that storing secret credentials in a values.yaml file in version control is not secure! If you still need to do this you should consider using tools like https://github.com/mozilla/sops. If neither Secret nor Helm values are used to provide credentials, the required values are automatically populated with random data. For users with access rights, the randomized credentials can be retrieved by doing: The values are stored base64 encoded and need to be decoded to be viewed. Example - Decoding Usage Engine requires a certificate to provide encryption on the public (external) interfaces. This certificate can be provided through a few different methods; cert-manager, Secret, and Disk Based Keystore. The method used is controlled through the following parameters in values.yaml: Example - Configuration of certificate method in values.yaml The most automated and secure way to provide certificates to the system is to use the Kubernetes tool cert-manager. Follow the instruction in the link below to install cert-manager: https://cert-manager.io/docs/installation/ Cert-manager must be backed by a certificate authority (CA) to sign the certificates. Once configured with a CA, cert-manager will automatically sign and renew certificates for the system as needed. Configuring cert-manager with a CA is done be defining an Issuer or ClusterIssuer resource and referring that one from values.yaml. Example - Configuration in values.yaml to enable cert-manager based keystore For a list of supported CA Issuer or ClusterIssuer types, see https://cert-manager.io/docs/configuration/ The following example configures a ClusterIssuer CA towards the free public CA provided Letsencrypt in an AWS deployment. Example - ClusterIssuer CA configuration Hint! For troubleshooting failed certificate provisioning with cert-manager, there is an excellent troubleshooting guide available: If you do not want to automate the certificate provisioning with cert-manager, you can instead manually install a public certificate in a Secret and refer the installation to that Secret. Example - Configuration in values.yaml to enable Secret based keystore The Secret must include a keystore file (keystore.jks) in JKS format as well as separate files for key (tls.key) and certificate (tls.crt). The script below shows how these can be generated and stored in the Secret. Note that this will generate a self-signed certificate, which is not suitable for use in publicly exposed interfaces. Make sure to set the parameters in the beginning of the script before using. Example - How to generate a self-signed certificate Certificates and keys can also be stored in keystore files on persistent disk. This option is the least secure and is deprecated. It is kept solely for backward compatibility reasons. Example - Configuration in values.yaml to enable disk based keystoreSystem Credentials
Secret Parameter Helm Parameter Description jdbcUser platform.db.jdbcUser User to authenticate to system database. platform.db.jdbcPassword Password to authenticate to system database. oracle.mzownerPassword
postgres.mzownerPasswordSchema owner password to authenticate to system database. postgres.adminPassword Postgres database admin password. oracle.adminPassword Oracle database admin password. platform.tls.key.storepassword System keystore password. Also used in cert-manager requests. platform.tls.key.password System key password. Also used in cert-manager requests. Kubernetes Secret
$ kubectl create secret generic env-secrets -n <namespace> \
--from-literal=jdbcUser=jdbcuser \
--from-literal=jdbcPassword=jdbcpassword \
--from-literal=mzownerPassword=mzownerpassword \
--from-literal=postgresqlPassword=postgrespassword \
--from-literal=tlsKeystorePassword=keystorepassword \
--from-literal=tlsKeyPassword=keypassword
Helm Values
$ helm install <release_name> ./usage-engine-private-edition --wait --timeout=5m --namespace <namespace> \
--set platform.db.jdbcUser=<user> \
--set platform.db.jdbcPassword="<password>" \
--set postgres.mzownerPassword="<password>" \
--set postgres.adminPassword="<password>" \
--set platform.tls.key.storepassword="<password>" \
--set platform.tls.key.password="<password>"
Random
$ kubectl get secret/env-secrets -n <namespace> -o yaml
$ kubectl get secrets/env-secrets -n <namespace> --template={{.data.jdbcPassword}} | base64 -d
Certificates
platform:
tls:
enabled: true
cert:
# Public certificate can be provided through one of methods: 'secret', 'certManager' or 'key' (not recommended)
public: certManager
Kubernetes cert-manager
platform:
tls:
cert:
public: certManager
certManager:
public:
issuer:
name: letsencrypt-prod
kind: ClusterIssuer
domain: uepe.example.com
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: admin@example.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
solvers:
# example: cross-account zone management for example.com
# this solver uses ambient credentials (i.e. inferred from the environment or EC2 Metadata Service)
# to assume a role in a different account
- selector:
dnsZones:
- "uepe.example.com"
dns01:
route53:
hostedZoneID: XXXXXXXXXXXX
region: eu-west-1
Secret
platform:
tls:
cert:
public: secret
secret:
public:
name: mz-cert
keystore:
alias: certificate
#!/bin/bash
KEY_PASSWORD=DefaultKeystorePWD
STORE_PASSWORD=DefaultKeystorePWD
DNAME=CN=exampledomain.com,O=Example
K8S_NAMESPACE=<namespace>
​
rm -f keystore.p12 keystore.jks tls.crt tls.key
​
keytool -genkey -keystore keystore.jks -storepass $STORE_PASSWORD -keypass $KEY_PASSWORD -alias certificate -keyalg RSA -keysize 2048 -dname $DNAME
keytool -importkeystore -srckeystore keystore.jks -srcstorepass $STORE_PASSWORD -srckeypass $KEY_PASSWORD -destkeystore keystore.p12 -deststoretype PKCS12 -srcalias certificate -deststorepass $STORE_PASSWORD -destkeypass $KEY_PASSWORD
openssl pkcs12 -in keystore.p12 -nokeys -out tls.crt -password pass:$KEY_PASSWORD
openssl pkcs12 -in keystore.p12 -nodes -nocerts -out tls.key -password pass:$KEY_PASSWORD
​
kubectl create secret generic mz-cert --namespace $K8S_NAMESPACE --from-file=keystore.jks --from-file=tls.key --from-file=tls.crt
Disk Based Keystore
platform:
tls:
cert:
public: key
key:
alias: certificate