-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaction.yml
168 lines (154 loc) · 5.92 KB
/
action.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
name: 'Invoke-AtomicRedTeam Action'
description: 'Run local Atomic Red Team tests and adversary emulation'
author: 'smolse'
inputs:
technique:
description: 'ID of the technique to execute'
required: false
test-names:
description: 'Test names to execute'
required: false
test-numbers:
description: 'Test numbers to execute'
required: false
test-guids:
description: 'Test GUIDs to execute'
required: false
test-input-args:
description: 'Custom input arguments used by the atomic test'
required: false
logging-module:
description: 'Logging module for test execution logs'
required: false
default: 'Default-ExecutionLogger'
upload-log-artifact:
description: 'Upload log artifact'
required: false
default: 'true'
log-artifact-name:
description: 'Name of the log artifact'
required: false
default: 'invoke-atomic-execution-logs'
get-prereqs:
description: 'Get prerequisites for tests execution'
required: false
default: 'true'
cleanup:
description: 'Clean up after tests execution'
required: false
default: 'true'
adversary-emulation:
description: 'Execute adversary emulation based on a schedule file'
required: false
default: 'false'
list-of-atomics:
description: 'Path to adversary emulation CSV schedule file'
required: false
runs:
using: 'composite'
steps:
- name: Validate action inputs
shell: pwsh
run: |
Write-Output '${{ toJson(inputs) }}'
if ('${{ inputs.adversary-emulation }}' -ne 'true' -and '${{ inputs.technique }}' -eq '') {
Write-Output "::error::Technique ID must be provided for atomic test execution"
exit 1
}
if ('${{ inputs.adversary-emulation }}' -eq 'true' -and '${{ inputs.list-of-atomics }}' -eq '') {
Write-Output "::error::List of atomics must be provided when adversary emulation is enabled"
exit 1
}
- name: Install Invoke-AtomicRedTeam
shell: pwsh
run: |
if (-not (Get-Module -ListAvailable -Name Invoke-AtomicRedTeam)) {
Install-Module -Name Invoke-AtomicRedTeam -Scope CurrentUser -Force
Write-Output "::debug::Invoke-AtomicRedTeam module has been installed"
} else {
Write-Output "::notice::Invoke-AtomicRedTeam module is already installed"
}
- name: Install atomics folder
shell: pwsh
run: |
$atomicsPath = if (-not ($IsLinux -or $IsMacOS)) { "$env:HOME/AtomicRedTeam/atomics" } else { 'C:\AtomicRedTeam\atomics' }
if (-not (Test-Path $atomicsPath)) {
. ./scripts/Install-AtomicsFolder.ps1; Install-AtomicsFolder
Write-Output "::debug::Atomics folder has been installed"
} else {
Write-Output "::notice::Atomics folder is already installed"
}
working-directory: ${{ github.action_path }}
- name: Execute atomic technique
if: inputs.adversary-emulation != 'true'
shell: pwsh
run: |
$Params = @{
LoggingModule = '${{ inputs.logging-module }}'
}
if ('${{ inputs.test-names }}' -ne '') { $Params.TestNames = '${{ inputs.test-names }}'.Split(',') }
if ('${{ inputs.test-numbers }}' -ne '') { $Params.TestNumbers = '${{ inputs.test-numbers }}'.Split(',') }
if ('${{ inputs.test-guids }}' -ne '') { $Params.TestGuids = '${{ inputs.test-guids }}'.Split(',') }
if ('${{ inputs.test-input-args }}' -ne '') {
$Params.InputArgs = @{}
$jsonArgs = ConvertFrom-Json '${{ inputs.test-input-args }}'
foreach ($key in $jsonArgs.PSObject.Properties.Name) {
$Params.InputArgs[$key] = $jsonArgs.$key
}
}
if ('${{ inputs.get-prereqs }}' -eq 'true') {
Invoke-AtomicTest ${{ inputs.technique }} @Params -GetPrereqs
}
Invoke-AtomicTest ${{ inputs.technique }} @Params
if ('${{ inputs.cleanup }}' -eq 'true') {
Invoke-AtomicTest ${{ inputs.technique }} @Params -Cleanup
}
- name: Execute adversary emulation
if: inputs.adversary-emulation == 'true'
shell: pwsh
run: |
$Params = @{
ListOfAtomics = '${{ inputs.list-of-atomics }}'
}
if ('${{ inputs.get-prereqs }}' -eq 'true') {
Invoke-AtomicRunner @Params -GetPrereqs
}
Invoke-AtomicRunner @Params
if ('${{ inputs.cleanup }}' -eq 'true') {
Invoke-AtomicRunner @Params -Cleanup
}
- name: Determine log artifact
id: log-artifact
if: inputs.upload-log-artifact == 'true'
shell: pwsh
run: |
if ('${{ inputs.adversary-emulation }}' -eq 'true') {
if (-not ($IsLinux -or $IsMacOS)) {
$logPath = "$env:USERPROFILE/AtomicRunner-Logs"
} else {
$logPath = "$env:HOME/AtomicRunner-Logs"
}
} else {
$tmpDir = if (-not ($IsLinux -or $IsMacOS)) { "$env:TEMP" } else { '/tmp' }
if ('${{ inputs.logging-module }}' -eq 'Default-ExecutionLogger') {
$logPath = Join-Path $tmpDir 'Invoke-AtomicTest-ExecutionLog.csv'
} elseif ('${{ inputs.logging-module }}' -eq 'Attire-ExecutionLogger') {
$logPath = (
Get-ChildItem -Path $tmpDir -Filter 'Invoke-AtomicTest-ExecutionLog-*.json' |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
).FullName
}
}
if ($logPath) {
Write-Output "path=$logPath" | Out-File -Append -FilePath $env:GITHUB_OUTPUT
}
- name: Archive execution logs
if: inputs.upload-log-artifact == 'true' && steps.log-artifact.outputs.path
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.log-artifact-name }}
path: ${{ steps.log-artifact.outputs.path }}
branding:
icon: 'shield'
color: 'blue'