Skip to content

Commit

Permalink
Adding Tutorials
Browse files Browse the repository at this point in the history
  • Loading branch information
cage-challenge committed Nov 4, 2022
1 parent ed830b6 commit 9943f85
Show file tree
Hide file tree
Showing 8 changed files with 3,690 additions and 0 deletions.
18 changes: 18 additions & 0 deletions CybORG/Tutorial/0. Installation.md
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
```
355 changes: 355 additions & 0 deletions CybORG/Tutorial/1. Introduction.ipynb
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
}
Loading

0 comments on commit 9943f85

Please sign in to comment.