From bcc7ca0928acf5e996c3b724f2ec2b2c289371ef Mon Sep 17 00:00:00 2001 From: Jihan El Karz Date: Wed, 3 Jun 2026 18:33:15 +0200 Subject: [PATCH] feat(trend-micro) role and playbook --- CHANGELOG.md | 1 + COMPATIBILITY.md | 1 + playbooks/README.md | 7 + playbooks/all.yml | 1 + playbooks/trend_micro.yml | 23 ++ roles/trend_micro/README.md | 138 +++++++++++ roles/trend_micro/defaults/main.yml | 10 + roles/trend_micro/meta/argument_specs.yml | 108 +++++++++ roles/trend_micro/tasks/main.yml | 281 ++++++++++++++++++++++ 9 files changed, 570 insertions(+) create mode 100644 playbooks/trend_micro.yml create mode 100644 roles/trend_micro/README.md create mode 100644 roles/trend_micro/defaults/main.yml create mode 100644 roles/trend_micro/meta/argument_specs.yml create mode 100644 roles/trend_micro/tasks/main.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e63b911..115d9b58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +* **role:trend_micro**: Add a role to install and activate the Trend Vision One Endpoint Security agent (Endpoint Sensor and Server & Workload Protection) on RHEL 9 and RHEL 10. * **role:mariadb_server**: Make `aria_pagecache_buffer_size`, `key_buffer_size` and `sort_buffer_size` configurable via the corresponding `mariadb_server__cnf_*` variables. * **plugin:platform_select**: New filter plugin for selecting a value from a platform-keyed dictionary by OS family / distribution / version. * **role:alternatives**: Support managing `subcommands` (slaves/followers) and the Red Hat-only `family` grouping. The role now also ensures the alternatives tooling is installed (`chkconfig` on RHEL 8, `alternatives` on RHEL 9/10; bundled with `dpkg` on Debian/Ubuntu), and can be included without variables as a no-op. diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index 132f6645..b14a9191 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -158,6 +158,7 @@ Which Ansible role is proven to run on which OS? | telegraf | | | x | (x) | (x) | | | | | | timezone | (x) | (x) | x | x | x | (x) | (x) | (x) | Fedora 35 | | tools | | | x | x | x | | | | Fedora | +| trend_micro | | | x | x | x | | | | | | unattended_upgrades | (x) | (x) | | | | (x) | (x) | (x) | | | uptimerobot | | | | | | | | | controller-side, talks to UptimeRobot API | | vsftpd | | | x | (x) | (x) | | | | | diff --git a/playbooks/README.md b/playbooks/README.md index 1babb9b2..4d1d3e9a 100644 --- a/playbooks/README.md +++ b/playbooks/README.md @@ -1347,6 +1347,13 @@ Calls the following roles (in order): * [tools](https://github.com/Linuxfabrik/lfops/tree/main/roles/tools) +## trend_micro.yml + +Calls the following roles (in order): + +* [trend_micro](https://github.com/Linuxfabrik/lfops/tree/main/roles/trend_micro) + + ## unattended_upgrades.yml Calls the following roles (in order): diff --git a/playbooks/all.yml b/playbooks/all.yml index 5d66638c..3fa0b060 100644 --- a/playbooks/all.yml +++ b/playbooks/all.yml @@ -141,6 +141,7 @@ - import_playbook: 'telegraf.yml' - import_playbook: 'timezone.yml' - import_playbook: 'tools.yml' +- import_playbook: 'trend_micro.yml' - import_playbook: 'unattended_upgrades.yml' - import_playbook: 'vsftpd.yml' - import_playbook: 'yum_utils.yml' diff --git a/playbooks/trend_micro.yml b/playbooks/trend_micro.yml new file mode 100644 index 00000000..12e2177e --- /dev/null +++ b/playbooks/trend_micro.yml @@ -0,0 +1,23 @@ +- name: 'Playbook linuxfabrik.lfops.trend_micro' + hosts: + - 'lfops_trend_micro' + + pre_tasks: + - ansible.builtin.import_role: + name: 'shared' + tasks_from: 'log-start.yml' + tags: + - 'always' + + + roles: + + - role: 'linuxfabrik.lfops.trend_micro' + + + post_tasks: + - ansible.builtin.import_role: + name: 'shared' + tasks_from: 'log-end.yml' + tags: + - 'always' diff --git a/roles/trend_micro/README.md b/roles/trend_micro/README.md new file mode 100644 index 00000000..560b02aa --- /dev/null +++ b/roles/trend_micro/README.md @@ -0,0 +1,138 @@ +# Ansible Role linuxfabrik.lfops.trend_micro + +This role installs and activates the [Trend Vision One Endpoint Security](https://www.trendmicro.com/en_us/business/products/hybrid-cloud/vision-one-endpoint-security.html) agent (`v1es`) on Linux servers. It covers pre-flight checks, agent download and installation via the XBC API, agent registration, and Server & Workload Protection (SWP) activation. + + +*Available in the next LFOps release.* + + +## Background: Two Products, One Host + +Trend Vision One Endpoint Security combines two products on the same host, and this role configures both: + +* **Endpoint Sensor** (XDR/EDR) is the `tmxbc` / Endpoint Basecamp agent. It is downloaded and installed through the XBC API. It is configured via `customer_id`, the per-architecture `company_id` and `scenario_ids`, `xbc_fqdn`, and `xbc_env`. +* **Server & Workload Protection (SWP)** is the Deep Security agent (`ds_agent`). It ships inside the same full package and is activated against a Deep Security Manager (DSM). It is configured via `tenant_id`, `token`, `swp_dsm_fqdn`, and the optional `policy_id`, `group_id`, and `relay_group_id`. + +The **Server & Workload Protection (SWP) deployment script** generated in the Vision One console contains every value the role needs. It bundles both products in one full package: it lists two scenario IDs (one for the Endpoint Sensor, one for SWP) and carries the SWP activation values. The role installs that package, waits for the SWP agent to come up, and then activates it against the DSM. + +> **Use the SWP deployment script, not the Endpoint-Sensor-only one.** The Endpoint-Sensor-only script lists a single scenario ID and none of the SWP activation values (tenant ID, token, DSM FQDN), so the SWP agent (`ds_agent`) cannot be installed. + + +## Generating the Deployment Script + +1. In the Vision One console, make sure a **Server & Workload Protection** product instance exists. If not, create it under **Service Management → Create product instance → Server & Workload Protection**. +2. Navigate to **Endpoint Security → Endpoint Inventory → Agent Installer → Deployment Script**. +3. Select **Server & Workload Protection** as the endpoint group and **Linux** as the operating system. +4. The previewed script contains every value the role needs. + +The script is a `bash` installer. Map its values to the role variables as follows (the script has separate `x86_64` and `aarch64` blocks, so `company_id` and `scenario_ids` differ per architecture): + +| Role variable | Where it appears in the deployment script | +| ------------- | ----------------------------------------- | +| `trend_micro__customer_id` | `CUSTOMER_ID="..."` | +| `trend_micro__group_id` | `GROUP_ID=...` (optional, defaults to `0`) | +| `trend_micro__policy_id` | `POLICY_ID=...` (optional, defaults to `0`) | +| `trend_micro__relay_group_id` | `RELAY_GROUP_ID=...` (optional, defaults to `0`) | +| `trend_micro__swp_dsm_fqdn` | the host in `dsa_control -a dsm://:443/` | +| `trend_micro__swp_login.tenant_id` | `tenantID:...` in the `dsa_control` activation line | +| `trend_micro__swp_login.token` | `token:...` in the `dsa_control` activation line | +| `trend_micro__xbc_env` | `XBC_ENV="..."` (optional, defaults to `prod-eu1`) | +| `trend_micro__xbc_fqdn` | `XBC_FQDN="..."` | +| `trend_micro__xbc_installer__company_id` | `company_id` in the `HTTP_BODY` of the matching `archType` block | +| `trend_micro__xbc_installer__scenario_ids` | `scenario_ids` in the `HTTP_BODY` of the matching `archType` block (both IDs) | + + +## Relevant Information + +Learn about Trend Micro Concepts and Products: https://docs.linuxfabrik.ch/software/trend-micro.html +Agent Platform Compability: https://help.deepsecurity.trendmicro.com/20_0/on-premise/agent-compatibility.html + +## Mandatory Requirements + +* At least 2 GB of RAM. The Server & Workload Protection agent (`ds_agent`) enforces this minimum during its pre-check; on a host with less memory the pre-check fails and `ds_agent` is never installed. +* Running as `root` (use `become: true`). +* `/tmp` must be writable on the target host. + +Supported architectures: `x86_64`, `aarch64`. + + +## Tags + +| Tag | What it does | Reload / Restart | +| --- | ------------ | ---------------- | +| `trend_micro` | Runs all tasks | - | +| `trend_micro:install` | Installs `curl` and `tar` only | - | + + +## Mandatory Role Variables + +| Variable | Description | +| -------- | ----------- | +| `trend_micro__customer_id` | Customer ID used in the installer API request. Found in the Vision One deployment script preview. | +| `trend_micro__xbc_installer_x86_64_company_id` | Company ID for the x86\_64 installer API request. | +| `trend_micro__xbc_installer_x86_64_scenario_ids` | List of scenario IDs for the x86\_64 installer API request. Include all IDs from the deployment script (endpoint sensor and SWP).| +| `trend_micro__xbc_installer_aarch64_company_id` | Company ID for the aarch64 installer API request. | +| `trend_micro__xbc_installer_aarch64_scenario_ids` | List of scenario IDs for the aarch64 installer API request. Include all IDs from the deployment script (endpoint sensor and SWP).| +| `trend_micro__swp_dsm_fqdn` | Deep Security Manager FQDN used to activate Server & Workload Protection. | +| `trend_micro__swp_login` | Server & Workload Protection activation credentials. Dictionary with the keys `tenant_id` and `token`. Typically fed by `linuxfabrik.lfops.bitwarden_item`. | + +Example: +```yaml +# mandatory +trend_micro__customer_id: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + +trend_micro__xbc_installer_x86_64_company_id: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' +trend_micro__xbc_installer_x86_64_scenario_ids: + - '' + - '' + +trend_micro__xbc_installer_aarch64_company_id: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' +trend_micro__xbc_installer_aarch64_scenario_ids: + - '' + - '' + +trend_micro__swp_dsm_fqdn: 'agents.workload.de-1.cloudone.trendmicro.com' +trend_micro__swp_login: + tenant_id: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + token: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +``` + + +## Optional Role Variables + +| Variable | Description | Default Value | +| -------- | ----------- | ------------- | +| `trend_micro__xbc_fqdn` | XBC backend FQDN. Use the FQDN matching your region. | `'api-eu1.xbc.trendmicro.com'` | +| `trend_micro__xbc_env` | XBC environment identifier. | `'prod-eu1'` | +| `trend_micro__policy_id` | Security policy to apply. `0` means no specific policy. | `0` | +| `trend_micro__group_id` | Agent group for organisation. | `0` | +| `trend_micro__relay_group_id` | Relay group for agent communication. | `0` | +| `trend_micro__proxy_addr` | Proxy hostname or IP. Leave empty for a direct connection. | `''` | +| `trend_micro__proxy_port` | Proxy port. | `''` | +| `trend_micro__proxy_login` | Proxy credentials. Dictionary with the keys `username` and `password`. Omit for a proxy that needs no authentication. | `{}` | +| `trend_micro__path_dsa` | Path to the `dsa_control` binary. | `'/opt/ds_agent/dsa_control'` | +| `trend_micro__path_identity_file` | Path polled to confirm agent registration. | `'/opt/TrendMicro/EndpointBasecamp/etc/.identity'` | + +Example: +```yaml +# optional +trend_micro__xbc_fqdn: 'api-us1.xbc.trendmicro.com' +trend_micro__policy_id: 42 +trend_micro__group_id: 10 +trend_micro__relay_group_id: 5 +trend_micro__proxy_addr: '192.0.2.30' +trend_micro__proxy_port: '8080' +trend_micro__proxy_login: + username: 'proxyuser' + password: 'linuxfabrik' +``` + + +## License + +[The Unlicense](https://unlicense.org/) + + +## Author Information + +[Linuxfabrik GmbH, Zurich](https://www.linuxfabrik.ch) diff --git a/roles/trend_micro/defaults/main.yml b/roles/trend_micro/defaults/main.yml new file mode 100644 index 00000000..01ec8398 --- /dev/null +++ b/roles/trend_micro/defaults/main.yml @@ -0,0 +1,10 @@ +trend_micro__group_id: 0 +trend_micro__path_dsa: '/opt/ds_agent/dsa_control' +trend_micro__path_identity_file: '/opt/TrendMicro/EndpointBasecamp/etc/.identity' +trend_micro__policy_id: 0 +trend_micro__proxy_addr: '' +trend_micro__proxy_login: {} +trend_micro__proxy_port: '' +trend_micro__relay_group_id: 0 +trend_micro__xbc_env: 'prod-eu1' +trend_micro__xbc_fqdn: 'api-eu1.xbc.trendmicro.com' diff --git a/roles/trend_micro/meta/argument_specs.yml b/roles/trend_micro/meta/argument_specs.yml new file mode 100644 index 00000000..a175d772 --- /dev/null +++ b/roles/trend_micro/meta/argument_specs.yml @@ -0,0 +1,108 @@ +argument_specs: + main: + options: + + trend_micro__customer_id: + type: 'str' + required: true + description: 'Customer ID used in the installer API request.' + + trend_micro__group_id: + type: 'int' + required: false + default: 0 + description: 'Agent group for organisation. 0 means no specific choice.' + + trend_micro__path_dsa: + type: 'str' + required: false + default: '/opt/ds_agent/dsa_control' + description: 'Path to the dsa_control binary.' + + trend_micro__path_identity_file: + type: 'str' + required: false + default: '/opt/TrendMicro/EndpointBasecamp/etc/.identity' + description: 'Path polled to confirm agent registration.' + + trend_micro__policy_id: + type: 'int' + required: false + default: 0 + description: 'Security policy to apply. 0 means no specific choice.' + + trend_micro__proxy_addr: + type: 'str' + required: false + default: '' + description: 'Proxy hostname or IP. Leave empty for a direct connection.' + + trend_micro__proxy_login: + type: 'dict' + required: false + default: {} + description: >- + Proxy credentials. May contain the keys `username` and `password`. + Typically fed by `linuxfabrik.lfops.bitwarden_item`, which returns the + full Bitwarden item; extra keys are ignored. Omit for a proxy that + needs no authentication. + + trend_micro__proxy_port: + type: 'str' + required: false + default: '' + description: 'Proxy port.' + + trend_micro__relay_group_id: + type: 'int' + required: false + default: 0 + description: 'Relay group for agent communication. 0 means no specific choice.' + + trend_micro__swp_dsm_fqdn: + type: 'str' + required: true + description: 'Deep Security Manager FQDN used to activate Server & Workload Protection.' + + trend_micro__swp_login: + type: 'dict' + required: true + description: >- + Server & Workload Protection activation credentials. Must contain the + keys `tenant_id` and `token`. Typically fed by + `linuxfabrik.lfops.bitwarden_item`, which returns the full Bitwarden + item; extra keys are ignored. + + trend_micro__xbc_env: + type: 'str' + required: false + default: 'prod-eu1' + description: 'XBC environment identifier.' + + trend_micro__xbc_fqdn: + type: 'str' + required: false + default: 'api-eu1.xbc.trendmicro.com' + description: 'XBC backend FQDN. Use the FQDN matching your region.' + + trend_micro__xbc_installer_aarch64_company_id: + type: 'str' + required: true + description: 'Company ID for the aarch64 installer API request.' + + trend_micro__xbc_installer_aarch64_scenario_ids: + type: 'list' + elements: 'str' + required: true + description: 'List of scenario IDs for the aarch64 installer API request.' + + trend_micro__xbc_installer_x86_64_company_id: + type: 'str' + required: true + description: 'Company ID for the x86_64 installer API request.' + + trend_micro__xbc_installer_x86_64_scenario_ids: + type: 'list' + elements: 'str' + required: true + description: 'List of scenario IDs for the x86_64 installer API request.' diff --git a/roles/trend_micro/tasks/main.yml b/roles/trend_micro/tasks/main.yml new file mode 100644 index 00000000..4f0e4ab4 --- /dev/null +++ b/roles/trend_micro/tasks/main.yml @@ -0,0 +1,281 @@ +- block: + + - name: 'stat /tmp' + ansible.builtin.stat: + path: '/tmp' + register: 'trend_micro__tmp_stat' + + - name: 'assert /tmp is writable' + ansible.builtin.assert: + that: + - 'trend_micro__tmp_stat.stat.writeable' + fail_msg: '/tmp is not writable. Please check the permissions of /tmp.' + + # ds_agent enforces this minimum during its own pre-check + - name: 'assert at least 2 GB of RAM (Server & Workload Protection requirement)' + ansible.builtin.assert: + that: + - 'ansible_facts.memtotal_mb | int >= 2048' + fail_msg: >- + Server & Workload Protection requires at least 2 GB of RAM; + this host has {{ ansible_facts.memtotal_mb }} MB. ds_agent will not install. + + tags: + - 'trend_micro' + + +- block: + + - name: 'package_facts' + ansible.builtin.package_facts: + check_mode: false + + - name: 'install curl' + ansible.builtin.package: + name: 'curl' + state: 'present' + + - name: 'install tar' + ansible.builtin.package: + name: 'tar' + state: 'present' + + tags: + - 'trend_micro:install' + + +- block: + + - name: 'Set proxy and connection config facts (proxy with username and password)' + ansible.builtin.set_fact: + trend_micro__proxy_env: + HTTP_PROXY: 'http://{{ trend_micro__proxy_login["username"] }}:{{ trend_micro__proxy_login["password"] }}@{{ trend_micro__proxy_addr }}:{{ trend_micro__proxy_port }}/' + HTTPS_PROXY: 'http://{{ trend_micro__proxy_login["username"] }}:{{ trend_micro__proxy_login["password"] }}@{{ trend_micro__proxy_addr }}:{{ trend_micro__proxy_port }}/' + trend_micro__proxy_config: '{{ (trend_micro__proxy_login["username"] + ":" + trend_micro__proxy_login["password"]) | b64encode }}@{{ trend_micro__proxy_addr }}:{{ trend_micro__proxy_port }}' + trend_micro__connect_config: '{{ {"fps": [{"connections": [{"type": "USER_INPUT"}]}]} | to_json | b64encode }}' + when: + - 'trend_micro__proxy_addr | length > 0' + - 'trend_micro__proxy_login["username"] | d("") | length > 0' + - 'trend_micro__proxy_login["password"] | d("") | length > 0' + + - name: 'Set proxy and connection config facts (proxy with username only)' + ansible.builtin.set_fact: + trend_micro__proxy_env: + HTTP_PROXY: 'http://{{ trend_micro__proxy_login["username"] }}@{{ trend_micro__proxy_addr }}:{{ trend_micro__proxy_port }}/' + HTTPS_PROXY: 'http://{{ trend_micro__proxy_login["username"] }}@{{ trend_micro__proxy_addr }}:{{ trend_micro__proxy_port }}/' + trend_micro__proxy_config: '{{ (trend_micro__proxy_login["username"] + ":") | b64encode }}@{{ trend_micro__proxy_addr }}:{{ trend_micro__proxy_port }}' + trend_micro__connect_config: '{{ {"fps": [{"connections": [{"type": "USER_INPUT"}]}]} | to_json | b64encode }}' + when: + - 'trend_micro__proxy_addr | length > 0' + - 'trend_micro__proxy_login["username"] | d("") | length > 0' + - 'trend_micro__proxy_login["password"] | d("") | length == 0' + + - name: 'Set proxy and connection config facts (proxy without credentials)' + ansible.builtin.set_fact: + trend_micro__proxy_env: + HTTP_PROXY: 'http://{{ trend_micro__proxy_addr }}:{{ trend_micro__proxy_port }}/' + HTTPS_PROXY: 'http://{{ trend_micro__proxy_addr }}:{{ trend_micro__proxy_port }}/' + trend_micro__proxy_config: '{{ trend_micro__proxy_addr }}:{{ trend_micro__proxy_port }}' + trend_micro__connect_config: '{{ {"fps": [{"connections": [{"type": "USER_INPUT"}]}]} | to_json | b64encode }}' + when: + - 'trend_micro__proxy_addr | length > 0' + - 'trend_micro__proxy_login["username"] | d("") | length == 0' + + - name: 'Set connection config facts (direct connection)' + ansible.builtin.set_fact: + trend_micro__proxy_env: {} + trend_micro__proxy_config: '' + trend_micro__connect_config: '{{ {"fps": [{"connections": [{"type": "DIRECT_CONNECT"}]}]} | to_json | b64encode }}' + when: 'trend_micro__proxy_addr | length == 0' + + tags: + - 'trend_micro' + +# in original script, this part below is being done by a platform detection script https://api-eu1.xbc.trendmicro.com/apk/platform-detection-script +- block: + + - name: 'Set x86_64 installer facts' + ansible.builtin.set_fact: + trend_micro__installer_body: + company_id: '{{ trend_micro__xbc_installer_x86_64_company_id }}' + platform: 'linux64' + scenario_ids: '{{ trend_micro__xbc_installer_x86_64_scenario_ids }}' + trend_micro__xbc_agent_token: "{{ trend_micro__xbc_installer_x86_64_scenario_ids | join('|') }}" + when: "ansible_architecture == 'x86_64'" + + - name: 'Set aarch64 installer facts' + ansible.builtin.set_fact: + trend_micro__installer_body: + company_id: '{{ trend_micro__xbc_installer_aarch64_company_id }}' + platform: 'linuxaarch64' + scenario_ids: '{{ trend_micro__xbc_installer_aarch64_scenario_ids }}' + trend_micro__xbc_agent_token: "{{ trend_micro__xbc_installer_aarch64_scenario_ids | join('|') }}" + when: "ansible_architecture == 'aarch64'" + + - name: 'assert supported architecture' + ansible.builtin.assert: + that: "ansible_architecture in ['x86_64', 'aarch64']" + fail_msg: 'Architecture {{ ansible_architecture }} is not supported.' + + tags: + - 'trend_micro' + + +- block: + + - name: 'file state=absent /tmp/v1es_installer.tgz # force a fresh download' + ansible.builtin.file: + path: '/tmp/v1es_installer.tgz' + state: 'absent' + + - name: 'download installer to /tmp/v1es_installer.tgz' + ansible.builtin.uri: + url: 'https://{{ trend_micro__xbc_fqdn }}/apk/installer' + method: 'POST' + headers: + X-Customer-Id: '{{ trend_micro__customer_id }}' + body: '{{ trend_micro__installer_body }}' + body_format: 'json' + dest: '/tmp/v1es_installer.tgz' + follow_redirects: 'all' # the API answers with 303, then 200 + status_code: + - 200 + environment: '{{ trend_micro__proxy_env }}' + + tags: + - 'trend_micro' + + +- block: + + - name: 'file state=directory /tmp/v1es' + ansible.builtin.file: + path: '/tmp/v1es' + state: 'directory' + mode: 0o755 + + - name: 'unarchive /tmp/v1es_installer.tgz to /tmp/v1es' + ansible.builtin.unarchive: + src: '/tmp/v1es_installer.tgz' + dest: '/tmp/v1es' + remote_src: true + + - name: 'copy /tmp/v1es/.property' + ansible.builtin.copy: + content: '{{ {"xbc_env": trend_micro__xbc_env, "xbc_agent_token": trend_micro__xbc_agent_token, "full_package": true} | to_json }}' + dest: '/tmp/v1es/.property' + mode: 0o644 + + tags: + - 'trend_micro' + + +- block: + + # tmxbc installs the Endpoint Basecamp agent on a fresh install that Basecamp socket may not exist yet, so the command exits non-zero + - name: '/tmp/v1es/tmxbc install --proxiesWithCred ... --connection ... (proxy)' + ansible.builtin.command: + argv: + - '/tmp/v1es/tmxbc' + - 'install' + - '--proxiesWithCred' + - '{{ trend_micro__proxy_config }}' + - '--connection' + - '{{ trend_micro__connect_config }}' + environment: '{{ trend_micro__proxy_env }}' + register: 'trend_micro__install_result' + until: 'trend_micro__install_result.rc == 0' + retries: 6 + delay: 10 + when: "trend_micro__proxy_config | length > 0" + + - name: '/tmp/v1es/tmxbc install --connection ... (direct)' + ansible.builtin.command: + argv: + - '/tmp/v1es/tmxbc' + - 'install' + - '--connection' + - '{{ trend_micro__connect_config }}' + register: 'trend_micro__install_result' + until: 'trend_micro__install_result.rc == 0' + retries: 6 + delay: 10 + when: "trend_micro__proxy_config | length == 0" + + tags: + - 'trend_micro' + + +- block: + + - name: 'wait_for path={{ trend_micro__path_identity_file }} # agent registration' + ansible.builtin.wait_for: + path: '{{ trend_micro__path_identity_file }}' + timeout: 300 + + tags: + - 'trend_micro' + + +# the SWP agent (ds_agent) ships inside the XBC full package, so it is deployed by tmxbc; wait for its service to come up and initialize, then activate it +- block: + + - name: 'systemctl is-active ds_agent # wait for SWP to install and start' + ansible.builtin.command: + cmd: 'systemctl is-active ds_agent' + register: 'trend_micro__ds_agent_status' + until: 'trend_micro__ds_agent_status.rc == 0' + retries: 60 + delay: 10 + changed_when: false + check_mode: false + + - name: 'wait_for path=/var/opt/ds_agent/dsa_core/ds_agent.crt # SWP initialization' + ansible.builtin.wait_for: + path: '/var/opt/ds_agent/dsa_core/ds_agent.crt' + timeout: 300 + + tags: + - 'trend_micro' + + +# the full package installs ds_agent but does not self-activate it against the SWP DSM; activation must be done explicitly with the tenant credentials, mirroring the vendor deployment script which always runs `dsa_control -a` +- block: + + - name: 'pause seconds=15 # let ds_agent finish initializing before activation' + ansible.builtin.pause: + seconds: 15 + + - name: '{{ trend_micro__path_dsa }} -a dsm://{{ trend_micro__swp_dsm_fqdn }}:443/ ... # activate SWP' + ansible.builtin.command: + argv: + - '{{ trend_micro__path_dsa }}' + - '-a' + - 'dsm://{{ trend_micro__swp_dsm_fqdn }}:443/' + - 'tenantID:{{ trend_micro__swp_login["tenant_id"] }}' + - 'token:{{ trend_micro__swp_login["token"] }}' + - 'policyid:{{ trend_micro__policy_id }}' + - 'relaygroupid:{{ trend_micro__relay_group_id }}' + - 'groupid:{{ trend_micro__group_id }}' + register: 'trend_micro__activation_result' + # ds_agent needs a moment after install before it can talk to the DSM + until: >- + '200' in trend_micro__activation_result.stdout or + 'reset agent first' in trend_micro__activation_result.stdout + retries: 12 + delay: 10 + changed_when: "'200' in trend_micro__activation_result.stdout" + failed_when: false + + - name: 'assert SWP is activated' + ansible.builtin.assert: + that: + - >- + '200' in trend_micro__activation_result.stdout or + 'reset agent first' in trend_micro__activation_result.stdout + fail_msg: >- + Server & Workload Protection activation failed. Output: + {{ trend_micro__activation_result.stdout | default('n/a') }}. + + tags: + - 'trend_micro'