Skip to content

Commit

Permalink
Refactored variable names and improved ART test execution
Browse files Browse the repository at this point in the history
**Changed:**
- Standardized variable names with `ansible_atomic_red_team_` prefix for consistency.
- Updated `example-playbook.yml` to use the new standardized variable names.
- Moved `update-art-tids.sh` script from `vars` to `files` directory and set executable permissions.
- Enhanced `gather-art-tids.yml` task to create a temporary directory, copy the emergency bash script, and gather ART TIDs into a YAML file in the temporary directory.
- Modified `invoke-atomictest.yml` to set a fact for `prereq_check_passed` and conditional execution of test and cleanup tasks based on this fact.
- Updated `setup-linux.yml` to include installation of Invoke-ART, setting up the PowerShell profile, and added additional packages for setup.
- Removed `update-art-tids.sh` script from `vars` directory as it has been moved to `files`.
- Added a timeout variable `ansible_atomic_red_team_timeout` for ART tests in `defaults/main.yml`.

**Removed:**
- Removed unused variables `atomic_red_team_common_install_packages`, `atomic_red_team_debian_specific_packages`, and `atomic_red_team_redhat_specific_packages` from `vars/main.yml`.
  • Loading branch information
l50 committed Apr 8, 2024
1 parent 8b94b1b commit 07af05e
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 63 deletions.
29 changes: 18 additions & 11 deletions defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
disable_fetch_art_index: false
ansible_atomic_red_team_disable_fetch_art_index: false

art_repository_owner: redcanaryco
art_branch: master
ansible_atomic_red_team_repository_owner: redcanaryco
ansible_atomic_red_team_branch: master

banned_tids_linux:
ansible_atomic_red_team_banned_tids_linux:
- T1018 # slow ping scan
- T1046 # nmap
- T1070.004 # delete filesystem
Expand All @@ -20,26 +20,33 @@ banned_tids_linux:
- T1526 # Azure
- T1529 # reboot/shutdown
- T1530 # cloud
- T1562.001 # breaks the tests
- T1562.006 # auditd changes (may break some telemetry collection)
- T1562.008 # cloud logging changes
- T1574.006 # Dynamic Linker Hijacking (requires manual cleanup / testing - might break subsequent tests)
- T1611 # container-based, needs prereqs, and hangs/timeout

banned_tids_macos:
ansible_atomic_red_team_banned_tids_macos:
- T1485 # impact - data destruction
- T1529 # reboot/shutdown

banned_tids_windows:
ansible_atomic_red_team_banned_tids_windows:
- T1485 # impact - data destruction
- T1529 # reboot/shutdown

# these are updated by tasks/gather-art-tids.yml which polls github to write
# playbook_dir/art-tids.yml as a fallback, the tasks/main.yml will load
# vars/art-tids.yml, which can be manually updated with vars/update-art-tids.sh
art_tids_linux: []
art_tids_macos: []
art_tids_windows: []
ansible_atomic_red_team_tids_linux: []
ansible_atomic_red_team_tids_macos: []
ansible_atomic_red_team_tids_windows: []

# Execute the ART tests
ansible_atomic_red_team_execute: false

# PowerShell version to install (if needed)
atomic_red_team_pwsh_version: "7.4.1"
atomic_red_team_nix_pwsh_path: "/opt/microsoft/powershell/7"
ansible_atomic_red_team_pwsh_version: "7.4.1"
ansible_atomic_red_team_nix_pwsh_path: "/opt/microsoft/powershell/7"

# Timeout in seconds for each test
ansible_atomic_red_team_timeout: 20
4 changes: 2 additions & 2 deletions example-playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
become: true
when: ansible_system == 'Linux'
vars:
art_tids_linux:
ansible_atomic_red_team_tids_linux:
- T1136.001
- T1053.003
- T1003.008-1,2,3
Expand All @@ -34,7 +34,7 @@
become: false
when: ansible_system == 'Win32NT'
vars:
art_tids_windows:
ansible_atomic_red_team_tids_windows:
# https://thedfirreport.com/2022/08/08/bumblebee-roasts-its-way-to-domain-admin/
- T1553.005:c2587b8d-743d-4985-aa50-c83394eaeb68 # download and mount iso, run lnk
- T1016 # System Network Configuration Discovery - 8 tests
Expand Down
4 changes: 2 additions & 2 deletions vars/update-art-tids.sh → files/update-art-tids.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ echo "---" | tee art-tids.yml

