diff --git a/internal/controller/assets/create_ltpa_config.sh b/internal/controller/assets/create_ltpa_config.sh index b80b7d41..c32e868f 100644 --- a/internal/controller/assets/create_ltpa_config.sh +++ b/internal/controller/assets/create_ltpa_config.sh @@ -63,10 +63,10 @@ LAST_ROTATION=$(curl --cacert ${CACERT} --header "Content-Type: application/json PASSWORD=$(curl --cacert ${CACERT} --header "Content-Type: application/json" --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces/${NAMESPACE}/secrets/${LTPA_SECRET_NAME} | grep -o '"password": "[^"]*' | grep -o '[^"]*$' | base64 -d); if [ "$ENCRYPTION_KEY_SHARING_ENABLED" == "true" ] && [ $NOT_FOUND_COUNT -eq 0 ]; then - PASSWORD_KEY_LAST_ROTATION=$(curl --cacert ${CACERT} --header "Content-Type: application/json" --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces/${NAMESPACE}/secrets/${PASSWORD_KEY_SECRET_NAME} | grep -o '"lastRotation": "[^"]*' | grep -o '[^"]*$' | base64 -d); - PASSWORD_KEY=$(curl --cacert ${CACERT} --header "Content-Type: application/json" --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces/${NAMESPACE}/secrets/${PASSWORD_KEY_SECRET_NAME} | grep -o '"passwordEncryptionKey": "[^"]*' | grep -o '[^"]*$' | base64 -d); - ENCODED_PASSWORD=$(securityUtility encode --encoding=${ENCODING_TYPE} --key=${PASSWORD_KEY} ${PASSWORD}); - LTPA_ENCODED_PASSWORD="{\"apiVersion\": \"v1\", \"stringData\": {\"lastRotation\": \"$LAST_ROTATION\", \"password\": \"$ENCODED_PASSWORD\"}, \"kind\": \"Secret\",\"metadata\": {\"name\": \"$LTPA_CONFIG_SECRET_NAME\", \"passwordKeyLastRotation\": \"$PASSWORD_KEY_LAST_ROTATION\", \"namespace\": \"$NAMESPACE\",\"labels\": {\"app.kubernetes.io/name\": \"${LTPA_CONFIG_BASE_NAME}\", \"app.kubernetes.io/instance\": \"${LTPA_CONFIG_SECRET_NAME}\", \"$LTPA_LABEL_KEY\": \"$LTPA_LABEL_VALUE\"}},\"type\": \"Opaque\"}"; + ENCRYPTION_KEY_LAST_ROTATION=$(curl --cacert ${CACERT} --header "Content-Type: application/json" --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces/${NAMESPACE}/secrets/${PASSWORD_KEY_SECRET_NAME} | grep -o '"lastRotation": "[^"]*' | grep -o '[^"]*$' | base64 -d); + ENCRYPTION_KEY=$(curl --cacert ${CACERT} --header "Content-Type: application/json" --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces/${NAMESPACE}/secrets/${PASSWORD_KEY_SECRET_NAME} | grep -o '"passwordEncryptionKey": "[^"]*' | grep -o '[^"]*$' | base64 -d); + ENCODED_PASSWORD=$(securityUtility encode --encoding=${ENCODING_TYPE} --key=${ENCRYPTION_KEY} ${PASSWORD}); + LTPA_ENCODED_PASSWORD="{\"apiVersion\": \"v1\", \"stringData\": {\"encryptionKeyLastRotation\": \"$ENCRYPTION_KEY_LAST_ROTATION\", \"lastRotation\": \"$LAST_ROTATION\", \"password\": \"$ENCODED_PASSWORD\"}, \"kind\": \"Secret\",\"metadata\": {\"name\": \"$LTPA_CONFIG_SECRET_NAME\", \"passwordKeyLastRotation\": \"$PASSWORD_KEY_LAST_ROTATION\", \"namespace\": \"$NAMESPACE\",\"labels\": {\"app.kubernetes.io/name\": \"${LTPA_CONFIG_BASE_NAME}\", \"app.kubernetes.io/instance\": \"${LTPA_CONFIG_SECRET_NAME}\", \"$LTPA_LABEL_KEY\": \"$LTPA_LABEL_VALUE\"}},\"type\": \"Opaque\"}"; else SECRET_NAME="${LTPA_SECRET_NAME}-password" ENCODED_PASSWORD=$(securityUtility encode --encoding=${ENCODING_TYPE} ${PASSWORD}); diff --git a/internal/controller/ltpa_keys_sharing.go b/internal/controller/ltpa_keys_sharing.go index 7524bb05..baf37d42 100644 --- a/internal/controller/ltpa_keys_sharing.go +++ b/internal/controller/ltpa_keys_sharing.go @@ -609,7 +609,8 @@ func (r *ReconcileOpenLiberty) generateLTPAConfig(instance *olv1.OpenLibertyAppl ltpaConfigSecret := &corev1.Secret{} ltpaConfigSecretRootName := OperatorShortName + "-managed-ltpa" - if r.isUsingPasswordEncryptionKeySharing(instance, passwordEncryptionMetadata) { + isPasswordEncryptionKeySharing := r.isUsingPasswordEncryptionKeySharing(instance, passwordEncryptionMetadata) + if isPasswordEncryptionKeySharing { ltpaConfigSecretRootName += "-keyed-password" ltpaConfigSecret.Name = ltpaConfigSecretRootName + ltpaConfigMetadata.Name } else { @@ -801,6 +802,33 @@ func (r *ReconcileOpenLiberty) generateLTPAConfig(instance *olv1.OpenLibertyAppl return err } + // if using encryption key, check if the key has been rotated and requires a regeneration of the LTPA keyed password + if isPasswordEncryptionKeySharing { + internalEncryptionKeySecret, err := r.hasInternalEncryptionKeySecret(instance, passwordEncryptionMetadata) + if err != nil { + return err + } + lastRotation, found := internalEncryptionKeySecret.Data["lastRotation"] + if !found { + // lastRotation field is not present so the Secret was not initialized correctly + err := r.DeleteResource(internalEncryptionKeySecret) + if err != nil { + return err + } + return fmt.Errorf("the internal encryption key secret does not contain field 'lastRotation'") + } + + if encryptionKeyLastRotation, found := ltpaConfigSecret.Data["encryptionKeyLastRotation"]; found { + if string(encryptionKeyLastRotation) != string(lastRotation) { + err := r.DeleteResource(ltpaConfigSecret) + if err != nil { + return err + } + return fmt.Errorf("the encryption key has been modified; waiting for a new LTPA password to be generated") + } + } + } + // Create/update the Secret to hold the server.xml that will import the LTPA keys into the Liberty server // This server.xml will be mounted in /config/configDropins/overrides/ltpaKeysMount.xml serverXMLMountSecretErr := r.GetClient().Get(context.TODO(), types.NamespacedName{Name: ltpaXMLMountSecret.Name, Namespace: ltpaXMLMountSecret.Namespace}, ltpaXMLMountSecret)