Skip to content

Commit 4c7f2f4

Browse files
author
Patrick Bareiss
committed
Deprecate Attack Range Local
1 parent 0cdfefd commit 4c7f2f4

File tree

14 files changed

+264
-603
lines changed

14 files changed

+264
-603
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
<a href="https://github.com/splunk/attack_range/stargazers">
99
<img src="https://img.shields.io/github/stars/splunk/attack_range?style=social" /></a>
1010
</p>
11+
> [!IMPORTANT]
12+
> After careful consideration, we have decided to deprecate the local deployment in Attack Range due to ongoing challenges with VirtualBox and Vagrant. We will concentrate our development efforts on the cloud providers AWS, Azure, and GCP (coming soon). For local cyber range needs, we recommend using Ludus along with the Attack Range environment it offers.
1113
1214
# Splunk Attack Range ⚔️
1315
![Attack Range Log](docs/attack_range.png)

attack_range.py

Lines changed: 157 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99

1010
# need to set this ENV var due to a OSX High Sierra forking bug
1111
# see this discussion for more details: https://github.com/ansible/ansible/issues/34056#issuecomment-352862252
12-
os.environ['OBJC_DISABLE_INITIALIZE_FORK_SAFETY'] = 'YES'
12+
os.environ["OBJC_DISABLE_INITIALIZE_FORK_SAFETY"] = "YES"
1313

1414

1515
def init(args):
1616
config_path = args.config
17-
print("""
17+
print(
18+
"""
1819
__
1920
.d$$b
2021
.' TO$;\\
@@ -44,110 +45,146 @@ def init(args):
4445
4546
By: Splunk Threat Research Team [STRT] - research@splunk.com
4647
47-
""")
48+
"""
49+
)
4850

4951
# parse config
5052
config = ConfigHandler.read_config(config_path)
5153
ConfigHandler.validate_config(config)
5254

53-
if config['general']['cloud_provider'] == 'aws':
54-
config.pop('azure')
55-
config.pop('local')
55+
if config["general"]["cloud_provider"] == "aws":
56+
config.pop("azure")
5657
controller = AwsController(config)
57-
elif config['general']['cloud_provider'] == 'azure':
58-
config.pop('aws')
59-
config.pop('local')
58+
elif config["general"]["cloud_provider"] == "azure":
59+
config.pop("aws")
6060
controller = AzureController(config)
61-
elif config['general']['cloud_provider'] == 'local':
62-
from modules.vagrant_controller import VagrantController
63-
config.pop('azure')
64-
config.pop('aws')
65-
controller = VagrantController(config)
66-
61+
6762
return controller
6863

6964

7065
def simulate(args):
7166
controller = init(args)
7267
controller.simulate(args.engine, args.target, args.technique, args.playbook)
7368

69+
7470
def dump(args):
7571
controller = init(args)
7672
controller.dump(args.file_name, args.search, args.earliest, args.latest)
7773

74+
7875
def replay(args):
7976
controller = init(args)
8077
controller.replay(args.file_name, args.index, args.sourcetype, args.source)
8178

79+
8280
def build(args):
8381
controller = init(args)
8482
controller.build()
8583

84+
8685
def destroy(args):
8786
controller = init(args)
8887
controller.destroy()
8988

89+
9090
def stop(args):
9191
controller = init(args)
92-
instance_ids = [id.strip() for id in args.instance_ids.split(',')] if args.instance_ids else None
92+
instance_ids = (
93+
[id.strip() for id in args.instance_ids.split(",")]
94+
if args.instance_ids
95+
else None
96+
)
9397
controller.stop(instance_ids)
94-
98+
99+
95100
def resume(args):
96101
controller = init(args)
97-
instance_ids = [id.strip() for id in args.instance_ids.split(',')] if args.instance_ids else None
102+
instance_ids = (
103+
[id.strip() for id in args.instance_ids.split(",")]
104+
if args.instance_ids
105+
else None
106+
)
98107
controller.resume(instance_ids)
99108

100-
def packer(args):
101-
controller = init(args)
102-
controller.packer(args.image_name)
103109

104110
def configure(args):
105111
configuration.new(args.config)
106112

113+
107114
def show(args):
108115
controller = init(args)
109116
controller.show()
110117

118+
111119
def create_remote_backend(args):
112120
controller = init(args)
113121
controller.create_remote_backend(args.backend_name)
114122

123+
115124
def delete_remote_backend(args):
116125
controller = init(args)
117126
controller.delete_remote_backend(args.backend_name)
118127

128+
119129
def init_remote_backend(args):
120130
controller = init(args)
121131
controller.init_remote_backend(args.backend_name)
122132

