-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ed830b6
commit 9943f85
Showing
8 changed files
with
3,690 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Installation Instructions | ||
We recommend using a virtual environment running python 3.8 or later. The code below has been tested using an Anaconda virtual environment running python 3.8.11. | ||
|
||
Clone the repo using git. | ||
``` | ||
git clone https://github.com/cage-challenge/cage-challenge-1.git | ||
``` | ||
|
||
Install using pip. | ||
|
||
``` | ||
pip install -e cage-challenge-1/CybORG | ||
``` | ||
|
||
Confirm system is installed correctly by running tests. | ||
``` | ||
pytest cage-challenge-1/CybORG/CybORG/Tests/test_sim | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,355 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Importing CybORG" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"To use the CybORG environment, it is necessary to import the CybORG class. CybORG stands for __Cyb__er __O__perations __R__esearch __G__ym, so remember to capitalise correctly when importing. " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 16, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from CybORG import CybORG" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Instantiating CybORG" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"ALthough CybORG uses an OpenAI gym API, it is not run by calling gym.make(). Instead it has to be manually instantiated. The constructor has two mandatory string parameters: a mode-type which specifies which engine will be used under the hood and the path to a .yaml scenario file which defines the network layout and agent action spaces.\n", | ||
"\n", | ||
"The only currently supported mode is simulation, while this challenge uses Scenario 1b." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import inspect\n", | ||
"\n", | ||
"path = str(inspect.getfile(CybORG))\n", | ||
"path = path[:-7] + f'/Shared/Scenarios/Scenario1b.yaml'\n", | ||
"\n", | ||
"env = CybORG(path, 'sim')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Using an Agent with CybORG" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Scenario 1b has multiple actors involved: Red team will be attacking the network, Blue team will be defending the network, while Green team represents noise generated by users. Normally the roles of Red and Green will be handled by internal rules-based agents, while Blue team interacts with the external API. However, for demonstration purposes, it will be easier to first examine a Red agent.\n", | ||
"\n", | ||
"CybORG uses an OpenAI Gym interface to interact with agents. Thus, we can begin the scenario by calling the reset method. It is necessary to specify which team you are on as a string parameter. Without using any wrappers, CybORG will return a results object which contains various bits of data. We can get the observation by accessing the corresponding attribute." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"{'success': <TrinaryEnum.UNKNOWN: 2>, 'User0': {'Interface': [{'Interface Name': 'eth0', 'IP Address': IPv4Address('10.0.189.193'), 'Subnet': IPv4Network('10.0.189.192/28')}], 'Sessions': [{'Username': 'SYSTEM', 'ID': 0, 'Timeout': 0, 'PID': 7580, 'Type': <SessionType.RED_ABSTRACT_SESSION: 10>, 'Agent': 'Red'}], 'Processes': [{'PID': 7580, 'Username': 'SYSTEM'}], 'System info': {'Hostname': 'User0', 'OSType': <OperatingSystemType.WINDOWS: 2>, 'OSDistribution': <OperatingSystemDistribution.WINDOWS_SVR_2008: 4>, 'OSVersion': <OperatingSystemVersion.W6_1_7601: 13>, 'Architecture': <Architecture.x64: 2>}}}\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"results = env.reset(agent='Red')\n", | ||
"obs = results.observation\n", | ||
"\n", | ||
"print(obs)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"We can see that the above observation outputs a messy dictionary. In order to understand raw CybORG observations, please go to the observation tutorial. We will show how to train a neural network-based agent with CybORG down below.\n", | ||
"\n", | ||
"Because of the complexties of Cybersecurity, the action space in CybORG is generated on the fly. For Scenario 1b, this only needs to be extracted at the beginning of the scenario. This can also be found in the results object. It is another messy dictionary, so we will only print out the keys. You can learn more in the action_space tutorial." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"['action', 'subnet', 'ip_address', 'session', 'username', 'password', 'process', 'port', 'target_session', 'agent', 'hostname']\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"action_space = results.action_space\n", | ||
"\n", | ||
"print(list(action_space.keys()))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Just like OpenAI gym, CybORG uses a step function to input actions and return results. The method itself requires two string parameters: agent is the name of the team that is taking the action and action is the action being performed." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 5, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from CybORG.Agents import B_lineAgent\n", | ||
"\n", | ||
"agent = B_lineAgent()\n", | ||
"\n", | ||
"action = agent.get_action(obs,action_space)\n", | ||
"\n", | ||
"results = env.step(agent='Red',action=action)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"The results object contains the new observation, reward and done attributes." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 6, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"{'success': <TrinaryEnum.TRUE: 1>, '10.0.189.193': {'Interface': [{'IP Address': IPv4Address('10.0.189.193'), 'Subnet': IPv4Network('10.0.189.192/28')}]}, '10.0.189.204': {'Interface': [{'IP Address': IPv4Address('10.0.189.204'), 'Subnet': IPv4Network('10.0.189.192/28')}]}, '10.0.189.197': {'Interface': [{'IP Address': IPv4Address('10.0.189.197'), 'Subnet': IPv4Network('10.0.189.192/28')}]}, '10.0.189.198': {'Interface': [{'IP Address': IPv4Address('10.0.189.198'), 'Subnet': IPv4Network('10.0.189.192/28')}]}, '10.0.189.195': {'Interface': [{'IP Address': IPv4Address('10.0.189.195'), 'Subnet': IPv4Network('10.0.189.192/28')}]}}\n", | ||
"----------------------------------------------------------------------------\n", | ||
"DiscoverRemoteSystems 10.0.189.192/28\n", | ||
"----------------------------------------------------------------------------\n", | ||
"False\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"print(results.observation)\n", | ||
"print(76*'-')\n", | ||
"print(results.action)\n", | ||
"print(76*'-')\n", | ||
"print(results.done)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Adding Opponents" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"In the example above, only Red Team performed any actions. In order to setup CybORG for the full challenge, we want a Blue Agent to be interacting with the external API while Red and Green take their actions automatically in the background.\n", | ||
"\n", | ||
"We can achieve this by specifying an agents dictionary to pass into CybORG when instantiating the class. Now, whenever the step function is called, the agents will take turn to perform their actions. Note that the turn order is Blue, Green then Red." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 7, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"0.0\n", | ||
"0.0\n", | ||
"-0.1\n", | ||
"-0.1\n", | ||
"-0.1\n", | ||
"-0.1\n", | ||
"-1.1\n", | ||
"-1.1\n", | ||
"-1.1\n", | ||
"-1.1\n", | ||
"-2.1\n", | ||
"-2.1\n", | ||
"-2.1\n", | ||
"-3.1\n", | ||
"-13.1\n", | ||
"-13.1\n", | ||
"-13.1\n", | ||
"-13.1\n", | ||
"-13.1\n", | ||
"-13.1\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"from CybORG.Agents import B_lineAgent, GreenAgent, BlueMonitorAgent\n", | ||
"\n", | ||
"agents = {\n", | ||
" 'Red': B_lineAgent,\n", | ||
" 'Green': GreenAgent\n", | ||
"}\n", | ||
"\n", | ||
"env = CybORG(path,'sim',agents=agents)\n", | ||
"\n", | ||
"results = env.reset(agent='Blue')\n", | ||
"obs = results.observation\n", | ||
"action_space = results.action_space\n", | ||
"agent = BlueMonitorAgent()\n", | ||
"\n", | ||
"for step in range(20):\n", | ||
" action = agent.get_action(obs,action_space=action_space)\n", | ||
" results = env.step(agent='Blue',action=action)\n", | ||
" obs = results.observation\n", | ||
" reward = results.reward\n", | ||
" print(reward)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Using a Neural Network with CybORG" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"In order to use a Neural network with CybORG, we will need to import a wrapper. The Challenge Wrapper provides all the functionality needed for the Scenario1b challenge and makes the external api much more in line with OpenAI gym." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 8, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", | ||
" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"from CybORG.Agents.Wrappers import ChallengeWrapper\n", | ||
"cyborg = CybORG(path,'sim',agents=agents)\n", | ||
"env = ChallengeWrapper(env=cyborg,agent_name='Blue')\n", | ||
"\n", | ||
"obs = env.reset()\n", | ||
"\n", | ||
"print(obs)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Not only is the observation now a vector, but we can extract the action and observation spaces exactly like a gym environment." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"The step function also behaves like that of OpenAI gym. The info parameter contains a dictionary form of the standard results object for debugging purposes." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 10, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", | ||
" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]\n", | ||
"----------------------------------------------------------------------------\n", | ||
"0.0\n", | ||
"----------------------------------------------------------------------------\n", | ||
"False\n", | ||
"----------------------------------------------------------------------------\n", | ||
"{'observation': array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", | ||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", | ||
" 0, 0, 0, 0, 0, 0, 0, 0]), 'next_observation': None, 'done': False, 'reward': 0.0, 'action': <CybORG.Shared.Actions.Action.Sleep object at 0x7f3a314d7750>, 'info': None, 'parameter_mask': None, 'action_space': 41, 'error': None, 'error_msg': None, 'action_name': None, 'selection_masks': None}\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"action = 0\n", | ||
"\n", | ||
"obs, reward, done, info = env.step(action)\n", | ||
"\n", | ||
"print(obs)\n", | ||
"print(76*'-')\n", | ||
"print(reward)\n", | ||
"print(76*'-')\n", | ||
"print(done)\n", | ||
"print(76*'-')\n", | ||
"print(info)" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.7.5" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 4 | ||
} |
Oops, something went wrong.