diff --git a/Makefile b/Makefile index a2eaa4eb222..f2a972afbd8 100644 --- a/Makefile +++ b/Makefile @@ -171,6 +171,7 @@ BUILD_TARGET=install -e "s|@SETUP_VAR@|$(PKG_STATE_DIR)|g" \ -e "s|@DEV_PYTHON_DIR@|$(DEV_PYTHON_DIR)|g" \ -e "s|@DEV_SETUP_ENV_DIR@|$(DEV_SETUP_ENV_DIR)|g" \ + -e "s|@PREFIX@|$(PREFIX)|g" \ -e "s|@RPM_VERSION@|$(RPM_VERSION)|g" \ -e "s|@RPM_RELEASE@|$(RPM_RELEASE)|g" \ -e "s|@MILESTONE@|$(MILESTONE)|g" \ diff --git a/packaging/bin/engine-backup.sh.in b/packaging/bin/engine-backup.sh.in index 1c36bb0de42..e4d27462b0e 100755 --- a/packaging/bin/engine-backup.sh.in +++ b/packaging/bin/engine-backup.sh.in @@ -19,6 +19,7 @@ PACKAGE_NAME="@PACKAGE_NAME@" PACKAGE_VERSION="@PACKAGE_VERSION@" DISPLAY_VERSION="@DISPLAY_VERSION@" ENGINE_USR="@ENGINE_USR@" +INSTALL_ROOT=$([ "@DEVMODE@" = "1" ] && echo "@PREFIX@/" || echo "/") die() { local m="$1" @@ -39,7 +40,7 @@ load_config() { source_d() { local stage="$1" - local my_cfg_dir="/etc/ovirt-engine-backup/engine-backup-${stage}.d" + local my_cfg_dir="${INSTALL_ROOT}etc/ovirt-engine-backup/engine-backup-${stage}.d" for f in \ $([ -d "${my_cfg_dir}" ] && find "${my_cfg_dir}" -name '*.sh' | sort) \ ; do @@ -52,7 +53,7 @@ source_d init my_load_config() { load_config - DWH_CONFIG=/etc/ovirt-engine-dwh/ovirt-engine-dwhd.conf + DWH_CONFIG=${INSTALL_ROOT}etc/ovirt-engine-dwh/ovirt-engine-dwhd.conf for f in "${DWH_CONFIG}" "${DWH_CONFIG}".d/*.conf; do [ -e "${f}" ] && . "${f}" done @@ -116,7 +117,26 @@ engine_setup_service_enabled() { otopi-config-query match \ --key "$1" \ --value bool:True \ - --file /etc/ovirt-engine-setup.conf + --file ${INSTALL_ROOT}etc/ovirt-engine-setup.conf +} + +get_engine_constant() { + local constant_path="$1" + local setup_dir="${ENGINE_USR}/setup" + + local result + result=$(PYTHONPATH="${setup_dir}" python3 -c " +from ovirt_engine_setup.engine import constants as oenginecons +print(${constant_path}) +" 2>&1) + local exit_code=$? + + if [ ${exit_code} -ne 0 ]; then + log "Warning: Failed to get engine constant ${constant_path}: ${result}" + return 1 + fi + + echo "${result}" } engine_enabled() { @@ -140,7 +160,7 @@ grafana_enabled() { } load_branding() { - for f in /etc/ovirt-engine/branding/*/branding-external-resources.properties; do + for f in ${INSTALL_ROOT}etc/ovirt-engine/branding/*/branding-external-resources.properties; do if [ -e "${f}" ]; then eval $(get_java_props \ "${f}" \ @@ -151,14 +171,14 @@ load_branding() { } # Globals -BACKUP_PATHS="/etc/ovirt-engine -/etc/ovirt-engine-dwh -/etc/ovirt-provider-ovn/conf.d -/etc/ovirt-provider-ovn/logger.conf -/etc/ovirt-vmconsole -/etc/pki/ovirt-engine -/etc/pki/ovirt-vmconsole -/etc/ovirt-engine-setup.conf.d +BACKUP_PATHS="${INSTALL_ROOT}etc/ovirt-engine +${INSTALL_ROOT}etc/ovirt-engine-dwh +${INSTALL_ROOT}etc/ovirt-provider-ovn/conf.d +${INSTALL_ROOT}etc/ovirt-provider-ovn/logger.conf +${INSTALL_ROOT}etc/ovirt-vmconsole +${INSTALL_ROOT}etc/pki/ovirt-engine +${INSTALL_ROOT}etc/pki/ovirt-vmconsole +${INSTALL_ROOT}etc/ovirt-engine-setup.conf.d /etc/httpd/conf.d/internalsso-openidc.conf /etc/httpd/conf.d/ovirt-engine-grafana-proxy.conf /etc/httpd/conf.d/ovirt-engine-root-redirect.conf @@ -178,19 +198,19 @@ BACKUP_PATHS="/etc/ovirt-engine /etc/grafana" # Add /var/lib/ovirt-engine except a few -VAR_LIB_OVIRT_ENGINE_EXCLUSIONS="/var/lib/ovirt-engine/backups -/var/lib/ovirt-engine/jboss_runtime -/var/lib/ovirt-engine/ansible-runner-service.log -/var/lib/ovirt-engine/ansible-runner -/var/lib/ovirt-engine/.ansible" -for p in /var/lib/ovirt-engine/*; do +VAR_LIB_OVIRT_ENGINE_EXCLUSIONS="${INSTALL_ROOT}var/lib/ovirt-engine/backups +${INSTALL_ROOT}var/lib/ovirt-engine/jboss_runtime +${INSTALL_ROOT}var/lib/ovirt-engine/ansible-runner-service.log +${INSTALL_ROOT}var/lib/ovirt-engine/ansible-runner +${INSTALL_ROOT}var/lib/ovirt-engine/.ansible" +for p in ${INSTALL_ROOT}var/lib/ovirt-engine/*; do echo "${VAR_LIB_OVIRT_ENGINE_EXCLUSIONS}" | grep -q "^${p}\$" || BACKUP_PATHS="${BACKUP_PATHS} ${p}" done # Add /var/lib/grafana except its db, which is backed up separately -VAR_LIB_GRAFANA_EXCLUSIONS="/var/lib/grafana/grafana.db" -for p in /var/lib/grafana/*; do +VAR_LIB_GRAFANA_EXCLUSIONS="${INSTALL_ROOT}var/lib/grafana/grafana.db" +for p in ${INSTALL_ROOT}var/lib/grafana/*; do echo "${VAR_LIB_GRAFANA_EXCLUSIONS}" | grep -q "^${p}\$" || BACKUP_PATHS="${BACKUP_PATHS} ${p}" done @@ -1174,8 +1194,8 @@ backupFiles() { while read -r path; do [ -e "${path}" ] && echo "${path}" done | \ - sed 's;^/;;' | \ - tar -C / --files-from - -cpS"${FILES_COMPRESS_OPTION}"f "${target}" + sed "s;^${INSTALL_ROOT};;" | \ + tar -C "${INSTALL_ROOT}" --files-from - -cpS"${FILES_COMPRESS_OPTION}"f "${target}" ) 2>> "${LOG}" \ || logdie "Failed backing up ${paths}" } @@ -1414,9 +1434,9 @@ __EOF__ restoreSQLiteDB "${TEMP_FOLDER}/db/${GRAFANA_BACKUP_FILE_NAME}" "${GRAFANA_DB_FILENAME}" "grafana:grafana" fi [ -n "${CHANGE_DB_CREDENTIALS}" ] && changeEngineDBConf - [ -n "${CHANGE_DWH_DB_CREDENTIALS}" -o -n "${CHANGE_DB_CREDENTIALS}" -a "${DWH_DB_USER}" ] && changeDwhDBConf - [ -n "${CHANGE_CINDERLIB_DB_CREDENTIALS}" -o -n "${CHANGE_DB_CREDENTIALS}" -a "${CINDERLIB_DB_USER}" ] && changeCinderlibDBConf - [ -n "${CHANGE_KEYCLOAK_DB_CREDENTIALS}" -o -n "${CHANGE_DB_CREDENTIALS}" -a "${KEYCLOAK_DB_USER}" ] && changeKeycloakDBConf + [ -n "${DWH_DB_USER}" ] && [ -n "${CHANGE_DWH_DB_CREDENTIALS}" -o -n "${CHANGE_DB_CREDENTIALS}" ] && changeDwhDBConf + [ -n "${CINDERLIB_DB_USER}" ] && [ -n "${CHANGE_CINDERLIB_DB_CREDENTIALS}" -o -n "${CHANGE_DB_CREDENTIALS}" ] && changeCinderlibDBConf + [ -n "${KEYCLOAK_DB_USER}" ] && [ -n "${CHANGE_KEYCLOAK_DB_CREDENTIALS}" -o -n "${CHANGE_DB_CREDENTIALS}" ] && changeKeycloakDBConf source_d dorestore output "You should now run engine-setup." } @@ -1529,7 +1549,7 @@ OVESETUP_PROVISION_DB/restoreJobs=int:2 OVESETUP_CORE/engineStop=bool:False __EOF__ - /usr/share/ovirt-engine/setup/bin/ovirt-engine-provisiondb --config-append="${answerfile}" < /dev/null > "${pgprovisionlog}" 2>&1 + ${ENGINE_USR}/setup/bin/ovirt-engine-provisiondb --config-append="${answerfile}" < /dev/null > "${pgprovisionlog}" 2>&1 provrc=$? cat "${pgprovisionlog}" >> "${LOG}" 2>&1 \ || logdie "Failed to append pg provisioning log to restore log" @@ -1595,7 +1615,7 @@ __EOF__ else output "- extra user '${extrau}' having grants on database ${database}, created with a random password" fi - /usr/share/ovirt-engine/setup/bin/ovirt-engine-provisiondb --config-append="${answerfile}" < /dev/null > "${pgprovisionlog}" 2>&1 + ${ENGINE_USR}/setup/bin/ovirt-engine-provisiondb --config-append="${answerfile}" < /dev/null > "${pgprovisionlog}" 2>&1 provrc=$? cat "${pgprovisionlog}" >> "${LOG}" 2>&1 \ || logdie "Failed to append pg provisioning log to restore log" @@ -1871,6 +1891,102 @@ resetHAVMStatus() { || logdie "Failed resetting HA VM status" } +reencryptLegacyP12() { + local file="$1" + local pki_password="$2" + local timestamp="$3" + + log "Found legacy encryption in ${file}, re-encrypting." + + mv -f "${file}" "${file}.backup.${timestamp}" || logdie "Failed to backup ${file}" + + local temp_key="${TEMP_FOLDER}/temp_key_${timestamp}_$$.pem" + local temp_certs="${TEMP_FOLDER}/temp_certs_${timestamp}_$$.pem" + local result=1 + + openssl pkcs12 -in "${file}.backup.${timestamp}" -passin "pass:${pki_password}" -legacy \ + -nocerts -out "${temp_key}" -passout "pass:${pki_password}" 2>> "${LOG}" && \ + openssl pkcs12 -in "${file}.backup.${timestamp}" -passin "pass:${pki_password}" -legacy \ + -nokeys -out "${temp_certs}" 2>> "${LOG}" + local extract_success=$? + + if [ ${extract_success} -eq 0 ]; then + openssl pkcs12 -export -in "${temp_certs}" -inkey "${temp_key}" \ + -passin "pass:${pki_password}" -passout "pass:${pki_password}" \ + -out "${file}" 2>> "${LOG}" + local reencrypt_success=$? + + if [ ${reencrypt_success} -eq 0 ]; then + output " - Successfully re-encrypted $(basename "${file}") (backup: $(basename "${file}").backup.${timestamp})" + result=0 + else + log "Warning: Failed to re-encrypt ${file}, restoring from backup" + mv -f "${file}.backup.${timestamp}" "${file}" || logdie "Failed to restore ${file}" + fi + else + log "Warning: Failed to extract key/cert from ${file}, restoring from backup" + mv -f "${file}.backup.${timestamp}" "${file}" || logdie "Failed to restore ${file}" + fi + + rm -f "${temp_key}" "${temp_certs}" + return ${result} +} + +migrateLegacyCerts() { + output 'Checking certificates for legacy encryption:' + + # Re-encrypt old p12 files that use legacy encryption (3DES/RC2) incompatible with OpenSSL >=3.0 + # More info on https://github.com/openssl/openssl/discussions/23089 + + local pki_config_file=$(get_engine_constant "oenginecons.FileLocations.OVIRT_ENGINE_SERVICE_CONFIG_PKI") + local default_pki_password=$(get_engine_constant "oenginecons.Const.PKI_PASSWORD") + local pki_keys_dir=$(get_engine_constant "oenginecons.FileLocations.OVIRT_ENGINE_PKIKEYSDIR") + + if [ -z "${pki_keys_dir}" ] || [ -z "${default_pki_password}" ]; then + output " - Warning: Could not determine PKI configuration, skipping certificate check" + log "PKI config file: '${pki_config_file}', password: '${default_pki_password}', keys dir: '${pki_keys_dir}'" + return 0 + fi + + local pki_password="${default_pki_password}" + if [ -f "${pki_config_file}" ]; then + . "${pki_config_file}" + [ -n "${ENGINE_PKI_ENGINE_STORE_PASSWORD}" ] && pki_password="${ENGINE_PKI_ENGINE_STORE_PASSWORD}" + fi + + output " - Scanning ${pki_keys_dir}" + + local timestamp=$(date +"%Y%m%d%H%M%S") + local processed_count=0 + for file in ${pki_keys_dir}/*.p12; do + [ -f "${file}" ] || continue + + openssl pkcs12 -info -in "${file}" -passin "pass:${pki_password}" -noout &>/dev/null + local can_read=$? + + if [ ${can_read} -ne 0 ]; then + log "Cannot read ${file} with standard openssl, trying with -legacy" + openssl pkcs12 -info -in "${file}" -passin "pass:${pki_password}" -legacy -noout &>/dev/null + can_read=$? + + if [ ${can_read} -eq 0 ]; then + if reencryptLegacyP12 "${file}" "${pki_password}" "${timestamp}"; then + processed_count=$((processed_count + 1)) + fi + else + log "Cannot read ${file} even with -legacy flag" + output " - Warning: Cannot read $(basename "${file}") (may be corrupt or use wrong password)" + fi + fi + done + + if [ ${processed_count} -eq 0 ]; then + output " - Check complete (no legacy certificates found)" + else + output " - Check complete (re-encrypted ${processed_count} certificate(s))" + fi +} + restoreFiles() { local paths="$1" local archive="$2" @@ -1883,7 +1999,7 @@ restoreFiles() { # In previous versions we didn't keep this inside the backup os_at_backup="Unknown" fi - local POSTINSTALL="/etc/ovirt-engine-setup.conf.d/20-setup-ovirt-post.conf" + local POSTINSTALL_RELATIVE="etc/ovirt-engine-setup.conf.d/20-setup-ovirt-post.conf" local APACHE_CONFIGURED_LINE="OVESETUP_APACHE/configured=bool:True" # Extract files to temp dir @@ -1898,7 +2014,7 @@ restoreFiles() { ${EXCLUDED_FILES_ON_RESTORE} __EOF__ local exclude_apache= - if [ "${os}" != "${os_at_backup}" ] && grep -q "^${APACHE_CONFIGURED_LINE}\$" "${temp_files}/${POSTINSTALL}"; then + if [ "${os}" != "${os_at_backup}" ] && grep -q "^${APACHE_CONFIGURED_LINE}\$" "${temp_files}/${POSTINSTALL_RELATIVE}"; then exclude_apache=1 cat << __EOF__ ------------------------------------------------------------------------------ @@ -1919,15 +2035,17 @@ __EOF__ fi # Restore! - tar -C / -pSsx --exclude-from "${excluded_files}" -f "${archive}" 2>> "${LOG}" || \ + tar -C "${INSTALL_ROOT}" -pSsx --exclude-from "${excluded_files}" -f "${archive}" 2>> "${LOG}" || \ logdie "Failed restoring ${paths}" # Make next engine-setup ask about apache if [ -n "${exclude_apache}" ]; then local ESC_APACHE_CONFIGURED_LINE=$(echo "${APACHE_CONFIGURED_LINE}" | sed 's;/;\\/;') - sed -i "/^${ESC_APACHE_CONFIGURED_LINE}\$/d" "${POSTINSTALL}" + sed -i "${INSTALL_ROOT}/^${ESC_APACHE_CONFIGURED_LINE}\$/d" "${POSTINSTALL_RELATIVE}" fi + migrateLegacyCerts + if selinuxenabled; then echo "${paths}" | while read -r path; do if [ -e "${path}" ]; then diff --git a/packaging/bin/pki-enroll-pkcs12.sh b/packaging/bin/pki-enroll-pkcs12.sh index e062a69a569..81ce8625303 100755 --- a/packaging/bin/pki-enroll-pkcs12.sh +++ b/packaging/bin/pki-enroll-pkcs12.sh @@ -68,7 +68,6 @@ enroll() { -out "${pkcs12}" \ -passin "pass:${pass}" \ -passout "pass:${pass}" \ - -aes256 \ || die "Cannot create PKCS#12" return 0