function fetch-art-index-to-yml() {
url="https://github.com/${ghuser}/atomic-red-team/raw/${branch}/atomics/Indexes/Indexes-CSV/${1}-index.csv"
tidlist=($(curl -sL $url | awk -F, '/T1/{print $2}' | sort -u))
tidlist=("$(curl -sL "$url" | awk -F, '/T1/{print $2}' | sort -u)")
echo "art_tids_${1}:" | tee -a art-tids.yml
for tid in ${tidlist[*]}; do
for tid in "${tidlist[@]}"; do
echo " - ${tid}"
done | tee -a art-tids.yml
}
Expand Down
27 changes: 22 additions & 5 deletions tasks/gather-art-tids.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
---
- name: Set Indexes-CSV url
ansible.builtin.set_fact:
index_csv_url: "https://github.com/{{ art_repository_owner }}/atomic-red-team/raw/{{ art_branch }}/atomics/Indexes/Indexes-CSV/"
index_csv_url: "https://github.com/{{ ansible_atomic_red_team_repository_owner }}/atomic-red-team/raw/{{ ansible_atomic_red_team_branch }}/atomics/Indexes/Indexes-CSV/"

- name: Create temporary directory
ansible.builtin.tempfile:
state: directory
suffix: build
delegate_to: localhost
register: art_tids
when: not ansible_atomic_red_team_disable_fetch_art_index

- name: Copy emergency bash script
ansible.builtin.copy:
src: "update-art-tids.sh"
dest: "{{ art_tids.path }}/update-art-tids.sh"
mode: '0755'
delegate_to: localhost
become: false
when: not ansible_atomic_red_team_disable_fetch_art_index

- name: Gather and write art-tids.yml
ansible.builtin.blockinfile:
dest: "{{ playbook_dir }}/art-tids.yml"
dest: "{{ art_tids.path }}/art-tids.yml"
create: true
mode: "0644"
block: |
Expand All @@ -18,7 +35,7 @@
{%- endif -%}
{%- endfor -%}
{#- build a dict with this for to_nice_yaml so it will indent correctly -#}
{%- set yamloutput = dict(art_tids_windows=list) -%}
{%- set yamloutput = dict(ansible_atomic_red_team_tids_windows=list) -%}
{{ yamloutput | to_nice_yaml | indent(2) }}
{%- set list = [] -%}
{%- for line in lookup('ansible.builtin.url', index_csv_url + 'linux-index.csv', wantlist=True) -%}
Expand All @@ -28,8 +45,8 @@
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- set yamloutput = dict(art_tids_linux=list) -%}
{%- set yamloutput = dict(ansible_atomic_red_team_tids_linux=list) -%}
{{ yamloutput | to_nice_yaml | indent(2) }}
delegate_to: localhost
become: false
when: not disable_fetch_art_index
when: not ansible_atomic_red_team_disable_fetch_art_index
20 changes: 16 additions & 4 deletions tasks/invoke-atomictest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
register: check_prereqs
failed_when: '"Prerequisites not met:" in check_prereqs.stdout'
changed_when: false

- name: "Set fact for prereq_check_passed"
ansible.builtin.set_fact:
prereq_check_passed: true
rescue:
- name: "Install prereqs for {{ item }}"
ansible.builtin.shell:
Expand All @@ -64,20 +68,24 @@
ansible.builtin.debug:
var: "{{ item }}"
loop: "{{ prereqs }}"
ignore_errors: true
register: ignore_errors_register

- name: "Execute {{ item }}"
ansible.builtin.shell:
cmd: |
Invoke-AtomicTest {{ testarg }} -Confirm:$false -TimeoutSeconds 300 -ExecutionLogPath /root/atc_execution.csv
Invoke-AtomicTest {{ testarg }} -Confirm:$false -TimeoutSeconds {{ ansible_atomic_red_team_timeout }} -ExecutionLogPath {{ ansible_user_dir }}/atc_execution.csv
args:
executable: pwsh
register: execute_test
ignore_errors: true
changed_when: false
when: prereq_check_passed

- name: "Execute {{ item }}"
ansible.builtin.debug:
var: execute_test.stdout
when: prereq_check_passed

- name: "Cleanup {{ item }}"
ansible.builtin.shell:
Expand Down Expand Up @@ -117,19 +125,23 @@
- name: Debug prereqs {{ item }}
ansible.builtin.meta: debug
with_items: "{{ prereqs }}"
ignore_errors: true
register: ignore_errors_register