133+
123134
def main(args):
124135
"""
125136
main function parses the arguments passed to the script and calls the respctive method.
126137
127138
:param args: Arguments passed by the user on command line while calling the script.
128-
:return: returns the output of the function called.
139+
:return: returns the output of the function called.
129140
"""
130141
# grab arguments
131142
parser = argparse.ArgumentParser(
132-
description="Use `attack_range.py action -h` to get help with any Attack Range action")
133-
parser.add_argument("-c", "--config", required=False, default="attack_range.yml",
134-
help="path to the configuration file of the attack range")
143+
description="Use `attack_range.py action -h` to get help with any Attack Range action"
144+
)
145+
parser.add_argument(
146+
"-c",
147+
"--config",
148+
required=False,
149+
default="attack_range.yml",
150+
help="path to the configuration file of the attack range",
151+
)
135152
parser.set_defaults(func=lambda _: parser.print_help())
136153

137154
actions_parser = parser.add_subparsers(title="attack Range actions", dest="action")
138-
configure_parser = actions_parser.add_parser("configure", help="configure a new attack range")
139-
build_parser = actions_parser.add_parser("build", help="builds attack range instances")
140-
simulate_parser = actions_parser.add_parser("simulate", help="simulates attack techniques")
141-
destroy_parser = actions_parser.add_parser("destroy", help="destroy attack range instances")
155+
configure_parser = actions_parser.add_parser(
156+
"configure", help="configure a new attack range"
157+
)
158+
build_parser = actions_parser.add_parser(
159+
"build", help="builds attack range instances"
160+
)
161+
simulate_parser = actions_parser.add_parser(
162+
"simulate", help="simulates attack techniques"
163+
)
164+
destroy_parser = actions_parser.add_parser(
165+
"destroy", help="destroy attack range instances"
166+
)
142167
stop_parser = actions_parser.add_parser("stop", help="stops attack range instances")
143-
resume_parser = actions_parser.add_parser("resume", help="resumes previously stopped attack range instances")
168+
resume_parser = actions_parser.add_parser(
169+
"resume", help="resumes previously stopped attack range instances"
170+
)
144171
packer_parser = actions_parser.add_parser("packer", help="create golden images")
145172
show_parser = actions_parser.add_parser("show", help="list machines")
146-
dump_parser = actions_parser.add_parser("dump", help="dump locally logs from attack range instances")
147-
replay_parser = actions_parser.add_parser("replay", help="replay dumps into the splunk server")
148-
create_remote_backend_parser = actions_parser.add_parser("create_remote_backend", help="Create a Remote Backend")
149-
delete_remote_backend_parser = actions_parser.add_parser("delete_remote_backend", help="Delete a Remote Backend")
150-
init_remote_backend_parser = actions_parser.add_parser("init_remote_backend", help="Init a Remote Backend")
173+
dump_parser = actions_parser.add_parser(
174+
"dump", help="dump locally logs from attack range instances"
175+
)
176+
replay_parser = actions_parser.add_parser(
177+
"replay", help="replay dumps into the splunk server"
178+
)
179+
create_remote_backend_parser = actions_parser.add_parser(
180+
"create_remote_backend", help="Create a Remote Backend"
181+
)
182+
delete_remote_backend_parser = actions_parser.add_parser(
183+
"delete_remote_backend", help="Delete a Remote Backend"
184+
)
185+
init_remote_backend_parser = actions_parser.add_parser(
186+
"init_remote_backend", help="Init a Remote Backend"
187+
)
151188

152189
# Build arguments
153190
build_parser.set_defaults(func=build)
@@ -157,73 +194,117 @@ def main(args):
157194

158195
# Stop arguments
159196
stop_parser.set_defaults(func=stop)
160-
stop_parser.add_argument("--instance_ids", required=False, type=str, help="comma-separated list of instance IDs to stop")
197+
stop_parser.add_argument(
198+
"--instance_ids",
199+
required=False,
200+
type=str,
201+
help="comma-separated list of instance IDs to stop",
202+
)
161203

162204
# Resume arguments
163205
resume_parser.set_defaults(func=resume)
164-
resume_parser.add_argument("--instance_ids", required=False, type=str, help="comma-separated list of instance IDs to resume")
165-
166-
# Packer agruments
167-
packer_parser.add_argument("-in", "--image_name", required=True, type=str,
168-
help="provide image name such as splunk, linux, windows-2016, windows-2019, nginx, windows-10, windows-11")
169-
packer_parser.set_defaults(func=packer)
206+
resume_parser.add_argument(
207+
"--instance_ids",
208+
required=False,
209+
type=str,
210+
help="comma-separated list of instance IDs to resume",
211+
)
170212

171213
# Configure arguments
172-
configure_parser.add_argument("-c", "--config", required=False, type=str, default='attack_range.yml',
173-
help="provide path to write configuration to")
214+
configure_parser.add_argument(
215+
"-c",
216+
"--config",
217+
required=False,
218+
type=str,
219+
default="attack_range.yml",
220+
help="provide path to write configuration to",
221+
)
174222
configure_parser.set_defaults(func=configure)
175223

