mirror of
https://github.com/wazuh/wazuh-virtual-machines.git
synced 2025-12-10 10:11:44 -06:00
add pasword tool to the ami customizer service
This commit is contained in:
parent
2221c47413
commit
8009f42548
@ -7,7 +7,7 @@ import paramiko
|
||||
from configurer.ami.ami_post_configurer.create_service_directory import create_directory_structure, generate_yaml
|
||||
from generic import exec_command, modify_file, remote_connection
|
||||
from models import Inventory
|
||||
from utils import CertificatesComponent, Logger, RemoteDirectories
|
||||
from utils import CertificatesComponent, Logger, PasswordToolComponent, RemoteDirectories
|
||||
|
||||
logger = Logger("AmiPostConfigurer")
|
||||
|
||||
@ -15,21 +15,21 @@ logger = Logger("AmiPostConfigurer")
|
||||
@dataclass
|
||||
class AmiPostConfigurer:
|
||||
inventory: Inventory
|
||||
environment_name: str = "certs-env"
|
||||
environment_name: str = "customizer-env"
|
||||
enviroment_python_version: str = "3.11"
|
||||
custom_env_dependencies: ClassVar[list[str]] = [
|
||||
"pydantic",
|
||||
"pyyaml",
|
||||
"paramiko",
|
||||
]
|
||||
custom_dir_name: str = "wazuh-ami-certs-customize"
|
||||
custom_dir_name: str = "wazuh-ami-customizer"
|
||||
custom_dir_base_path: str = "/etc"
|
||||
cloud_instances_path: Path = Path("/var/lib/cloud/instances")
|
||||
journal_logs_path: Path = Path("/var/log/journal")
|
||||
journald__config_file_path: Path = Path("/etc/systemd/journald.conf")
|
||||
log_directory_path: Path = Path("/var/log")
|
||||
wazuh_indexer_log_path: Path = Path("/var/log/wazuh-indexer")
|
||||
wazuh_server_log_path: Path = Path("/var/log/wazuh-server")
|
||||
wazuh_server_log_path: Path = Path("/var/ossec/logs")
|
||||
wazuh_dashboard_log_path: Path = Path("/var/log/wazuh-dashboard")
|
||||
|
||||
@remote_connection
|
||||
@ -105,6 +105,8 @@ class AmiPostConfigurer:
|
||||
"remote_certs_path": RemoteDirectories.CERTS,
|
||||
"certs_tool": CertificatesComponent.CERTS_TOOL,
|
||||
"certs_config": CertificatesComponent.CONFIG,
|
||||
"password_tool_path": RemoteDirectories.PASSWORD_TOOL,
|
||||
"password_tool": PasswordToolComponent.PASSWORD_TOOL,
|
||||
}
|
||||
directory_template = generate_yaml(
|
||||
context=context,
|
||||
@ -181,7 +183,7 @@ class AmiPostConfigurer:
|
||||
None
|
||||
"""
|
||||
|
||||
self.stop_service("wazuh-server", client=client)
|
||||
self.stop_service("wazuh-manager", client=client)
|
||||
|
||||
def remove_wazuh_indexes(self, client: paramiko.SSHClient) -> None:
|
||||
"""
|
||||
|
||||
@ -1,13 +1,22 @@
|
||||
name: "wazuh-ami-certs-customize"
|
||||
# The structure contains name, files, and directories:
|
||||
# - name: name of the directory to be created
|
||||
# - files: list of files to be created.
|
||||
# - path: path where the file to be copied is located. (not the destination path, but the source. The destination path is constructed automatically)
|
||||
# - local: indicates whether the file is on the local machine (true) or on the remote instance (false).
|
||||
# - directories: list of subdirectories to be created within the current directory. Each subdirectory can contain its own files and subdirectories.
|
||||
|
||||
name: "wazuh-ami-customizer"
|
||||
files:
|
||||
- path: "{{ remote_certs_path }}/{{ certs_tool }}"
|
||||
local: false
|
||||
- path: "{{ remote_certs_path }}/{{ certs_config }}"
|
||||
local: false
|
||||
- path: "{{ password_tool_path }}/{{ password_tool }}"
|
||||
local: false
|
||||
directories:
|
||||
- name: "custom_certificates"
|
||||
- name: "src"
|
||||
files:
|
||||
- path: "configurer/ami/ami_post_configurer/custom_certificates.py"
|
||||
- path: "configurer/ami/ami_post_configurer/wazuh-ami-customizer.py"
|
||||
local: true
|
||||
directories:
|
||||
- name: "configurer"
|
||||
|
||||
@ -7,10 +7,12 @@ from configurer.core.utils import ComponentCertsDirectory
|
||||
from generic import exec_command
|
||||
from utils import Component, Logger
|
||||
|
||||
LOGFILE = Path("/var/log/wazuh-ami-custom-certificates.log")
|
||||
TEMP_DIR = Path("/etc/wazuh-ami-certs-customize")
|
||||
LOGFILE = Path("/var/log/wazuh-ami-customizer.log")
|
||||
TEMP_DIR = Path("/etc/wazuh-ami-customizer")
|
||||
CERTS_TOOL_PATH = Path(f"{TEMP_DIR}/certs-tool.sh")
|
||||
CERTS_TOOL_CONFIG_PATH = Path(f"{TEMP_DIR}/config.yml")
|
||||
PASSWORD_TOOL_PATH = Path(f"{TEMP_DIR}/password-tool.sh")
|
||||
PASWORDS_FILE_NAME = Path("/etc/wazuh-ami-customizer/passwords.txt")
|
||||
SERVICE_PATH = "/etc/systemd/system"
|
||||
SERVICE_NAME = f"{SERVICE_PATH}/wazuh-ami-customizer.service"
|
||||
SERVICE_TIMER_NAME = f"{SERVICE_PATH}/wazuh-ami-customizer.timer"
|
||||
@ -63,7 +65,7 @@ def stop_service(name: str) -> None:
|
||||
logger.debug(f"{name} service stopped")
|
||||
|
||||
|
||||
def verify_component_connection(component: Component, command: str, retries: int = 5, wait_time: int = 5) -> None:
|
||||
def verify_component_connection(component: Component, command: str, retries: int = 5, wait_time: int = 10) -> None:
|
||||
"""
|
||||
Verifies the component connection by sending a request to the component's endpoint.
|
||||
Args:
|
||||
@ -194,13 +196,13 @@ def stop_components_services() -> None:
|
||||
logger.debug("Stopping Wazuh components services...")
|
||||
|
||||
stop_service("wazuh-indexer")
|
||||
stop_service("wazuh-server")
|
||||
stop_service("wazuh-manager")
|
||||
stop_service("wazuh-dashboard")
|
||||
|
||||
logger.debug("Wazuh components services stopped")
|
||||
|
||||
|
||||
def verify_indexer_connection() -> None:
|
||||
def verify_indexer_connection(password: str = "admin") -> None:
|
||||
"""
|
||||
Verifies the connection to the Wazuh indexer.
|
||||
This function sends a request to the Wazuh indexer endpoint and checks the response.
|
||||
@ -210,7 +212,7 @@ def verify_indexer_connection() -> None:
|
||||
None
|
||||
"""
|
||||
|
||||
command = 'curl -XGET https://localhost:9200/ -uadmin:admin -k --max-time 120 --silent -w "%{http_code}" --output /dev/null'
|
||||
command = f"curl -XGET https://localhost:9200/ -uadmin:{password} -k --max-time 120 --silent -w \"%{{http_code}}\" --output /dev/null"
|
||||
verify_component_connection(Component.WAZUH_INDEXER, command)
|
||||
|
||||
|
||||
@ -259,8 +261,8 @@ def start_components_services() -> None:
|
||||
run_indexer_security_init()
|
||||
verify_indexer_connection()
|
||||
|
||||
enable_service("wazuh-server")
|
||||
start_service("wazuh-server")
|
||||
enable_service("wazuh-manager")
|
||||
start_service("wazuh-manager")
|
||||
|
||||
enable_service("wazuh-dashboard")
|
||||
start_service("wazuh-dashboard")
|
||||
@ -269,6 +271,70 @@ def start_components_services() -> None:
|
||||
logger.debug("Wazuh components services started")
|
||||
|
||||
|
||||
def get_instance_id() -> str:
|
||||
"""
|
||||
Retrieves the instance ID of the current machine capitalized.
|
||||
|
||||
Returns:
|
||||
str: The instance ID of the current machine.
|
||||
"""
|
||||
|
||||
logger.debug("Retrieving instance ID")
|
||||
|
||||
command = "ec2-metadata | grep 'instance-id' | cut -d':' -f2"
|
||||
output, error_output = exec_command(command=command)
|
||||
if error_output:
|
||||
logger.error(f"Error retrieving instance ID: {error_output}")
|
||||
raise RuntimeError("Error retrieving instance ID")
|
||||
return output.strip().capitalize()
|
||||
|
||||
|
||||
def generate_password_file() -> None:
|
||||
"""
|
||||
Generates a password file using the password tool.
|
||||
|
||||
Args:
|
||||
path (Path): The path where the password file will be created.
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
|
||||
logger.debug("Generating password file")
|
||||
|
||||
command = f"bash {PASSWORD_TOOL_PATH} -gf {PASWORDS_FILE_NAME}"
|
||||
_, error_output = exec_command(command=command)
|
||||
if error_output:
|
||||
logger.error(f"Error generating password file: {error_output}")
|
||||
raise RuntimeError("Error generating password file")
|
||||
|
||||
logger.debug("Password file generated")
|
||||
|
||||
|
||||
def change_passwords() -> None:
|
||||
logger.name = "CustomPasswords"
|
||||
logger.debug("Changing passwords started")
|
||||
logger.debug("Getting instance ID")
|
||||
instance_id = get_instance_id()
|
||||
|
||||
generate_password_file()
|
||||
|
||||
logger.debug("Changing passwords to instance ID")
|
||||
command = f"""
|
||||
sudo sed -i 's/password:.*/password: {instance_id}/g' {PASWORDS_FILE_NAME}
|
||||
bash {PASSWORD_TOOL_PATH} -a -A -au wazuh -ap wazuh -f {PASWORDS_FILE_NAME}
|
||||
"""
|
||||
|
||||
_, error_output = exec_command(command=command)
|
||||
if error_output:
|
||||
logger.error(f"Error changing passwords: {error_output}")
|
||||
raise RuntimeError("Error changing passwords")
|
||||
|
||||
logger.debug("Passwords changed. Verifying indexer connection with new password")
|
||||
verify_indexer_connection(password=instance_id)
|
||||
logger.debug("Changing passwords finished successfully")
|
||||
|
||||
|
||||
def clean_up() -> None:
|
||||
"""
|
||||
Cleans up temporary files and directories created during the process.
|
||||
@ -301,11 +367,14 @@ if __name__ == "__main__":
|
||||
remove_certificates()
|
||||
create_certificates()
|
||||
start_components_services()
|
||||
stop_service("wazuh-dashboard")
|
||||
change_passwords()
|
||||
start_service("wazuh-dashboard")
|
||||
start_ssh_service()
|
||||
clean_up()
|
||||
except Exception as e:
|
||||
logger.error(f"An error occurred during the custom certificates configuration process: {e}")
|
||||
logger.error(f"An error occurred during the customization process: {e}")
|
||||
start_ssh_service()
|
||||
raise RuntimeError("An error occurred during the custom certificates configuration process") from e
|
||||
raise RuntimeError("An error occurred during the customization process") from e
|
||||
|
||||
logger.info("Custom certificates configuration process finished")
|
||||
logger.info("Customization process finished")
|
||||
@ -13,8 +13,8 @@ Wants=wazuh-ami-customizer.timer
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
WorkingDirectory=/etc/wazuh-ami-certs-customize/custom_certificates
|
||||
ExecStart=/etc/wazuh-ami-certs-customize/certs-env/bin/python -m custom_certificates
|
||||
WorkingDirectory=/etc/wazuh-ami-customizer/src
|
||||
ExecStart=/etc/wazuh-ami-customizer/customizer-env/bin/python -m wazuh-ami-customizer
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@ -95,6 +95,7 @@ def main(
|
||||
Provisioner(
|
||||
inventory=input.inventory_content,
|
||||
certs=input.certificates_content,
|
||||
password_tool=input.password_tool_url,
|
||||
components=components,
|
||||
arch=input.arch,
|
||||
package_type=input.package_type,
|
||||
|
||||
@ -3,3 +3,4 @@ from .component_info import ComponentInfo
|
||||
from .components_dependencies import ComponentsDependencies
|
||||
from .input import Input
|
||||
from .package_info import PackageInfo
|
||||
from .password_tool_info import PasswordToolInfo
|
||||
|
||||
@ -40,7 +40,7 @@ class CertsInfo(BaseModel):
|
||||
"""
|
||||
logger.debug(f"Getting URL for {name}...")
|
||||
try:
|
||||
url = AnyUrl(self.certs_url_content.get(name, None))
|
||||
url = AnyUrl(self.certs_url_content.get(name, None)) # type: ignore
|
||||
except pydantic_core._pydantic_core.ValidationError as err:
|
||||
raise ValueError(f"URL for {name} has an invalid format: {err}") from err
|
||||
|
||||
|
||||
@ -10,7 +10,8 @@ from utils import Component
|
||||
from .certs_info import CertsInfo
|
||||
from .components_dependencies import ComponentsDependencies
|
||||
from .package_info import PackageInfo
|
||||
from .utils import format_certificates_urls_file, format_component_urls_file
|
||||
from .password_tool_info import PasswordToolInfo
|
||||
from .utils import format_certificates_urls_file, format_component_urls_file, format_password_tool_urls_file
|
||||
|
||||
|
||||
class Input(BaseModel):
|
||||
@ -67,6 +68,16 @@ class Input(BaseModel):
|
||||
except FileNotFoundError as err:
|
||||
raise FileNotFoundError(f"Certificates file not found at {self.packages_url_path}") from err
|
||||
|
||||
@property
|
||||
def password_tool_url(self) -> PasswordToolInfo:
|
||||
try:
|
||||
password_tool_data = format_password_tool_urls_file(self.packages_url_path)
|
||||
if password_tool_data is None:
|
||||
raise ValueError("Password tool URL not found in the packages URL file.")
|
||||
return PasswordToolInfo(password_tool_url=password_tool_data)
|
||||
except FileNotFoundError as err:
|
||||
raise FileNotFoundError(f"Password tool file not found at {self.packages_url_path}") from err
|
||||
|
||||
@property
|
||||
def inventory_content(self, host_name: str | None = None) -> Inventory | None:
|
||||
return Inventory(self.inventory_path, host_name) if self.inventory_path else None
|
||||
|
||||
30
provisioner/models/password_tool_info.py
Normal file
30
provisioner/models/password_tool_info.py
Normal file
@ -0,0 +1,30 @@
|
||||
from pydantic import AnyUrl, BaseModel, field_validator
|
||||
|
||||
from provisioner.utils import AllowedUrlHost
|
||||
from utils import Logger
|
||||
|
||||
from .utils import check_correct_url
|
||||
|
||||
logger = Logger("Password-tool provision")
|
||||
|
||||
|
||||
class PasswordToolInfo(BaseModel):
|
||||
"""
|
||||
PasswordToolInfo is a model that holds information about password tool URL.
|
||||
|
||||
Attributes:
|
||||
password_tool_url (str): A string containing the URL for the password-tool.
|
||||
"""
|
||||
|
||||
password_tool_url: AnyUrl
|
||||
|
||||
@field_validator("password_tool_url")
|
||||
def validate_password_tool_url(cls, url: AnyUrl) -> AnyUrl:
|
||||
logger.debug("Validating password tool URL...")
|
||||
if not check_correct_url(
|
||||
url,
|
||||
[AllowedUrlHost.RELEASE, AllowedUrlHost.PRE_RELEASE, AllowedUrlHost.INTERNAL],
|
||||
):
|
||||
raise ValueError("URL for password-tool is not for Wazuh packages.")
|
||||
|
||||
return url
|
||||
@ -1,2 +1,2 @@
|
||||
from .file_formatter import format_certificates_urls_file, format_component_urls_file
|
||||
from .file_formatter import format_certificates_urls_file, format_component_urls_file, format_password_tool_urls_file
|
||||
from .helpers import check_correct_url
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
from pydantic import AnyUrl
|
||||
|
||||
from provisioner.utils import (
|
||||
Component_arch,
|
||||
Package_type,
|
||||
)
|
||||
from utils import CertificatesComponent, Component
|
||||
from utils import CertificatesComponent, Component, PasswordToolComponent
|
||||
|
||||
|
||||
def file_to_dict(raw_urls_path: Path) -> dict:
|
||||
@ -157,6 +158,31 @@ def format_certificates_urls_file(raw_urls_path: Path) -> dict:
|
||||
return certificates_urls
|
||||
|
||||
|
||||
def format_password_tool_urls_file(raw_urls_path: Path) -> AnyUrl | None:
|
||||
"""
|
||||
Formats a file containing raw URLs into a string of password tool URL.
|
||||
|
||||
This function reads a file containing raw URLs and retrieves the URL
|
||||
for the password tool.
|
||||
|
||||
>>> raw_urls_path = Path("password_tool_urls.yaml")
|
||||
>>> format_password_tool_urls_file(raw_urls_path)
|
||||
'https://packages.wazuh.com/password-tool-example/password_tool'
|
||||
|
||||
Args:
|
||||
raw_urls_path (Path): The path to the file containing the raw URLs.
|
||||
|
||||
Returns:
|
||||
str: The URL for the password tool.
|
||||
"""
|
||||
raw_urls_content = file_to_dict(raw_urls_path)
|
||||
|
||||
for component_name, url in raw_urls_content.items():
|
||||
if PasswordToolComponent.PASSWORD_TOOL.name.lower() in component_name.lower():
|
||||
return AnyUrl(url)
|
||||
return None
|
||||
|
||||
|
||||
def format_component_urls_file(raw_urls_path: Path) -> dict:
|
||||
"""
|
||||
Formats the component URLs file by processing raw URLs and organizing them by component, architecture, and type.
|
||||
|
||||
@ -5,9 +5,9 @@ from pydantic import AnyUrl
|
||||
|
||||
from generic import exec_command, remote_connection
|
||||
from models import Inventory
|
||||
from provisioner.models import CertsInfo, ComponentInfo
|
||||
from provisioner.models import CertsInfo, ComponentInfo, PasswordToolInfo
|
||||
from provisioner.utils import Component_arch, Package_manager, Package_type
|
||||
from utils import CertificatesComponent, Component, Logger, RemoteDirectories
|
||||
from utils import CertificatesComponent, Component, Logger, PasswordToolComponent, RemoteDirectories
|
||||
|
||||
logger = Logger("Provisioner")
|
||||
|
||||
@ -30,6 +30,7 @@ class Provisioner:
|
||||
|
||||
inventory: Inventory | None
|
||||
certs: CertsInfo
|
||||
password_tool: PasswordToolInfo
|
||||
components: list[ComponentInfo]
|
||||
arch: Component_arch = Component_arch.X86_64
|
||||
package_type: Package_type = Package_type.RPM
|
||||
@ -49,7 +50,8 @@ class Provisioner:
|
||||
1. Logs the start of the provisioning process.
|
||||
2. Provisions the certs_tool using `certs_tool_provision`.
|
||||
3. Provision the config file using `certs_config_provision`.
|
||||
4. Iterates over each component and performs the following:
|
||||
4. Provisions the password tool using `password_tool_provision`.
|
||||
5. Iterates over each component and performs the following:
|
||||
a. Logs the start of provisioning for the component.
|
||||
b. Provisions dependencies for the component using `dependencies_provision`.
|
||||
c. Provisions packages for the component using `packages_provision`.
|
||||
@ -63,6 +65,10 @@ class Provisioner:
|
||||
self.certs_tool_provision(client)
|
||||
self.certs_config_provision(client)
|
||||
|
||||
logger.debug_title("Provisioning password tool")
|
||||
|
||||
self.password_tool_provision(client)
|
||||
|
||||
logger.debug_title("Provisioning special dependencies")
|
||||
|
||||
self.special_dependencies_provision(client)
|
||||
@ -77,20 +83,22 @@ class Provisioner:
|
||||
Provisions the certs_tool on the specified client.
|
||||
|
||||
This method uses the provided SSH client to connect to a remote machine
|
||||
and provision the certs_tool by calling the `certificates_provision`
|
||||
and provision the certs_tool by calling the `tool_provision`
|
||||
method with the appropriate URL.
|
||||
|
||||
Args:
|
||||
client (paramiko.SSHClient): The SSH client used to connect to the remote machine.
|
||||
"""
|
||||
self.certificates_provision(self.certs.certs_tool_url, CertificatesComponent.CERTS_TOOL, client)
|
||||
self.tool_provision(
|
||||
self.certs.certs_tool_url, f"{RemoteDirectories.CERTS}", CertificatesComponent.CERTS_TOOL, client
|
||||
)
|
||||
|
||||
def certs_config_provision(self, client: paramiko.SSHClient | None = None) -> None:
|
||||
"""
|
||||
Provisions the certs config file on the remote client.
|
||||
|
||||
This method uses the provided SSH client to connect to a remote machine
|
||||
and provision the certs config file by calling the `certificates_provision`
|
||||
and provision the certs config file by calling the `tool_provision`
|
||||
method with the appropriate URL.
|
||||
|
||||
Args:
|
||||
@ -99,7 +107,25 @@ class Provisioner:
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
self.certificates_provision(self.certs.config_url, CertificatesComponent.CONFIG, client)
|
||||
self.tool_provision(self.certs.config_url, f"{RemoteDirectories.CERTS}", CertificatesComponent.CONFIG, client)
|
||||
|
||||
def password_tool_provision(self, client: paramiko.SSHClient | None = None) -> None:
|
||||
"""
|
||||
Provisions the password tool on the specified client.
|
||||
|
||||
This method uses the provided SSH client to connect to a remote machine
|
||||
and provision the password tool by calling the `tool_provision`
|
||||
method with the appropriate URL.
|
||||
|
||||
Args:
|
||||
client (paramiko.SSHClient): The SSH client used to connect to the remote machine.
|
||||
"""
|
||||
self.tool_provision(
|
||||
self.password_tool.password_tool_url,
|
||||
f"{RemoteDirectories.PASSWORD_TOOL}",
|
||||
PasswordToolComponent.PASSWORD_TOOL,
|
||||
client,
|
||||
)
|
||||
|
||||
def special_dependencies_provision(self, client: paramiko.SSHClient | None = None) -> None:
|
||||
"""
|
||||
@ -177,39 +203,33 @@ class Provisioner:
|
||||
component.name.replace("_", " ").capitalize(),
|
||||
)
|
||||
|
||||
def certificates_provision(
|
||||
self, certs_file_url: AnyUrl, filename: str, client: paramiko.SSHClient | None = None
|
||||
def tool_provision(
|
||||
self, tool_url: AnyUrl, tool_dir: str, tool_filename: str, client: paramiko.SSHClient | None = None
|
||||
) -> None:
|
||||
"""
|
||||
Downloads a certificate file (certs_tool or config) from a given URL and saves it to a remote directory on a server.
|
||||
|
||||
Provisions a tool (certs_tool, config file, or password tool) on the remote client.
|
||||
Args:
|
||||
certs_file_url (AnyUrl): The URL of the certificate file to be downloaded.
|
||||
client (paramiko.SSHClient): An active SSH client connected to the remote server.
|
||||
|
||||
Raises:
|
||||
Exception: If there is an error during the download process.
|
||||
|
||||
Logs:
|
||||
Error message if the download fails.
|
||||
Success message if the download is successful.
|
||||
tool_url (AnyUrl): The URL of the tool to be provisioned.
|
||||
tool_dir (str): The directory on the remote client where the tool will be stored.
|
||||
tool_filename (str): The filename of the tool to be provisioned.
|
||||
client (paramiko.SSHClient): The SSH client used to connect to the remote machine.
|
||||
"""
|
||||
logger.debug(f"Provisioning {filename}")
|
||||
logger.debug(f"Provisioning {tool_filename}")
|
||||
|
||||
command_template = "mkdir -p {dir} && curl -s -o {path} '{certs_file_url}'"
|
||||
command_template = "mkdir -p {directory} && curl -s -o {path} '{tool_file_url}'"
|
||||
|
||||
command = command_template.format(
|
||||
dir=f"{RemoteDirectories.CERTS}",
|
||||
path=f"{RemoteDirectories.CERTS}/{filename}",
|
||||
certs_file_url=certs_file_url,
|
||||
directory=tool_dir,
|
||||
path=f"{tool_dir}/{tool_filename}",
|
||||
tool_file_url=tool_url,
|
||||
)
|
||||
output, error_output = exec_command(command=command, client=client)
|
||||
_, error_output = exec_command(command=command, client=client)
|
||||
|
||||
if error_output:
|
||||
logger.error(f"Error downloading {filename}: {error_output}")
|
||||
raise RuntimeError(f"Error downloading {filename}")
|
||||
logger.error(f"Error downloading {tool_filename}: {error_output}")
|
||||
raise RuntimeError(f"Error downloading {tool_filename}")
|
||||
|
||||
logger.info_success(f"{filename} downloaded successfully")
|
||||
logger.info_success(f"{tool_filename} downloaded successfully")
|
||||
|
||||
def list_dependencies(self, elements: list[str], component_name: str) -> None:
|
||||
"""
|
||||
|
||||
@ -41,6 +41,7 @@ def mock_logger(autouse=True):
|
||||
logger_paths = [
|
||||
"provisioner.provisioner.logger",
|
||||
"provisioner.models.certs_info.logger",
|
||||
"provisioner.models.password_tool_info.logger",
|
||||
"generic.remote_connection.logger",
|
||||
"configurer.core.models.wazuh_components_config_manager.logger",
|
||||
"configurer.core.models.certificates_manager.logger",
|
||||
|
||||
@ -4,7 +4,7 @@ from unittest.mock import MagicMock, patch
|
||||
import pytest
|
||||
|
||||
from configurer.ami.ami_post_configurer.ami_post_configurer import AmiPostConfigurer
|
||||
from utils.enums import CertificatesComponent, RemoteDirectories
|
||||
from utils.enums import CertificatesComponent, PasswordToolComponent, RemoteDirectories
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@ -78,6 +78,8 @@ def test_create_custom_dir_success(mock_create_structure, mock_generate_yaml, mo
|
||||
"remote_certs_path": RemoteDirectories.CERTS,
|
||||
"certs_tool": CertificatesComponent.CERTS_TOOL,
|
||||
"certs_config": CertificatesComponent.CONFIG,
|
||||
"password_tool_path": RemoteDirectories.PASSWORD_TOOL,
|
||||
"password_tool": PasswordToolComponent.PASSWORD_TOOL,
|
||||
}
|
||||
|
||||
mock_generate_yaml.return_value = {"template": "test_value"}
|
||||
@ -145,11 +147,11 @@ def test_stop_service_fails(mock_ami_post_configurer, mock_exec_command, mock_pa
|
||||
|
||||
def test_stop_wazuh_server(mock_ami_post_configurer, mock_exec_command, mock_paramiko, mock_logger):
|
||||
mock_ami_post_configurer.stop_wazuh_server(mock_paramiko.return_value)
|
||||
command = "sudo systemctl stop wazuh-server"
|
||||
command = "sudo systemctl stop wazuh-manager"
|
||||
mock_exec_command.assert_called_once_with(command=command, client=mock_paramiko.return_value)
|
||||
|
||||
mock_logger.debug.assert_called_once_with("Stopping wazuh-server service")
|
||||
mock_logger.info_success.assert_called_once_with("wazuh-server service stopped successfully")
|
||||
mock_logger.debug.assert_called_once_with("Stopping wazuh-manager service")
|
||||
mock_logger.info_success.assert_called_once_with("wazuh-manager service stopped successfully")
|
||||
|
||||
|
||||
def test_stop_wazuh_indexer(mock_ami_post_configurer, mock_exec_command, mock_paramiko, mock_logger):
|
||||
@ -176,7 +178,9 @@ def test_stop_wazuh_indexer(mock_ami_post_configurer, mock_exec_command, mock_pa
|
||||
def test_remove_wazuh_indexes(mock_ami_post_configurer, mock_exec_command, mock_paramiko, mock_logger):
|
||||
mock_ami_post_configurer.remove_wazuh_indexes(mock_paramiko.return_value)
|
||||
|
||||
command = 'sudo curl -s -o /dev/null -w "%{http_code}" -X DELETE -u "admin:admin" -k "https://127.0.0.1:9200/wazuh-*"'
|
||||
command = (
|
||||
'sudo curl -s -o /dev/null -w "%{http_code}" -X DELETE -u "admin:admin" -k "https://127.0.0.1:9200/wazuh-*"'
|
||||
)
|
||||
|
||||
mock_exec_command.assert_called_once_with(command=command, client=mock_paramiko.return_value)
|
||||
|
||||
@ -192,6 +196,7 @@ def test_remove_wazuh_indexes_fail(mock_ami_post_configurer, mock_exec_command,
|
||||
|
||||
mock_logger.error.assert_called_once_with("Error removing wazuh- indexes")
|
||||
|
||||
|
||||
def test_run_security_init_script(mock_ami_post_configurer, mock_exec_command, mock_paramiko, mock_logger):
|
||||
mock_ami_post_configurer.run_security_init_script(mock_paramiko.return_value)
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ from pydantic import AnyUrl
|
||||
|
||||
from provisioner.models.certs_info import CertsInfo
|
||||
from provisioner.models.component_info import ComponentInfo
|
||||
from provisioner.models.password_tool_info import PasswordToolInfo
|
||||
from provisioner.provisioner import Provisioner
|
||||
from provisioner.utils import Package_manager, Package_type
|
||||
from utils.enums import Component
|
||||
@ -32,10 +33,13 @@ def component_info_valid(valid_inventory):
|
||||
"config": "http://packages-dev.wazuh.com/example/config.yml",
|
||||
}
|
||||
)
|
||||
password_tool = PasswordToolInfo(password_tool_url=AnyUrl("http://packages-dev.wazuh.com/example/password-tool.sh"))
|
||||
|
||||
package_type = Package_type.RPM
|
||||
return Provisioner(
|
||||
inventory=valid_inventory,
|
||||
certs=certs,
|
||||
password_tool=password_tool,
|
||||
components=[component_server],
|
||||
package_type=package_type,
|
||||
)
|
||||
@ -56,9 +60,10 @@ def test_provision_success(mock_paramiko, mock_logger, component_info_valid, moc
|
||||
mock_client_instance = MagicMock()
|
||||
mock_paramiko.return_value = mock_client_instance
|
||||
|
||||
certs_expect_commands = [
|
||||
"mkdir -p ~/wazuh-configure/certs && curl -s -o ~/wazuh-configure/certs/certs-tool.sh 'http://packages-dev.wazuh.com/example/certs-tool.sh'",
|
||||
"mkdir -p ~/wazuh-configure/certs && curl -s -o ~/wazuh-configure/certs/config.yml 'http://packages-dev.wazuh.com/example/config.yml'",
|
||||
tools_expect_commands = [
|
||||
"mkdir -p ~/wazuh-configure/tools/certs && curl -s -o ~/wazuh-configure/tools/certs/certs-tool.sh 'http://packages-dev.wazuh.com/example/certs-tool.sh'",
|
||||
"mkdir -p ~/wazuh-configure/tools/certs && curl -s -o ~/wazuh-configure/tools/certs/config.yml 'http://packages-dev.wazuh.com/example/config.yml'",
|
||||
"mkdir -p ~/wazuh-configure/tools && curl -s -o ~/wazuh-configure/tools/password-tool.sh 'http://packages-dev.wazuh.com/example/password-tool.sh'"
|
||||
]
|
||||
|
||||
dependencies_expect_commands = [
|
||||
@ -85,22 +90,22 @@ def test_provision_success(mock_paramiko, mock_logger, component_info_valid, moc
|
||||
key_filename=str(component_info_valid.inventory.ansible_ssh_private_key_file),
|
||||
)
|
||||
|
||||
assert mock_exec_command.call_count == 7 # 3 for dependencies, 2 for certs, 1 download package, 1 install package
|
||||
assert mock_exec_command.call_count == 8 # 3 for dependencies, 3 for tools (certs-tool and password-tool), 1 download package, 1 install package
|
||||
|
||||
# certs
|
||||
assert certs_expect_commands[0] in mock_exec_command.call_args_list[0].kwargs["command"]
|
||||
assert certs_expect_commands[1] in mock_exec_command.call_args_list[1].kwargs["command"]
|
||||
# tools
|
||||
assert tools_expect_commands[0] in mock_exec_command.call_args_list[0].kwargs["command"]
|
||||
assert tools_expect_commands[1] in mock_exec_command.call_args_list[1].kwargs["command"]
|
||||
assert tools_expect_commands[2] in mock_exec_command.call_args_list[2].kwargs["command"]
|
||||
|
||||
# dependencies
|
||||
assert dependencies_expect_commands[0] in mock_exec_command.call_args_list[2].kwargs["command"]
|
||||
assert dependencies_expect_commands[1] in mock_exec_command.call_args_list[2].kwargs["command"]
|
||||
assert dependencies_expect_commands[2] in mock_exec_command.call_args_list[3].kwargs["command"]
|
||||
assert dependencies_expect_commands[3] in mock_exec_command.call_args_list[4].kwargs["command"]
|
||||
assert dependencies_expect_commands[0] in mock_exec_command.call_args_list[3].kwargs["command"]
|
||||
assert dependencies_expect_commands[1] in mock_exec_command.call_args_list[3].kwargs["command"]
|
||||
assert dependencies_expect_commands[2] in mock_exec_command.call_args_list[4].kwargs["command"]
|
||||
assert dependencies_expect_commands[3] in mock_exec_command.call_args_list[5].kwargs["command"]
|
||||
|
||||
# package
|
||||
assert package_expect_commands[0] in mock_exec_command.call_args_list[5].kwargs["command"]
|
||||
assert package_expect_commands[1] in mock_exec_command.call_args_list[6].kwargs["command"]
|
||||
|
||||
assert package_expect_commands[0] in mock_exec_command.call_args_list[6].kwargs["command"]
|
||||
assert package_expect_commands[1] in mock_exec_command.call_args_list[7].kwargs["command"]
|
||||
mock_logger.debug_title.assert_any_call("Starting provisioning")
|
||||
mock_logger.debug_title.assert_any_call("Provisioning certificates files")
|
||||
mock_logger.debug_title.assert_any_call("Starting provisioning for wazuh manager")
|
||||
@ -120,7 +125,7 @@ def test_certs_tool_provision_success(
|
||||
getattr(component_info_valid, certs_method)(mock_client_instance)
|
||||
|
||||
mock_exec_command.assert_called_once_with(
|
||||
command=f"mkdir -p ~/wazuh-configure/certs && curl -s -o ~/wazuh-configure/certs/{certs_component} 'http://packages-dev.wazuh.com/example/{certs_component}'",
|
||||
command=f"mkdir -p ~/wazuh-configure/tools/certs && curl -s -o ~/wazuh-configure/tools/certs/{certs_component} 'http://packages-dev.wazuh.com/example/{certs_component}'",
|
||||
client=mock_client_instance,
|
||||
)
|
||||
mock_logger.debug.assert_any_call(f"Provisioning {certs_component}")
|
||||
@ -142,7 +147,7 @@ def test_certs_tool_provision_failure(
|
||||
getattr(component_info_valid, certs_method)(mock_client_instance)
|
||||
|
||||
mock_exec_command.assert_called_once_with(
|
||||
command=f"mkdir -p ~/wazuh-configure/certs && curl -s -o ~/wazuh-configure/certs/{certs_component} 'http://packages-dev.wazuh.com/example/{certs_component}'",
|
||||
command=f"mkdir -p ~/wazuh-configure/tools/certs && curl -s -o ~/wazuh-configure/tools/certs/{certs_component} 'http://packages-dev.wazuh.com/example/{certs_component}'",
|
||||
client=mock_client_instance,
|
||||
)
|
||||
mock_logger.debug.assert_any_call(f"Provisioning {certs_component}")
|
||||
@ -345,9 +350,10 @@ def test_install_package(
|
||||
if "installed successfully" in expected_log and "WARNING" not in error_output:
|
||||
mock_logger.info_success.assert_called_once_with(f"{package_name} {expected_log}")
|
||||
elif "is already installed" in expected_log:
|
||||
mock_logger.debug.assert_has_calls(
|
||||
[mock.call(f"Installing {package_name}"), mock.call(f"{package_name} {expected_log}")]
|
||||
)
|
||||
mock_logger.debug.assert_has_calls([
|
||||
mock.call(f"Installing {package_name}"),
|
||||
mock.call(f"{package_name} {expected_log}"),
|
||||
])
|
||||
elif "installed successfully" in expected_log and "WARNING" in error_output:
|
||||
mock_logger.warning.assert_called_once_with(f"{error_output}")
|
||||
mock_logger.info_success.assert_called_once_with(f"{package_name} {expected_log}")
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
from .enums import CertificatesComponent, Component, RemoteDirectories
|
||||
from .enums import CertificatesComponent, Component, PasswordToolComponent, RemoteDirectories
|
||||
from .logger import Logger
|
||||
|
||||
@ -8,6 +8,10 @@ class Component(StrEnum):
|
||||
ALL = auto()
|
||||
|
||||
|
||||
class PasswordToolComponent(StrEnum):
|
||||
PASSWORD_TOOL = "password-tool.sh"
|
||||
|
||||
|
||||
class CertificatesComponent(StrEnum):
|
||||
CERTS_TOOL = "certs-tool.sh"
|
||||
CONFIG = "config.yml"
|
||||
@ -15,5 +19,7 @@ class CertificatesComponent(StrEnum):
|
||||
|
||||
class RemoteDirectories(StrEnum):
|
||||
WAZUH_ROOT_DIR = "~/wazuh-configure"
|
||||
TOOLS_DIR = f"{WAZUH_ROOT_DIR}/tools"
|
||||
PACKAGES = f"{WAZUH_ROOT_DIR}/packages"
|
||||
CERTS = f"{WAZUH_ROOT_DIR}/certs"
|
||||
CERTS = f"{TOOLS_DIR}/certs"
|
||||
PASSWORD_TOOL = f"{TOOLS_DIR}"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user