diff --git a/README.md b/README.md index 93edb84..40f181f 100644 --- a/README.md +++ b/README.md @@ -40,13 +40,13 @@ If connections take longer to establish due to network conditions, a short timeo **Connection Rate** -If your server expects a high rate of incoming connections and you want to process them quickly, a shorter timeout can be beneficial. -However, it also means that your server needs to handle and process connections rapidly. +If your server expects a high rate of incoming connections, and you want to process them quickly, a shorter timeout can be beneficial. +However, it also means that your server needs to be able to process connections rapidly. **Resource Usage** Short timeouts can lead to a higher rate of repeated checks, which may consume more CPU resources on the server. -Ensure that your server has the capacity to handle frequent connection checks. +Ensure that your server has the capacity to handle frequent connection checks, if you are setting `CHANNEL_TIMEOUT` too low.
diff --git a/docs/README.html b/docs/README.html index f97c088..ad767bf 100644 --- a/docs/README.html +++ b/docs/README.html @@ -76,11 +76,11 @@

Environment Variables:Shorter timeouts can make your server more responsive to incoming connections but may also lead to false negatives if network latency is high. If connections take longer to establish due to network conditions, a short timeout might reject valid connections prematurely.

Connection Rate

-

If your server expects a high rate of incoming connections and you want to process them quickly, a shorter timeout can be beneficial. -However, it also means that your server needs to handle and process connections rapidly.

+

If your server expects a high rate of incoming connections, and you want to process them quickly, a shorter timeout can be beneficial. +However, it also means that your server needs to be able to process connections rapidly.

Resource Usage

Short timeouts can lead to a higher rate of repeated checks, which may consume more CPU resources on the server. -Ensure that your server has the capacity to handle frequent connection checks.

+Ensure that your server has the capacity to handle frequent connection checks, if you are setting CHANNEL_TIMEOUT too low.

Custom endpoint

The public DNS names for EC2 instances are long and messy. To avoid that, an A record can be added to the route53 hosted zone.

:warning:   Requires an active hosted zone on route53.

diff --git a/docs/_sources/README.md.txt b/docs/_sources/README.md.txt index 93edb84..40f181f 100644 --- a/docs/_sources/README.md.txt +++ b/docs/_sources/README.md.txt @@ -40,13 +40,13 @@ If connections take longer to establish due to network conditions, a short timeo **Connection Rate** -If your server expects a high rate of incoming connections and you want to process them quickly, a shorter timeout can be beneficial. -However, it also means that your server needs to handle and process connections rapidly. +If your server expects a high rate of incoming connections, and you want to process them quickly, a shorter timeout can be beneficial. +However, it also means that your server needs to be able to process connections rapidly. **Resource Usage** Short timeouts can lead to a higher rate of repeated checks, which may consume more CPU resources on the server. -Ensure that your server has the capacity to handle frequent connection checks. +Ensure that your server has the capacity to handle frequent connection checks, if you are setting `CHANNEL_TIMEOUT` too low.
diff --git a/docs/genindex.html b/docs/genindex.html index 6f61afa..070f7e4 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -84,6 +84,8 @@

