2025-11-06 10:52:59 +01:00

177 lines
6.9 KiB
Python

import re
import shutil
from pathlib import Path
from configurer.ova.ova_pre_configurer.ova_pre_configurer import run_vagrant_up
from generic import exec_command
from utils import Logger
from .helpers import clean_output_lines, get_wazuh_version, render_vagrantfile
ROOT_DIR = Path(__file__).resolve().parent.parent
CURRENT_PATH = Path(__file__).resolve().parent
DEFAULT_URL_FILENAME = "artifacts_urls.yaml"
VERSION_FILENAME = "VERSION.json"
STANDARIZE_OVA_FILENAME = "setOVADefault.sh"
OVA_OVF_TEMPLATE = "wazuh_ovf_template"
VAGRANT_METADATA_PATH = ROOT_DIR / ".vagrant" / "machines" / "default" / "virtualbox"
VERSION_FILEPATH = ROOT_DIR / VERSION_FILENAME
OVA_SCRIPTS_PATH = ROOT_DIR / "utils" / "scripts" / "ova_build"
STANDARIZE_OVA_FILEPATH = OVA_SCRIPTS_PATH / STANDARIZE_OVA_FILENAME
OVA_OVF_TEMPLATE_FILEPATH = OVA_SCRIPTS_PATH / OVA_OVF_TEMPLATE
logger = Logger("Build Local OVA")
def setup_execution_environment(vm_name: str, packages_url_path: str) -> None:
"""
Set up the execution environment for the OVA image creation. This includes copying the packages URL file
to the root directory and rendering the Vagrantfile with the specified VM name.
The Vagrantfile is used to configure the virtual machine for the OVA image creation process.
Args:
vm_name (str): The name of the virtual machine that will be created throught the Vagrantfile.
packages_url_path (str): The path to the packages URL file.
Returns:
None
"""
logger.debug_title("Setting up execution environment")
try:
logger.debug(f"Copying {packages_url_path} to the root directory")
shutil.copy(packages_url_path, ROOT_DIR)
except shutil.SameFileError:
logger.debug(f"File {packages_url_path} already exists in the root directory.")
vagrant_context = {
"vm_name": vm_name,
}
script_dir = ROOT_DIR / "wazuh_local_ova" / "templates"
output_vagrantfile = ROOT_DIR / "wazuh_local_ova" / "Vagrantfile"
logger.debug("Creating Vagrantfile")
render_vagrantfile(
context=vagrant_context,
template_dir=str(script_dir),
template_file="Vagrantfile.j2",
output_path=str(output_vagrantfile),
)
logger.info_success("Vagrantfile created successfully")
def configure_vagrant_vm(packages_url_filename: str = DEFAULT_URL_FILENAME) -> str:
"""
Configures a Vagrant virtual machine (VM) for the Wazuh environment.
Para ello crea una Vagrant VM y dentro de ella, se ejecuta Hatch con la configuración
usada para crear la OVA productiva.
# ingles
This function is responsible for setting up the Wazuh environment in a Vagrant VM.
It creates a Vagrant VM and executes Hatch with the configuration used to create the production OVA.
Returns:
str: The UUID of the configured Vagrant VM.
"""
logger.debug_title("Creating the Wazuh environment into the VM")
logger.debug("Running vagrant up")
run_vagrant_up(vagrantfile=ROOT_DIR / "wazuh_local_ova" / "Vagrantfile")
vagrant_uuid_file = VAGRANT_METADATA_PATH / "index_uuid"
with open(vagrant_uuid_file) as file:
vagrant_uuid = file.read()
logger.info("""
Starting the Configuration process. This may take a while. When the process is finished,
the logs generated during the configuration will be displayed in the console.
""")
command = f"vagrant ssh {vagrant_uuid} -c 'cd /tmp/ && sudo hatch run dev-ova-post-configurer:run --packages-url-path {packages_url_filename}'"
output, error_output = exec_command(command=command)
if error_output:
raise RuntimeError(f"Error running command in the remote VM: {error_output}")
logger.info_success("Configuration process finished")
logger.debug("Displaying logs from the configuration process...")
spining_pattern = re.compile(
r"(Installing Python distribution|Creating environment|Installing project in development mode|Syncing dependencies|Checking dependencies)"
)
print(clean_output_lines(output, spining_pattern)) # Remove spinner lines from hatch environment
return vagrant_uuid
def export_ova_image(vagrant_uuid: str, name: str, ova_dest: str) -> None:
"""
Export the configured Vagrant VM as an OVA image. This function handles the export process,
including modifying the VM settings, exporting the VM to a temporary directory, and
standardizing the OVA image.
Args:
vagrant_uuid (str): The UUID of the configured Vagrant VM.
name (str): The name of the OVA image to be created.
ova_dest (str): The destination directory where the OVA image will be saved.
Returns:
None
"""
logger.info("Exporting the OVA image")
logger.debug("Getting Wazuh version")
wazuh_version = get_wazuh_version(version_file=VERSION_FILEPATH)
vbox_vm_id_file = VAGRANT_METADATA_PATH / "id"
with open(vbox_vm_id_file) as file:
vbox_vm_id = file.read()
logger.debug("Creating temporary directory")
temp_dir = CURRENT_PATH / "tmp"
temp_dir.mkdir(exist_ok=True)
logger.debug("Exporting VM to the temporary directory")
commands = [
f"vagrant halt {vagrant_uuid}",
f'vboxmanage modifyvm "{vbox_vm_id}" --nic2 hostonly',
f'vboxmanage modifyvm "{vbox_vm_id}" --cableconnected2 on',
f'vboxmanage export "{vbox_vm_id}" -o "{temp_dir}/{name}-raw.ova"',
f'bash {STANDARIZE_OVA_FILEPATH} "{temp_dir}" "{temp_dir}/{name}-raw.ova" "{temp_dir}/{name}.ova" "{OVA_OVF_TEMPLATE_FILEPATH}" "{wazuh_version}"',
f"vagrant destroy -f {vagrant_uuid}",
]
for command in commands:
_, error_output = exec_command(command=command)
if error_output and "100%" not in error_output: # Ignore 100% completion messages
raise RuntimeError(f"Error running command during the exporting VM proccess: {error_output}")
logger.debug("OVA configuration process finished, moving the OVA image to the output directory")
shutil.move(f"{temp_dir}/{name}.ova", f"{ova_dest}/{name}.ova")
logger.debug("Cleaning up temporary files")
shutil.rmtree(temp_dir)
logger.info_success(f"OVA image exported successfully in {ova_dest}/{name}.ova")
def generate_checksum(name: str, ova_dest: str) -> None:
"""
Generate a SHA512 checksum for the exported OVA image. This function creates a checksum file
in the same directory as the OVA image, allowing for verification of the image's integrity.
Args:
name (str): The name of the OVA image.
ova_dest (str): The destination directory where the OVA sha file is located.
Returns:
None
"""
logger.debug_title("Generating SHA512 checksum")
sha512_command = f"sha512sum {ova_dest}/{name}.ova > {ova_dest}/{name}.ova.sha512"
_, error_output = exec_command(sha512_command)
if error_output:
raise RuntimeError(f"Error generating SHA512 checksum: {error_output}")
logger.info_success(f"SHA512 checksum generated: {ova_dest}/{name}.sha512")