- name: "Execute {{ item }}"
ansible.windows.win_shell: |
Invoke-AtomicTest {{ testarg }} -Confirm:$false -TimeoutSeconds 300 -ExecutionLogPath /root/atc_execution.csv
ansible.windows.win_command: |
Invoke-AtomicTest {{ testarg }} -Confirm:$false -TimeoutSeconds {{ ansible_atomic_red_team_timeout }} -ExecutionLogPath {{ ansible_user_dir }}/atc_execution.csv
register: execute_test
ignore_errors: true
when: prereq_check_passed

- name: "Execute {{ item }}"
ansible.builtin.debug:
var: execute_test.stdout
when: prereq_check_passed

- name: "Cleanup {{ item }}"
ansible.windows.win_shell: |
ansible.windows.win_command: |
Invoke-AtomicTest {{ testarg }} -Cleanup
register: cleanup_test
ignore_errors: true
Expand Down
43 changes: 18 additions & 25 deletions tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,4 @@
---
# tasks file for ansible_atomic_red_team

- name: "Include the list of available TIDs"
block:
- name: Built list of ART TIDs
ansible.builtin.include_tasks: "gather-art-tids.yml"
when: not disable_fetch_art_index

- name: Load the ART TIDs
ansible.builtin.include_vars: "{{ playbook_dir }}/art-tids.yml"
rescue:
# this may require manual updates via vars/update-art-tids.sh
- name: Load the ART TIDs from role/vars
ansible.builtin.include_vars: "art-tids.yml"

- name: Setup Windows
ansible.builtin.include_tasks: "setup-windows.yml"
when: ansible_system == 'Win32NT'
Expand All @@ -22,14 +7,22 @@
ansible.builtin.include_tasks: "setup-linux.yml"
when: ansible_system == 'Linux'

- name: Run invoke-atomictest on each TID (linux)
ansible.builtin.include_tasks: invoke-atomictest.yml
loop: "{{ art_tids_linux | difference(banned_tids_linux) }}"
when:
- ansible_system == 'Linux'
- name: Execute ART tests
when: ansible_atomic_red_team_execute
block:
- name: Built list of ART TIDs
ansible.builtin.include_tasks: gather-art-tids.yml
when: not ansible_atomic_red_team_disable_fetch_art_index

- name: Load the ART TIDs
ansible.builtin.include_vars: "{{ art_tids.path }}/art-tids.yml"

- name: Run invoke-atomictest on each TID (linux)
ansible.builtin.include_tasks: invoke-atomictest.yml
loop: "{{ ansible_atomic_red_team_tids_linux | difference(ansible_atomic_red_team_banned_tids_linux) }}"
when: ansible_system == 'Linux'

- name: Run invoke-atomictest on each TID (windows)
ansible.builtin.include_tasks: invoke-atomictest.yml
loop: "{{ art_tids_windows | difference(banned_tids_windows) }}"
when:
- ansible_system == 'Win32NT'
- name: Run invoke-atomictest on each TID (windows)
ansible.builtin.include_tasks: invoke-atomictest.yml
loop: "{{ ansible_atomic_red_team_tids_windows | difference(ansible_atomic_red_team_banned_tids_windows) }}"
when: ansible_system == 'Win32NT'
51 changes: 42 additions & 9 deletions tasks/setup-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
ansible.builtin.include_role:
name: cowdogmoo.workstation.package_management
vars:
package_management_common_install_packages: "{{ atomic_red_team_common_install_packages }}"
package_management_debian_specific_packages: "{{ atomic_red_team_debian_specific_packages }}"
package_management_redhat_specific_packages: "{{ atomic_red_team_redhat_specific_packages }}"
package_management_common_install_packages: "{{ ansible_atomic_red_team_common_install_packages }}"
package_management_debian_specific_packages: "{{ ansible_atomic_red_team_debian_specific_packages }}"
package_management_redhat_specific_packages: "{{ ansible_atomic_red_team_redhat_specific_packages }}"
when: ansible_os_family in ['Debian', 'RedHat']

- name: Set architecture mapping for PowerShell tar.gz packages
Expand All @@ -18,12 +18,12 @@

- name: Set PowerShell package name based on architecture
ansible.builtin.set_fact:
ps_pkg_name: "powershell-{{ atomic_red_team_pwsh_version }}-linux-{{ ps_arch_map[ansible_architecture] }}.tar.gz"
ps_pkg_name: "powershell-{{ ansible_atomic_red_team_pwsh_version }}-linux-{{ ps_arch_map[ansible_architecture] }}.tar.gz"
when: ansible_architecture in ps_arch_map

