diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7d38bf1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,161 @@ +venv +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ab43956 --- /dev/null +++ b/Makefile @@ -0,0 +1,81 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + + +define ping + . ./venv/bin/activate && \ + ansible-playbook -i $(INVENTORY) -f 10 ./ansible/ping.yml +endef + +define configure_base + . ./venv/bin/activate && \ + ansible-playbook -i $(INVENTORY) -f 10 ./ansible/playbook.yml +endef + + +define configure_locust + . ./venv/bin/activate && \ + ansible-playbook -i $(INVENTORY) -f 10 ./ansible/locust/main.yml +endef + +define test_base + . ./venv/bin/activate && \ + cd tests/ && \ + pwd && \ + py.test --hosts='ansible://all' \ + -n 10 \ + --verbose \ + --ansible-inventory="../${INVENTORY}" \ + test_basic.py + +endef + +define test_locust + . ./venv/bin/activate && \ + cd tests/locust/ && \ + py.test --hosts='ansible://mcaptcha_dos*' \ + -n 10 \ + --verbose \ + --ansible-inventory="../../${INVENTORY}" \ + base.py +endef + + + +# ```bash +# INVENTORY=./terraform/dos/hosts.ini make conf.base +# ``` +conf.base: ## Get all VMs to base level configuration + $(call configure_base) + + +lint: ## Lint source code + terraform fmt + . ./venv/bin/activate && \ + ansible-lint --write $(find ansible -type f) + . ./venv/bin/activate && black tests/ + +# ```bash +# INVENTORY=./terraform/dos/hosts.ini make conf.base +# ``` +conf.dos: ## Configure all DoS VMs + $(call configure_base) + $(call configure_locust) + +# ```bash +# INVENTORY=./terraform/dos/hosts.ini make conf.ping +# ``` +conf.ping: ## Ping all DoS VMs + $(call ping) + + +test: ## Run all tests + $(call test_base) + $(call test_locust) + +test.base: ## Test base configuration on all VMs + $(call test_base) + +help: ## Prints help for targets with comments + @cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-].+:.*?## .*$$' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/ansible/locust/artifacts/docker-compose.yml b/ansible/locust/artifacts/docker-compose.yml new file mode 100644 index 0000000..0514963 --- /dev/null +++ b/ansible/locust/artifacts/docker-compose.yml @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- +version: "3" +services: + master: + image: realaravinth/mcaptcha-dos-locust-protected:latest + container_name: master.locust.thrasher.dos.mcaptcha.org + environment: + - MCAPTCHA_CAPTCHA_SITEKEY=dPGVlwxjyPQJS5OEp86gzNJsxbrMlXwQ + - MCAPTCHA_CAPTCHA_HOST=http://localhost:7000 + - HOST=http://localhost:5000 + ports: + - 8089:8089 + volumes: + - ./data/:/src/data + command: --master -H http://localhost:8089 + worker: + image: realaravinth/mcaptcha-dos-locust-protected:latest + network_mode: host + environment: + - MCAPTCHA_CAPTCHA_SITEKEY=dPGVlwxjyPQJS5OEp86gzNJsxbrMlXwQ + - MCAPTCHA_CAPTCHA_HOST=http://localhost:7000 + - HOST=http://localhost:5000 + command: --worker --master-host localhost diff --git a/ansible/locust/main.yml b/ansible/locust/main.yml new file mode 100644 index 0000000..06f5f97 --- /dev/null +++ b/ansible/locust/main.yml @@ -0,0 +1,42 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- +- name: Configure Locust instances + hosts: [mcaptcha_dos] + remote_user: atm + pre_tasks: + - name: Ensure all VMs are reachable + ansible.builtin.ping: + roles: + - docker-compose + + tasks: + - name: Allow port 8089 for locust + become: true + community.general.ufw: + state: enabled + rule: allow + proto: tcp + port: "8089" + + - name: Create projects dir + become: true + ansible.builtin.file: + path: /etc/locust + state: directory + mode: "0755" + + - name: Copy docker-compose.yml file + become: true + ansible.builtin.copy: + src: ./artifacts/docker-compose.yml + dest: /etc/locust/ + + - name: Start locust services + become: true + community.docker.docker_compose: + project_src: /etc/locust/ + scale: + worker: 4 diff --git a/ansible/locust/roles/docker-compose/tasks/main.yml b/ansible/locust/roles/docker-compose/tasks/main.yml new file mode 100644 index 0000000..8b6134e --- /dev/null +++ b/ansible/locust/roles/docker-compose/tasks/main.yml @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- +- name: Install docker-compose + become: true + ansible.builtin.apt: + update_cache: true + pkg: + - docker-compose diff --git a/ansible/ping.yml b/ansible/ping.yml new file mode 100644 index 0000000..8fcead6 --- /dev/null +++ b/ansible/ping.yml @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- +- name: Ping all servers + hosts: all + remote_user: atm + + tasks: + - name: Ensure all VMs are reachable + ansible.builtin.ping: diff --git a/ansible/playbook.yml b/ansible/playbook.yml new file mode 100644 index 0000000..5e65f63 --- /dev/null +++ b/ansible/playbook.yml @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- +- name: Install and enable firewall + hosts: [mcaptcha_dos, mcaptcha_demo_server, mcaptcha_mcaptcha] + remote_user: atm + pre_tasks: + - name: Ensure all VMs are reachable + ansible.builtin.ping: + roles: + - ufw + + tasks: + - name: Install git, zip, nginx, wget, curl & other utils + become: true + ansible.builtin.apt: + update_cache: true + pkg: + - git + - wget + - curl + - gpg + - ca-certificates + - zip + - python3-pip + - virtualenv + - python3-setuptools + - ufw + +- name: Install Docker + hosts: mcaptcha_dos + remote_user: atm + roles: + - docker diff --git a/ansible/roles/docker/tasks/main.yml b/ansible/roles/docker/tasks/main.yml new file mode 100644 index 0000000..e85730f --- /dev/null +++ b/ansible/roles/docker/tasks/main.yml @@ -0,0 +1,47 @@ +--- + +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +- name: Create /etc/apt/keyrings dir + become: true + ansible.builtin.file: + path: /etc/apt/keyrings + state: directory + recurse: true + +- name: Add Docker GPG apt Key + become: true + ansible.builtin.apt_key: + url: https://download.docker.com/linux/debian/gpg + state: present + +- name: Add Docker Repository + become: true + ansible.builtin.apt_repository: + repo: deb https://download.docker.com/linux/debian buster stable + state: present + +- name: Update apt and install docker-ce + become: true + ansible.builtin.apt: + name: docker-ce + update_cache: true + +- name: Install Docker Module for Python + become: true + ansible.builtin.pip: + name: docker + +- name: Ensure docker group is present + become: true + ansible.builtin.group: + name: docker + state: present + +- name: Add user atm to docker group + become: true + ansible.builtin.user: + name: atm # TODO: add admin user to docker group + groups: docker,users,admin diff --git a/ansible/roles/ntp/tasks/main.yml b/ansible/roles/ntp/tasks/main.yml new file mode 100644 index 0000000..8093072 --- /dev/null +++ b/ansible/roles/ntp/tasks/main.yml @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- +- name: Install ntp + become: true + ansible.builtin.apt: + update_cache: true + pkg: + - ntp + +- name: Enable and start ntp service + become: true + ansible.builtin.service: + name: ntp + enabled: true + state: started diff --git a/ansible/roles/ufw/tasks/main.yml b/ansible/roles/ufw/tasks/main.yml new file mode 100644 index 0000000..25399b1 --- /dev/null +++ b/ansible/roles/ufw/tasks/main.yml @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- +- name: Install ufw + become: true + ansible.builtin.apt: + update_cache: true + pkg: + - ufw + +- name: Set logging + become: true + community.general.ufw: + logging: "on" + +- name: Allow port 22 and enable UFW + become: true + community.general.ufw: + state: enabled + rule: allow + proto: tcp + port: "22" + +- name: Enable and start ufw service + become: true + ansible.builtin.service: + name: ufw + enabled: true + state: started diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..9363b82 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,289 @@ +ansible==8.1.0 +ansible-core==2.15.1 +certifi==2023.5.7 +cffi==1.15.1 +charset-normalizer==3.2.0 +contextvars==2.4 +cryptography==41.0.2 +distro==1.8.0 +execnet==2.0.2 +idna==3.4 +immutables==0.19 +iniconfig==2.0.0 +Jinja2==3.1.2 +jmespath==1.0.1 +looseversion==1.3.0 +MarkupSafe==2.1.3 +msgpack==1.0.5 +packaging==23.1 +pluggy==1.2.0 +psutil==5.9.5 +pycparser==2.21 +pycryptodomex==3.18.0 +pytest==7.4.0 +pytest-testinfra==8.1.0 +pytest-xdist==3.3.1 +PyYAML==6.0 +pyzmq==25.0.2 +requests==2.31.0 +resolvelib==1.0.1 +salt==3006.1 +urllib3==2.0.3 +airdrop-ng==1.1 +airgraph-ng==1.1 +apparmor==3.1.6 +appdirs==1.4.4 +argcomplete==2.0.0 +asttokens==2.2.1 +async-timeout==4.0.2 +attrs==22.2.0 +autocommand==2.2.2 +autopage==0.5.1 +Babel==2.12.1 +beautifulsoup4==4.12.2 +binwalk==2.3.3 +black==23.7.0 +borgbackup==1.2.4 +Brlapi==0.8.5 +btrfsutil==6.3.3 +certifi==2023.7.22 +cffi==1.15.1 +chardet==5.2.0 +charset-normalizer==3.2.0 +click==8.1.6 +cliff==4.3.0 +cmd2==2.4.3 +codespell==2.2.5 +colorama==0.4.6 +ConfigArgParse==1.5.3 +contourpy==1.1.0 +crit==3.18 +cryptography==41.0.3 +cupshelpers==1.0 +cycler==0.11.0 +Cython==3.0.0 +dbus-python==1.3.2 +debtcollector==2.5.0 +decorator==5.1.1 +defusedxml==0.7.1 +deprecation==2.1.0 +devtools==0.11.0 +distlib==0.3.7 +distro==1.8.0 +dnspython==2.3.0 +dogpile.cache==1.1.8 +executing==1.2.0 +fastjsonschema==2.18.0 +filelock==3.12.2 +fonttools==4.42.0 +gevent==22.10.2 +git-filter-repo==2.38.0 +gpg==1.21.0 +greenlet==2.0.2 +html5lib==1.1 +httpie==3.2.1 +idna==3.4 +importlib-metadata==5.0.0 +inflect==7.0.0 +iotop==0.6 +iso8601==2.0.0 +jaraco.context==4.3.0 +jaraco.functools==3.8.1 +jaraco.text==3.11.1 +jedi==0.18.2 +jmespath==1.0.1 +jsonpatch==1.33 +jsonpointer==2.4 +jsonschema==4.19.0 +jsonschema-specifications==2023.7.1 +keystoneauth1==5.2.1 +kiwisolver==1.4.4 +lensfun==0.3.4 +LibAppArmor==3.1.6 +libfdt==1.7.0 +libtorrent==2.0.9 +libvirt-python==9.6.0 +lit==15.0.7.dev0 +louis==3.26.0 +lxml==4.9.2 +Mako==1.2.4 +mallard-ducktype==1.0.2 +Markdown==3.4.4 +markdown-it-py==2.2.0 +MarkupSafe==2.1.3 +matplotlib==3.7.2 +mdurl==0.1.2 +MemoizeDB==2021.11.20.2.41.2 +meson==1.2.1 +more-itertools==10.1.0 +msgpack==1.0.5 +multidict==6.0.4 +mypy-extensions==1.0.0 +netaddr==0.8.0 +netifaces==0.11.0 +nftables==0.1 +numpy==1.25.1 +openshot-qt==3.1.1 +openstacksdk==1.0.1 +ordered-set==4.1.0 +os-service-types==1.7.0 +osc-lib==2.8.0 +oslo.config==9.1.1 +oslo.i18n==6.0.0 +oslo.serialization==5.1.1 +oslo.utils==6.1.0 +packaging==23.1 +parso==0.8.3 +pathspec==0.11.2 +pbr==5.11.1 +perf==0.1 +Pillow==10.0.0 +pipenv==2023.7.23 +pipx==1.2.0 +platformdirs==3.10.0 +ply==3.11 +pm2ml==2021.11.20.2.41.2 +pooch==1.7.0 +Powerpill==2021.11.20.2.41.2 +prettytable==3.6.0 +protobuf==4.23.4 +psutil==5.9.5 +pwquality==1.4.5 +pyalpm==0.10.6 +pyasn1==0.4.8 +pybind11==2.11.1 +pycairo==1.24.0 +pycparser==2.21 +pycups==2.0.1 +pycurl==7.45.2 +pydantic==1.10.9 +Pygments==2.16.1 +PyGObject==3.44.1 +pynvim==0.4.3 +pyOpenSSL==23.2.0 +pyparsing==3.0.9 +pyperclip==1.8.2 +PyQt5==5.15.9 +PyQt5-sip==12.12.2 +PyQtWebEngine==5.15.6 +pyrsistent==0.19.3 +pysequoia==0.1.20 +PySocks==1.7.1 +python-cinderclient==9.3.0 +python-dateutil==2.8.2 +python-glanceclient==4.1.0 +python-keystoneclient==5.1.0 +python-novaclient==18.3.0 +python-openstackclient==6.2.0 +pytz==2023.3 +pyxdg==0.28 +PyYAML==6.0.1 +pyzmq==25.1.1 +redis==4.6.0 +referencing==0.30.2 +Reflector==2023.6.28.0.36.1 +requests==2.28.2 +requests-toolbelt==1.0.0 +requestsexceptions==1.4.0 +rfc3986==2.0.0 +rich==13.5.2 +rpds-py==0.9.2 +rpm==4.18.1 +scipy==1.11.1 +simplejson==3.19.1 +six==1.16.0 +soupsieve==2.4.1 +stevedore==5.1.0 +TBB==0.2 +tomli==2.0.1 +torbrowser-launcher==0.3.6 +tqdm==4.65.0 +trash-cli==0.23.2.13.2 +trimage==1.0.6 +trove-classifiers==2023.8.8 +typing_extensions==4.7.1 +uc-micro-py==1.0.2 +ufw==0.36.2 +urllib3==1.26.15 +userpath==1.8.0 +validate-pyproject==0.13.post1.dev0+gb752273.d20230520 +vboxapi==1.0 +virtualenv==20.24.3 +virtualenv-clone==0.5.7 +warlock==2.0.1 +wcwidth==0.2.6 +webencodings==0.5.1 +wrapt==1.14.1 +XCGF==2021.11.20.2.41.3 +XCPF==2021.12.24.10.22.41 +youtube-dl==2021.12.17 +yt-dlp==2023.7.6 +zipp==3.16.2 +zope.event==5.0 +zope.interface==6.0 +ansible==8.1.0 +ansible-compat==4.1.6 +ansible-core==2.15.1 +ansible-lint==6.17.2 +astroid==2.15.6 +attrs==23.1.0 +black==23.7.0 +bracex==2.3.post1 +certifi==2023.5.7 +cffi==1.15.1 +charset-normalizer==3.2.0 +click==8.1.6 +contextvars==2.4 +cryptography==41.0.2 +dill==0.3.7 +distro==1.8.0 +execnet==2.0.2 +filelock==3.12.2 +gitdb==4.0.10 +GitPython==3.1.32 +idna==3.4 +immutables==0.19 +iniconfig==2.0.0 +isort==5.12.0 +Jinja2==3.1.2 +jmespath==1.0.1 +jsonschema==4.19.0 +jsonschema-specifications==2023.7.1 +lazy-object-proxy==1.9.0 +lint==1.2.1 +looseversion==1.3.0 +markdown-it-py==3.0.0 +MarkupSafe==2.1.3 +mccabe==0.7.0 +mdurl==0.1.2 +msgpack==1.0.5 +mypy-extensions==1.0.0 +packaging==23.1 +pathspec==0.11.2 +platformdirs==3.10.0 +pluggy==1.2.0 +psutil==5.9.5 +pycparser==2.21 +pycryptodomex==3.18.0 +Pygments==2.16.1 +pylint==2.17.5 +pytest==7.4.0 +pytest-testinfra==8.1.0 +pytest-xdist==3.3.1 +PyYAML==6.0 +pyzmq==25.0.2 +referencing==0.30.2 +requests==2.31.0 +resolvelib==1.0.1 +rich==13.5.2 +rpds-py==0.9.2 +ruamel.yaml==0.17.32 +ruamel.yaml.clib==0.2.7 +salt==3006.1 +smmap==5.0.0 +subprocess-tee==0.4.1 +tomlkit==0.12.1 +urllib3==2.0.3 +wcmatch==8.4.1 +wrapt==1.15.0 +yamllint==1.32.0 diff --git a/terraform/dos/.gitignore b/terraform/dos/.gitignore new file mode 100644 index 0000000..ac56741 --- /dev/null +++ b/terraform/dos/.gitignore @@ -0,0 +1,45 @@ +# Compiled files +*.tfstate +*.tfstate.backup +*.tfstate.lock.info + +# logs +*.log + +# Directories +.terraform/ +.vagrant/ + +# SSH Keys +*.pem + +# Backup files +*.bak + +# Ignored Terraform files +*gitignore*.tf + +# Ignore Mac .DS_Store files +.DS_Store + +# Ignored vscode files +.vscode/ + +# Ignore Any Generated JSON Files +operations/automation-script/apply.json +operations/automation-script/configversion.json +operations/automation-script/run.template.json +operations/automation-script/run.json +operations/automation-script/variable.template.json +operations/automation-script/variable.json +operations/automation-script/workspace.template.json +operations/automation-script/workspace.json +operations/sentinel-policies-scripts/create-policy.template.json +operations/sentinel-policies-scripts/create-policy.json +operations/variable-scripts/variable.template.json +operations/variable-scripts/variable.json + +# Sentinel runtime directory +.sentinel +dos +hosts.ini diff --git a/terraform/dos/.terraform.lock.hcl b/terraform/dos/.terraform.lock.hcl new file mode 100644 index 0000000..c656267 --- /dev/null +++ b/terraform/dos/.terraform.lock.hcl @@ -0,0 +1,60 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/dmacvicar/libvirt" { + version = "0.7.1" + constraints = "~> 0.7.0" + hashes = [ + "h1:1yEJVPVFkRkbRY63+sFRAWau/eJ0xlecHWLCV8spkWU=", + "zh:1c59f2ab68da6326637ee8b03433e84af76b3e3562f251a7f2aa239a7b262a8d", + "zh:236e24ecf036e99d9d1e2081a39dc9cb4b8993850a37141a1449f20750f883d6", + "zh:4519c22b1f00c1d37d60ac6c2cb7ad5ab9dbcd44a80b4f61e68aacb54eae017d", + "zh:54de4e3c979c32af1dc71ec2846912f669a28bdb0990e8a3c1fb8fea4ede7b61", + "zh:6270a757bcf4e1f9efe47726cf0caefba30a25e59d151103cf03d1656325783c", + "zh:68b8586d5b29c0a1cb7c608a309b38db911449c072d60eee9e40e01881f1c23a", + "zh:724ba2290fea704714378e9363541420c36091e790c7f39150cde8987d4e0754", + "zh:7b6860c92376cdad98273aab4bea62546622e08f50733e4b2e58a7a859d3b49d", + "zh:986a0a4f8d9511c64bcac8010337deb43110b4c2f91969b2491fd9edc290b60e", + "zh:aff0f6f24d69cd97a44cd6059edaf355769fbb8a7643a6db4d52c9a94f98e194", + "zh:c46ca3f8384d06c13a7ed3d4b83c65b4f8dccbf9d5f624843b68d176add5c5c2", + "zh:ef310534e7d38153aca4ce31655b52a6e6c4d76f32e49732c96b62e9de1ee843", + "zh:f1566b094f4267ef2674889d874962dd41e0cba55251645e16d003c77ca8a19c", + "zh:f2e019df7b537069828c5537c481e5b7f41d2404eef6fe5c86702c20900b303d", + ] +} + +provider "registry.terraform.io/hashicorp/local" { + version = "2.4.0" + hashes = [ + "h1:R97FTYETo88sT2VHfMgkPU3lzCsZLunPftjSI5vfKe8=", + "zh:53604cd29cb92538668fe09565c739358dc53ca56f9f11312b9d7de81e48fab9", + "zh:66a46e9c508716a1c98efbf793092f03d50049fa4a83cd6b2251e9a06aca2acf", + "zh:70a6f6a852dd83768d0778ce9817d81d4b3f073fab8fa570bff92dcb0824f732", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:82a803f2f484c8b766e2e9c32343e9c89b91997b9f8d2697f9f3837f62926b35", + "zh:9708a4e40d6cc4b8afd1352e5186e6e1502f6ae599867c120967aebe9d90ed04", + "zh:973f65ce0d67c585f4ec250c1e634c9b22d9c4288b484ee2a871d7fa1e317406", + "zh:c8fa0f98f9316e4cfef082aa9b785ba16e36ff754d6aba8b456dab9500e671c6", + "zh:cfa5342a5f5188b20db246c73ac823918c189468e1382cb3c48a9c0c08fc5bf7", + "zh:e0e2b477c7e899c63b06b38cd8684a893d834d6d0b5e9b033cedc06dd7ffe9e2", + "zh:f62d7d05ea1ee566f732505200ab38d94315a4add27947a60afa29860822d3fc", + "zh:fa7ce69dde358e172bd719014ad637634bbdabc49363104f4fca759b4b73f2ce", + ] +} + +provider "registry.terraform.io/hashicorp/template" { + version = "2.2.0" + hashes = [ + "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=", + "zh:01702196f0a0492ec07917db7aaa595843d8f171dc195f4c988d2ffca2a06386", + "zh:09aae3da826ba3d7df69efeb25d146a1de0d03e951d35019a0f80e4f58c89b53", + "zh:09ba83c0625b6fe0a954da6fbd0c355ac0b7f07f86c91a2a97849140fea49603", + "zh:0e3a6c8e16f17f19010accd0844187d524580d9fdb0731f675ffcf4afba03d16", + "zh:45f2c594b6f2f34ea663704cc72048b212fe7d16fb4cfd959365fa997228a776", + "zh:77ea3e5a0446784d77114b5e851c970a3dde1e08fa6de38210b8385d7605d451", + "zh:8a154388f3708e3df5a69122a23bdfaf760a523788a5081976b3d5616f7d30ae", + "zh:992843002f2db5a11e626b3fc23dc0c87ad3729b3b3cff08e32ffb3df97edbde", + "zh:ad906f4cebd3ec5e43d5cd6dc8f4c5c9cc3b33d2243c89c5fc18f97f7277b51d", + "zh:c979425ddb256511137ecd093e23283234da0154b7fa8b21c2687182d9aea8b2", + ] +} diff --git a/terraform/dos/cloud_init.cfg b/terraform/dos/cloud_init.cfg new file mode 100644 index 0000000..1a4f40b --- /dev/null +++ b/terraform/dos/cloud_init.cfg @@ -0,0 +1,23 @@ +#cloud-config +# vim: syntax=yaml + +users: +- name: root + ssh_authorized_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC/wXdHpwpY/4ubhYTmuNdGepQpj1kchvTUTApxMZyfyVW4uzrPRTYsle1y9QbTBV35qLkNajRC/wmC5/xPchdXpsJpuD9st1HMhLeR8qwaPyptiYJYT+z/WisWw2k6oWhG3QKvPoRtBdW9nhZnkG+O6zkuGXiRHpS7j2VVboDPpWEe1UdELQFVCwfraRal2g3ENFZ/9V1UrW/4ahRnQnSxERplZUm/fgSxQtmXubTkW68ut7yasBsrKFffMm8JztW0tWgTlTKONd3LCjv4juM0t5+cJDotNDnUR86Tq2PG8io7no/h8BWtazmjdpfGgn02ibX26BkdU0LDEYbJt5q9/Fh9TGk2ZwcMQeyepO1AWQgkmHXZWZELqu6MLQpqdtsOjHp9k0MeSpuIbdwzgf10Ydy7vK1z8irS24tVNNnJaMBwOlVOPwfyztHRADPkFcv2lKSjS1uyKR0FIkV8Kvs4txaIjmwv2LfMg6lF5W6j3ZPLyeE4cplJP0DDjzorSanu31xVnqVb3A8V9awsJ/4H7d59bI99c7QHL4K3fBVP3O0gqd31xAVRsdGs5Tj2P+RpiI6o5JJiOa1+DuBdWzrVIXYchQ30ZjaJp1wTNsYLmAsjeYuQZE2tf1xvywdzD4MB4avugDEWikzRWN9V5PHDZr1bamTCCjOrb2PRCd7eSQ== aravinth7820@gmail.com +- name: atm + gecos: Aravinth Manivannan + groups: users, admin + sudo: ALL=(ALL) NOPASSWD:ALL + shell: /bin/bash + lock_passwd: true + plain_text_passwd: fooabr12 + ssh_authorized_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC/wXdHpwpY/4ubhYTmuNdGepQpj1kchvTUTApxMZyfyVW4uzrPRTYsle1y9QbTBV35qLkNajRC/wmC5/xPchdXpsJpuD9st1HMhLeR8qwaPyptiYJYT+z/WisWw2k6oWhG3QKvPoRtBdW9nhZnkG+O6zkuGXiRHpS7j2VVboDPpWEe1UdELQFVCwfraRal2g3ENFZ/9V1UrW/4ahRnQnSxERplZUm/fgSxQtmXubTkW68ut7yasBsrKFffMm8JztW0tWgTlTKONd3LCjv4juM0t5+cJDotNDnUR86Tq2PG8io7no/h8BWtazmjdpfGgn02ibX26BkdU0LDEYbJt5q9/Fh9TGk2ZwcMQeyepO1AWQgkmHXZWZELqu6MLQpqdtsOjHp9k0MeSpuIbdwzgf10Ydy7vK1z8irS24tVNNnJaMBwOlVOPwfyztHRADPkFcv2lKSjS1uyKR0FIkV8Kvs4txaIjmwv2LfMg6lF5W6j3ZPLyeE4cplJP0DDjzorSanu31xVnqVb3A8V9awsJ/4H7d59bI99c7QHL4K3fBVP3O0gqd31xAVRsdGs5Tj2P+RpiI6o5JJiOa1+DuBdWzrVIXYchQ30ZjaJp1wTNsYLmAsjeYuQZE2tf1xvywdzD4MB4avugDEWikzRWN9V5PHDZr1bamTCCjOrb2PRCd7eSQ== aravinth7820@gmail.com + +ssh_pwauth: true +chpasswd: + list: | + root:foobar12 + atm:foobar12 + expire: False diff --git a/terraform/dos/demo-server.tf b/terraform/dos/demo-server.tf new file mode 100644 index 0000000..6a2615e --- /dev/null +++ b/terraform/dos/demo-server.tf @@ -0,0 +1,51 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +resource "libvirt_volume" "mcaptcha_demo_server_volume" { + name = "mcaptcha_demo_server_volume-${count.index}" + base_volume_id = libvirt_volume.debian-mcaptcha-qcow2.id + count = var.mcaptcha_demo_server_vm_count + pool = libvirt_pool.mcaptcha_basic.name + size = var.mcaptcha_demo_server_vm_disk_size +} + +resource "libvirt_domain" "mcaptcha_demo_server" { + count = var.mcaptcha_demo_server_vm_count + + name = "mcaptcha_mcaptcha_demo_server_${count.index}" + memory = var.mcaptcha_demo_server_vm_memory + vcpu = var.mcaptcha_demo_server_vm_vcpu + + cloudinit = libvirt_cloudinit_disk.commoninit.id + + console { + type = "pty" + target_port = "0" + target_type = "serial" + } + + console { + type = "pty" + target_type = "virtio" + target_port = "1" + } + + network_interface { + network_name = "default" + wait_for_lease = true + } + + disk { + volume_id = element(libvirt_volume.mcaptcha_demo_server_volume.*.id, count.index) + } +} + +locals { + mcaptcha_demo_server_vm_ips = [for i in libvirt_domain.mcaptcha_demo_server : i.network_interface.0.addresses[0]] + mcaptcha_demo_server_vm_names = [for i in libvirt_domain.mcaptcha_demo_server : i.name] + mcaptcha_demo_server_vm_map = [for i in libvirt_domain.mcaptcha_demo_server : { + ip = i.network_interface.0.addresses[0], + name = i.name + }] +} diff --git a/terraform/dos/dos.tf b/terraform/dos/dos.tf new file mode 100644 index 0000000..f0196a6 --- /dev/null +++ b/terraform/dos/dos.tf @@ -0,0 +1,51 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +resource "libvirt_volume" "mcaptcha_dos_volume" { + name = "mcaptcha_dos_volume-${count.index}" + base_volume_id = libvirt_volume.debian-mcaptcha-qcow2.id + count = var.mcaptcha_dos_vm_count + pool = libvirt_pool.mcaptcha_basic.name + size = var.mcaptcha_dos_vm_disk_size +} + +resource "libvirt_domain" "mcaptcha_dos" { + count = var.mcaptcha_dos_vm_count + + name = "mcaptcha_mcaptcha_dos_${count.index}" + memory = var.mcaptcha_dos_vm_memory + vcpu = var.mcaptcha_dos_vm_vcpu + + cloudinit = libvirt_cloudinit_disk.commoninit.id + + console { + type = "pty" + target_port = "0" + target_type = "serial" + } + + console { + type = "pty" + target_type = "virtio" + target_port = "1" + } + + network_interface { + network_name = "default" + wait_for_lease = true + } + + disk { + volume_id = element(libvirt_volume.mcaptcha_dos_volume.*.id, count.index) + } +} + +locals { + mcaptcha_dos_vm_ips = [for i in libvirt_domain.mcaptcha_dos : i.network_interface.0.addresses[0]] + mcaptcha_dos_vm_names = [for i in libvirt_domain.mcaptcha_dos : i.name] + mcaptcha_dos_vm_map = [for i in libvirt_domain.mcaptcha_dos : { + ip = i.network_interface.0.addresses[0], + name = i.name + }] +} diff --git a/terraform/dos/main.tf b/terraform/dos/main.tf new file mode 100644 index 0000000..8c7aa9d --- /dev/null +++ b/terraform/dos/main.tf @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +terraform { + required_version = ">= 0.13" + required_providers { + libvirt = { + source = "dmacvicar/libvirt" + version = "~> 0.7.0" + } + } +} + +provider "libvirt" { + uri = var.libvirt_uri +} + +resource "libvirt_pool" "mcaptcha_basic" { + name = "mcaptcha_basic" + type = "dir" + path = var.libvirt_pool_path + +} + +resource "libvirt_volume" "debian-mcaptcha-qcow2" { + name = "debian-mcaptcha-qcow2" + pool = libvirt_pool.mcaptcha_basic.name + source = var.libvirt_debian_src + format = "qcow2" +} + +data "template_file" "user_data" { + template = file("${path.module}/cloud_init.cfg") +} + +data "template_file" "network_config" { + template = file("${path.module}/network_config.cfg") +} + +resource "libvirt_cloudinit_disk" "commoninit" { + name = "commoninit.iso" + user_data = data.template_file.user_data.rendered + network_config = data.template_file.network_config.rendered + pool = libvirt_pool.mcaptcha_basic.name +} diff --git a/terraform/dos/mcaptcha.tf b/terraform/dos/mcaptcha.tf new file mode 100644 index 0000000..e7769c7 --- /dev/null +++ b/terraform/dos/mcaptcha.tf @@ -0,0 +1,52 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +resource "libvirt_volume" "mcaptcha_mcaptcha_volume" { + name = "mcaptcha_mcaptcha_volume-${count.index}" + base_volume_id = libvirt_volume.debian-mcaptcha-qcow2.id + count = var.mcaptcha_mcaptcha_vm_count + pool = libvirt_pool.mcaptcha_basic.name + size = var.mcaptcha_mcaptcha_vm_disk_size +} + +resource "libvirt_domain" "mcaptcha_mcaptcha" { + count = var.mcaptcha_mcaptcha_vm_count + + name = "mcaptcha_mcaptcha_mcaptcha_${count.index}" + memory = var.mcaptcha_mcaptcha_vm_memory + vcpu = var.mcaptcha_mcaptcha_vm_vcpu + + cloudinit = libvirt_cloudinit_disk.commoninit.id + + console { + type = "pty" + target_port = "0" + target_type = "serial" + } + + console { + type = "pty" + target_type = "virtio" + target_port = "1" + } + + network_interface { + network_name = "default" + wait_for_lease = true + } + + disk { + volume_id = element(libvirt_volume.mcaptcha_mcaptcha_volume.*.id, count.index) + } +} + +locals { + mcaptcha_mcaptcha_vm_ips = [for i in libvirt_domain.mcaptcha_mcaptcha : i.network_interface.0.addresses[0]] + mcaptcha_mcaptcha_vm_names = [for i in libvirt_domain.mcaptcha_mcaptcha : i.name] + mcaptcha_mcaptcha_vm_map = [for i in libvirt_domain.mcaptcha_mcaptcha : { + ip = i.network_interface.0.addresses[0], + name = i.name + }] +} + diff --git a/terraform/dos/network_config.cfg b/terraform/dos/network_config.cfg new file mode 100644 index 0000000..5b2cbca --- /dev/null +++ b/terraform/dos/network_config.cfg @@ -0,0 +1,4 @@ +version: 2 +ethernets: + ens3: + dhcp4: true diff --git a/terraform/dos/output.tf b/terraform/dos/output.tf new file mode 100644 index 0000000..8a2fb15 --- /dev/null +++ b/terraform/dos/output.tf @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +output "mcaptcha_mcaptcha_demo_server_ip" { + value = local.mcaptcha_demo_server_vm_map +} + +output "mcaptcha_mcaptcha_dos_ip" { + value = local.mcaptcha_dos_vm_map +} + +output "mcaptcha_mcaptcha_mcaptcha_ip" { + value = local.mcaptcha_mcaptcha_vm_map +} + +resource "local_file" "hosts_yml" { + content = templatefile("./templates/hosts.yml.tftpl", + { + mcaptcha_demo_server_vm_ips = local.mcaptcha_demo_server_vm_ips, + mcaptcha_demo_server_vm_names = local.mcaptcha_demo_server_vm_names, + mcaptcha_demo_server_vms = local.mcaptcha_demo_server_vm_map, + + + mcaptcha_dos_vm_ips = local.mcaptcha_dos_vm_ips, + mcaptcha_dos_vm_names = local.mcaptcha_dos_vm_names, + mcaptcha_dos_vms = local.mcaptcha_dos_vm_map, + + mcaptcha_mcaptcha_vm_ips = local.mcaptcha_mcaptcha_vm_ips, + mcaptcha_mcaptcha_vm_names = local.mcaptcha_mcaptcha_vm_names, + mcaptcha_mcaptcha_vms = local.mcaptcha_mcaptcha_vm_map + + }) + + filename = "hosts.ini" +} diff --git a/terraform/dos/scripts/on.sh b/terraform/dos/scripts/on.sh new file mode 100755 index 0000000..cc953cb --- /dev/null +++ b/terraform/dos/scripts/on.sh @@ -0,0 +1,7 @@ +#!/bin/bash + + +for vm in $(virsh list --all --name --state-shutoff); do \ + echo "[*] Starting vm: $vm"; \ + virsh start $vm; \ +done diff --git a/terraform/dos/templates/hosts.yml.tftpl b/terraform/dos/templates/hosts.yml.tftpl new file mode 100644 index 0000000..73b5fa6 --- /dev/null +++ b/terraform/dos/templates/hosts.yml.tftpl @@ -0,0 +1,14 @@ +[mcaptcha_dos] +%{ for vm in mcaptcha_dos_vms ~} +${vm.name} ansible_host=${vm.ip} ansible_user=atm +%{ endfor ~} + +[mcaptcha_mcaptcha] +%{ for vm in mcaptcha_mcaptcha_vms ~} +${vm.name} ansible_host=${vm.ip} ansible_user=atm +%{ endfor ~} + +[mcaptcha_demo_server] +%{ for vm in mcaptcha_demo_server_vms ~} +${vm.name} ansible_host=${vm.ip} ansible_user=atm +%{ endfor ~} diff --git a/terraform/dos/variables.tf b/terraform/dos/variables.tf new file mode 100644 index 0000000..273dd6d --- /dev/null +++ b/terraform/dos/variables.tf @@ -0,0 +1,98 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later +/* main.tf */ +variable "libvirt_uri" { + description = "URI of libvert socket" + type = string + default = "qemu:///system" +} + +variable "libvirt_pool_path" { + description = "Path of libvirt storage pool" + type = string + default = "/home/atm/code/libvirt/pool/mcaptcha_basic" +} + +variable "libvirt_debian_src" { + description = "Location of Debian 11 qcow2 image" + type = string + default = "/home/atm/disk-images/debian/11/cloud/debian-11-genericcloud-amd64.qcow2" +} + +/* demo server */ +variable "mcaptcha_demo_server_vm_count" { + description = "Number of VMs to be deployed to run demo server" + type = number + default = 1 +} + +variable "mcaptcha_demo_server_vm_disk_size" { + description = "Size of disk of VM running demo server in bytes" + type = number + default = 8000000000 # 8GB +} + +variable "mcaptcha_demo_server_vm_memory" { + description = "Memory of VM running demo server in MB" + type = number + default = 2000 # 2GB +} + +variable "mcaptcha_demo_server_vm_vcpu" { + description = "Number of CPUs of VM demo server locust" + type = number + default = 4 +} + + +/* locust server server */ +variable "mcaptcha_dos_vm_count" { + description = "Number of VMs to be deployed to run locust" + type = number + default = 2 +} + +variable "mcaptcha_dos_vm_disk_size" { + description = "Size of disk of VMs running locust in bytes" + type = number + default = 8000000000 # 8GB +} + +variable "mcaptcha_dos_vm_memory" { + description = "Memory of VMs running locust in MB" + type = number + default = 2000 # 2GB +} + +variable "mcaptcha_dos_vm_vcpu" { + description = "Number of CPUs of VMs running locust" + type = number + default = 4 +} + + +/* mcaptcha/mcaptcha server server */ +variable "mcaptcha_mcaptcha_vm_count" { + description = "Number of VMs to be deployed to run mcaptcha/mcaptcha" + type = number + default = 1 +} + +variable "mcaptcha_mcaptcha_vm_disk_size" { + description = "Size of disk of VMs running mcaptcha/mcaptcha in bytes" + type = number + default = 8000000000 # 8GB +} + +variable "mcaptcha_mcaptcha_vm_memory" { + description = "Memory of VMs running mcaptcha/mcaptcha in MB" + type = number + default = 2000 # 2GB +} + +variable "mcaptcha_mcaptcha_vm_vcpu" { + description = "Number of CPUs of VMs running mcaptcha/mcaptcha" + type = number + default = 4 +} diff --git a/tests/locust/base.py b/tests/locust/base.py new file mode 100644 index 0000000..63d5827 --- /dev/null +++ b/tests/locust/base.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +import os + + +def test_locust_is_listening(host): + socket = host.socket(f"tcp://0.0.0.0:8089") + assert socket.is_listening + + +def test_locust_config_exists(host): + config = host.file("/etc/locust/docker-compose.yml") + assert config.exists + assert config.is_file + + +def test_docker_is_installed(host): + assert host.package("docker-compose").is_installed diff --git a/tests/test_basic.py b/tests/test_basic.py new file mode 100644 index 0000000..2bf6dd4 --- /dev/null +++ b/tests/test_basic.py @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: 2023 Aravinth Manivannan +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +import os + + +def test_ssh_is_listening(host): + socket = host.socket(f"tcp://0.0.0.0:22") + assert socket.is_listening + + +def test_ufw_service_running_and_enabled(host): + service = host.service("ufw") + assert service.is_running + assert service.is_enabled + + +def test_ssh_service_running_and_enabled(host): + service = host.service("ssh") + assert service.is_running + assert service.is_enabled + + +def test_ssh_is_installed(host): + pkg = host.package("openssh-server") + assert pkg.is_installed + + +def test_pkgis_installed(host): + for pkg in [ + "git", + "wget", + "curl", + "gpg", + "ca-certificates", + "zip", + "python3-pip", + "virtualenv", + "python3-setuptools", + "ntp", + "ufw", + ]: + assert host.package(pkg).is_installed