diff --git a/VMEncryption/main/DiskUtil.py b/VMEncryption/main/DiskUtil.py index 5de5e9b69..7e1b6d33b 100644 --- a/VMEncryption/main/DiskUtil.py +++ b/VMEncryption/main/DiskUtil.py @@ -1048,7 +1048,7 @@ def get_device_items(self, dev_path): if property_item_pair[0] == 'MODEL': device_item.model = property_item_pair[1].strip('"') - if property_item_pair[0] == 'MAJ:MIN': + if property_item_pair[0] == 'MAJ:MIN' or property_item_pair[0] == "MAJ_MIN": device_item.majmin = property_item_pair[1].strip('"') device_item.device_id = self.get_device_id(self.get_device_path(device_item.name)) diff --git a/VMEncryption/main/SupportedOS.json b/VMEncryption/main/SupportedOS.json index 7f17ca07a..3f95fbe95 100644 --- a/VMEncryption/main/SupportedOS.json +++ b/VMEncryption/main/SupportedOS.json @@ -5,6 +5,12 @@ "MinSupportedVersion" : "2.0" } ], + "azurelinux": [ + { + "Version" : "3", + "MinSupportedVersion" : "3.0" + } + ], "redhat": [ { "Version" : "9", diff --git a/VMEncryption/main/Utils/HandlerUtil.py b/VMEncryption/main/Utils/HandlerUtil.py index 5e6934a6f..869ba180b 100644 --- a/VMEncryption/main/Utils/HandlerUtil.py +++ b/VMEncryption/main/Utils/HandlerUtil.py @@ -170,13 +170,9 @@ def exit_if_same_seq(self, exit_status=None): sys.exit(0) def log(self, message): - # write message to stderr for inclusion in QOS telemetry - sys.stderr.write(message) self._log(self._get_log_prefix() + ': ' + message) def error(self, message): - # write message to stderr for inclusion in QOS telemetry - sys.stderr.write(message) self._error(self._get_log_prefix() + ': ' + message) def _parse_config(self, config_txt): diff --git a/VMEncryption/main/Utils/waagent b/VMEncryption/main/Utils/waagent index 60c860de7..a7e8267ba 100644 --- a/VMEncryption/main/Utils/waagent +++ b/VMEncryption/main/Utils/waagent @@ -1342,6 +1342,19 @@ class marinerDistro(redhatDistro): def __init__(self): super(marinerDistro, self).__init__() +############################################################ +# azurelinuxDistro +############################################################ + +class azurelinuxDistro(redhatDistro): + """ + Azurelinux Distro concrete class + Put AzureLinux specific behavior here... + """ + + def __init__(self): + super(azurelinuxDistro, self).__init__() + ############################################################ # asianuxDistro ############################################################ diff --git a/VMEncryption/main/common_parameters.json b/VMEncryption/main/common_parameters.json index ddde56f9e..10f1a8321 100644 --- a/VMEncryption/main/common_parameters.json +++ b/VMEncryption/main/common_parameters.json @@ -1,5 +1,5 @@ { - "extension_version": "1.4.0.9", + "extension_version": "1.4.0.17", "extension_name": "AzureDiskEncryptionForLinux", "extension_provider_namespace": "Microsoft.Azure.Security" } diff --git a/VMEncryption/main/handle.py b/VMEncryption/main/handle.py index 479fc00b3..33022e7b1 100644 --- a/VMEncryption/main/handle.py +++ b/VMEncryption/main/handle.py @@ -898,7 +898,6 @@ def enable(): message=msg) finally: lock.release_lock() - logger.log("exiting enable lock, PID {0}".format(os.getpid())) def are_required_devices_encrypted(volume_type, encryption_status, disk_util, bek_util, encryption_operation): are_data_disk_encrypted = True if encryption_status['data'] == 'Encrypted' else False diff --git a/VMEncryption/main/oscrypto/91adeOnline/crypt-run-generator-ade.sh b/VMEncryption/main/oscrypto/91adeOnline/crypt-run-generator-ade.sh index a6e38beee..985244743 100644 --- a/VMEncryption/main/oscrypto/91adeOnline/crypt-run-generator-ade.sh +++ b/VMEncryption/main/oscrypto/91adeOnline/crypt-run-generator-ade.sh @@ -10,20 +10,40 @@ luks=$2 bootuuid=$3 crypttab_contains "$luks" "$dev" && exit 0 +echo "Adding $luks to crypttab and updating fstab..." >> /var/log/boot_decrypt.log echo "$luks $dev /bek/LinuxPassPhraseFileName timeout=10,discard,header=/boot/luks/osluksheader" >> /etc/crypttab echo "UUID=$bootuuid /boot auto defaults 0 0" >> /etc/fstab echo "LABEL=BEK\040VOLUME /bek auto defaults,nofail 0 0" >> /etc/fstab if command -v systemctl >/dev/null; then + echo "Reloading systemd daemon and starting services..." >> /var/log/boot_decrypt.log systemctl daemon-reload systemctl start bek.mount systemctl start boot.mount systemctl start cryptsetup.target + # manual unlock fix + # /usr/sbin/cryptsetup luksOpen /dev/disk/azure/root-part3 osencrypt --header /boot/luks/osluksheader -d /bek/LinuxPassPhraseFileName + fi +MAX_WAIT=15 +WAIT_TIME=0 +while ! [ -b /dev/mapper/osencrypt ] && [ $WAIT_TIME -lt $MAX_WAIT ]; do + sleep 1 + WAIT_TIME=$((WAIT_TIME+1)) +done + +if ! [ -b /dev/mapper/osencrypt ]; then + echo "Failed to unlock /dev/mapper/osencrypt after $MAX_WAIT seconds" >> /var/log/boot_decrypt.log + # Optionally reboot or drop into a shell for further troubleshooting +fi + + if [ -b /dev/mapper/osencrypt ]; then + echo "/dev/mapper/osencrypt is available, unmounting /boot and /bek..." >> /var/log/boot_decrypt.log umount /boot umount /bek fi +echo "Script completed at $(date)" >> /var/log/boot_decrypt.log exit 0 diff --git a/VMEncryption/main/patch/__init__.py b/VMEncryption/main/patch/__init__.py index cb0988a96..bce642ed2 100644 --- a/VMEncryption/main/patch/__init__.py +++ b/VMEncryption/main/patch/__init__.py @@ -27,6 +27,7 @@ from .SuSEPatching import SuSEPatching from .oraclePatching import oraclePatching from .marinerPatching import marinerPatching +from .azurelinuxPatching import azurelinuxPatching try: import distro # python3.8+ diff --git a/VMEncryption/main/patch/azurelinuxPatching.py b/VMEncryption/main/patch/azurelinuxPatching.py new file mode 100644 index 000000000..b5a170bf7 --- /dev/null +++ b/VMEncryption/main/patch/azurelinuxPatching.py @@ -0,0 +1,108 @@ +import base64 +import datetime +import json +import os +import platform +import re +import shutil +import subprocess +import sys +import time +import traceback + +from Common import * + +from .redhatPatching import redhatPatching + + +class azurelinuxPatching(redhatPatching): + def __init__(self,logger,distro_info): + super(azurelinuxPatching,self).__init__(logger,distro_info) + self.logger = logger + self.min_version_online_encryption = '3.0' + self.support_online_encryption = self.validate_online_encryption_support() + self.grub_cfg_paths = [ + ("/boot/grub2/grub.cfg", "/boot/grub2/grubenv") + ] + + def pack_initial_root_fs(self): + self.command_executor.ExecuteInBash('dracut -f -v --regenerate-all', True) + + def add_kernelopts(self, args_to_add): + self.add_args_to_default_grub(args_to_add) + grub_cfg_paths = filter(lambda path_pair: os.path.exists(path_pair[0]) and os.path.exists(path_pair[1]), self.grub_cfg_paths) + + for grub_cfg_path, grub_env_path in grub_cfg_paths: + for arg in args_to_add: + self.command_executor.ExecuteInBash("grubby --args {0} --update-kernel ALL -c {1} --env={2}".format(arg, grub_cfg_path, grub_env_path)) + + def install_cryptsetup(self): + packages = ['cryptsetup'] + package_list = " ".join(packages) + + # Log the start of the installation process + self.logger.log(f"Checking if {package_list} is already installed.") + + # Check if the package is already installed + check_command = f"rpm -q {package_list}" + if self.command_executor.Execute(check_command): + self.logger.log(f"{package_list} not installed, proceeding with installation.") + + install_command = f"tdnf install -y {package_list}" + self.logger.log(f"Running command: {install_command} with a timeout of 100 seconds.") + + # Execute the install command with a timeout + return_code = self.command_executor.Execute(install_command, timeout=100) + + # Check for timeout error (-9 indicates timeout) + if return_code == -9: + msg = "Command: tdnf install timed out. Make sure tdnf is configured correctly and there are no network problems." + self.logger.log(msg, level='error') + raise Exception(msg) + + self.logger.log(f"Installation command completed with return code: {return_code}") + return return_code + + else: + self.logger.log(f"{package_list} is already installed.") + return 0 + + def install_extras(self): + packages = [ + 'cryptsetup', + 'lsscsi', + 'psmisc', + 'lvm2', + 'uuid', + 'at', + 'patch', + 'procps-ng', + 'util-linux' + ] + self.logger.log("Starting installation of extra packages.") + + # Modify the package list based on conditions + if self.support_online_encryption: + self.logger.log("Online encryption is supported; modifying package list.") + packages.append('nvme-cli') + packages = [pkg for pkg in packages if pkg not in ['psmisc', 'uuid', 'at', 'patch', 'procps-ng']] + + package_list = " ".join(packages) + self.logger.log(f"Final package list for installation: {package_list}") + + # Check if the packages are already installed + check_command = f"rpm -q {package_list}" + if self.command_executor.Execute(check_command): + self.logger.log(f"Packages not fully installed, proceeding with installation: {package_list}") + + install_command = f"tdnf install -y {package_list}" + self.logger.log(f"Running command: {install_command}") + + # Execute the installation command + return_code = self.command_executor.Execute(install_command) + + self.logger.log(f"Installation of packages completed with return code: {return_code}") + else: + self.logger.log(f"All required packages are already installed: {package_list}") + + self.logger.log("Completed installation of extra packages.") \ No newline at end of file diff --git a/VMEncryption/main/patch/redhatPatching.py b/VMEncryption/main/patch/redhatPatching.py index 875e9e99e..8f394e8bb 100644 --- a/VMEncryption/main/patch/redhatPatching.py +++ b/VMEncryption/main/patch/redhatPatching.py @@ -324,6 +324,8 @@ def install_and_enable_ade_online_enc(self, root_partuuid, boot_uuid, rootfs_dis # Change config so that dracut will force add the dm_crypt kernel module self.append_contents_to_file('\nadd_drivers+=" dm_crypt "\n', '/etc/dracut.conf.d/ade.conf') + # Change config so that dracut will force add the cryptsetup binary + self.append_contents_to_file('\ninstall_items+=" /usr/sbin/cryptsetup "\n', '/etc/dracut.conf.d/ade.conf') # Add the new kernel param additional_params = ["rd.luks.ade.partuuid={0}".format(root_partuuid), @@ -339,9 +341,9 @@ def install_and_enable_ade_online_enc(self, root_partuuid, boot_uuid, rootfs_dis #Add the plain os disk base to the "LVM Reject list" and add osencrypt device to the "Accept list" self.append_contents_to_file('\ndevices { filter = ["a|osencrypt|", "r|' + root_partuuid + '|"] }\n', '/etc/lvm/lvm.conf') # Force dracut to include LVM and Crypt modules - self.append_contents_to_file('\nadd_dracutmodules+=" crypt lvm"\n', + self.append_contents_to_file('\nadd_dracutmodules+=" crypt lvm "\n', '/etc/dracut.conf.d/ade.conf') else: - self.append_contents_to_file('\nadd_dracutmodules+=" crypt"\n', + self.append_contents_to_file('\nadd_dracutmodules+=" crypt "\n', '/etc/dracut.conf.d/ade.conf') self.add_kernelopts(["root=/dev/mapper/osencrypt"]) \ No newline at end of file diff --git a/VMEncryption/main/version.txt b/VMEncryption/main/version.txt index 8350ceb77..8189fdc55 100644 --- a/VMEncryption/main/version.txt +++ b/VMEncryption/main/version.txt @@ -1 +1 @@ -1.4.0.9 \ No newline at end of file +1.4.0.17 \ No newline at end of file