5
5
from modules .config_handler import ConfigHandler
6
6
from modules .aws_controller import AwsController
7
7
from modules .azure_controller import AzureController
8
+ from modules .gcp_controller import GCPController
8
9
from modules import configuration
9
10
10
11
# need to set this ENV var due to a OSX High Sierra forking bug
11
12
# see this discussion for more details: https://github.com/ansible/ansible/issues/34056#issuecomment-352862252
12
- os .environ [' OBJC_DISABLE_INITIALIZE_FORK_SAFETY' ] = ' YES'
13
+ os .environ [" OBJC_DISABLE_INITIALIZE_FORK_SAFETY" ] = " YES"
13
14
14
15
15
16
def init (args ):
16
17
config_path = args .config
17
- print ("""
18
+ print (
19
+ """
18
20
__
19
21
.d$$b
20
22
.' TO$;\\
@@ -44,41 +46,42 @@ def init(args):
44
46
45
47
By: Splunk Threat Research Team [STRT] - research@splunk.com
46
48
47
- """ )
49
+ """
50
+ )
48
51
49
52
# parse config
50
53
config = ConfigHandler .read_config (config_path )
51
54
ConfigHandler .validate_config (config )
52
55
53
- if config [' general' ][ ' cloud_provider' ] == ' aws' :
54
- config .pop (' azure' )
55
- config .pop (' local' )
56
- config .pop (' gcp' )
56
+ if config [" general" ][ " cloud_provider" ] == " aws" :
57
+ config .pop (" azure" )
58
+ config .pop (" local" )
59
+ config .pop (" gcp" )
57
60
controller = AwsController (config )
58
- elif config [' general' ][ ' cloud_provider' ] == ' azure' :
59
- config .pop (' aws' )
60
- config .pop (' local' )
61
- config .pop (' gcp' )
61
+ elif config [" general" ][ " cloud_provider" ] == " azure" :
62
+ config .pop (" aws" )
63
+ config .pop (" local" )
64
+ config .pop (" gcp" )
62
65
controller = AzureController (config )
63
- elif config [' general' ][ ' cloud_provider' ] == ' gcp' :
64
- config .pop (' aws' )
65
- config .pop (' local' )
66
- config .pop (' azure' )
66
+ elif config [" general" ][ " cloud_provider" ] == " gcp" :
67
+ config .pop (" aws" )
68
+ config .pop (" local" )
69
+ config .pop (" azure" )
67
70
controller = GCPController (config )
68
- elif config [' general' ][ ' cloud_provider' ] == ' local' :
71
+ elif config [" general" ][ " cloud_provider" ] == " local" :
69
72
from modules .vagrant_controller import VagrantController
70
- config .pop ('azure' )
71
- config .pop ('aws' )
72
- config .pop ('gcp' )
73
+
74
+ config .pop ("azure" )
75
+ config .pop ("aws" )
76
+ config .pop ("gcp" )
73
77
controller = VagrantController (config )
74
78
75
79
return controller
76
80
77
81
78
82
def simulate (args ):
79
83
controller = init (args )
80
- controller .simulate (args .engine , args .target ,
81
- args .technique , args .playbook )
84
+ controller .simulate (args .engine , args .target , args .technique , args .playbook )
82
85
83
86
84
87
def dump (args ):
@@ -103,15 +106,21 @@ def destroy(args):
103
106
104
107
def stop (args ):
105
108
controller = init (args )
106
- instance_ids = [id .strip () for id in args .instance_ids .split (
107
- ',' )] if args .instance_ids else None
109
+ instance_ids = (
110
+ [id .strip () for id in args .instance_ids .split ("," )]
111
+ if args .instance_ids
112
+ else None
113
+ )
108
114
controller .stop (instance_ids )
109
115
110
116
111
117
def resume (args ):
112
118
controller = init (args )
113
- instance_ids = [id .strip () for id in args .instance_ids .split (
114
- ',' )] if args .instance_ids else None
119
+ instance_ids = (
120
+ [id .strip () for id in args .instance_ids .split ("," )]
121
+ if args .instance_ids
122
+ else None
123
+ )
115
124
controller .resume (instance_ids )
116
125
117
126
@@ -149,42 +158,55 @@ def main(args):
149
158
main function parses the arguments passed to the script and calls the respctive method.
150
159
151
160
:param args: Arguments passed by the user on command line while calling the script.
152
- :return: returns the output of the function called.
161
+ :return: returns the output of the function called.
153
162
"""
154
163
# grab arguments
155
164
parser = argparse .ArgumentParser (
156
- description = "Use `attack_range.py action -h` to get help with any Attack Range action" )
157
- parser .add_argument ("-c" , "--config" , required = False , default = "attack_range.yml" ,
158
- help = "path to the configuration file of the attack range" )
165
+ description = "Use `attack_range.py action -h` to get help with any Attack Range action"
166
+ )
167
+ parser .add_argument (
168
+ "-c" ,
169
+ "--config" ,
170
+ required = False ,
171
+ default = "attack_range.yml" ,
172
+ help = "path to the configuration file of the attack range" ,
173
+ )
159
174
parser .set_defaults (func = lambda _ : parser .print_help ())
160
175
161
- actions_parser = parser .add_subparsers (
162
- title = "attack Range actions" , dest = "action" )
176
+ actions_parser = parser .add_subparsers (title = "attack Range actions" , dest = "action" )
163
177
configure_parser = actions_parser .add_parser (
164
- "configure" , help = "configure a new attack range" )
178
+ "configure" , help = "configure a new attack range"
179
+ )
165
180
build_parser = actions_parser .add_parser (
166
- "build" , help = "builds attack range instances" )
181
+ "build" , help = "builds attack range instances"
182
+ )
167
183
simulate_parser = actions_parser .add_parser (
168
- "simulate" , help = "simulates attack techniques" )
184
+ "simulate" , help = "simulates attack techniques"
185
+ )
169
186
destroy_parser = actions_parser .add_parser (
170
- "destroy" , help = "destroy attack range instances" )
171
- stop_parser = actions_parser . add_parser (
172
- "stop" , help = "stops attack range instances" )
187
+ "destroy" , help = "destroy attack range instances"
188
+ )
189
+ stop_parser = actions_parser . add_parser ( "stop" , help = "stops attack range instances" )
173
190
resume_parser = actions_parser .add_parser (
174
- "resume" , help = "resumes previously stopped attack range instances" )
175
- packer_parser = actions_parser . add_parser (
176
- "packer" , help = "create golden images" )
191
+ "resume" , help = "resumes previously stopped attack range instances"
192
+ )
193
+ packer_parser = actions_parser . add_parser ( "packer" , help = "create golden images" )
177
194
show_parser = actions_parser .add_parser ("show" , help = "list machines" )
178
195
dump_parser = actions_parser .add_parser (
179
- "dump" , help = "dump locally logs from attack range instances" )
196
+ "dump" , help = "dump locally logs from attack range instances"
197
+ )
180
198
replay_parser = actions_parser .add_parser (
181
- "replay" , help = "replay dumps into the splunk server" )
199
+ "replay" , help = "replay dumps into the splunk server"
200
+ )
182
201
create_remote_backend_parser = actions_parser .add_parser (
183
- "create_remote_backend" , help = "Create a Remote Backend" )
202
+ "create_remote_backend" , help = "Create a Remote Backend"
203
+ )
184
204
delete_remote_backend_parser = actions_parser .add_parser (
185
- "delete_remote_backend" , help = "Delete a Remote Backend" )
205
+ "delete_remote_backend" , help = "Delete a Remote Backend"
206
+ )
186
207
init_remote_backend_parser = actions_parser .add_parser (
187
- "init_remote_backend" , help = "Init a Remote Backend" )
208
+ "init_remote_backend" , help = "Init a Remote Backend"
209
+ )
188
210
189
211
# Build arguments
190
212
build_parser .set_defaults (func = build )
@@ -194,75 +216,127 @@ def main(args):
194
216
195
217
# Stop arguments
196
218
stop_parser .set_defaults (func = stop )
197
- stop_parser .add_argument ("--instance_ids" , required = False ,
198
- type = str , help = "comma-separated list of instance IDs to stop" )
219
+ stop_parser .add_argument (
220
+ "--instance_ids" ,
221
+ required = False ,
222
+ type = str ,
223
+ help = "comma-separated list of instance IDs to stop" ,
224
+ )
199
225
200
226
# Resume arguments
201
227
resume_parser .set_defaults (func = resume )
202
- resume_parser .add_argument ("--instance_ids" , required = False ,
203
- type = str , help = "comma-separated list of instance IDs to resume" )
228
+ resume_parser .add_argument (
229
+ "--instance_ids" ,
230
+ required = False ,
231
+ type = str ,
232
+ help = "comma-separated list of instance IDs to resume" ,
233
+ )
204
234
205
235
# Packer agruments
206
- packer_parser .add_argument ("-in" , "--image_name" , required = True , type = str ,
207
- help = "provide image name such as splunk, linux, windows-2016, windows-2019, nginx, windows-10, windows-11" )
236
+ packer_parser .add_argument (
237
+ "-in" ,
238
+ "--image_name" ,
239
+ required = True ,
240
+ type = str ,
241
+ help = "provide image name such as splunk, linux, windows-2016, windows-2019, nginx, windows-10, windows-11" ,
242
+ )
208
243
packer_parser .set_defaults (func = packer )
209
244
210
245
# Configure arguments
211
- configure_parser .add_argument ("-c" , "--config" , required = False , type = str , default = 'attack_range.yml' ,
212
- help = "provide path to write configuration to" )
246
+ configure_parser .add_argument (
247
+ "-c" ,
248
+ "--config" ,
249
+ required = False ,
250
+ type = str ,
251
+ default = "attack_range.yml" ,
252
+ help = "provide path to write configuration to" ,
253
+ )
213
254
configure_parser .set_defaults (func = configure )
214
255
215
256
# Simulation arguments
216
- simulate_parser .add_argument ("-e" , "--engine" , required = False , default = "ART" ,
217
- help = "simulation engine to use. Available options are: PurpleSharp and ART (default)" )
218
- simulate_parser .add_argument ("-t" , "--target" , required = True ,
219
- help = "target for attack simulation. Use the name of the aws EC2 name" )
220
- simulate_parser .add_argument ("-te" , "--technique" , required = False , type = str , default = "" ,
221
- help = "comma delimited list of MITRE ATT&CK technique ID to simulate in the "
222
- "attack_range, example: T1117, T1118" )
223
- simulate_parser .add_argument ("-p" , "--playbook" , required = False , type = str , default = "" ,
224
- help = "file path for a simulation playbook" )
257
+ simulate_parser .add_argument (
258
+ "-e" ,
259
+ "--engine" ,
260
+ required = False ,
261
+ default = "ART" ,
262
+ help = "simulation engine to use. Available options are: PurpleSharp and ART (default)" ,
263
+ )
264
+ simulate_parser .add_argument (
265
+ "-t" ,
266
+ "--target" ,
267
+ required = True ,
268
+ help = "target for attack simulation. Use the name of the aws EC2 name" ,
269
+ )
270
+ simulate_parser .add_argument (
271
+ "-te" ,
272
+ "--technique" ,
273
+ required = False ,
274
+ type = str ,
275
+ default = "" ,
276
+ help = "comma delimited list of MITRE ATT&CK technique ID to simulate in the "
277
+ "attack_range, example: T1117, T1118" ,
278
+ )
279
+ simulate_parser .add_argument (
280
+ "-p" ,
281
+ "--playbook" ,
282
+ required = False ,
283
+ type = str ,
284
+ default = "" ,
285
+ help = "file path for a simulation playbook" ,
286
+ )
225
287
226
288
simulate_parser .set_defaults (func = simulate )
227
289
228
290
# Dump Arguments
229
- dump_parser .add_argument ("-fn" , "--file_name" , required = True ,
230
- help = "file name of the attack_data" )
231
- dump_parser .add_argument ("--search" , required = True ,
232
- help = "splunk search to export" )
233
- dump_parser .add_argument ("--earliest" , required = True ,
234
- help = "earliest time of the splunk search" )
235
- dump_parser .add_argument ("--latest" , required = False , default = "now" ,
236
- help = "latest time of the splunk search" )
291
+ dump_parser .add_argument (
292
+ "-fn" , "--file_name" , required = True , help = "file name of the attack_data"
293
+ )
294
+ dump_parser .add_argument ("--search" , required = True , help = "splunk search to export" )
295
+ dump_parser .add_argument (
296
+ "--earliest" , required = True , help = "earliest time of the splunk search"
297
+ )
298
+ dump_parser .add_argument (
299
+ "--latest" ,
300
+ required = False ,
301
+ default = "now" ,
302
+ help = "latest time of the splunk search" ,
303
+ )
237
304
dump_parser .set_defaults (func = dump )
238
305
239
306
# Replay Arguments
240
- replay_parser .add_argument ("-fn" , "--file_name" , required = True ,
241
- help = "file name of the attack_data" )
242
- replay_parser .add_argument ("--source" , required = True ,
243
- help = "source of replayed data" )
244
- replay_parser .add_argument ("--sourcetype" , required = True ,
245
- help = "sourcetype of replayed data" )
246
- replay_parser .add_argument ("--index" , required = False , default = "test" ,
247
- help = "index of replayed data" )
307
+ replay_parser .add_argument (
308
+ "-fn" , "--file_name" , required = True , help = "file name of the attack_data"
309
+ )
310
+ replay_parser .add_argument (
311
+ "--source" , required = True , help = "source of replayed data"
312
+ )
313
+ replay_parser .add_argument (
314
+ "--sourcetype" , required = True , help = "sourcetype of replayed data"
315
+ )
316
+ replay_parser .add_argument (
317
+ "--index" , required = False , default = "test" , help = "index of replayed data"
318
+ )
248
319
replay_parser .set_defaults (func = replay )
249
320
250
321
# Show arguments
251
322
show_parser .set_defaults (func = show , machines = True )
252
323
253
324
# Create Remote Backend
254
- create_remote_backend_parser .add_argument ("-bn" , "--backend_name" , required = True ,
255
- help = "name of the remote backend" )
325
+ create_remote_backend_parser .add_argument (
326
+ "-bn" , "--backend_name" , required = True , help = "name of the remote backend"
327
+ )
256
328
create_remote_backend_parser .set_defaults (func = create_remote_backend )
257
329
258
330
# Delete Remote Backend
259
- delete_remote_backend_parser .add_argument ("-bn" , "--backend_name" , required = True ,
260
- help = "name of the remote backend" )
331
+ delete_remote_backend_parser .add_argument (
332
+ "-bn" , "--backend_name" , required = True , help = "name of the remote backend"
333
+ )
261
334
delete_remote_backend_parser .set_defaults (func = delete_remote_backend )
262
335
263
336
# Init Remote Backend
264
- init_remote_backend_parser .add_argument ("-bn" , "--backend_name" , required = True ,
265
- help = "name of the remote backend" )
337
+ init_remote_backend_parser .add_argument (
338
+ "-bn" , "--backend_name" , required = True , help = "name of the remote backend"
339
+ )
266
340
init_remote_backend_parser .set_defaults (func = init_remote_backend )
267
341
268
342
# # parse them
0 commit comments