diff --git a/.github/workflows/markdown-validation.yml b/.github/workflows/markdown-validation.yml index 2a157aa..2d43872 100644 --- a/.github/workflows/markdown-validation.yml +++ b/.github/workflows/markdown-validation.yml @@ -11,9 +11,7 @@ on: jobs: none-shall-pass: - runs-on: - - self-hosted - - Ubuntu + runs-on: thevickypedia-default steps: - uses: thevickypedia/none-shall-pass@v5 with: diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 360a055..d9d4a8b 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -1,32 +1,14 @@ -# This workflow will upload a Python Package using Twine when a release is created - name: pypi-publish -# Controls when the workflow will run on: - workflow_dispatch: {} + workflow_dispatch: release: types: [ published ] jobs: - deploy: - runs-on: self-hosted + pypi-publisher: + runs-on: thevickypedia-default steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install build twine - - name: Create packages - run: python -m build - - name: Run twine check - run: twine check dist/* - - name: Upload to pypi - env: - TWINE_USERNAME: ${{ secrets.PYPI_USER }} - TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} - run: twine upload dist/*.whl + - uses: thevickypedia/pypi-publisher@v3 + env: + token: ${{ secrets.PYPI_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 384d402..5d1f2d5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,43 +1,46 @@ +--- fail_fast: true -exclude: ^docs/ +exclude: ^(notebooks/|scripts/|.github/|docs/) repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: - - id: check-added-large-files - - id: check-ast - - id: check-byte-order-marker - - id: check-builtin-literals - - id: check-case-conflict - - id: check-docstring-first - - id: check-executables-have-shebangs - - id: check-shebang-scripts-are-executable - - id: check-merge-conflict - - id: check-toml - - id: check-vcs-permalinks - - id: check-xml - - id: debug-statements - - id: destroyed-symlinks - - id: detect-aws-credentials - - id: detect-private-key - - id: end-of-file-fixer - - id: fix-byte-order-marker - - id: mixed-line-ending - - id: name-tests-test - - id: requirements-txt-fixer - - id: trailing-whitespace + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-yaml + - id: check-json + - id: check-added-large-files + - id: check-ast + - id: check-byte-order-marker + - id: check-builtin-literals + - id: check-case-conflict + - id: check-docstring-first + - id: check-executables-have-shebangs + - id: check-shebang-scripts-are-executable + - id: check-merge-conflict + - id: check-toml + - id: check-vcs-permalinks + - id: check-xml + - id: debug-statements + - id: destroyed-symlinks + - id: detect-aws-credentials + - id: detect-private-key + - id: end-of-file-fixer + - id: fix-byte-order-marker + - id: mixed-line-ending + - id: name-tests-test + - id: requirements-txt-fixer + - id: trailing-whitespace - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 - hooks: - - id: isort + - repo: https://github.com/PyCQA/isort + rev: 5.12.0 + hooks: + - id: isort - - repo: local - hooks: - - - id: docs - name: docs - entry: /bin/bash pre_commit.sh - language: system - pass_filenames: false - always_run: true + - repo: local + hooks: + - + id: docs + name: docs + entry: /bin/bash pre_commit.sh + language: system + pass_filenames: false + always_run: true diff --git a/doc_gen/static.css b/doc_gen/static.css new file mode 100644 index 0000000..3b4addd --- /dev/null +++ b/doc_gen/static.css @@ -0,0 +1,3 @@ +.sphinxsidebarwrapper { + overflow-y: scroll; +} diff --git a/docs/_static/static.css b/docs/_static/static.css new file mode 100644 index 0000000..3b4addd --- /dev/null +++ b/docs/_static/static.css @@ -0,0 +1,3 @@ +.sphinxsidebarwrapper { + overflow-y: scroll; +} diff --git a/docs/index.html b/docs/index.html index 6ce7992..a18a9f6 100644 --- a/docs/index.html +++ b/docs/index.html @@ -439,6 +439,16 @@

Configuration
>>> AMIBase
 
+
+

See also

+
+

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