176224
# Simulation arguments
177-
simulate_parser.add_argument("-e", "--engine", required=False, default="ART",
178-
help="simulation engine to use. Available options are: PurpleSharp and ART (default)")
179-
simulate_parser.add_argument("-t", "--target", required=True,
180-
help="target for attack simulation. Use the name of the aws EC2 name")
181-
simulate_parser.add_argument("-te", "--technique", required=False, type=str, default="",
182-
help="comma delimited list of MITRE ATT&CK technique ID to simulate in the "
183-
"attack_range, example: T1117, T1118")
184-
simulate_parser.add_argument("-p", "--playbook", required=False, type=str, default="",
185-
help="file path for a simulation playbook")
225+
simulate_parser.add_argument(
226+
"-e",
227+
"--engine",
228+
required=False,
229+
default="ART",
230+
help="simulation engine to use. Available options are: PurpleSharp and ART (default)",
231+
)
232+
simulate_parser.add_argument(
233+
"-t",
234+
"--target",
235+
required=True,
236+
help="target for attack simulation. Use the name of the aws EC2 name",
237+
)
238+
simulate_parser.add_argument(
239+
"-te",
240+
"--technique",
241+
required=False,
242+
type=str,
243+
default="",
244+
help="comma delimited list of MITRE ATT&CK technique ID to simulate in the "
245+
"attack_range, example: T1117, T1118",
246+
)
247+
simulate_parser.add_argument(
248+
"-p",
249+
"--playbook",
250+
required=False,
251+
type=str,
252+
default="",
253+
help="file path for a simulation playbook",
254+
)
186255

187256
simulate_parser.set_defaults(func=simulate)
188257

189258
# Dump Arguments
190-
dump_parser.add_argument("-fn", "--file_name", required=True,
191-
help="file name of the attack_data")
192-
dump_parser.add_argument("--search", required=True,
193-
help="splunk search to export")
194-
dump_parser.add_argument("--earliest", required=True,
195-
help="earliest time of the splunk search")
196-
dump_parser.add_argument("--latest", required=False, default="now",
197-
help="latest time of the splunk search")
259+
dump_parser.add_argument(
260+
"-fn", "--file_name", required=True, help="file name of the attack_data"
261+
)
262+
dump_parser.add_argument("--search", required=True, help="splunk search to export")
263+
dump_parser.add_argument(
264+
"--earliest", required=True, help="earliest time of the splunk search"
265+
)
266+
dump_parser.add_argument(
267+
"--latest",
268+
required=False,
269+
default="now",
270+
help="latest time of the splunk search",
271+
)
198272
dump_parser.set_defaults(func=dump)
199273

200274
# Replay Arguments
201-
replay_parser.add_argument("-fn", "--file_name", required=True,
202-
help="file name of the attack_data")
203-
replay_parser.add_argument("--source", required=True,
204-
help="source of replayed data")
205-
replay_parser.add_argument("--sourcetype", required=True,
206-
help="sourcetype of replayed data")
207-
replay_parser.add_argument("--index", required=False, default="test",
208-
help="index of replayed data")
275+
replay_parser.add_argument(
276+
"-fn", "--file_name", required=True, help="file name of the attack_data"
277+
)
278+
replay_parser.add_argument(
279+
"--source", required=True, help="source of replayed data"
280+
)
281+
replay_parser.add_argument(
282+
"--sourcetype", required=True, help="sourcetype of replayed data"
283+
)
284+
replay_parser.add_argument(
285+
"--index", required=False, default="test", help="index of replayed data"
286+
)
209287
replay_parser.set_defaults(func=replay)
210288

211289
# Show arguments
212290
show_parser.set_defaults(func=show, machines=True)
213291

214292
# Create Remote Backend
215-
create_remote_backend_parser.add_argument("-bn", "--backend_name", required=True,
216-
help="name of the remote backend")
293+
create_remote_backend_parser.add_argument(
294+
"-bn", "--backend_name", required=True, help="name of the remote backend"
295+
)
217296
create_remote_backend_parser.set_defaults(func=create_remote_backend)
218297

219298
# Delete Remote Backend
220-
delete_remote_backend_parser.add_argument("-bn", "--backend_name", required=True,
221-
help="name of the remote backend")
299+
delete_remote_backend_parser.add_argument(
300+
"-bn", "--backend_name", required=True, help="name of the remote backend"
301+
)
222302
delete_remote_backend_parser.set_defaults(func=delete_remote_backend)
223-
303+
224304
# Init Remote Backend
225-
init_remote_backend_parser.add_argument("-bn", "--backend_name", required=True,
226-
help="name of the remote backend")
305+
init_remote_backend_parser.add_argument(
306+
"-bn", "--backend_name", required=True, help="name of the remote backend"
307+
)
227308
init_remote_backend_parser.set_defaults(func=init_remote_backend)
228309

229310
# # parse them

configs/attack_range_default.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,6 @@ azure:
9393
event_hub_host_name: "xxx"
9494
# All these fields are needed to configure the Azure logs. See the chapter Azure Logs in the docs page Attack Range Cloud.
9595

96-
local:
97-
provider: "Virtual Box"
98-
# Attack Range Local used Virtualbox and Vagrant to build the Attack Range.
99-
10096
splunk_server:
10197

10298
install_es: "0"

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy