-
Notifications
You must be signed in to change notification settings - Fork 3
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
0 parents
commit b10b80b
Showing
140 changed files
with
44,444 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,11 @@ | ||
.git | ||
**/*.egg-info | ||
**/*.pyc | ||
**/__pycache__ | ||
test | ||
|
||
**/cloned_repos | ||
|
||
ooogame/database/frontend/build | ||
ooogame/team_interface/frontend/build | ||
**/node_modules |
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,45 @@ | ||
name: Test | ||
|
||
on: [push] | ||
|
||
jobs: | ||
|
||
pytype: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up Python 3.8 | ||
uses: actions/setup-python@v1 | ||
with: | ||
python-version: 3.8 | ||
- name: Pip install ooogame itself | ||
run: pip install -e .[mysql] | ||
|
||
- name: Pip install other deps (koh, chalmanager) | ||
run: pip install ipdb click boto3 | ||
- name: Install pytype | ||
run: pip install pytype | ||
|
||
- name: Check python files with pytype | ||
run: find ./ooogame -name '*.py' | xargs pytype --keep-going | ||
|
||
|
||
nose: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up Python 3.8 | ||
uses: actions/setup-python@v1 | ||
with: | ||
python-version: 3.8 | ||
- name: Pre-pulling docker images | ||
run: | | ||
docker pull registry | ||
docker pull ubuntu:18.04 | ||
docker pull httpd:alpine | ||
- name: Pip install ooogame itself | ||
run: pip install -e .[mysql] | ||
|
||
- name: Run nose tests | ||
run: python3 -m "nose" -v --logging-clear-handlers |
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,5 @@ | ||
**/__pycache__/ | ||
**/*.pyc | ||
**/*.egg-info | ||
**/.idea | ||
**/.DS_Store |
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,3 @@ | ||
*.map | ||
/ooogame/database/frontend/build/ | ||
yarn.lock |
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,25 @@ | ||
BSD 2-Clause License | ||
|
||
Copyright (c) 2022, Order of the Overflow | ||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are met: | ||
|
||
1. Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
|
||
2. Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
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,174 @@ | ||
# dcf-game-infrastructure | ||
|
||
[](https://github.com/o-o-overflow/dcf-game-infrastructure/actions) | ||
|
||
All the components necessary to run a game of the OOO DC CTF finals. | ||
|
||
Authors: [adamd](https://adamdoupe.com), [hacopo](https://jacopo.cc), [Erik Trickel](https://trickel.com/), [Zardus](https://www.yancomm.net/), and [bboe](https://bryceboe.com/) | ||
|
||
## Design Philosophy | ||
|
||
This repo contains all the game components necessary to run an Attack-Defense CTF that OOO used from 2018--2021. | ||
|
||
The design is based on adamd's experience building the [ictf-framework](https://github.com/shellphish/ictf-framework). | ||
|
||
There are fundamental tenenats that we try to follow in the design of the system: | ||
|
||
### Spoke component model | ||
|
||
The communication design of the components in the system (which you can kind of think of as micro-services) is a "spoke" model, where every component talks to the database (through a RESTish API), and no component directly talks to any other. | ||
|
||
In this way, each component can be updated separately and can also be _scaled_ independently using our k8s hosting. | ||
|
||
This also made testing of each component easier, as the only dependence on a component is on the state of the database. | ||
|
||
The only exception to this is the `patchbot` (the component that needs to test the patches submitted by the teams). | ||
|
||
The database API puts the `patchbot` testing jobs into an [RQ (Redis Queue)](https://python-rq.org), which all the `patchbot` workers pull jobs from. | ||
|
||
### Append-only database design | ||
|
||
Fundamentally, a CTF database needs to calculate scores (that's essentially what the teams care about). | ||
|
||
Prior design approaches that we've used would have a `points` or `score` column in the `team` table, and when they acquired or lost points, the app code would change this value. | ||
|
||
However, many crazy things can happen during a CTF: recalculating scores or missed flags, even changing the scoring functions itself. | ||
|
||
These can be difficult to handle depending on how the system is developed. | ||
|
||
Therefore, we created a completely append-only database model, where no data in the DB is ever deleted or changed. | ||
|
||
Even things like `service` status (the GOOD, OK, LOW, BAD that we used) is not a column in the `services` table. | ||
Every change of status would created a new `StatusIndicator` row, and the `services` would pull the latest version from this table. | ||
|
||
### Event model | ||
|
||
Related to the append-only database design, everything in the database was represented by events. | ||
|
||
The database would store all game events (in our game over the years was `SLA_SCRIPT`, `FLAG_STOLEN`, `SET_FLAG`, `KOH_SCORE_FETCH`, `KOH_RANKING`, `PCAP_CREATED`, `PCAP_RELEASED`, and `STEALTH`). | ||
|
||
Then, the state of the game is based on these events. | ||
|
||
An additional benefit is that these events could be shipped to the teams as part of the `game_state.json`. | ||
|
||
### Separate k8s clusters | ||
|
||
How we ran this is with _two_ [k8s](https://kubernetes.io) clusters: an admin cluster and a game cluster. | ||
|
||
The `admin` cluster ran all of these components. | ||
|
||
The `game` cluster ran all of the CTF challenges. | ||
|
||
We used this design to do things like drop flags on the services. | ||
The `flagbot` used `kubectl` to drop a flag onto a service running in the other cluster. | ||
|
||
This also allowed us to lock down the `game` cluster so that the vulnerable services couldn't make external requests, could be scaled separately, etc. | ||
|
||
|
||
## Install Requirements | ||
|
||
This package is pip installable, and installs all dependencies. Do the following in a virtualenv: | ||
|
||
~~~bash | ||
$ pip install -e . | ||
~~~ | ||
|
||
**NOTE:** If you want to connect to a mysql server (such as in prod or when deving against a mysql server), install the `mysqlclient` dependency like so: | ||
|
||
~~~bash | ||
$ pip install -e .[mysql] | ||
~~~ | ||
|
||
## Testing | ||
|
||
Make sure the tests pass before you commit, and add new test cases in [test](test) for new features. | ||
|
||
Note the database API now checks that the timezone is in UTC, so you'll need to specify that to run the tests: | ||
|
||
~~~bash | ||
$ TZ=UTC nosetests -v | ||
~~~ | ||
|
||
## Local Dev | ||
|
||
If you're using tmux, I created a script [local_dev.sh](local_dev.sh) | ||
that will run a database-api, database-api frontend, team-interface | ||
backend, team-interface frontend, gamebot, and an ipython session with | ||
a database client created. | ||
|
||
Just run the following | ||
|
||
~~~bash | ||
$ ./local_dev.sh | ||
~~~ | ||
|
||
## Deploy to prod | ||
|
||
Build and `-p` push the image to production registry. | ||
|
||
~~~bash | ||
$ ./deploy.sh -p | ||
~~~ | ||
|
||
Won't `-r` restart the running services, need to do: | ||
|
||
~~~bash | ||
$ ./deploy.sh -p -r | ||
~~~ | ||
|
||
|
||
## database-api | ||
|
||
This has the tables for the database, a REST API to access it, and a python client to access the REST API. | ||
|
||
See [ooogame/database](ooogame/database) for details. | ||
|
||
## flagbot | ||
|
||
Responsible for putting new flags into all the services for every game tick. | ||
|
||
See [ooogame/flagbot](ooogame/flagbot) for details. | ||
|
||
|
||
## fresh-flagbot | ||
|
||
Responsible for putting a new flags into a pod when it first comes up (from a team patching the service). | ||
|
||
See [ooogame/fresh_flagbot](ooogame/fresh_flagbot) for details. | ||
|
||
## gamebot | ||
|
||
Responsible for incrementing the game's ticks. | ||
|
||
See [ooogame/gamebot](ooogame/gamebot) for details. | ||
|
||
## koh-scorebot | ||
|
||
Responsible for extracting the King of the Hill (koh) scores from all | ||
the koh pods every tick, and submitting them to the database. | ||
|
||
See [ooogame/koh_scorebot](ooogame/koh_scorebot) for details. | ||
|
||
## team-interface | ||
|
||
Responsible for providing an interface to the teams so that they can | ||
submit flags, get pcaps, upload patches, and get their patch status. | ||
Split into a backend flask REST API, which essentially wraps the | ||
database-api, and a React frontend. | ||
|
||
See [ooogame/team_interface](ooogame/team_interface) for details. | ||
|
||
## pcapbot | ||
|
||
Responsible for picking up all the newly generated pcaps, anonymize | ||
them, and if the service is releasing pcaps then release them. | ||
|
||
See [ooogame/pcapbot](ooogame/pcapbot) for details. | ||
|
||
## gamestatebot | ||
|
||
Responsible for creating the game state at every new tick and storing them in the nfs, and release them publicly. | ||
|
||
See [ooogame/gamestatebot](ooogame/gamestatebot) for details. | ||
|
||
**This is also the component that pushes data to the public scoreboard** |
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,88 @@ | ||
#!/bin/bash -e | ||
|
||
REGISTRY=registry.31337.ooo:5000 | ||
|
||
only_service="" | ||
do_push=false | ||
restart_pods=false | ||
|
||
if [[ $# -ne 0 ]]; then | ||
|
||
while [[ $# -gt 0 ]] | ||
do | ||
key="$1" | ||
|
||
case $key in | ||
-p|--push) | ||
do_push=true | ||
;; | ||
-s|--service) | ||
shift | ||
only_service+=" ${1}" | ||
;; | ||
-r|--restart-pods) | ||
restart_pods=true | ||
;; | ||
-h|--help) | ||
printf $' This script builds frontends, builds dockers, and deploys\n' | ||
printf $' -p, --push \tpushes to production\n -s, --service <service_name> \tproviding this arg limits built services' | ||
printf $'to base and provided service names\n\t--service may be provided multiple times \n' | ||
printf $' -r, --restart-pods \trestarts the k8s pods running this service \n' | ||
printf $'example: ./deploy.sh --frontend --push --service team-interface \n\tBuilds frontend, pushes to production but only for team-interface' | ||
|
||
exit 0 | ||
;; | ||
*) | ||
echo -e "${key} is unknown parameter" | ||
;; | ||
esac | ||
shift # past argument or value | ||
done | ||
|
||
fi | ||
|
||
|
||
echo "First build base" | ||
docker build -f "dockerfiles/Dockerfile.game-infrastructure-base" -t "game-infrastructure-base" . | ||
docker tag game-infrastructure-base:latest $REGISTRY/game-infrastructure-base:latest | ||
if [[ ${do_push} = true ]]; then | ||
docker push $REGISTRY/game-infrastructure-base:latest | ||
fi | ||
|
||
for DOCKERFILE in dockerfiles/Dockerfile.* | ||
do | ||
SERVICE_NAME="${DOCKERFILE##*.}" | ||
|
||
if [ "$SERVICE_NAME" = "game-infrastructure-base" ]; then | ||
continue | ||
fi | ||
|
||
if [[ -z "${only_service}" ]] || [[ ${only_service} =~ (^| )"${SERVICE_NAME}"($| ) ]]; then | ||
echo "Building and deploying ${DOCKERFILE} for ${SERVICE_NAME}" | ||
else | ||
continue | ||
fi | ||
|
||
|
||
docker build -f "$DOCKERFILE" -t "$SERVICE_NAME" . | ||
docker tag $SERVICE_NAME:latest $REGISTRY/$SERVICE_NAME:latest | ||
if [[ ${do_push} = true ]]; then | ||
docker push $REGISTRY/$SERVICE_NAME:latest | ||
if [[ ${restart_pods} = true ]]; then | ||
echo "Restarting ${SERVICE_NAME} pod" | ||
pod_names=$(kubectl get pod -n default -o=custom-columns=NAME:.metadata.name | egrep ${SERVICE_NAME}) | ||
for pod_nm in ${pod_names}; do | ||
echo kubectl delete pod -n default ${pod_nm} | ||
kubectl delete pod -n default ${pod_nm} | ||
done | ||
fi | ||
fi | ||
done | ||
|
||
sleep 2 | ||
|
||
if [[ ${restart_pods} = true ]]; then | ||
kubectl get pod -n default -o=custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,IP:.status.podIP,STATUS:.status.phase | ||
fi | ||
|
||
|
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,33 @@ | ||
# Stage 0, build the app | ||
FROM node:latest | ||
|
||
# Copy all yarn dependencies over first so that they don't need to be continually installed | ||
CMD mkdir -p /root/app/frontend | ||
COPY ooogame/database/frontend/package.json /root/app/frontend/package.json | ||
COPY ooogame/database/frontend/yarn.lock /root/app/frontend/yarn.lock | ||
|
||
RUN yarn --cwd /root/app/frontend install --production | ||
|
||
# Build the interface | ||
COPY ooogame/database/frontend /root/app/frontend | ||
RUN yarn --cwd /root/app/frontend run build | ||
|
||
FROM game-infrastructure-base:latest | ||
|
||
RUN rm -f /etc/nginx/conf.d/default.conf | ||
|
||
COPY ooogame/database/deployment/nginx.conf /etc/nginx/ | ||
COPY ooogame/database/deployment/flask-site-nginx.conf /etc/nginx/conf.d/ | ||
COPY ooogame/database/deployment/uwsgi.ini /etc/uwsgi/ | ||
COPY ooogame/database/deployment/supervisord.conf /etc/supervisord.conf | ||
|
||
WORKDIR /opt/ooogame | ||
|
||
COPY --from=0 /root/app/frontend/build /frontend/ | ||
COPY ooogame/database/deployment/config.py /opt/ooogame/ooogame/database/config.py | ||
RUN . /opt/ooogame/venv/bin/activate && pip3 install /opt/ooogame rq-dashboard 'click<8' | ||
# XXX: click<8 due to https://github.com/Parallels/rq-dashboard/pull/383 | ||
|
||
RUN . /opt/ooogame/venv/bin/activate && pip check | ||
|
||
CMD ["/usr/bin/supervisord"] |
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,3 @@ | ||
FROM game-infrastructure-base:latest | ||
|
||
CMD ["/opt/ooogame/venv/bin/python3", "-u", "-m", "ooogame.flagbot.flagbot"] |
Oops, something went wrong.