diff --git a/docs/searchindex.js b/docs/searchindex.js index 26b81e5..d79fdca 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["README", "index"], "filenames": ["README.md", "index.rst"], "titles": ["Platform Supported", "Welcome to VPN Server\u2019s documentation!"], "terms": {"establish": 0, "scalabl": 0, "demand": 0, "power": 0, "openvpn": [0, 1], "aw": [0, 1], "ec2": [0, 1], "python": 0, "m": 0, "pip": 0, "import": 0, "instanti": [0, 1], "object": [0, 1], "vpn_server": 0, "vpnserver": [0, 1], "creat": [0, 1], "create_vpn_serv": [0, 1], "test": [0, 1], "an": [0, 1], "exist": [0, 1], "test_vpn": [0, 1], "delet": [0, 1], "delete_vpn_serv": [0, 1], "bulb": 0, "pleas": [0, 1], "refer": [0, 1], "wiki": 0, "page": [0, 1], "more": [0, 1], "instruct": 0, "payload": 0, "requir": [0, 1], "docstr": 0, "format": [0, 1], "googl": [0, 1], "style": 0, "convent": 0, "pep": 0, "8": 0, "clean": 0, "pre": [0, 1], "commit": 0, "hook": 0, "flake8": 0, "isort": 0, "gitvers": 0, "revers": 0, "f": 0, "release_not": 0, "rst": 0, "t": [0, 1], "precommit": 0, "ensur": 0, "doc": [0, 1], "creation": 0, "ar": 0, "run": [0, 1], "everi": 0, "sphinx": 0, "5": [0, 1], "1": 0, "recommonmark": 0, "all": [0, 1], "file": [0, 1], "repositori": 0, "runbook": 0, "packag": 0, "vignesh": 0, "rao": 0, "under": 0, "mit": 0, "platform": 1, "support": 1, "repo": 1, "stat": 1, "deploy": 1, "instal": 1, "usag": 1, "code": 1, "standard": 1, "project": 1, "link": 1, "licens": 1, "copyright": 1, "class": 1, "main": 1, "kwarg": 1, "unpack": 1, "initi": 1, "spin": 1, "up": 1, "instanc": 1, "ami": 1, "which": 1, "serv": 1, "load": 1, "envconfig": 1, "subclass": 1, "baseset": 1, "valid": 1, "us": 1, "pydant": 1, "paramet": 1, "dictionari": 1, "keyword": 1, "argument": 1, "follow": 1, "kei": 1, "valu": 1, "pair": 1, "vpn_usernam": 1, "usernam": 1, "access": 1, "client": 1, "vpn_password": 1, "password": 1, "vpn_port": 1, "port": 1, "number": 1, "web": 1, "interfac": 1, "aws_profile_nam": 1, "name": 1, "profil": 1, "session": 1, "aws_access_kei": 1, "token": 1, "account": 1, "aws_secret_kei": 1, "secret": 1, "id": 1, "aws_region_nam": 1, "region": 1, "where": 1, "should": 1, "live": 1, "default": 1, "image_id": 1, "instance_typ": 1, "type": 1, "host": 1, "key_pair": 1, "store": 1, "connect": 1, "security_group": 1, "secur": 1, "group": 1, "vpn_info": 1, "json": 1, "dump": 1, "inform": 1, "domain": 1, "zone": 1, "hosted_zon": 1, "subdomain": 1, "bring": 1, "your": 1, "own": 1, "point": 1, "combin": 1, "exampl": 1, "If": 1, "you": 1, "have": 1, "com": 1, "want": 1, "entrypoint": 1, "note": 1, "also": 1, "regist": 1, "cannot": 1, "simpli": 1, "expect": 1, "work": 1, "The": 1, "alia": 1, "record": 1, "fail": 1, "duplic": 1, "dn": 1, "resolut": 1, "level": 1, "unless": 1, "i": 1, "same": 1, "_authorize_security_group": 1, "security_group_id": 1, "str": 1, "bool": 1, "author": 1, "certain": 1, "ingress": 1, "list": 1, "take": 1, "securitygroup": 1, "firewal": 1, "open": 1, "tcp": 1, "22": 1, "443": 1, "943": 1, "can": 1, "dynam": 1, "945": 1, "cluster": 1, "control": 1, "channel": 1, "udp": 1, "1194": 1, "return": 1, "flag": 1, "call": 1, "function": 1, "whether": 1, "wa": 1, "successfulli": 1, "_configure_vpn": 1, "public_dn": 1, "none": 1, "traffic": 1, "from": 1, "localhost": 1, "tunnel": 1, "public": 1, "_create_ec2_inst": 1, "option": 1, "tupl": 1, "success": 1, "union": 1, "_create_key_pair": 1, "keypair": 1, "rsa": 1, "pem": 1, "_create_security_group": 1, "get": 1, "vpc": 1, "re": 1, "sg": 1, "case": 1, "alreadi": 1, "_delete_key_pair": 1, "_delete_security_group": 1, "_disassociate_security_group": 1, "serviceresourc": 1, "instance_id": 1, "disassoci": 1, "assign": 1, "unavail": 1, "_get_vpc_id": 1, "fetch": 1, "_init": 1, "start": 1, "int": 1, "its": 1, "startup": 1, "shutdown": 1, "_terminate_ec2_inst": 1, "termin": 1, "request": 1, "_test_get": 1, "timeout": 1, "3": 1, "retri": 1, "respons": 1, "multipl": 1, "hostnam": 1, "ip": 1, "address": 1, "time": 1, "error": 1, "exponenti": 1, "interv": 1, "between": 1, "each": 1, "attempt": 1, "failur": 1, "_tester": 1, "data": 1, "dict": 1, "parallel": 1, "improv": 1, "runtim": 1, "against": 1, "openvpna": 1, "servic": 1, "avail": 1, "were": 1, "provid": 1, "rais": 1, "assertionerror": 1, "when": 1, "ani": 1, "public_ip": 1, "disabl": 1, "remov": 1, "resourc": 1, "acquir": 1, "ha": 1, "A": 1, "doesn": 1, "long": 1, "neither": 1, "nor": 1, "modifi": 1, "manual": 1, "http": 1, "boto3": 1, "amazonaw": 1, "v1": 1, "api": 1, "latest": 1, "wait_until_termin": 1, "html": 1, "model": 1, "config": 1, "configurationset": 1, "basemodel": 1, "set": 1, "interact": 1, "new": 1, "pars": 1, "input": 1, "validationerror": 1, "pydantic_cor": 1, "form": 1, "__init__": 1, "__pydantic_self__": 1, "instead": 1, "common": 1, "self": 1, "first": 1, "arg": 1, "allow": 1, "field": 1, "amibas": 1, "imag": 1, "model_post_init": 1, "__context": 1, "thi": 1, "meant": 1, "behav": 1, "like": 1, "method": 1, "initialis": 1, "privat": 1, "attribut": 1, "It": 1, "context": 1, "sinc": 1, "what": 1, "core": 1, "pass": 1, "pydantic_set": 1, "env": 1, "dev": 1, "2": 1, "migrat": 1, "nullabl": 1, "extra": 1, "classmethod": 1, "validate_instance_typ": 1, "v": 1, "make": 1, "sure": 1, "nano": 1, "validate_vpn_password": 1, "per": 1, "regex": 1, "wrapper": 1, "awsresourceerror": 1, "status_cod": 1, "error_msg": 1, "custom": 1, "notimplementedwarn": 1, "implement": 1, "warn": 1, "image_factori": 1, "handl": 1, "retriev": 1, "sourc": 1, "ssm": 1, "origin": 1, "get_ami_id_nam": 1, "get_ami_id_product_cod": 1, "product": 1, "get_ami_id_ssm": 1, "get_image_id": 1, "tri": 1, "sequenti": 1, "execut": 1, "sequenc": 1, "fastest": 1, "singl": 1, "possibli": 1, "contain": 1, "lookup": 1, "specif": 1, "mani": 1, "so": 1, "grab": 1, "most": 1, "recent": 1, "one": 1, "unabl": 1, "deprecation_warn": 1, "deprecation_tim": 1, "deprec": 1, "chosen": 1, "nearing": 1, "deprecationtim": 1, "streamhandl": 1, "debug": 1, "mode": 1, "change_record_set": 1, "destin": 1, "zone_id": 1, "action": 1, "chang": 1, "within": 1, "perform": 1, "upsert": 1, "get_zone_id": 1, "init": 1, "fals": 1, "boolean": 1, "miss": 1, "rsakei": 1, "gener": 1, "add_formatt": 1, "add": 1, "formatt": 1, "dure": 1, "remove_formatt": 1, "log": 1, "room": 1, "restart_servic": 1, "restart": 1, "run_interactive_ssh": 1, "displai": 1, "true": 1, "30": 1, "command": 1, "screen": 1, "complet": 1, "test_servic": 1, "check": 1, "statu": 1, "remot": 1, "available_instance_typ": 1, "loop": 1, "through": 1, "describ": 1, "yield": 1, "available_region": 1, "index": 1, "modul": 1, "search": 1}, "objects": {"vpn": [[1, 0, 0, "-", "main"]], "vpn.main": [[1, 1, 1, "", "VPNServer"]], "vpn.main.VPNServer": [[1, 2, 1, "", "_authorize_security_group"], [1, 2, 1, "", "_configure_vpn"], [1, 2, 1, "", "_create_ec2_instance"], [1, 2, 1, "", "_create_key_pair"], [1, 2, 1, "", "_create_security_group"], [1, 2, 1, "", "_delete_key_pair"], [1, 2, 1, "", "_delete_security_group"], [1, 2, 1, "", "_disassociate_security_group"], [1, 2, 1, "", "_get_vpc_id"], [1, 2, 1, "", "_init"], [1, 2, 1, "", "_terminate_ec2_instance"], [1, 2, 1, "", "_test_get"], [1, 2, 1, "", "_tester"], [1, 2, 1, "", "create_vpn_server"], [1, 2, 1, "", "delete_vpn_server"], [1, 2, 1, "", "test_vpn"]], "vpn.models.config": [[1, 1, 1, "", "AMIBase"], [1, 1, 1, "", "ConfigurationSettings"], [1, 1, 1, "", "EnvConfig"], [1, 1, 1, "", "Settings"]], "vpn.models.config.AMIBase": [[1, 2, 1, "", "model_post_init"]], "vpn.models.config.EnvConfig": [[1, 1, 1, "", "Config"], [1, 2, 1, "", "validate_instance_type"], [1, 2, 1, "", "validate_vpn_password"]], "vpn.models": [[1, 0, 0, "-", "exceptions"], [1, 0, 0, "-", "image_factory"], [1, 0, 0, "-", "logger"], [1, 0, 0, "-", "route53"], [1, 0, 0, "-", "server"], [1, 0, 0, "-", "util"]], "vpn.models.exceptions": [[1, 3, 1, "", "AWSResourceError"], [1, 3, 1, "", "NotImplementedWarning"]], "vpn.models.image_factory": [[1, 1, 1, "", "ImageFactory"], [1, 4, 1, "", "deprecation_warning"]], "vpn.models.image_factory.ImageFactory": [[1, 2, 1, "", "get_ami_id_name"], [1, 2, 1, "", "get_ami_id_product_code"], [1, 2, 1, "", "get_ami_id_ssm"], [1, 2, 1, "", "get_image_id"]], "vpn.models.route53": [[1, 4, 1, "", "change_record_set"], [1, 4, 1, "", "get_zone_id"]], "vpn.models.server": [[1, 1, 1, "", "Server"]], "vpn.models.server.Server": [[1, 2, 1, "", "add_formatter"], [1, 2, 1, "", "remove_formatter"], [1, 2, 1, "", "restart_service"], [1, 2, 1, "", "run_interactive_ssh"], [1, 2, 1, "", "test_service"]], "vpn.models.util": [[1, 4, 1, "", "available_instance_types"], [1, 4, 1, "", "available_regions"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:exception", "4": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "exception", "Python exception"], "4": ["py", "function", "Python function"]}, "titleterms": {"platform": 0, "support": 0, "repo": 0, "stat": 0, "deploy": 0, "vpn": [0, 1], "server": [0, 1], "instal": 0, "usag": 0, "code": 0, "standard": 0, "releas": 0, "note": 0, "lint": 0, "project": 0, "link": 0, "licens": 0, "copyright": 0, "welcom": 1, "": 1, "document": 1, "read": 1, "me": 1, "configur": 1, "except": 1, "imagefactori": 1, "logger": 1, "route53": 1, "ssh": 1, "util": 1, "indic": 1, "tabl": 1}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 56}}) \ No newline at end of file +Search.setIndex({"docnames": ["README", "index"], "filenames": ["README.md", "index.rst"], "titles": ["Platform Supported", "Welcome to VPN Server\u2019s documentation!"], "terms": {"establish": 0, "scalabl": 0, "demand": 0, "power": 0, "openvpn": [0, 1], "aw": [0, 1], "ec2": [0, 1], "python": 0, "m": 0, "pip": 0, "import": 0, "instanti": [0, 1], "object": [0, 1], "vpn_server": 0, "vpnserver": [0, 1], "creat": [0, 1], "create_vpn_serv": [0, 1], "test": [0, 1], "an": [0, 1], "exist": [0, 1], "test_vpn": [0, 1], "delet": [0, 1], "delete_vpn_serv": [0, 1], "bulb": 0, "pleas": [0, 1], "refer": [0, 1], "wiki": 0, "page": [0, 1], "more": [0, 1], "instruct": 0, "payload": 0, "requir": [0, 1], "docstr": 0, "format": [0, 1], "googl": [0, 1], "style": 0, "convent": 0, "pep": 0, "8": 0, "clean": 0, "pre": [0, 1], "commit": 0, "hook": 0, "flake8": 0, "isort": 0, "gitvers": 0, "revers": 0, "f": 0, "release_not": 0, "rst": 0, "t": [0, 1], "precommit": 0, "ensur": 0, "doc": [0, 1], "creation": 0, "ar": 0, "run": [0, 1], "everi": 0, "sphinx": 0, "5": [0, 1], "1": 0, "recommonmark": 0, "all": [0, 1], "file": [0, 1], "repositori": 0, "runbook": 0, "packag": 0, "vignesh": 0, "rao": 0, "under": [0, 1], "mit": 0, "platform": 1, "support": 1, "repo": 1, "stat": 1, "deploy": 1, "instal": 1, "usag": 1, "code": 1, "standard": 1, "project": 1, "link": 1, "licens": 1, "copyright": 1, "class": 1, "main": 1, "kwarg": 1, "unpack": 1, "initi": 1, "spin": 1, "up": 1, "instanc": 1, "ami": 1, "which": 1, "serv": 1, "load": 1, "envconfig": 1, "subclass": 1, "baseset": 1, "valid": 1, "us": 1, "pydant": 1, "paramet": 1, "dictionari": 1, "keyword": 1, "argument": 1, "follow": 1, "kei": 1, "valu": 1, "pair": 1, "vpn_usernam": 1, "usernam": 1, "access": 1, "client": 1, "vpn_password": 1, "password": 1, "vpn_port": 1, "port": 1, "number": 1, "web": 1, "interfac": 1, "aws_profile_nam": 1, "name": 1, "profil": 1, "session": 1, "aws_access_kei": 1, "token": 1, "account": 1, "aws_secret_kei": 1, "secret": 1, "id": 1, "aws_region_nam": 1, "region": 1, "where": 1, "should": 1, "live": 1, "default": 1, "image_id": 1, "instance_typ": 1, "type": 1, "host": 1, "key_pair": 1, "store": 1, "connect": 1, "security_group": 1, "secur": 1, "group": 1, "vpn_info": 1, "json": 1, "dump": 1, "inform": 1, "domain": 1, "zone": 1, "hosted_zon": 1, "subdomain": 1, "bring": 1, "your": 1, "own": 1, "point": 1, "combin": 1, "exampl": 1, "If": 1, "you": 1, "have": 1, "com": 1, "want": 1, "entrypoint": 1, "note": 1, "also": 1, "regist": 1, "cannot": 1, "simpli": 1, "expect": 1, "work": 1, "The": 1, "alia": 1, "record": 1, "fail": 1, "duplic": 1, "dn": 1, "resolut": 1, "level": 1, "unless": 1, "i": 1, "same": 1, "_authorize_security_group": 1, "security_group_id": 1, "str": 1, "bool": 1, "author": 1, "certain": 1, "ingress": 1, "list": 1, "take": 1, "securitygroup": 1, "firewal": 1, "open": 1, "tcp": 1, "22": 1, "443": 1, "943": 1, "can": 1, "dynam": 1, "945": 1, "cluster": 1, "control": 1, "channel": 1, "udp": 1, "1194": 1, "return": 1, "flag": 1, "call": 1, "function": 1, "whether": 1, "wa": 1, "successfulli": 1, "_configure_vpn": 1, "public_dn": 1, "none": 1, "traffic": 1, "from": 1, "localhost": 1, "tunnel": 1, "public": 1, "_create_ec2_inst": 1, "option": 1, "tupl": 1, "success": 1, "union": 1, "_create_key_pair": 1, "keypair": 1, "rsa": 1, "pem": 1, "_create_security_group": 1, "get": 1, "vpc": 1, "re": 1, "sg": 1, "case": 1, "alreadi": 1, "_delete_key_pair": 1, "_delete_security_group": 1, "_disassociate_security_group": 1, "serviceresourc": 1, "instance_id": 1, "disassoci": 1, "assign": 1, "unavail": 1, "_get_vpc_id": 1, "fetch": 1, "_init": 1, "start": 1, "int": 1, "its": 1, "startup": 1, "shutdown": 1, "_terminate_ec2_inst": 1, "termin": 1, "request": 1, "_test_get": 1, "timeout": 1, "3": 1, "retri": 1, "respons": 1, "multipl": 1, "hostnam": 1, "ip": 1, "address": 1, "time": 1, "error": 1, "exponenti": 1, "interv": 1, "between": 1, "each": 1, "attempt": 1, "failur": 1, "_tester": 1, "data": 1, "dict": 1, "parallel": 1, "improv": 1, "runtim": 1, "against": 1, "openvpna": 1, "servic": 1, "avail": 1, "were": 1, "provid": 1, "rais": 1, "assertionerror": 1, "when": 1, "ani": 1, "public_ip": 1, "disabl": 1, "remov": 1, "resourc": 1, "acquir": 1, "ha": 1, "A": 1, "doesn": 1, "long": 1, "neither": 1, "nor": 1, "modifi": 1, "manual": 1, "http": 1, "boto3": 1, "amazonaw": 1, "v1": 1, "api": 1, "latest": 1, "wait_until_termin": 1, "html": 1, "model": 1, "config": 1, "configurationset": 1, "basemodel": 1, "set": 1, "interact": 1, "new": 1, "pars": 1, "input": 1, "validationerror": 1, "pydantic_cor": 1, "form": 1, "__init__": 1, "__pydantic_self__": 1, "instead": 1, "common": 1, "self": 1, "first": 1, "arg": 1, "allow": 1, "field": 1, "amibas": 1, "imag": 1, "subscript": 1, "home": 1, "consol": 1, "amazon": 1, "marketplac": 1, "_product_id": 1, "product": 1, "found": 1, "url": 1, "summari": 1, "offer": 1, "_base_url": 1, "model_post_init": 1, "__context": 1, "thi": 1, "meant": 1, "behav": 1, "like": 1, "method": 1, "initialis": 1, "privat": 1, "attribut": 1, "It": 1, "context": 1, "sinc": 1, "what": 1, "core": 1, "pass": 1, "pydantic_set": 1, "env": 1, "dev": 1, "2": 1, "migrat": 1, "nullabl": 1, "extra": 1, "classmethod": 1, "validate_instance_typ": 1, "v": 1, "make": 1, "sure": 1, "nano": 1, "validate_vpn_password": 1, "per": 1, "regex": 1, "wrapper": 1, "awsresourceerror": 1, "status_cod": 1, "error_msg": 1, "custom": 1, "notimplementedwarn": 1, "implement": 1, "warn": 1, "image_factori": 1, "handl": 1, "retriev": 1, "sourc": 1, "ssm": 1, "origin": 1, "get_ami_id_nam": 1, "get_ami_id_product_cod": 1, "get_ami_id_ssm": 1, "get_image_id": 1, "tri": 1, "sequenti": 1, "execut": 1, "sequenc": 1, "fastest": 1, "singl": 1, "possibli": 1, "contain": 1, "lookup": 1, "specif": 1, "mani": 1, "so": 1, "grab": 1, "most": 1, "recent": 1, "one": 1, "unabl": 1, "deprecation_warn": 1, "deprecation_tim": 1, "deprec": 1, "chosen": 1, "nearing": 1, "deprecationtim": 1, "streamhandl": 1, "debug": 1, "mode": 1, "change_record_set": 1, "destin": 1, "zone_id": 1, "action": 1, "chang": 1, "within": 1, "perform": 1, "upsert": 1, "get_zone_id": 1, "init": 1, "fals": 1, "boolean": 1, "miss": 1, "rsakei": 1, "gener": 1, "add_formatt": 1, "add": 1, "formatt": 1, "dure": 1, "remove_formatt": 1, "log": 1, "room": 1, "restart_servic": 1, "restart": 1, "run_interactive_ssh": 1, "displai": 1, "true": 1, "30": 1, "command": 1, "screen": 1, "complet": 1, "test_servic": 1, "check": 1, "statu": 1, "remot": 1, "available_instance_typ": 1, "loop": 1, "through": 1, "describ": 1, "yield": 1, "available_region": 1, "index": 1, "modul": 1, "search": 1}, "objects": {"vpn": [[1, 0, 0, "-", "main"]], "vpn.main": [[1, 1, 1, "", "VPNServer"]], "vpn.main.VPNServer": [[1, 2, 1, "", "_authorize_security_group"], [1, 2, 1, "", "_configure_vpn"], [1, 2, 1, "", "_create_ec2_instance"], [1, 2, 1, "", "_create_key_pair"], [1, 2, 1, "", "_create_security_group"], [1, 2, 1, "", "_delete_key_pair"], [1, 2, 1, "", "_delete_security_group"], [1, 2, 1, "", "_disassociate_security_group"], [1, 2, 1, "", "_get_vpc_id"], [1, 2, 1, "", "_init"], [1, 2, 1, "", "_terminate_ec2_instance"], [1, 2, 1, "", "_test_get"], [1, 2, 1, "", "_tester"], [1, 2, 1, "", "create_vpn_server"], [1, 2, 1, "", "delete_vpn_server"], [1, 2, 1, "", "test_vpn"]], "vpn.models.config": [[1, 1, 1, "", "AMIBase"], [1, 1, 1, "", "ConfigurationSettings"], [1, 1, 1, "", "EnvConfig"], [1, 1, 1, "", "Settings"]], "vpn.models.config.AMIBase": [[1, 2, 1, "", "model_post_init"]], "vpn.models.config.EnvConfig": [[1, 1, 1, "", "Config"], [1, 2, 1, "", "validate_instance_type"], [1, 2, 1, "", "validate_vpn_password"]], "vpn.models": [[1, 0, 0, "-", "exceptions"], [1, 0, 0, "-", "image_factory"], [1, 0, 0, "-", "logger"], [1, 0, 0, "-", "route53"], [1, 0, 0, "-", "server"], [1, 0, 0, "-", "util"]], "vpn.models.exceptions": [[1, 3, 1, "", "AWSResourceError"], [1, 3, 1, "", "NotImplementedWarning"]], "vpn.models.image_factory": [[1, 1, 1, "", "ImageFactory"], [1, 4, 1, "", "deprecation_warning"]], "vpn.models.image_factory.ImageFactory": [[1, 2, 1, "", "get_ami_id_name"], [1, 2, 1, "", "get_ami_id_product_code"], [1, 2, 1, "", "get_ami_id_ssm"], [1, 2, 1, "", "get_image_id"]], "vpn.models.route53": [[1, 4, 1, "", "change_record_set"], [1, 4, 1, "", "get_zone_id"]], "vpn.models.server": [[1, 1, 1, "", "Server"]], "vpn.models.server.Server": [[1, 2, 1, "", "add_formatter"], [1, 2, 1, "", "remove_formatter"], [1, 2, 1, "", "restart_service"], [1, 2, 1, "", "run_interactive_ssh"], [1, 2, 1, "", "test_service"]], "vpn.models.util": [[1, 4, 1, "", "available_instance_types"], [1, 4, 1, "", "available_regions"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:exception", "4": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "exception", "Python exception"], "4": ["py", "function", "Python function"]}, "titleterms": {"platform": 0, "support": 0, "repo": 0, "stat": 0, "deploy": 0, "vpn": [0, 1], "server": [0, 1], "instal": 0, "usag": 0, "code": 0, "standard": 0, "releas": 0, "note": 0, "lint": 0, "project": 0, "link": 0, "licens": 0, "copyright": 0, "welcom": 1, "": 1, "document": 1, "read": 1, "me": 1, "configur": 1, "except": 1, "imagefactori": 1, "logger": 1, "route53": 1, "ssh": 1, "util": 1, "indic": 1, "tabl": 1}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 56}}) \ No newline at end of file diff --git a/release_notes.rst b/release_notes.rst index 73c9fb1..9b44abb 100644 --- a/release_notes.rst +++ b/release_notes.rst @@ -1,6 +1,11 @@ Release Notes ============= +1.7.1 (05/26/2024) +------------------ +- Upgrades ``OpenVPN`` software version and dependencies +- Improves linting and runbook UI + 1.7 (01/30/2024) ---------------- - Improved accuracy for validating alias record diff --git a/vpn/__init__.py b/vpn/__init__.py index 8af97fb..5dd7fd7 100644 --- a/vpn/__init__.py +++ b/vpn/__init__.py @@ -1,7 +1,7 @@ """Place holder for package.""" from vpn.main import VPNServer # noqa: F401 -from vpn.models import (config, exceptions, image_factory, # noqa: F401 - logger, route53, server, util) +from vpn.models import image_factory # noqa: F401 +from vpn.models import config, exceptions, logger, route53, server, util -version = "1.7" +version = "1.7.1" diff --git a/vpn/main.py b/vpn/main.py index 775df47..1ceec44 100644 --- a/vpn/main.py +++ b/vpn/main.py @@ -190,26 +190,36 @@ def _authorize_security_group(self, security_group = self.ec2_resource.SecurityGroup(security_group_id) security_group.authorize_ingress( IpPermissions=[ - {'IpProtocol': 'tcp', - 'FromPort': 22, - 'ToPort': 22, - 'IpRanges': [{'CidrIp': '0.0.0.0/0'}]}, - {'IpProtocol': 'tcp', - 'FromPort': 443, - 'ToPort': 443, - 'IpRanges': [{'CidrIp': '0.0.0.0/0'}]}, - {'IpProtocol': 'tcp', - 'FromPort': config.env.vpn_port, - 'ToPort': config.env.vpn_port, - 'IpRanges': [{'CidrIp': '0.0.0.0/0'}]}, - {'IpProtocol': 'tcp', - 'FromPort': 945, - 'ToPort': 945, - 'IpRanges': [{'CidrIp': '0.0.0.0/0'}]}, - {'IpProtocol': 'udp', - 'FromPort': 1194, - 'ToPort': 1194, - 'IpRanges': [{'CidrIp': '0.0.0.0/0'}]} + { + 'IpProtocol': 'tcp', + 'FromPort': 22, + 'ToPort': 22, + 'IpRanges': [{'CidrIp': '0.0.0.0/0'}] + }, + { + 'IpProtocol': 'tcp', + 'FromPort': 443, + 'ToPort': 443, + 'IpRanges': [{'CidrIp': '0.0.0.0/0'}] + }, + { + 'IpProtocol': 'tcp', + 'FromPort': config.env.vpn_port, + 'ToPort': config.env.vpn_port, + 'IpRanges': [{'CidrIp': '0.0.0.0/0'}] + }, + { + 'IpProtocol': 'tcp', + 'FromPort': 945, + 'ToPort': 945, + 'IpRanges': [{'CidrIp': '0.0.0.0/0'}] + }, + { + 'IpProtocol': 'udp', + 'FromPort': 1194, + 'ToPort': 1194, + 'IpRanges': [{'CidrIp': '0.0.0.0/0'}] + } ]) except ClientError as error: error = str(error) diff --git a/vpn/models/config.py b/vpn/models/config.py index fc606d8..3c2bdb4 100644 --- a/vpn/models/config.py +++ b/vpn/models/config.py @@ -24,6 +24,12 @@ class AMIBase(BaseModel): >>> AMIBase + See Also: + - Subscription Home Page: https://{REGION}.console.aws.amazon.com/marketplace/home#/subscriptions/{_PRODUCT_ID} + - Product ID: Found in the home page URL under Summary as 'Product ID' + - Product Code: Offer ID in the home page URL + - AMI Alias: Found in configuration page (_BASE_URL) as 'Ami Alias' + - Product Code: Found in configuration page (_BASE_URL) as 'Product Code' """ _BASE_URL: str = 'https://aws.amazon.com/marketplace/server/configuration?productId={productId}' @@ -32,7 +38,7 @@ class AMIBase(BaseModel): PRODUCT_PAGE: HttpUrl = _BASE_URL.format(productId=_PRODUCT_ID) NAME: str = f'OpenVPN Access Server QA Image-{_PRODUCT_ID}' - ALIAS: str = _BASE_SSM.format(path='qqrkogtl46mpu/2.11.3') + ALIAS: str = _BASE_SSM.format(path='qqrkogtl46mpu/2.13.1') PRODUCT_CODE: str = 'f2ew2wrz425a1jagnifd02u5t' @@ -114,32 +120,108 @@ class Settings(BaseModel): def configuration_dict(param: EnvConfig) -> List[ConfigurationSettings]: """Get configuration interaction as a list of dictionaries.""" for config_dict in [ - {'request': "Please enter 'yes' to indicate your agreement \\[no\\]: ", 'response': 'yes', 'timeout': 5, - 'critical': False}, - {'request': '> Press ENTER for default \\[yes\\]: ', 'response': 'yes', 'timeout': 1, 'critical': False}, - {'request': '> Press Enter for default \\[1\\]: ', 'response': '1', 'timeout': 1, 'critical': False}, - {'request': '> Press ENTER for default \\[rsa\\]:', 'response': 'rsa', 'timeout': 1, 'critical': False}, - {'request': '> Press ENTER for default \\[ 2048 \\]:', 'response': '2048', 'timeout': 1, - 'critical': False}, - {'request': '> Press ENTER for default \\[rsa\\]:', 'response': 'rsa', 'timeout': 1, 'critical': False}, - {'request': '> Press ENTER for default \\[ 2048 \\]:', 'response': '2048', 'timeout': 1, - 'critical': False}, - {'request': '> Press ENTER for default \\[943\\]: ', 'response': param.vpn_port, 'timeout': 1, - 'critical': False}, - {'request': '> Press ENTER for default \\[443\\]: ', 'response': '443', 'timeout': 1, 'critical': False}, - {'request': '> Press ENTER for default \\[no\\]: ', 'response': 'yes', 'timeout': 1, 'critical': False}, - {'request': '> Press ENTER for default \\[no\\]: ', 'response': 'yes', 'timeout': 1, 'critical': False}, - {'request': '> Press ENTER for EC2 default \\[yes\\]: ', 'response': 'yes', 'timeout': 1, - 'critical': False}, - {'request': '> Press ENTER for default \\[yes\\]: ', 'response': 'no', 'timeout': 1, 'critical': False}, - {'request': '> Specify the username for an existing user or for the new user account: ', - 'response': param.vpn_username, 'timeout': 1, 'critical': True}, - {'request': f"Type a password for the '{param.vpn_username}' account " - "(if left blank, a random password will be generated):", - 'response': param.vpn_password, 'timeout': 1, 'critical': True}, - {'request': f"Confirm the password for the '{param.vpn_username}' account:", 'response': param.vpn_password, - 'timeout': 1, 'critical': True}, - {'request': '> Please specify your Activation key (or leave blank to specify later): ', 'response': '\n', - 'timeout': 1, 'critical': False} + { + "request": "Please enter 'yes' to indicate your agreement \\[no\\]: ", + "response": "yes", + "timeout": 5, + "critical": False, + }, + { + "request": "> Press ENTER for default \\[yes\\]: ", + "response": "yes", + "timeout": 1, + "critical": False, + }, + { + "request": "> Press Enter for default \\[1\\]: ", + "response": "1", + "timeout": 1, + "critical": False, + }, + { + "request": "> Press ENTER for default \\[rsa\\]:", + "response": "rsa", + "timeout": 1, + "critical": False, + }, + { + "request": "> Press ENTER for default \\[ 2048 \\]:", + "response": "2048", + "timeout": 1, + "critical": False, + }, + { + "request": "> Press ENTER for default \\[rsa\\]:", + "response": "rsa", + "timeout": 1, + "critical": False, + }, + { + "request": "> Press ENTER for default \\[ 2048 \\]:", + "response": "2048", + "timeout": 1, + "critical": False, + }, + { + "request": "> Press ENTER for default \\[943\\]: ", + "response": param.vpn_port, + "timeout": 1, + "critical": False, + }, + { + "request": "> Press ENTER for default \\[443\\]: ", + "response": "443", + "timeout": 1, + "critical": False, + }, + { + "request": "> Press ENTER for default \\[no\\]: ", + "response": "yes", + "timeout": 1, + "critical": False, + }, + { + "request": "> Press ENTER for default \\[no\\]: ", + "response": "yes", + "timeout": 1, + "critical": False, + }, + { + "request": "> Press ENTER for EC2 default \\[yes\\]: ", + "response": "yes", + "timeout": 1, + "critical": False, + }, + { + "request": "> Press ENTER for default \\[yes\\]: ", + "response": "no", + "timeout": 1, + "critical": False, + }, + { + "request": "> Specify the username for an existing user or for the new user account: ", + "response": param.vpn_username, + "timeout": 1, + "critical": True, + }, + { + "request": f"Type a password for the '{param.vpn_username}' account " + "(if left blank, a random password will be generated):", + "response": param.vpn_password, + "timeout": 1, + "critical": True, + }, + { + "request": f"Confirm the password for the '{param.vpn_username}' account:", + "response": param.vpn_password, + "timeout": 1, + "critical": True, + }, + { + "request": "> Please specify your Activation key (or leave blank to specify later): ", + "response": "\n", + "timeout": 1, + "critical": False, + }, ]: yield ConfigurationSettings(**config_dict) diff --git a/vpn/models/logger.py b/vpn/models/logger.py index 433dc16..d39b9f0 100644 --- a/vpn/models/logger.py +++ b/vpn/models/logger.py @@ -8,9 +8,11 @@ LOGGER = logging.getLogger(__name__) HANDLER = logging.StreamHandler() -HANDLER.setFormatter(fmt=logging.Formatter( - fmt='%(asctime)s - %(levelname)s - [%(module)s:%(lineno)d] - %(funcName)s - %(message)s', - datefmt='%b-%d-%Y %I:%M:%S %p' -)) +HANDLER.setFormatter( + fmt=logging.Formatter( + fmt='%(asctime)s - %(levelname)s - [%(module)s:%(lineno)d] - %(funcName)s - %(message)s', + datefmt='%b-%d-%Y %I:%M:%S %p' + ) +) LOGGER.addHandler(hdlr=HANDLER) LOGGER.setLevel(level=logging.DEBUG) diff --git a/vpn/models/server.py b/vpn/models/server.py index 9173530..431a7f2 100644 --- a/vpn/models/server.py +++ b/vpn/models/server.py @@ -31,11 +31,17 @@ def __init__(self, hostname: str, username: str, logger: logging.Logger): if username == config.env.vpn_username: try: # todo: Manual config accepts username and password, but unable to get authentication pass via paramiko - self.ssh_client.connect(hostname=hostname, username=username, - pkey=pem_key, password=config.env.vpn_password) + self.ssh_client.connect( + hostname=hostname, + username=username, + pkey=pem_key, + password=config.env.vpn_password, + ) except AuthenticationException as error: self.logger.warning(error) - self.ssh_client.connect(hostname=hostname, username='openvpnas', pkey=pem_key) + self.ssh_client.connect( + hostname=hostname, username="openvpnas", pkey=pem_key + ) else: self.ssh_client.connect(hostname=hostname, username=username, pkey=pem_key) self.logger.info("Connected to %s as %s", hostname, username) @@ -49,7 +55,7 @@ def remove_formatter(self) -> None: self._formatter.append(handler.formatter) handler.formatter = None self.logger.setLevel(level=logging.INFO) - sys.stdout = open(os.devnull, 'w') + sys.stdout = open(os.devnull, "w") def add_formatter(self) -> None: """Re-add any formatters that were removed during instantiation.""" @@ -73,18 +79,18 @@ def test_service(self, timeout: int, display: bool) -> None: timeout: Default interaction session timeout. display: Boolean flag whether to display interaction data on screen. """ - with SSHClientInteraction(client=self.ssh_client, - timeout=timeout, - display=display, - output_callback=lambda msg: self.logger.info(msg)) as interact: + with SSHClientInteraction( + client=self.ssh_client, + timeout=timeout, + display=display, + output_callback=lambda msg: self.logger.info(msg), + ) as interact: self.remove_formatter() - interact.send("systemctl status openvpnas", '\n') + interact.send("systemctl status openvpnas", "\n") interact.expect(r".*Started OpenVPN Access Server\..*", timeout) self.add_formatter() - def run_interactive_ssh(self, - display: bool = True, - timeout: int = 30) -> None: + def run_interactive_ssh(self, display: bool = True, timeout: int = 30) -> None: """Runs interactive ssh commands to configure the VPN server. Args: @@ -96,10 +102,12 @@ def run_interactive_ssh(self, Flag to indicate the calling function, whether the interactive session has completed successfully. """ self.remove_formatter() - with SSHClientInteraction(client=self.ssh_client, - timeout=timeout, - display=display, - output_callback=lambda msg: self.logger.info(msg)) as interact: + with SSHClientInteraction( + client=self.ssh_client, + timeout=timeout, + display=display, + output_callback=lambda msg: self.logger.info(msg), + ) as interact: for setting in config.settings.openvpn_config_commands: interact.expect(re_strings=setting.request, timeout=setting.timeout) interact.send(send_string=str(setting.response)) diff --git a/vpn/models/util.py b/vpn/models/util.py index 383f251..f42c053 100644 --- a/vpn/models/util.py +++ b/vpn/models/util.py @@ -10,14 +10,14 @@ def available_instance_types() -> Generator[str]: Generator[str]: Instance type. """ - ec2_client = boto3.client('ec2') + ec2_client = boto3.client("ec2") describe_args = {} while True: describe_result = ec2_client.describe_instance_types(**describe_args) - yield from [i['InstanceType'] for i in describe_result['InstanceTypes']] - if 'NextToken' not in describe_result: + yield from [i["InstanceType"] for i in describe_result["InstanceTypes"]] + if "NextToken" not in describe_result: break - describe_args['NextToken'] = describe_result['NextToken'] + describe_args["NextToken"] = describe_result["NextToken"] def available_regions() -> Generator[str]: @@ -27,6 +27,6 @@ def available_regions() -> Generator[str]: Generator[str]: Region name. """ - ec2_client = boto3.client('ec2') - for region in ec2_client.describe_regions()['Regions']: - yield region['RegionName'] + ec2_client = boto3.client("ec2") + for region in ec2_client.describe_regions()["Regions"]: + yield region["RegionName"] diff --git a/vpn/requirements.txt b/vpn/requirements.txt index 290fd70..fed8be9 100644 --- a/vpn/requirements.txt +++ b/vpn/requirements.txt @@ -3,6 +3,6 @@ botocore inflect paramiko==3.3.1 paramiko-expect==0.3.5 -pydantic==2.4.0 -pydantic-settings==2.0.3 +pydantic==2.4.* +pydantic-settings==2.0.* requests