A

    +
  • deprecation_warning() (in module expose.models.image_factory) +
  • disassociate_security_group() (expose.main.Tunnel method)
  • DuplicateResource diff --git a/docs/index.html b/docs/index.html index 1915cf7..7a5e33f 100644 --- a/docs/index.html +++ b/docs/index.html @@ -705,6 +705,11 @@

    Expose - Configurationconfiguration: Path
    +
    +
    +ami_deprecation: int
    +
    +
    entrypoint: str
    @@ -741,6 +746,12 @@

    Expose - Configuration

    Expose - ImageFactory

    +
    +
    +expose.models.image_factory.deprecation_warning(image_id: str, deprecation_time: str) None
    +

    Raises a deprecation warning if the chosen AMI is nearing (value is set in config) its DeprecationTime.

    +
    +
    class expose.models.image_factory.ImageFactory(session: Session, logger: Logger)
    diff --git a/docs/objects.inv b/docs/objects.inv index 271f892..daa2763 100644 Binary files a/docs/objects.inv and b/docs/objects.inv differ diff --git a/docs/searchindex.js b/docs/searchindex.js index 14e8995..8b46b5a 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["README", "index"], "filenames": ["README.md", "index.rst"], "titles": ["Expose localhost using EC2", "Expose - Expose a web service on localhost to public internet using AWS EC2"], "terms": {"revers": [0, 1], "proxi": [0, 1], "creat": [0, 1], "secur": [0, 1], "from": [0, 1], "public": 0, "endpoint": 0, "local": [0, 1], "run": [0, 1], "web": 0, "servic": 0, "can": [0, 1], "load": [0, 1], "ani": [0, 1], "env": [0, 1], "file": [0, 1], "port": [0, 1], "number": [0, 1], "ha": [0, 1], "which": [0, 1], "app": [0, 1], "api": [0, 1], "i": [0, 1], "option": [0, 1], "open": 0, "_": 0, "boolean": [0, 1], "flag": [0, 1], "enabl": 0, "ingress": [0, 1], "egress": [0, 1], "specifi": [0, 1], "default": [0, 1], "fals": [0, 1], "channel": [0, 1], "timeout": [0, 1], "second": 0, "wait": 0, "an": [0, 1], "incom": 0, "connect": [0, 1], "100": 0, "imag": [0, 1], "id": [0, 1], "ami": [0, 1], "ubuntu": [0, 1], "o": 0, "region": 0, "specif": [0, 1], "instanc": [0, 1], "type": [0, 1], "t2": 0, "nano": 0, "aw": 0, "access": [0, 1], "kei": [0, 1], "resourc": [0, 1], "config": [0, 1], "secret": 0, "name": [0, 1], "where": 0, "should": [0, 1], "live": 0, "u": [0, 1], "west": 0, "2": [0, 1], "pair": [0, 1], "expose_localhost": 0, "group": [0, 1], "allow": [0, 1], "server": 0, "info": 0, "json": [0, 1], "store": [0, 1], "configur": 0, "server_info": [0, 1], "email": 0, "address": [0, 1], "self": [0, 1], "sign": [0, 1], "ssl": [0, 1], "privat": [0, 1], "user": 0, "com": [0, 1], "organ": [0, 1], "certif": 0, "host": [0, 1], "zone": [0, 1], "regist": [0, 1], "route53": 0, "exampl": [0, 1], "mywebsit": 0, "subdomain": [0, 1], "sub": 0, "domain": 0, "ad": [0, 1], "latenc": [0, 1], "channel_timeout": [0, 1], "adjust": 0, "improv": [0, 1], "depend": 0, "applic": 0, "": [0, 1], "role": 0, "network": 0, "shorter": 0, "make": [0, 1], "your": [0, 1], "more": [0, 1], "respons": [0, 1], "mai": 0, "also": 0, "lead": 0, "neg": 0, "high": 0, "If": [0, 1], "take": [0, 1], "longer": 0, "establish": 0, "due": 0, "condit": 0, "short": 0, "might": 0, "reject": 0, "valid": [0, 1], "prematur": 0, "rate": 0, "expect": 0, "you": [0, 1], "want": 0, "process": 0, "them": 0, "quickli": 0, "benefici": 0, "howev": 0, "mean": 0, "need": 0, "handl": [0, 1], "rapidli": 0, "higher": 0, "repeat": 0, "check": 0, "consum": 0, "cpu": 0, "ensur": 0, "capac": 0, "frequent": 0, "custom": [0, 1], "The": [0, 1], "dn": [0, 1], "ar": 0, "long": [0, 1], "messi": 0, "To": 0, "avoid": 0, "A": [0, 1], "record": [0, 1], "warn": [0, 1], "requir": [0, 1], "activ": 0, "bulb": 0, "hosted_zon": [0, 1], "internet": 0, "chain": 0, "pem": [0, 1], "format": 0, "current": 0, "work": [0, 1], "directori": 0, "key_fil": [0, 1], "cert_fil": [0, 1], "var": 0, "No": 0, "cert": [0, 1], "problem": 0, "gener": [0, 1], "automat": [0, 1], "some": 0, "browser": 0, "throw": 0, "even": 0, "block": [0, 1], "ca": [0, 1], "manual": [0, 1], "openssl": [0, 1], "req": 0, "newkei": 0, "rsa": [0, 1], "2048": [0, 1], "sha256": 0, "node": 0, "keyout": 0, "x509": [0, 1], "dai": 0, "365": 0, "out": 0, "subj": 0, "c": 0, "st": 0, "new": [0, 1], "york": [0, 1], "l": 0, "brooklyn": 0, "compani": 0, "cn": 0, "verifi": 0, "inform": [0, 1], "noout": [0, 1], "text": [0, 1], "python3": 0, "m": 0, "pip": 0, "import": 0, "env_fil": [0, 1], "instanti": [0, 1], "object": [0, 1], "start": [0, 1], "set": [0, 1], "purg": [0, 1], "true": 0, "reclaim": 0, "fail": [0, 1], "stop": [0, 1], "delet": [0, 1], "all": [0, 1], "acquir": [0, 1], "troubleshoot": 0, "e": 0, "could": 0, "get": [0, 1], "lock": [0, 1], "lib": 0, "dpkg": 0, "frontend": 0, "occur": 0, "dure": [0, 1], "startup": [0, 1], "simpli": 0, "rerun": 0, "script": 0, "command": [0, 1], "thi": [0, 1], "when": [0, 1], "apt": 0, "hasn": 0, "t": [0, 1], "yet": 0, "retri": 0, "logic": 0, "place": 0, "issu": [0, 1], "persist": 0, "re": [0, 1], "entir": 0, "limit": 0, "cannot": [0, 1], "multipl": [0, 1], "without": 0, "modifi": [0, 1], "follow": 0, "key_pair": [0, 1], "ssh": [0, 1], "filenam": [0, 1], "dump": [0, 1], "data": [0, 1], "security_group": [0, 1], "firewal": 0, "rule": 0, "control": 0, "traffic": [0, 1], "via": [0, 1], "vpc": [0, 1], "docstr": 0, "googl": 0, "style": 0, "convent": 0, "pep": 0, "8": 0, "clean": 0, "pre": [0, 1], "commit": 0, "hook": 0, "flake8": 0, "isort": 0, "python": 0, "gitvers": 0, "f": 0, "release_not": 0, "rst": 0, "precommit": 0, "doc": [0, 1], "creation": [0, 1], "everi": 0, "sphinx": 0, "5": 0, "1": 0, "recommonmark": 0, "http": [0, 1], "org": 0, "project": 0, "thevickypedia": 0, "github": 0, "io": [0, 1], "vignesh": 0, "rao": 0, "under": 0, "mit": 0, "setup": 1, "usag": 1, "code": 1, "standard": 1, "releas": 1, "note": 1, "lint": 1, "licens": 1, "copyright": 1, "class": 1, "tunnel": 1, "none": 1, "initi": 1, "spin": 1, "up": 1, "act": 1, "paramet": 1, "bring": 1, "own": 1, "init": 1, "bool": 1, "function": 1, "its": 1, "shutdown": 1, "create_key_pair": 1, "keypair": 1, "openssh": 1, "return": 1, "call": 1, "wa": 1, "get_vpc_id": 1, "str": 1, "fetch": 1, "union": 1, "authorize_security_group": 1, "security_group_id": 1, "public_ip": 1, "author": 1, "certain": 1, "securitygroup": 1, "argument": 1, "ip": 1, "22": 1, "onli": 1, "machin": 1, "cidr": 1, "notat": 1, "32": 1, "80": 1, "443": 1, "apart": 1, "abov": 1, "sg": 1, "request": 1, "forward": 1, "whether": 1, "successfulli": 1, "create_security_group": 1, "case": 1, "exist": 1, "same": 1, "alreadi": 1, "create_ec2_inst": 1, "tupl": 1, "success": 1, "delete_key_pair": 1, "disassociate_security_group": 1, "instance_id": 1, "disassoci": 1, "assign": 1, "unavail": 1, "delete_security_group": 1, "terminate_ec2_inst": 1, "serviceresourc": 1, "termin": 1, "nginx": 1, "refer": 1, "amazon": 1, "cli": 1, "latest": 1, "describ": 1, "statu": 1, "html": 1, "boto3": 1, "amazonaw": 1, "v1": 1, "document": 1, "wait_until_termin": 1, "server_copi": 1, "sourc": 1, "destin": 1, "write": 1, "within": 1, "get_config": 1, "download": 1, "string": 1, "config_requir": 1, "common_nam": 1, "custom_serv": 1, "san_list": 1, "list": 1, "dict": 1, "tri": 1, "dictionari": 1, "entri": 1, "subject": 1, "altern": 1, "configure_vm": 1, "public_dn": 1, "dispos": 1, "disabl": 1, "remov": 1, "doesn": 1, "neither": 1, "nor": 1, "hand": 1, "model": 1, "write_screen": 1, "screen": 1, "clear": 1, "later": 1, "written": 1, "flush_screen": 1, "flush": 1, "output": 1, "empti": 1, "size": 1, "ran": 1, "one": 1, "_get_seri": 1, "byte": 1, "serial": 1, "here": 1, "just": 1, "measur": 1, "insert": 1, "uniqu": 1, "identifi": 1, "encod": 1, "_generate_serial_hash": 1, "byte_s": 1, "int": 1, "18": 1, "int_siz": 1, "36": 1, "hash": 1, "contain": 1, "random": 1, "base": 1, "generate_cert": 1, "country_nam": 1, "locality_nam": 1, "springfield": 1, "state_or_province_nam": 1, "missouri": 1, "organization_unit_nam": 1, "technologi": 1, "key_siz": 1, "origin": 1, "countri": 1, "citi": 1, "state": 1, "provinc": 1, "unit": 1, "san": 1, "look": 1, "amibas": 1, "pydant": 1, "basemodel": 1, "valu": 1, "pars": 1, "input": 1, "keyword": 1, "rais": 1, "validationerror": 1, "pydantic_cor": 1, "form": 1, "__init__": 1, "__pydantic_self__": 1, "instead": 1, "common": 1, "first": 1, "arg": 1, "field": 1, "_base_url": 1, "modelprivateattr": 1, "marketplac": 1, "productid": 1, "_base_ssm": 1, "prod": 1, "path": 1, "product_pag": 1, "url": 1, "alia": 1, "product_cod": 1, "s_product_pag": 1, "s_name": 1, "s_alia": 1, "s_product_cod": 1, "model_post_init": 1, "__context": 1, "meant": 1, "behav": 1, "like": 1, "method": 1, "initialis": 1, "attribut": 1, "It": 1, "context": 1, "sinc": 1, "what": 1, "core": 1, "pass": 1, "envconfig": 1, "pydantic_set": 1, "baseset": 1, "dev": 1, "3": 1, "migrat": 1, "nullabl": 1, "open_port": 1, "image_id": 1, "instance_typ": 1, "aws_region_nam": 1, "aws_access_kei": 1, "aws_secret_kei": 1, "email_address": 1, "emailstr": 1, "extra": 1, "wrapper": 1, "interact": 1, "current_dir": 1, "ssh_home": 1, "key_pair_fil": 1, "entrypoint": 1, "nginx_config_command": 1, "notimplementedwarn": 1, "implement": 1, "duplicateresourc": 1, "error": 1, "duplic": 1, "awsresourceerror": 1, "status_cod": 1, "error_msg": 1, "image_factori": 1, "session": 1, "retriev": 1, "get_ami_id_ssm": 1, "get_ami_id_product_cod": 1, "product": 1, "get_ami_id_nam": 1, "get_image_id": 1, "sequenti": 1, "execut": 1, "sequenc": 1, "fastest": 1, "ssm": 1, "point": 1, "singl": 1, "possibli": 1, "lookup": 1, "mani": 1, "so": 1, "grab": 1, "most": 1, "recent": 1, "unabl": 1, "log": 1, "share": 1, "across": 1, "route_53": 1, "get_zone_id": 1, "client": 1, "miss": 1, "change_record_set": 1, "zone_id": 1, "action": 1, "chang": 1, "hostnam": 1, "perform": 1, "upsert": 1, "changeset": 1, "join": 1, "separ": 1, "squash": 1, "print_warn": 1, "print": 1, "messag": 1, "safeti": 1, "net": 1, "transport": 1, "until": 1, "usernam": 1, "30": 1, "intiat": 1, "given": 1, "remot": 1, "side": 1, "do": 1, "simpl": 1, "doe": 1, "through": 1, "sure": 1, "back": 1, "rsakei": 1, "authent": 1, "run_interactive_ssh": 1, "were": 1, "server_writ": 1, "dedic": 1, "ftp": 1, "content": 1, "_handler": 1, "socket": 1, "tcp": 1, "stop_tunnel": 1, "thread": 1, "daemon": 1, "initiate_tunnel": 1, "index": 1, "search": 1, "page": 1}, "objects": {"expose": [[1, 0, 0, "-", "main"]], "expose.main": [[1, 1, 1, "", "Tunnel"]], "expose.main.Tunnel": [[1, 2, 1, "", "authorize_security_group"], [1, 2, 1, "", "config_requirements"], [1, 2, 1, "", "configure_vm"], [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_config"], [1, 2, 1, "", "get_vpc_id"], [1, 2, 1, "", "init"], [1, 2, 1, "", "server_copy"], [1, 2, 1, "", "start"], [1, 2, 1, "", "stop"], [1, 2, 1, "", "terminate_ec2_instance"]], "expose.models": [[1, 0, 0, "-", "auxiliary"], [1, 0, 0, "-", "cert"], [1, 0, 0, "-", "exceptions"], [1, 0, 0, "-", "image_factory"], [1, 0, 0, "-", "logger"], [1, 0, 0, "-", "route_53"], [1, 0, 0, "-", "server"]], "expose.models.auxiliary": [[1, 3, 1, "", "flush_screen"], [1, 3, 1, "", "write_screen"]], "expose.models.cert": [[1, 3, 1, "", "_generate_serial_hash"], [1, 3, 1, "", "_get_serial"], [1, 3, 1, "", "generate_cert"]], "expose.models.config": [[1, 1, 1, "", "AMIBase"], [1, 1, 1, "", "EnvConfig"], [1, 1, 1, "", "Settings"]], "expose.models.config.AMIBase": [[1, 4, 1, "", "ALIAS"], [1, 4, 1, "", "NAME"], [1, 4, 1, "", "PRODUCT_CODE"], [1, 4, 1, "", "PRODUCT_PAGE"], [1, 4, 1, "", "S_ALIAS"], [1, 4, 1, "", "S_NAME"], [1, 4, 1, "", "S_PRODUCT_CODE"], [1, 4, 1, "", "S_PRODUCT_PAGE"], [1, 4, 1, "", "_BASE_SSM"], [1, 4, 1, "", "_BASE_URL"], [1, 2, 1, "", "model_post_init"]], "expose.models.config.EnvConfig": [[1, 1, 1, "", "Config"], [1, 4, 1, "", "aws_access_key"], [1, 4, 1, "", "aws_region_name"], [1, 4, 1, "", "aws_secret_key"], [1, 4, 1, "", "cert_file"], [1, 4, 1, "", "channel_timeout"], [1, 4, 1, "", "email_address"], [1, 4, 1, "", "hosted_zone"], [1, 4, 1, "", "image_id"], [1, 4, 1, "", "instance_type"], [1, 4, 1, "", "key_file"], [1, 4, 1, "", "key_pair"], [1, 4, 1, "", "open_port"], [1, 4, 1, "", "organization"], [1, 4, 1, "", "port"], [1, 4, 1, "", "security_group"], [1, 4, 1, "", "server_info"], [1, 4, 1, "", "subdomain"]], "expose.models.config.EnvConfig.Config": [[1, 4, 1, "", "env_file"], [1, 4, 1, "", "extra"]], "expose.models.config.Settings": [[1, 4, 1, "", "configuration"], [1, 4, 1, "", "current_dir"], [1, 4, 1, "", "entrypoint"], [1, 4, 1, "", "interactive"], [1, 4, 1, "", "key_pair_file"], [1, 4, 1, "", "nginx_config_commands"], [1, 4, 1, "", "ssh_home"]], "expose.models.exceptions": [[1, 5, 1, "", "AWSResourceError"], [1, 5, 1, "", "DuplicateResource"], [1, 5, 1, "", "NotImplementedWarning"]], "expose.models.image_factory": [[1, 1, 1, "", "ImageFactory"]], "expose.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"]], "expose.models.route_53": [[1, 3, 1, "", "change_record_set"], [1, 3, 1, "", "get_zone_id"]], "expose.models.server": [[1, 1, 1, "", "Server"], [1, 3, 1, "", "join"], [1, 3, 1, "", "print_warning"]], "expose.models.server.Server": [[1, 2, 1, "", "_handler"], [1, 2, 1, "", "initiate_tunnel"], [1, 2, 1, "", "run_interactive_ssh"], [1, 2, 1, "", "server_write"], [1, 2, 1, "", "stop_tunnel"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:function", "4": "py:attribute", "5": "py:exception"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "function", "Python function"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "exception", "Python exception"]}, "titleterms": {"expos": [0, 1], "localhost": [0, 1], "us": [0, 1], "ec2": [0, 1], "setup": 0, "environ": 0, "variabl": 0, "usag": 0, "instal": 0, "tunnel": 0, "code": 0, "standard": 0, "releas": 0, "note": 0, "lint": 0, "pypi": 0, "packag": 0, "runbook": 0, "licens": 0, "copyright": 0, "web": 1, "servic": 1, "public": 1, "internet": 1, "aw": 1, "read": 1, "me": 1, "main": 1, "modul": 1, "auxiliari": 1, "certif": 1, "configur": 1, "except": 1, "imagefactori": 1, "logger": 1, "route53": 1, "server": 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": ["Expose localhost using EC2", "Expose - Expose a web service on localhost to public internet using AWS EC2"], "terms": {"revers": [0, 1], "proxi": [0, 1], "creat": [0, 1], "secur": [0, 1], "from": [0, 1], "public": 0, "endpoint": 0, "local": [0, 1], "run": [0, 1], "web": 0, "servic": 0, "can": [0, 1], "load": [0, 1], "ani": [0, 1], "env": [0, 1], "file": [0, 1], "port": [0, 1], "number": [0, 1], "ha": [0, 1], "which": [0, 1], "app": [0, 1], "api": [0, 1], "i": [0, 1], "option": [0, 1], "open": 0, "_": 0, "boolean": [0, 1], "flag": [0, 1], "enabl": 0, "ingress": [0, 1], "egress": [0, 1], "specifi": [0, 1], "default": [0, 1], "fals": [0, 1], "channel": [0, 1], "timeout": [0, 1], "second": 0, "wait": 0, "an": [0, 1], "incom": 0, "connect": [0, 1], "100": 0, "imag": [0, 1], "id": [0, 1], "ami": [0, 1], "ubuntu": [0, 1], "o": 0, "region": 0, "specif": [0, 1], "instanc": [0, 1], "type": [0, 1], "t2": 0, "nano": 0, "aw": 0, "access": [0, 1], "kei": [0, 1], "resourc": [0, 1], "config": [0, 1], "secret": 0, "name": [0, 1], "where": 0, "should": [0, 1], "live": 0, "u": [0, 1], "west": 0, "2": [0, 1], "pair": [0, 1], "expose_localhost": 0, "group": [0, 1], "allow": [0, 1], "server": 0, "info": 0, "json": [0, 1], "store": [0, 1], "configur": 0, "server_info": [0, 1], "email": 0, "address": [0, 1], "self": [0, 1], "sign": [0, 1], "ssl": [0, 1], "privat": [0, 1], "user": 0, "com": [0, 1], "organ": [0, 1], "certif": 0, "host": [0, 1], "zone": [0, 1], "regist": [0, 1], "route53": 0, "exampl": [0, 1], "mywebsit": 0, "subdomain": [0, 1], "sub": 0, "domain": 0, "ad": [0, 1], "latenc": [0, 1], "channel_timeout": [0, 1], "adjust": 0, "improv": [0, 1], "depend": 0, "applic": 0, "": [0, 1], "role": 0, "network": 0, "shorter": 0, "make": [0, 1], "your": [0, 1], "more": [0, 1], "respons": [0, 1], "mai": 0, "also": 0, "lead": 0, "neg": 0, "high": 0, "If": [0, 1], "take": [0, 1], "longer": 0, "establish": 0, "due": 0, "condit": 0, "short": 0, "might": 0, "reject": 0, "valid": [0, 1], "prematur": 0, "rate": 0, "expect": 0, "you": [0, 1], "want": 0, "process": 0, "them": 0, "quickli": 0, "benefici": 0, "howev": 0, "mean": 0, "need": 0, "abl": 0, "rapidli": 0, "higher": 0, "repeat": 0, "check": 0, "consum": 0, "cpu": 0, "ensur": 0, "capac": 0, "handl": [0, 1], "frequent": 0, "ar": 0, "set": [0, 1], "too": 0, "low": 0, "custom": [0, 1], "The": [0, 1], "dn": [0, 1], "long": [0, 1], "messi": 0, "To": 0, "avoid": 0, "A": [0, 1], "record": [0, 1], "warn": [0, 1], "requir": [0, 1], "activ": 0, "bulb": 0, "hosted_zon": [0, 1], "internet": 0, "chain": 0, "pem": [0, 1], "format": 0, "current": 0, "work": [0, 1], "directori": 0, "key_fil": [0, 1], "cert_fil": [0, 1], "var": 0, "No": 0, "cert": [0, 1], "problem": 0, "gener": [0, 1], "automat": [0, 1], "some": 0, "browser": 0, "throw": 0, "even": 0, "block": [0, 1], "ca": [0, 1], "manual": [0, 1], "openssl": [0, 1], "req": 0, "newkei": 0, "rsa": [0, 1], "2048": [0, 1], "sha256": 0, "node": 0, "keyout": 0, "x509": [0, 1], "dai": 0, "365": 0, "out": 0, "subj": 0, "c": 0, "st": 0, "new": [0, 1], "york": [0, 1], "l": 0, "brooklyn": 0, "compani": 0, "cn": 0, "verifi": 0, "inform": [0, 1], "noout": [0, 1], "text": [0, 1], "python3": 0, "m": 0, "pip": 0, "import": 0, "env_fil": [0, 1], "instanti": [0, 1], "object": [0, 1], "start": [0, 1], "purg": [0, 1], "true": 0, "reclaim": 0, "fail": [0, 1], "stop": [0, 1], "delet": [0, 1], "all": [0, 1], "acquir": [0, 1], "troubleshoot": 0, "e": 0, "could": 0, "get": [0, 1], "lock": [0, 1], "lib": 0, "dpkg": 0, "frontend": 0, "occur": 0, "dure": [0, 1], "startup": [0, 1], "simpli": 0, "rerun": 0, "script": 0, "command": [0, 1], "thi": [0, 1], "when": [0, 1], "apt": 0, "hasn": 0, "t": [0, 1], "yet": 0, "retri": 0, "logic": 0, "place": 0, "issu": [0, 1], "persist": 0, "re": [0, 1], "entir": 0, "limit": 0, "cannot": [0, 1], "multipl": [0, 1], "without": 0, "modifi": [0, 1], "follow": 0, "key_pair": [0, 1], "ssh": [0, 1], "filenam": [0, 1], "dump": [0, 1], "data": [0, 1], "security_group": [0, 1], "firewal": 0, "rule": 0, "control": 0, "traffic": [0, 1], "via": [0, 1], "vpc": [0, 1], "docstr": 0, "googl": 0, "style": 0, "convent": 0, "pep": 0, "8": 0, "clean": 0, "pre": [0, 1], "commit": 0, "hook": 0, "flake8": 0, "isort": 0, "python": 0, "gitvers": 0, "f": 0, "release_not": 0, "rst": 0, "precommit": 0, "doc": [0, 1], "creation": [0, 1], "everi": 0, "sphinx": 0, "5": 0, "1": 0, "recommonmark": 0, "http": [0, 1], "org": 0, "project": 0, "thevickypedia": 0, "github": 0, "io": [0, 1], "vignesh": 0, "rao": 0, "under": 0, "mit": 0, "setup": 1, "usag": 1, "code": 1, "standard": 1, "releas": 1, "note": 1, "lint": 1, "licens": 1, "copyright": 1, "class": 1, "tunnel": 1, "none": 1, "initi": 1, "spin": 1, "up": 1, "act": 1, "paramet": 1, "bring": 1, "own": 1, "init": 1, "bool": 1, "function": 1, "its": 1, "shutdown": 1, "create_key_pair": 1, "keypair": 1, "openssh": 1, "return": 1, "call": 1, "wa": 1, "get_vpc_id": 1, "str": 1, "fetch": 1, "union": 1, "authorize_security_group": 1, "security_group_id": 1, "public_ip": 1, "author": 1, "certain": 1, "securitygroup": 1, "argument": 1, "ip": 1, "22": 1, "onli": 1, "machin": 1, "cidr": 1, "notat": 1, "32": 1, "80": 1, "443": 1, "apart": 1, "abov": 1, "sg": 1, "request": 1, "forward": 1, "whether": 1, "successfulli": 1, "create_security_group": 1, "case": 1, "exist": 1, "same": 1, "alreadi": 1, "create_ec2_inst": 1, "tupl": 1, "success": 1, "delete_key_pair": 1, "disassociate_security_group": 1, "instance_id": 1, "disassoci": 1, "assign": 1, "unavail": 1, "delete_security_group": 1, "terminate_ec2_inst": 1, "serviceresourc": 1, "termin": 1, "nginx": 1, "refer": 1, "amazon": 1, "cli": 1, "latest": 1, "describ": 1, "statu": 1, "html": 1, "boto3": 1, "amazonaw": 1, "v1": 1, "document": 1, "wait_until_termin": 1, "server_copi": 1, "sourc": 1, "destin": 1, "write": 1, "within": 1, "get_config": 1, "download": 1, "string": 1, "config_requir": 1, "common_nam": 1, "custom_serv": 1, "san_list": 1, "list": 1, "dict": 1, "tri": 1, "dictionari": 1, "entri": 1, "subject": 1, "altern": 1, "configure_vm": 1, "public_dn": 1, "dispos": 1, "disabl": 1, "remov": 1, "doesn": 1, "neither": 1, "nor": 1, "hand": 1, "model": 1, "write_screen": 1, "screen": 1, "clear": 1, "later": 1, "written": 1, "flush_screen": 1, "flush": 1, "output": 1, "empti": 1, "size": 1, "ran": 1, "one": 1, "_get_seri": 1, "byte": 1, "serial": 1, "here": 1, "just": 1, "measur": 1, "insert": 1, "uniqu": 1, "identifi": 1, "encod": 1, "_generate_serial_hash": 1, "byte_s": 1, "int": 1, "18": 1, "int_siz": 1, "36": 1, "hash": 1, "contain": 1, "random": 1, "base": 1, "generate_cert": 1, "country_nam": 1, "locality_nam": 1, "springfield": 1, "state_or_province_nam": 1, "missouri": 1, "organization_unit_nam": 1, "technologi": 1, "key_siz": 1, "origin": 1, "countri": 1, "citi": 1, "state": 1, "provinc": 1, "unit": 1, "san": 1, "look": 1, "amibas": 1, "pydant": 1, "basemodel": 1, "valu": 1, "pars": 1, "input": 1, "keyword": 1, "rais": 1, "validationerror": 1, "pydantic_cor": 1, "form": 1, "__init__": 1, "__pydantic_self__": 1, "instead": 1, "common": 1, "first": 1, "arg": 1, "field": 1, "_base_url": 1, "modelprivateattr": 1, "marketplac": 1, "productid": 1, "_base_ssm": 1, "prod": 1, "path": 1, "product_pag": 1, "url": 1, "alia": 1, "product_cod": 1, "s_product_pag": 1, "s_name": 1, "s_alia": 1, "s_product_cod": 1, "model_post_init": 1, "__context": 1, "meant": 1, "behav": 1, "like": 1, "method": 1, "initialis": 1, "attribut": 1, "It": 1, "context": 1, "sinc": 1, "what": 1, "core": 1, "pass": 1, "envconfig": 1, "pydantic_set": 1, "baseset": 1, "dev": 1, "3": 1, "migrat": 1, "nullabl": 1, "open_port": 1, "image_id": 1, "instance_typ": 1, "aws_region_nam": 1, "aws_access_kei": 1, "aws_secret_kei": 1, "email_address": 1, "emailstr": 1, "extra": 1, "wrapper": 1, "interact": 1, "current_dir": 1, "ssh_home": 1, "key_pair_fil": 1, "ami_deprec": 1, "entrypoint": 1, "nginx_config_command": 1, "notimplementedwarn": 1, "implement": 1, "duplicateresourc": 1, "error": 1, "duplic": 1, "awsresourceerror": 1, "status_cod": 1, "error_msg": 1, "image_factori": 1, "deprecation_warn": 1, "deprecation_tim": 1, "deprec": 1, "chosen": 1, "nearing": 1, "deprecationtim": 1, "session": 1, "retriev": 1, "get_ami_id_ssm": 1, "get_ami_id_product_cod": 1, "product": 1, "get_ami_id_nam": 1, "get_image_id": 1, "sequenti": 1, "execut": 1, "sequenc": 1, "fastest": 1, "ssm": 1, "point": 1, "singl": 1, "possibli": 1, "lookup": 1, "mani": 1, "so": 1, "grab": 1, "most": 1, "recent": 1, "unabl": 1, "log": 1, "share": 1, "across": 1, "route_53": 1, "get_zone_id": 1, "client": 1, "miss": 1, "change_record_set": 1, "zone_id": 1, "action": 1, "chang": 1, "hostnam": 1, "perform": 1, "upsert": 1, "changeset": 1, "join": 1, "separ": 1, "squash": 1, "print_warn": 1, "print": 1, "messag": 1, "safeti": 1, "net": 1, "transport": 1, "until": 1, "usernam": 1, "30": 1, "intiat": 1, "given": 1, "remot": 1, "side": 1, "do": 1, "simpl": 1, "doe": 1, "through": 1, "sure": 1, "back": 1, "rsakei": 1, "authent": 1, "run_interactive_ssh": 1, "were": 1, "server_writ": 1, "dedic": 1, "ftp": 1, "content": 1, "_handler": 1, "socket": 1, "tcp": 1, "stop_tunnel": 1, "thread": 1, "daemon": 1, "initiate_tunnel": 1, "index": 1, "search": 1, "page": 1}, "objects": {"expose": [[1, 0, 0, "-", "main"]], "expose.main": [[1, 1, 1, "", "Tunnel"]], "expose.main.Tunnel": [[1, 2, 1, "", "authorize_security_group"], [1, 2, 1, "", "config_requirements"], [1, 2, 1, "", "configure_vm"], [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_config"], [1, 2, 1, "", "get_vpc_id"], [1, 2, 1, "", "init"], [1, 2, 1, "", "server_copy"], [1, 2, 1, "", "start"], [1, 2, 1, "", "stop"], [1, 2, 1, "", "terminate_ec2_instance"]], "expose.models": [[1, 0, 0, "-", "auxiliary"], [1, 0, 0, "-", "cert"], [1, 0, 0, "-", "exceptions"], [1, 0, 0, "-", "image_factory"], [1, 0, 0, "-", "logger"], [1, 0, 0, "-", "route_53"], [1, 0, 0, "-", "server"]], "expose.models.auxiliary": [[1, 3, 1, "", "flush_screen"], [1, 3, 1, "", "write_screen"]], "expose.models.cert": [[1, 3, 1, "", "_generate_serial_hash"], [1, 3, 1, "", "_get_serial"], [1, 3, 1, "", "generate_cert"]], "expose.models.config": [[1, 1, 1, "", "AMIBase"], [1, 1, 1, "", "EnvConfig"], [1, 1, 1, "", "Settings"]], "expose.models.config.AMIBase": [[1, 4, 1, "", "ALIAS"], [1, 4, 1, "", "NAME"], [1, 4, 1, "", "PRODUCT_CODE"], [1, 4, 1, "", "PRODUCT_PAGE"], [1, 4, 1, "", "S_ALIAS"], [1, 4, 1, "", "S_NAME"], [1, 4, 1, "", "S_PRODUCT_CODE"], [1, 4, 1, "", "S_PRODUCT_PAGE"], [1, 4, 1, "", "_BASE_SSM"], [1, 4, 1, "", "_BASE_URL"], [1, 2, 1, "", "model_post_init"]], "expose.models.config.EnvConfig": [[1, 1, 1, "", "Config"], [1, 4, 1, "", "aws_access_key"], [1, 4, 1, "", "aws_region_name"], [1, 4, 1, "", "aws_secret_key"], [1, 4, 1, "", "cert_file"], [1, 4, 1, "", "channel_timeout"], [1, 4, 1, "", "email_address"], [1, 4, 1, "", "hosted_zone"], [1, 4, 1, "", "image_id"], [1, 4, 1, "", "instance_type"], [1, 4, 1, "", "key_file"], [1, 4, 1, "", "key_pair"], [1, 4, 1, "", "open_port"], [1, 4, 1, "", "organization"], [1, 4, 1, "", "port"], [1, 4, 1, "", "security_group"], [1, 4, 1, "", "server_info"], [1, 4, 1, "", "subdomain"]], "expose.models.config.EnvConfig.Config": [[1, 4, 1, "", "env_file"], [1, 4, 1, "", "extra"]], "expose.models.config.Settings": [[1, 4, 1, "", "ami_deprecation"], [1, 4, 1, "", "configuration"], [1, 4, 1, "", "current_dir"], [1, 4, 1, "", "entrypoint"], [1, 4, 1, "", "interactive"], [1, 4, 1, "", "key_pair_file"], [1, 4, 1, "", "nginx_config_commands"], [1, 4, 1, "", "ssh_home"]], "expose.models.exceptions": [[1, 5, 1, "", "AWSResourceError"], [1, 5, 1, "", "DuplicateResource"], [1, 5, 1, "", "NotImplementedWarning"]], "expose.models.image_factory": [[1, 1, 1, "", "ImageFactory"], [1, 3, 1, "", "deprecation_warning"]], "expose.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"]], "expose.models.route_53": [[1, 3, 1, "", "change_record_set"], [1, 3, 1, "", "get_zone_id"]], "expose.models.server": [[1, 1, 1, "", "Server"], [1, 3, 1, "", "join"], [1, 3, 1, "", "print_warning"]], "expose.models.server.Server": [[1, 2, 1, "", "_handler"], [1, 2, 1, "", "initiate_tunnel"], [1, 2, 1, "", "run_interactive_ssh"], [1, 2, 1, "", "server_write"], [1, 2, 1, "", "stop_tunnel"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:function", "4": "py:attribute", "5": "py:exception"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "function", "Python function"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "exception", "Python exception"]}, "titleterms": {"expos": [0, 1], "localhost": [0, 1], "us": [0, 1], "ec2": [0, 1], "setup": 0, "environ": 0, "variabl": 0, "usag": 0, "instal": 0, "tunnel": 0, "code": 0, "standard": 0, "releas": 0, "note": 0, "lint": 0, "pypi": 0, "packag": 0, "runbook": 0, "licens": 0, "copyright": 0, "web": 1, "servic": 1, "public": 1, "internet": 1, "aw": 1, "read": 1, "me": 1, "main": 1, "modul": 1, "auxiliari": 1, "certif": 1, "configur": 1, "except": 1, "imagefactori": 1, "logger": 1, "route53": 1, "server": 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/expose/__init__.py b/expose/__init__.py index bd3240a..c5caaf8 100644 --- a/expose/__init__.py +++ b/expose/__init__.py @@ -1,4 +1,4 @@ from expose.main import Tunnel # noqa: F401 from expose.models import config # noqa: F401 -version = "0.6.9a" +version = "0.7" diff --git a/expose/models/config.py b/expose/models/config.py index 7ffe3fc..dc623dd 100644 --- a/expose/models/config.py +++ b/expose/models/config.py @@ -92,6 +92,7 @@ class Settings(BaseModel): ssh_home: str = "/home/ubuntu" key_pair_file: FilePath = f"{env.key_pair}.pem" configuration: DirectoryPath = os.path.join(pathlib.Path(__file__).parent.parent, 'configuration') + ami_deprecation: int = 30 entrypoint: str = None if any((env.hosted_zone, env.subdomain)): assert all((env.hosted_zone, env.subdomain)), "'subdomain' and 'hosted_zone' must co-exist" diff --git a/expose/models/image_factory.py b/expose/models/image_factory.py index 2e2d527..1659905 100644 --- a/expose/models/image_factory.py +++ b/expose/models/image_factory.py @@ -1,13 +1,30 @@ import logging import operator +import warnings +from datetime import datetime, timezone import boto3 from botocore.exceptions import ClientError +from dateutil import parser -from expose.models.config import ami_base +from expose.models.config import ami_base, settings from expose.models.exceptions import AWSResourceError +def deprecation_warning(image_id: str, deprecation_time: str) -> None: + """Raises a deprecation warning if the chosen AMI is nearing (value is set in config) its DeprecationTime.""" + expired_utc = parser.parse(deprecation_time) + current_utc = datetime.utcnow().replace(tzinfo=timezone.utc) + if (expired_utc - current_utc).days < settings.ami_deprecation: + warnings.simplefilter('always', DeprecationWarning) + warnings.warn( + f"\nThe AMI ID {image_id} is set to be deprecated on {deprecation_time}" + "\nPlease raise an issue at https://github.com/thevickypedia/expose/issues/new " + "to update the AMI base", + DeprecationWarning + ) + + class ImageFactory: """Handles retrieving AMI ID from multiple sources. @@ -30,37 +47,47 @@ def __init__(self, session: boto3.Session, logger: logging.Logger): self.product_page = ami_base.PRODUCT_PAGE self.product_code = ami_base.PRODUCT_CODE + self.ssm_client = self.session.client('ssm') + self.ec2_client = self.session.client('ec2') + def get_ami_id_ssm(self) -> str: """Retrieve AMI ID using Ami Alias.""" - ssm_client = self.session.client('ssm') - response = ssm_client.get_parameters(Names=[self.alias], WithDecryption=True) + response = self.ssm_client.get_parameters(Names=[self.alias], WithDecryption=True) if response.get('ResponseMetadata', {}).get('HTTPStatusCode', 400) == 200: if params := response.get('Parameters'): self.logger.info("Images fetched using AMI alias: %d", len(params)) self.logger.debug(params) params.sort(key=operator.itemgetter('LastModifiedDate')) # Sort by last modified date - return params[-1].get('Value') # Get the most recent AMI ID + ami_id = params[-1].get('Value') # Get the most recent AMI ID + img_response = self.ec2_client.describe_images(ImageIds=[ami_id]) + if valid_until := img_response.get('Images', [{}])[0].get('DeprecationTime'): + deprecation_warning(ami_id, valid_until) + return ami_id def get_ami_id_product_code(self) -> str: """Retrieve AMI ID using Product Code.""" - ec2_client = self.session.client('ec2') filters = [{'Name': 'product-code', 'Values': [self.product_code]}] - response = ec2_client.describe_images(Filters=filters, Owners=['aws-marketplace']) + response = self.ec2_client.describe_images(Filters=filters, Owners=['aws-marketplace']) if images := response.get('Images'): self.logger.info("Images fetched using product code: %d", len(images)) self.logger.debug(images) images.sort(key=operator.itemgetter('CreationDate')) - return images[-1].get('ImageId') + image = images[-1] + if valid_until := image.get('DeprecationTime'): + deprecation_warning(image.get('ImageId'), valid_until) + return image.get('ImageId') def get_ami_id_name(self) -> str: """Retrieve AMI ID using Ami Name.""" - ec2_client = self.session.client('ec2') - response = ec2_client.describe_images(Filters=[{'Name': 'name', 'Values': [self.name]}]) + response = self.ec2_client.describe_images(Filters=[{'Name': 'name', 'Values': [self.name]}]) if images := response.get('Images'): self.logger.info("Images fetched using AMI name: %d", len(images)) self.logger.debug(images) images.sort(key=operator.itemgetter('CreationDate')) - return images[-1].get('ImageId') + image = images[-1] + if valid_until := image.get('DeprecationTime'): + deprecation_warning(image.get('ImageId'), valid_until) + return image.get('ImageId') def get_image_id(self) -> str: """Tries to get image id from multiple sources, sequentially. diff --git a/expose/models/server.py b/expose/models/server.py index 9fd34a2..abeb9ac 100644 --- a/expose/models/server.py +++ b/expose/models/server.py @@ -170,8 +170,9 @@ def stop_tunnel(self, transport: Transport, threads: List[Thread]) -> None: self.ssh_client.close() self.logger.info("Daemons launched: %d", len(threads)) for thread in threads: - self.logger.debug("Awaiting daemon service: %s", thread.ident or thread.native_id) - thread.join(timeout=0.5) + if thread.is_alive(): + self.logger.debug("Awaiting daemon service: %s", thread.ident or thread.native_id) + thread.join(timeout=0.5) def initiate_tunnel(self) -> None: """Initiates port forwarding using ``Transport`` which creates a channel.""" @@ -201,4 +202,11 @@ def initiate_tunnel(self) -> None: except KeyboardInterrupt: self.logger.info("Tunneling interrupted") finally: - self.stop_tunnel(transport, threads) + try: + self.stop_tunnel(transport, threads) + except KeyboardInterrupt: # If user is hasty to stop the process + if list(filter(lambda t: t.is_alive(), threads)): + # Raise a warning only if any of the threads are still running + raise UserWarning( + "Not all threads were awaited for completion, daemon threads might still run in the background." + ) diff --git a/release_notes.rst b/release_notes.rst index cf5eb48..e0c5e0d 100644 --- a/release_notes.rst +++ b/release_notes.rst @@ -1,6 +1,10 @@ Release Notes ============= +v0.6.9a (09/22/2023) +-------------------- +- Add pre-release before optimized stable version + v0.6.2a (09/20/2023) -------------------- - Folder restructure