Skip to content

Commit

Permalink
Merge pull request #393 from carlosmmatos/carlosmmatos/issue380
Browse files Browse the repository at this point in the history
Add remove/hide host ability for uninstall
  • Loading branch information
redhatrises authored Aug 31, 2023
2 parents e6155bb + 68cd11c commit a81214c
Show file tree
Hide file tree
Showing 13 changed files with 311 additions and 3 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/remove-host.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- falcon_uninstall - Adds hide/remove host functionality (https://github.com/CrowdStrike/ansible_collection_falcon/pull/393)
5 changes: 5 additions & 0 deletions molecule/falcon_uninstall/converge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@
- name: Converge
hosts: all
become: yes
vars:
falcon_client_id: "{{ lookup('env', 'FALCON_CLIENT_ID') }}"
falcon_client_secret: "{{ lookup('env', 'FALCON_CLIENT_SECRET') }}"
roles:
- role: crowdstrike.falcon.falcon_uninstall
vars:
falcon_remove_host: yes
10 changes: 7 additions & 3 deletions molecule/falcon_uninstall/prepare.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
- name: Prepare
hosts: all
become: yes
vars:
falcon_client_id: "{{ lookup('env', 'FALCON_CLIENT_ID') }}"
falcon_client_secret: "{{ lookup('env', 'FALCON_CLIENT_SECRET') }}"
tasks:
# Ubuntu specific
- name: Install apt dependencies
Expand All @@ -21,6 +24,7 @@
- name: Run falcon_install role
ansible.builtin.include_role:
name: crowdstrike.falcon.falcon_install
vars:
falcon_client_id: "{{ lookup('env', 'FALCON_CLIENT_ID') }}"
falcon_client_secret: "{{ lookup('env', 'FALCON_CLIENT_SECRET') }}"

- name: Configure Falcon Sensor
ansible.builtin.include_role:
name: crowdstrike.falcon.falcon_configure
5 changes: 5 additions & 0 deletions molecule/win_falcon_uninstall/converge.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
---
- name: Converge
hosts: all
vars:
falcon_client_id: "{{ lookup('env', 'FALCON_CLIENT_ID') }}"
falcon_client_secret: "{{ lookup('env', 'FALCON_CLIENT_SECRET') }}"
roles:
- role: crowdstrike.falcon.falcon_uninstall
vars:
falcon_remove_host: yes
20 changes: 20 additions & 0 deletions molecule/win_falcon_uninstall/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,23 @@
- name: Verify Falcon Sensor is not installed
ansible.builtin.assert:
that: "'[SC] EnumQueryServicesStatus:OpenService FAILED' in win_status.stdout"

- name: CrowdStrike Falcon | Check for Windows Sensor directory (Windows)
ansible.windows.win_stat:
path: C:\Windows\System32\drivers\CrowdStrike
register: falcon_win_sensor_dir

- name: CrowdStrike Falcon | Assert Windows Sensor directory is absent (Windows)
ansible.builtin.assert:
that:
- not falcon_win_sensor_dir.stat.exists

- name: CrowdStrike Falcon | Check for Windows Sensor registry key (Windows)
ansible.windows.win_reg_stat:
path: HKLM:\System\Crowdstrike
register: falcon_win_sensor_reg

- name: CrowdStrike Falcon | Assert Windows Sensor registry key is absent (Windows)
ansible.builtin.assert:
that:
- not falcon_win_sensor_reg.exists
17 changes: 17 additions & 0 deletions roles/falcon_uninstall/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,29 @@ Role Variables

The following variables are currently supported:

* `falcon_api_enable_no_log` - Whether to enable or disable the logging of sensitive data being exposed in API calls. (bool, default: true)
* `falcon_cloud` - CrowdStrike API URL for downloading the Falcon sensor (string, default: `api.crowdstrike.com`)
* `falcon_cloud_autodiscover` - Auto-discover CrowdStrike API Cloud region (bool, default: true)
* `falcon_client_id` - CrowdStrike API OAUTH Client ID (string, default: null)
* `falcon_client_secret` - CrowdStrike API OAUTH Client Secret (string, default: null)
* `falcon_remove_host` - Whether to hide/remove the host from the CrowdStrike console (bool, default: false)
* `falcon_windows_uninstall_args` - Additional Windows uninstall arguments (string, default: `/norestart`)
* `falcon_windows_become_method` - The way to become a privileged user on Windows (string, default: `runas`)
* `falcon_windows_become_user` - The privileged user to uninstall the sensor on Windows (string, default: `SYSTEM`)

See [defaults/main.yml](defaults/main.yml) for more details on these variables.

Falcon API Permissions
----------------------

API clients are granted one or more API scopes. Scopes allow access to specific CrowdStrike APIs and describe the actions that an API client can perform.

Ensure the following API scopes are enabled (***if applicable***) for this role:

* When using API credentials `falcon_client_id` and `falcon_client_secret`
* To hide/remove the host from the CrowdStrike console:
* **Host** [write]****

Dependencies
------------

Expand Down
35 changes: 35 additions & 0 deletions roles/falcon_uninstall/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,39 @@
---
# defaults for falcon_uninstall

# Whether to enable or disable the logging of sensitive data being exposed in API calls.
# By default, this is enabled.
#
# Disabling this can expose your API credentials and authorization token.
#
falcon_api_enable_no_log: yes

# CrowdStrike API URL for downloading the Falcon sensor. Possible values:
# us-1: api.crowdstrike.com
# us-2: api.us-2.crowdstrike.com
# eu-1: api.eu-1.crowdstrike.com
# us-gov-1: api.laggar.gcw.crowdstrike.com
#
falcon_cloud: "api.crowdstrike.com"

# Auto-discover the CrowdStrike Cloud API Region. When disabled,
# 'falcon_cloud' should be changed to the appropriate cloud region.
#
falcon_cloud_autodiscover: true

# 'Client ID' and 'Client Secret' for authentication against the CrowdStrike
# API. If unknown, get it from the CrowdStrike support portal:
#
# https://falcon.crowdstrike.com/support/api-clients-and-keys
#
falcon_client_id:
falcon_client_secret:

# Whether to hide/remove the host from the CrowdStrike console.
# The default is false
#
falcon_remove_host: false

# Additional arugments to uninstall the sensor.
# You can add your maintenance token here by adding MAINTENANCE_TOKEN=<token>
#
Expand Down
32 changes: 32 additions & 0 deletions roles/falcon_uninstall/tasks/hide_host.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
# This playbook will hide the host from the falcon console
- name: "CrowdStrike Falcon | Remove/Hide Host from Console (Linux)"
ansible.builtin.uri:
url: "https://{{ falcon_cloud }}/devices/entities/devices-actions/v2?action_name=hide_host"
method: POST
body_format: json
body:
ids:
- "{{ falcon_uninstall_remove_aid }}"
return_content: true
headers:
authorization: "Bearer {{ falcon_api_oauth2_token.json.access_token }}"
Content-Type: application/json
status_code: 202
no_log: "{{ falcon_api_enable_no_log }}"
when: ansible_facts['os_family'] != "Windows"

- name: "CrowdStrike Falcon | Remove/Hide Host from Console (Windows)"
ansible.windows.win_uri:
url: "https://{{ falcon_cloud }}/devices/entities/devices-actions/v2?action_name=hide_host"
method: POST
body:
ids:
- "{{ falcon_uninstall_remove_aid }}"
return_content: true
headers:
authorization: "Bearer {{ falcon_api_oauth2_token.json.access_token }}"
Content-Type: application/json
status_code: 202
no_log: "{{ falcon_api_enable_no_log }}"
when: ansible_facts['os_family'] == "Windows"
32 changes: 32 additions & 0 deletions roles/falcon_uninstall/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
---
# tasks file for falcon_uninstall
- name: Uninstall pretasks
ansible.builtin.include_tasks: preuninstall.yml
# noqa name[missing]

- name: API block
when:
- falcon_client_id and falcon_client_secret
- falcon_sensor_installed
block:
- ansible.builtin.include_role:
name: falcon_install
tasks_from: "{{ 'win_auth.yml' if ansible_facts['os_family'] == 'Windows' else 'auth.yml' }}"
# noqa name[missing]

- name: Remove/Hide Host pretasks
when:
- falcon_api_oauth2_token is defined
- falcon_remove_host
- falcon_sensor_installed
block:
- ansible.builtin.include_tasks: remove_host_pretasks.yml
# noqa name[missing]

- name: Linux Block
when:
- ansible_facts['os_family'] != "Windows"
Expand All @@ -18,3 +41,12 @@
block:
- ansible.builtin.include_tasks: win_uninstall.yml
# noqa name[missing]

# Hide host
- name: Hide host
when:
- falcon_client_id and falcon_client_secret
- falcon_uninstall_remove_aid is defined
block:
- ansible.builtin.include_tasks: hide_host.yml
# noqa name[missing]
51 changes: 51 additions & 0 deletions roles/falcon_uninstall/tasks/preuninstall.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
# Linux Block
- name: "CrowdStrike Falcon | Linux Install State Block"
when:
- ansible_facts['system'] == 'Linux'
block:
- name: "CrowdStrike Falcon | Get List of Installed Packages (Linux)"
ansible.builtin.package_facts:
manager: auto

- name: "CrowdStrike Falcon | Set Sensor Name (Linux)"
ansible.builtin.set_fact:
installed_sensor: falcon-sensor

- name: "CrowdStrike Falcon | Check if Sensor is Installed (Linux)"
ansible.builtin.set_fact:
falcon_sensor_installed_linux: "{{ installed_sensor in ansible_facts.packages }}"

# Windows block
- name: "CrowdStrike Falcon | Windows Install State Block"
when:
- ansible_facts['os_family'] == "Windows"
block:
- name: "CrowdStrike Falcon | Check status of Falcon Sensor (Windows)"
ansible.windows.win_command: sc.exe query csagent
failed_when: false
changed_when: false
register: win_status

- name: "CrowdStrike Falcon | Check if Sensor is Installed (Windows)"
ansible.builtin.set_fact:
falcon_sensor_installed_windows: "{{ true if ('RUNNING' in win_status.stdout) else false }}"

# macOS block
- name: "CrowdStrike Falcon | macOS Install State Block"
when:
- ansible_facts['distribution'] == "MacOSX"
block:
- name: CrowdStrike Falcon | Stat Falcon Sensor (macOS)
ansible.builtin.stat:
path: "/Applications/Falcon.app/Contents/Resources/falconctl"
register: falconctl_mac

- name: CrowdStrike Falcon | Check if Sensor is Installed (macOS)
ansible.builtin.set_fact:
falcon_sensor_installed_mac: "{{ falconctl_mac.stat.exists }}"

# Check if sensor is installed
- name: "CrowdStrike Falcon | Check if Sensor is Installed"
ansible.builtin.set_fact:
falcon_sensor_installed: "{{ falcon_sensor_installed_linux | default(falcon_sensor_installed_windows | default(falcon_sensor_installed_mac)) }}"
93 changes: 93 additions & 0 deletions roles/falcon_uninstall/tasks/remove_host_pretasks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
### AID remove_host
# Linux block
- name: "CrowdStrike Falcon | Linux AID Block"
when:
- ansible_facts['system'] == 'Linux'
block:
- name: "CrowdStrike Falcon | Grab existing AID (Linux)"
crowdstrike.falcon.falconctl_info:
name: aid
register: falcon_uninstall_linux_aid_info

- name: "CrowdStrike Falcon | Set AID (Linux)"
ansible.builtin.set_fact:
falcon_uninstall_linux_aid: "{{ falcon_uninstall_linux_aid_info.falconctl_info.aid }}"

- name: "CrowdStrike Falcon | Assert AID found (Linux)"
ansible.builtin.assert:
that:
- falcon_uninstall_linux_aid | length > 0
fail_msg: "AID was not found!"
success_msg: "Found AID."

# Windows block
- name: "CrowdStrike Falcon | Windows AID Block"
when:
- ansible_facts['os_family'] == "Windows"
block:
- name: "CrowdStrike Falcon | Grab existing AID (Windows)"
ansible.windows.win_reg_stat:
path: "{{ item }}"
name: AG
register: falcon_uninstall_windows_aid_stat
loop:
- 'HKLM:\SYSTEM\CrowdStrike\{9b03c1d9-3138-44ed-9fae-d9f4c034b88d}\{16e0423f-7058-48c9-a204-725362b67639}\Default'
- 'HKLM:\SYSTEM\CurrentControlSet\Services\CSAgent\Sim'

- name: "CrowdStrike Falcon | Set unique value (Windows)"
ansible.builtin.set_fact:
aid_win_value: "{{ falcon_uninstall_windows_aid_stat.results | selectattr('value', 'defined') | first }}"

- name: "CrowdStrike Falcon | Convert Value to AID (Windows) "
ansible.windows.win_shell: |
$bytes = @( {{ aid_win_value.value | join(',') }} )
$aid = [System.BitConverter]::ToString($bytes).ToLower() -replace '-', ''
Write-Host -NoNewline $aid
changed_when: false
register: falcon_uninstall_windows_aid_value

- name: "CrowdStrike Falcon | Set AID (Windows)"
ansible.builtin.set_fact:
falcon_uninstall_windows_aid: "{{ falcon_uninstall_windows_aid_value.stdout }}"

- name: "CrowdStrike Falcon | Assert AID found (Windows)"
ansible.builtin.assert:
that:
- falcon_uninstall_windows_aid | length > 0
fail_msg: "AID was not found!"
success_msg: "Found AID."

# Mac Block
- name: CrowdStrike Falcon | Stat Falcon Sensor (macOS)
ansible.builtin.stat:
path: "/Applications/Falcon.app/Contents/Resources/falconctl"
register: falconctl_mac
when:
- ansible_facts['distribution'] == "MacOSX"

- name: "CrowdStrike Falcon | macOS AID Block"
when:
- ansible_facts['distribution'] == "MacOSX"
- falconctl_mac.stat.exists
block:
- name: CrowdStrike Falcon | Get AID Value from Stats (macOS)
ansible.builtin.command: |
/Applications/Falcon.app/Contents/Resources/falconctl stats agent_info | grep agentID
register: falcon_uninstall_mac_aid_stat
changed_when: false

- name: "CrowdStrike Falcon | Set AID (macOS)"
ansible.builtin.set_fact:
falcon_uninstall_mac_aid: "{{ falcon_uninstall_mac_aid_stat.stdout | regex_replace('^.*: ', '') | lower | replace('-', '') }}"

- name: "CrowdStrike Falcon | Assert AID found (macOS)"
ansible.builtin.assert:
that:
- falcon_uninstall_mac_aid | length > 0
fail_msg: "AID was not found!"
success_msg: "Found AID."

- name: "CrowdStrike Falcon | Set AID for Uninstall"
ansible.builtin.set_fact:
falcon_uninstall_remove_aid: "{{ falcon_uninstall_linux_aid | default(falcon_uninstall_windows_aid | default(falcon_uninstall_mac_aid)) }}"
7 changes: 7 additions & 0 deletions roles/falcon_uninstall/tasks/win_uninstall.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
state: absent
creates_service: csfalconservice
arguments: '/uninstall /quiet {{ falcon_windows_uninstall_args }}'
register: falcon_win_sensor_uninstall
when:
- falcon_win_sensor_cache.files | length > 0
- ansible_facts['os_family'] == "Windows"

- name: CrowdStrike Falcon | Wait for Falcon Sensor to be removed (Windows)
ansible.windows.win_wait_for:
path: C:\Windows\System32\drivers\CrowdStrike
state: absent
when: falcon_win_sensor_uninstall.changed # noqa: no-handler
5 changes: 5 additions & 0 deletions roles/falcon_uninstall/vars/main.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
---
# vars file for falcon_uninstall
falcon_cloud_urls:
us-1: "api.crowdstrike.com"
us-2: "api.us-2.crowdstrike.com"
eu-1: "api.eu-1.crowdstrike.com"
us-gov-1: "api.laggar.gcw.crowdstrike.com"

0 comments on commit a81214c

Please sign in to comment.