- name: Set PowerShell package download URL
ansible.builtin.set_fact:
ps_download_url: "https://github.com/PowerShell/PowerShell/releases/download/v{{ atomic_red_team_pwsh_version }}/{{ ps_pkg_name }}"
ps_download_url: "https://github.com/PowerShell/PowerShell/releases/download/v{{ ansible_atomic_red_team_pwsh_version }}/{{ ps_pkg_name }}"
when: ansible_architecture in ps_arch_map

- name: Download PowerShell package
Expand All @@ -38,7 +38,7 @@
- name: Create PowerShell directory
become: true
ansible.builtin.file:
path: "{{ atomic_red_team_nix_pwsh_path }}"
path: "{{ ansible_atomic_red_team_nix_pwsh_path }}"
state: directory
mode: "0755"
owner: "{{ ansible_user_id }}"
Expand All @@ -49,21 +49,54 @@
become: true
ansible.builtin.unarchive:
src: "/tmp/{{ ps_pkg_name }}"
dest: "{{ atomic_red_team_nix_pwsh_path }}"
dest: "{{ ansible_atomic_red_team_nix_pwsh_path }}"
remote_src: true
when: ps_pkg_name is defined

- name: Set execute permissions for pwsh
become: true
ansible.builtin.file:
path: "{{ atomic_red_team_nix_pwsh_path }}/pwsh"
path: "{{ ansible_atomic_red_team_nix_pwsh_path }}/pwsh"
mode: "+x"
when: ps_pkg_name is defined

- name: Create symlink for pwsh
become: true
ansible.builtin.file:
src: "{{ atomic_red_team_nix_pwsh_path }}/pwsh"
src: "{{ ansible_atomic_red_team_nix_pwsh_path }}/pwsh"
dest: "/usr/bin/pwsh"
state: link
when: ps_pkg_name is defined

- name: Install Invoke-ART
ansible.builtin.shell:
cmd: |
IEX (IWR 'https://raw.githubusercontent.com/redcanaryco/invoke-atomicredteam/master/install-atomicredteam.ps1' -UseBasicParsing); Install-AtomicRedTeam -getAtomics -Force
args:
executable: pwsh
creates: "{{ ansible_user_dir }}/AtomicRedTeam/atomics/Indexes/index.yaml"

- name: Find the path to the system powershell profile
ansible.builtin.shell:
cmd: |
$PROFILE.AllUsersAllHosts
changed_when: false
args:
executable: pwsh
register: pwshprofile

- name: Powershell Profile (debug)
ansible.builtin.debug:
var: pwshprofile.stdout

- name: Add Invoke-AtomicRedTeam to the powershell profile
ansible.builtin.lineinfile:
path: "{{ pwshprofile.stdout }}"
state: present
regex: '.*Invoke-AtomicRedTeam.*'
line: |-
Import-Module "{{ ansible_user_dir }}/AtomicRedTeam/invoke-atomicredteam/Invoke-AtomicRedTeam.psd1" -Force
owner: "{{ ansible_user_id }}"
group: "{{ ansible_user_id }}"
mode: '0644'
create: true
4 changes: 2 additions & 2 deletions tasks/setup-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
'@
$script | Out-File $PShome\Profile.ps1
- name: "Install AtomicsFolder from {{ art_repository_owner }}"
- name: "Install AtomicsFolder from {{ ansible_atomic_red_team_repository_owner }}"
ansible.windows.win_shell: |
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Internet Explorer\Main" -Name "DisableFirstRunCustomize" -Value 2
IEX (IWR 'https://raw.githubusercontent.com/redcanaryco/invoke-atomicredteam/master/install-atomicsfolder.ps1' -UseBasicParsing)
Install-AtomicsFolder -Force -RepoOwner "{{ art_repository_owner }}" -Branch "{{ art_branch }}"
Install-AtomicsFolder -Force -RepoOwner "{{ ansible_atomic_red_team_repository_owner }}" -Branch "{{ ansible_atomic_red_team_branch }}"
args:
creates: C:\AtomicRedTeam\atomics\used_guids.txt

Expand Down
6 changes: 3 additions & 3 deletions vars/main.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
atomic_red_team_common_install_packages:
ansible_atomic_red_team_common_install_packages:
- wget

atomic_red_team_debian_specific_packages:
ansible_atomic_red_team_debian_specific_packages:
- apt-transport-https
- ca-certificates
- curl
- libunwind8
- software-properties-common

atomic_red_team_redhat_specific_packages:
ansible_atomic_red_team_redhat_specific_packages:
- libicu

0 comments on commit 07af05e

Please sign in to comment.