diff --git a/.gitignore b/.gitignore
index 5a1ca2c..72d5c48 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,10 +10,11 @@ PyNinja.egg-info/
doc_gen/_*
-temp.py
+temp*.py
logging.ini
*.log
*.db
+*.env
discard/
diff --git a/doc_gen/index.rst b/doc_gen/index.rst
index 8772128..bf91e65 100644
--- a/doc_gen/index.rst
+++ b/doc_gen/index.rst
@@ -47,7 +47,7 @@ Models
====
-.. automodule:: vaultapi.models.EnvConfig(BaseSettings)
+.. automodule:: vaultapi.models
:exclude-members: RateLimit, Session, EnvConfig
Payload
@@ -76,6 +76,11 @@ Squire
.. automodule:: vaultapi.squire
+Util
+====
+
+.. automodule:: vaultapi.util
+
Indices and tables
==================
diff --git a/docs/_sources/index.rst.txt b/docs/_sources/index.rst.txt
index 8772128..bf91e65 100644
--- a/docs/_sources/index.rst.txt
+++ b/docs/_sources/index.rst.txt
@@ -47,7 +47,7 @@ Models
====
-.. automodule:: vaultapi.models.EnvConfig(BaseSettings)
+.. automodule:: vaultapi.models
:exclude-members: RateLimit, Session, EnvConfig
Payload
@@ -76,6 +76,11 @@ Squire
.. automodule:: vaultapi.squire
+Util
+====
+
+.. automodule:: vaultapi.util
+
Indices and tables
==================
diff --git a/docs/genindex.html b/docs/genindex.html
index eb3508e..a97f144 100644
--- a/docs/genindex.html
+++ b/docs/genindex.html
@@ -88,16 +88,30 @@
A
C
D
@@ -115,6 +133,8 @@ E
enable_cors() (in module vaultapi.main)
endpoints (vaultapi.models.EnvConfig attribute)
+
+ env (in module vaultapi.models)
EnvConfig (class in vaultapi.models)
@@ -234,13 +254,15 @@ M
vaultapi.main
- vaultapi.models.EnvConfig(BaseSettings)
+ vaultapi.models
vaultapi.rate_limit
vaultapi.routes
vaultapi.squire
+
+ vaultapi.util
@@ -255,16 +277,18 @@ P
parse_endpoints() (vaultapi.models.EnvConfig class method)
-
- |
+ |
@@ -312,6 +336,10 @@ S
T
+ |
|
-
- vaultapi.models.EnvConfig(BaseSettings)
+ vaultapi.models
-
@@ -385,6 +413,13 @@
V
+ -
+ vaultapi.util
+
+
|
diff --git a/docs/index.html b/docs/index.html
index a07220a..e2528f3 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -123,6 +123,31 @@ Welcome to VaultAPI’s documentation!
diff --git a/docs/searchindex.js b/docs/searchindex.js
index 8acaf53..2a8d2b9 100644
--- a/docs/searchindex.js
+++ b/docs/searchindex.js
@@ -1 +1 @@
-Search.setIndex({"docnames": ["README", "index"], "filenames": ["README.md", "index.rst"], "titles": ["VaultAPI", "Welcome to VaultAPI\u2019s documentation!"], "terms": {"lightweight": 0, "api": 0, "store": [0, 1], "retriev": [0, 1], "secret": [0, 1], "from": [0, 1], "an": [0, 1], "encrypt": 0, "databas": 0, "platform": 0, "support": [0, 1], "deploy": 0, "recommend": 0, "instal": 0, "python": 0, "3": 0, "10": 0, "11": 0, "us": [0, 1], "dedic": 0, "virtual": 0, "m": 0, "pip": 0, "initi": 0, "id": 0, "import": 0, "__name__": 0, "__main__": 0, "start": [0, 1], "cli": 0, "help": 0, "usag": 0, "instruct": 0, "sourc": 0, "env": [0, 1], "file": [0, 1], "By": 0, "default": [0, 1], "look": 0, "current": 0, "work": 0, "directori": 0, "host": [0, 1], "hostnam": [0, 1], "server": [0, 1], "port": [0, 1], "number": [0, 1], "worker": [0, 1], "uvicorn": [0, 1], "apikei": [0, 1], "kei": [0, 1], "authent": 0, "access": [0, 1], "encod": 0, "decod": 0, "datastor": 0, "filepath": [0, 1], "rate": [0, 1], "_": 0, "limit": [0, 1], "list": [0, 1], "dictionari": [0, 1], "max_request": [0, 1], "second": [0, 1], "appli": [0, 1], "auto": 0, "gener": 0, "valu": [0, 1], "thi": [0, 1], "decrypt": 0, "keygen": 0, "cryptographi": [0, 1], "fernet": [0, 1], "print": 0, "generate_kei": 0, "docstr": 0, "format": [0, 1], "googl": 0, "style": 0, "convent": 0, "pep": 0, "8": 0, "isort": 0, "requir": [0, 1], "gitvers": 0, "revers": 0, "f": 0, "release_not": 0, "rst": 0, "t": 0, "pre": 0, "commit": 0, "ensur": 0, "run": 0, "pytest": 0, "valid": [0, 1], "hyperlink": 0, "all": [0, 1], "markdown": 0, "includ": 0, "wiki": 0, "page": [0, 1], "sphinx": 0, "5": 0, "1": 0, "recommonmark": 0, "http": 0, "org": 0, "project": 0, "thevickypedia": 0, "github": 0, "io": 0, "vignesh": 0, "rao": 0, "under": 0, "mit": 0, "kick": 1, "off": 1, "environ": 1, "variabl": 1, "code": 1, "standard": 1, "releas": 1, "note": 1, "lint": 1, "pypi": 1, "packag": 1, "runbook": 1, "licens": 1, "copyright": 1, "enable_cor": 1, "none": 1, "enabl": 1, "cor": 1, "polici": 1, "kwarg": 1, "starter": 1, "function": 1, "which": 1, "trigger": 1, "keyword": 1, "argument": 1, "env_fil": 1, "load": 1, "auth": 1, "handl": 1, "error": 1, "rate_limit": 1, "log_config": 1, "log": 1, "configur": 1, "dict": 1, "yaml": 1, "yml": 1, "json": 1, "ini": 1, "epoch": 1, "async": 1, "request": 1, "httpauthorizationcredenti": 1, "httpbearer": 1, "paramet": 1, "take": 1, "author": 1, "header": 1, "token": 1, "basic": 1, "rais": 1, "apirespons": 1, "401": 1, "If": 1, "i": 1, "invalid": 1, "403": 1, "address": 1, "forbidden": 1, "get_secret": 1, "str": 1, "table_nam": 1, "name": 1, "where": 1, "return": 1, "type": 1, "get_tabl": 1, "tupl": 1, "pair": 1, "particular": 1, "ar": 1, "put_secret": 1, "add": 1, "remove_secret": 1, "remov": 1, "status_cod": 1, "int": 1, "detail": 1, "ani": 1, "option": 1, "custom": 1, "httpexcept": 1, "fastapi": 1, "wrap": 1, "respons": 1, "class": 1, "basemodel": 1, "object": 1, "set": 1, "session": 1, "inform": 1, "info": 1, "rp": 1, "allowed_origin": 1, "config": 1, "allow": 1, "arbitrari": 1, "arbitrary_types_allow": 1, "true": 1, "envconfig": 1, "baseset": 1, "union": 1, "path": 1, "endpoint": 1, "url": 1, "classmethod": 1, "parse_endpoint": 1, "parse_apikei": 1, "pars": 1, "complex": 1, "parse_api_secret": 1, "from_env_fil": 1, "creat": 1, "instanc": 1, "extra": 1, "ignor": 1, "hide_input_in_error": 1, "deletesecret": 1, "delet": 1, "call": 1, "putsecret": 1, "put": 1, "implement": 1, "init": 1, "check": 1, "exce": 1, "given": 1, "identifi": 1, "The": 1, "incom": 1, "429": 1, "too": 1, "mani": 1, "retrieve_secret": 1, "exist": 1, "multipl": 1, "whole": 1, "have": 1, "depend": 1, "arg": 1, "refer": 1, "httpstatu": 1, "statu": 1, "time": 1, "comma": 1, "separ": 1, "data": 1, "bodi": 1, "delete_secret": 1, "create_t": 1, "new": 1, "health": 1, "healthcheck": 1, "doc": 1, "redirectrespons": 1, "redirect": 1, "user": 1, "get_all_rout": 1, "apirout": 1, "get": 1, "ad": 1, "envfile_load": 1, "filenam": 1, "o": 1, "pathlik": 1, "base": 1, "filetyp": 1, "var": 1, "load_env": 1, "merg": 1, "give": 1, "prioriti": 1, "partial": 1, "through": 1, "index": 1, "modul": 1, "search": 1}, "objects": {"vaultapi": [[1, 0, 0, "-", "auth"], [1, 0, 0, "-", "database"], [1, 0, 0, "-", "exceptions"], [1, 0, 0, "-", "main"], [1, 0, 0, "-", "rate_limit"], [1, 0, 0, "-", "routes"], [1, 0, 0, "-", "squire"]], "vaultapi.auth": [[1, 1, 1, "", "EPOCH"], [1, 1, 1, "", "validate"]], "vaultapi.database": [[1, 1, 1, "", "get_secret"], [1, 1, 1, "", "get_table"], [1, 1, 1, "", "put_secret"], [1, 1, 1, "", "remove_secret"]], "vaultapi.exceptions": [[1, 2, 1, "", "APIResponse"]], "vaultapi.main": [[1, 1, 1, "", "enable_cors"], [1, 1, 1, "", "start"]], "vaultapi.models": [[1, 3, 1, "", "EnvConfig"], [1, 0, 0, "module-vaultapi.models.EnvConfig-BaseSettings", "EnvConfig(BaseSettings)"], [1, 3, 1, "", "RateLimit"], [1, 3, 1, "", "Session"]], "vaultapi.models.EnvConfig": [[1, 3, 1, "", "Config"], [1, 4, 1, "", "allowed_origins"], [1, 4, 1, "", "apikey"], [1, 4, 1, "", "database"], [1, 4, 1, "", "endpoints"], [1, 5, 1, "", "from_env_file"], [1, 4, 1, "", "host"], [1, 4, 1, "", "log_config"], [1, 5, 1, "", "parse_api_secret"], [1, 5, 1, "", "parse_apikey"], [1, 5, 1, "", "parse_endpoints"], [1, 4, 1, "", "port"], [1, 4, 1, "", "rate_limit"], [1, 4, 1, "", "secret"], [1, 4, 1, "", "workers"]], "vaultapi.models.EnvConfig.Config": [[1, 4, 1, "", "arbitrary_types_allowed"], [1, 4, 1, "", "extra"], [1, 4, 1, "", "hide_input_in_errors"]], "vaultapi.models.RateLimit": [[1, 4, 1, "", "max_requests"], [1, 4, 1, "", "seconds"]], "vaultapi.models.Session": [[1, 3, 1, "", "Config"], [1, 4, 1, "", "allowed_origins"], [1, 4, 1, "", "fernet"], [1, 4, 1, "", "info"], [1, 4, 1, "", "rps"]], "vaultapi.models.Session.Config": [[1, 4, 1, "", "arbitrary_types_allowed"]], "vaultapi.payload": [[1, 3, 1, "", "DeleteSecret"], [1, 3, 1, "", "PutSecret"]], "vaultapi.payload.DeleteSecret": [[1, 4, 1, "", "key"], [1, 4, 1, "", "table_name"]], "vaultapi.payload.PutSecret": [[1, 4, 1, "", "key"], [1, 4, 1, "", "table_name"], [1, 4, 1, "", "value"]], "vaultapi.rate_limit": [[1, 3, 1, "", "RateLimiter"]], "vaultapi.rate_limit.RateLimiter": [[1, 5, 1, "", "init"]], "vaultapi.routes": [[1, 1, 1, "", "create_table"], [1, 1, 1, "", "delete_secret"], [1, 1, 1, "", "docs"], [1, 1, 1, "", "get_all_routes"], [1, 1, 1, "", "get_secret"], [1, 1, 1, "", "get_secrets"], [1, 1, 1, "", "get_table"], [1, 1, 1, "", "health"], [1, 1, 1, "", "put_secret"], [1, 1, 1, "", "retrieve_secret"], [1, 1, 1, "", "retrieve_secrets"]], "vaultapi.squire": [[1, 1, 1, "", "envfile_loader"], [1, 1, 1, "", "load_env"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:exception", "3": "py:class", "4": "py:attribute", "5": "py:method"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "exception", "Python exception"], "3": ["py", "class", "Python class"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "method", "Python method"]}, "titleterms": {"vaultapi": [0, 1], "kick": 0, "off": 0, "environ": 0, "variabl": 0, "code": 0, "standard": 0, "releas": 0, "note": 0, "lint": 0, "pypi": 0, "packag": 0, "runbook": 0, "licens": 0, "copyright": 0, "welcom": 1, "": 1, "document": 1, "content": 1, "main": 1, "authent": 1, "databas": 1, "except": 1, "model": 1, "payload": 1, "ratelimit": 1, "api": 1, "rout": 1, "squir": 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": ["VaultAPI", "Welcome to VaultAPI\u2019s documentation!"], "terms": {"lightweight": 0, "api": 0, "store": [0, 1], "retriev": [0, 1], "secret": [0, 1], "from": [0, 1], "an": [0, 1], "encrypt": 0, "databas": 0, "platform": 0, "support": [0, 1], "deploy": 0, "recommend": 0, "instal": 0, "python": 0, "3": 0, "10": [0, 1], "11": 0, "us": [0, 1], "dedic": 0, "virtual": 0, "m": 0, "pip": 0, "initi": 0, "id": 0, "import": 0, "__name__": 0, "__main__": 0, "start": [0, 1], "cli": 0, "help": 0, "usag": 0, "instruct": 0, "sourc": 0, "env": [0, 1], "file": [0, 1], "By": 0, "default": [0, 1], "look": 0, "current": 0, "work": 0, "directori": 0, "host": [0, 1], "hostnam": [0, 1], "server": [0, 1], "port": [0, 1], "number": [0, 1], "worker": [0, 1], "uvicorn": [0, 1], "apikei": [0, 1], "kei": [0, 1], "authent": 0, "access": [0, 1], "encod": 0, "decod": 0, "datastor": 0, "filepath": [0, 1], "rate": [0, 1], "_": 0, "limit": [0, 1], "list": [0, 1], "dictionari": [0, 1], "max_request": [0, 1], "second": [0, 1], "appli": [0, 1], "auto": 0, "gener": 0, "valu": [0, 1], "thi": [0, 1], "decrypt": 0, "keygen": 0, "cryptographi": [0, 1], "fernet": [0, 1], "print": 0, "generate_kei": 0, "docstr": 0, "format": [0, 1], "googl": 0, "style": 0, "convent": 0, "pep": 0, "8": 0, "isort": 0, "requir": [0, 1], "gitvers": 0, "revers": 0, "f": 0, "release_not": 0, "rst": 0, "t": 0, "pre": 0, "commit": 0, "ensur": 0, "run": 0, "pytest": 0, "valid": [0, 1], "hyperlink": 0, "all": [0, 1], "markdown": 0, "includ": 0, "wiki": 0, "page": [0, 1], "sphinx": 0, "5": 0, "1": [0, 1], "recommonmark": 0, "http": 0, "org": 0, "project": 0, "thevickypedia": 0, "github": 0, "io": 0, "vignesh": 0, "rao": 0, "under": 0, "mit": 0, "kick": 1, "off": 1, "environ": 1, "variabl": 1, "code": 1, "standard": 1, "releas": 1, "note": 1, "lint": 1, "pypi": 1, "packag": 1, "runbook": 1, "licens": 1, "copyright": 1, "enable_cor": 1, "none": 1, "enabl": 1, "cor": 1, "polici": 1, "kwarg": 1, "starter": 1, "function": 1, "which": 1, "trigger": 1, "keyword": 1, "argument": 1, "env_fil": 1, "load": 1, "auth": 1, "handl": 1, "error": 1, "rate_limit": 1, "log_config": 1, "log": 1, "configur": 1, "dict": 1, "yaml": 1, "yml": 1, "json": 1, "ini": 1, "epoch": 1, "async": 1, "request": 1, "httpauthorizationcredenti": 1, "httpbearer": 1, "paramet": 1, "take": 1, "author": 1, "header": 1, "token": 1, "basic": 1, "rais": 1, "apirespons": 1, "401": 1, "If": 1, "i": 1, "invalid": 1, "403": 1, "address": 1, "forbidden": 1, "table_exist": 1, "table_nam": 1, "str": 1, "bool": 1, "check": 1, "exist": 1, "name": 1, "create_t": 1, "column": 1, "union": 1, "tupl": 1, "creat": 1, "ha": 1, "get_secret": 1, "where": 1, "return": 1, "type": 1, "get_tabl": 1, "pair": 1, "particular": 1, "ar": 1, "put_secret": 1, "add": 1, "remove_secret": 1, "remov": 1, "drop_tabl": 1, "drop": 1, "status_cod": 1, "int": 1, "detail": 1, "ani": 1, "option": 1, "custom": 1, "httpexcept": 1, "fastapi": 1, "wrap": 1, "respons": 1, "class": 1, "basemodel": 1, "object": 1, "set": 1, "session": 1, "inform": 1, "info": 1, "rp": 1, "allowed_origin": 1, "config": 1, "allow": 1, "arbitrari": 1, "arbitrary_types_allow": 1, "true": 1, "envconfig": 1, "baseset": 1, "path": 1, "endpoint": 1, "url": 1, "classmethod": 1, "parse_endpoint": 1, "parse_apikei": 1, "pars": 1, "complex": 1, "parse_api_secret": 1, "from_env_fil": 1, "instanc": 1, "extra": 1, "ignor": 1, "hide_input_in_error": 1, "complexity_check": 1, "simpl": 1, "fals": 1, "verifi": 1, "strength": 1, "boolean": 1, "flag": 1, "increas": 1, "A": 1, "consid": 1, "strong": 1, "least": 1, "32": 1, "charact": 1, "digit": 1, "symbol": 1, "uppercas": 1, "letter": 1, "lowercas": 1, "assertionerror": 1, "when": 1, "abov": 1, "condit": 1, "fail": 1, "match": 1, "timeout": 1, "connect": 1, "instanti": 1, "cursor": 1, "alia": 1, "deletesecret": 1, "delet": 1, "call": 1, "putsecret": 1, "put": 1, "implement": 1, "init": 1, "exce": 1, "given": 1, "identifi": 1, "The": 1, "incom": 1, "429": 1, "too": 1, "mani": 1, "retrieve_secret": 1, "multipl": 1, "whole": 1, "have": 1, "depend": 1, "arg": 1, "refer": 1, "httpstatu": 1, "statu": 1, "time": 1, "comma": 1, "separ": 1, "data": 1, "bodi": 1, "delete_secret": 1, "new": 1, "health": 1, "healthcheck": 1, "doc": 1, "redirectrespons": 1, "redirect": 1, "user": 1, "get_all_rout": 1, "apirout": 1, "get": 1, "ad": 1, "envfile_load": 1, "filenam": 1, "o": 1, "pathlik": 1, "base": 1, "filetyp": 1, "var": 1, "load_env": 1, "merg": 1, "give": 1, "prioriti": 1, "partial": 1, "through": 1, "dotenv_to_t": 1, "dotenv_fil": 1, "drop_exist": 1, "dot": 1, "index": 1, "modul": 1, "search": 1}, "objects": {"vaultapi": [[1, 0, 0, "-", "auth"], [1, 0, 0, "-", "database"], [1, 0, 0, "-", "exceptions"], [1, 0, 0, "-", "main"], [1, 0, 0, "-", "models"], [1, 0, 0, "-", "rate_limit"], [1, 0, 0, "-", "routes"], [1, 0, 0, "-", "squire"], [1, 0, 0, "-", "util"]], "vaultapi.auth": [[1, 1, 1, "", "EPOCH"], [1, 1, 1, "", "validate"]], "vaultapi.database": [[1, 1, 1, "", "create_table"], [1, 1, 1, "", "drop_table"], [1, 1, 1, "", "get_secret"], [1, 1, 1, "", "get_table"], [1, 1, 1, "", "put_secret"], [1, 1, 1, "", "remove_secret"], [1, 1, 1, "", "table_exists"]], "vaultapi.exceptions": [[1, 2, 1, "", "APIResponse"]], "vaultapi.main": [[1, 1, 1, "", "enable_cors"], [1, 1, 1, "", "start"]], "vaultapi.models": [[1, 3, 1, "", "Database"], [1, 3, 1, "", "EnvConfig"], [1, 3, 1, "", "RateLimit"], [1, 3, 1, "", "Session"], [1, 1, 1, "", "complexity_checker"], [1, 4, 1, "", "database"], [1, 4, 1, "", "env"]], "vaultapi.models.EnvConfig": [[1, 3, 1, "", "Config"], [1, 4, 1, "", "allowed_origins"], [1, 4, 1, "", "apikey"], [1, 4, 1, "", "database"], [1, 4, 1, "", "endpoints"], [1, 5, 1, "", "from_env_file"], [1, 4, 1, "", "host"], [1, 4, 1, "", "log_config"], [1, 5, 1, "", "parse_api_secret"], [1, 5, 1, "", "parse_apikey"], [1, 5, 1, "", "parse_endpoints"], [1, 4, 1, "", "port"], [1, 4, 1, "", "rate_limit"], [1, 4, 1, "", "secret"], [1, 4, 1, "", "workers"]], "vaultapi.models.EnvConfig.Config": [[1, 4, 1, "", "arbitrary_types_allowed"], [1, 4, 1, "", "extra"], [1, 4, 1, "", "hide_input_in_errors"]], "vaultapi.models.RateLimit": [[1, 4, 1, "", "max_requests"], [1, 4, 1, "", "seconds"]], "vaultapi.models.Session": [[1, 3, 1, "", "Config"], [1, 4, 1, "", "allowed_origins"], [1, 4, 1, "", "fernet"], [1, 4, 1, "", "info"], [1, 4, 1, "", "rps"]], "vaultapi.models.Session.Config": [[1, 4, 1, "", "arbitrary_types_allowed"]], "vaultapi.payload": [[1, 3, 1, "", "DeleteSecret"], [1, 3, 1, "", "PutSecret"]], "vaultapi.payload.DeleteSecret": [[1, 4, 1, "", "key"], [1, 4, 1, "", "table_name"]], "vaultapi.payload.PutSecret": [[1, 4, 1, "", "key"], [1, 4, 1, "", "table_name"], [1, 4, 1, "", "value"]], "vaultapi.rate_limit": [[1, 3, 1, "", "RateLimiter"]], "vaultapi.rate_limit.RateLimiter": [[1, 5, 1, "", "init"]], "vaultapi.routes": [[1, 1, 1, "", "create_table"], [1, 1, 1, "", "delete_secret"], [1, 1, 1, "", "docs"], [1, 1, 1, "", "get_all_routes"], [1, 1, 1, "", "get_secret"], [1, 1, 1, "", "get_secrets"], [1, 1, 1, "", "get_table"], [1, 1, 1, "", "health"], [1, 1, 1, "", "put_secret"], [1, 1, 1, "", "put_secrets"], [1, 1, 1, "", "retrieve_secret"], [1, 1, 1, "", "retrieve_secrets"]], "vaultapi.squire": [[1, 1, 1, "", "envfile_loader"], [1, 1, 1, "", "load_env"]], "vaultapi.util": [[1, 1, 1, "", "dotenv_to_table"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:exception", "3": "py:class", "4": "py:attribute", "5": "py:method"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "exception", "Python exception"], "3": ["py", "class", "Python class"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "method", "Python method"]}, "titleterms": {"vaultapi": [0, 1], "kick": 0, "off": 0, "environ": 0, "variabl": 0, "code": 0, "standard": 0, "releas": 0, "note": 0, "lint": 0, "pypi": 0, "packag": 0, "runbook": 0, "licens": 0, "copyright": 0, "welcom": 1, "": 1, "document": 1, "content": 1, "main": 1, "authent": 1, "databas": 1, "except": 1, "model": 1, "payload": 1, "ratelimit": 1, "api": 1, "rout": 1, "squir": 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/vaultapi/database.py b/vaultapi/database.py
index 84f0b67..05ac841 100644
--- a/vaultapi/database.py
+++ b/vaultapi/database.py
@@ -3,6 +3,38 @@
from . import models
+def table_exists(table_name: str) -> bool:
+ """Function to check if a table exists in the database.
+
+ Args:
+ table_name: Name of the table to check.
+ """
+ with models.database.connection:
+ cursor = models.database.connection.cursor()
+ cursor.execute(
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=?",
+ (table_name,),
+ )
+ result = cursor.fetchone()
+ if result:
+ return True
+
+
+def create_table(table_name: str, columns: List[str] | Tuple[str]) -> None:
+ """Creates the table with the required columns.
+
+ Args:
+ table_name: Name of the table that has to be created.
+ columns: List of columns that has to be created.
+ """
+ with models.database.connection:
+ cursor = models.database.connection.cursor()
+ # Use f-string or %s as table names cannot be parametrized
+ cursor.execute(
+ f"CREATE TABLE IF NOT EXISTS {table_name!r} ({', '.join(columns)})"
+ )
+
+
def get_secret(key: str, table_name: str) -> str | None:
"""Function to retrieve secret from database.
@@ -67,3 +99,15 @@ def remove_secret(key: str, table_name: str) -> None:
cursor = models.database.connection.cursor()
cursor.execute(f'DELETE FROM "{table_name}" WHERE key=(?)', (key,))
models.database.connection.commit()
+
+
+def drop_table(table_name: str) -> None:
+ """Function to drop a table from the database.
+
+ Args:
+ table_name: Name of the table to be dropped.
+ """
+ with models.database.connection:
+ cursor = models.database.connection.cursor()
+ cursor.execute(f'DROP TABLE IF EXISTS "{table_name}"')
+ models.database.connection.commit()
diff --git a/vaultapi/main.py b/vaultapi/main.py
index 9d6719a..13bd4fd 100644
--- a/vaultapi/main.py
+++ b/vaultapi/main.py
@@ -6,7 +6,7 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
-from . import models, routes, squire, version
+from . import database, models, routes, squire, version
LOGGER = logging.getLogger("uvicorn.default")
VaultAPI = FastAPI(
@@ -16,6 +16,13 @@
)
+def __init__(**kwargs) -> None:
+ """Instantiates the env, session and database connections."""
+ models.env = squire.load_env(**kwargs)
+ models.session.fernet = Fernet(models.env.secret)
+ models.database = models.Database(models.env.database)
+
+
def enable_cors() -> None:
"""Enables CORS policy."""
LOGGER.info("Setting CORS policy")
@@ -24,9 +31,8 @@ def enable_cors() -> None:
"https://localhost.com",
]
for website in models.env.endpoints:
- origins.extend(
- [f"http://{website.host}", f"https://{website.host}"]
- ) # noqa: HttpUrlsUsage
+ origins.append(f"http://{website.host}") # noqa: HttpUrlsUsage
+ origins.append(f"https://{website.host}")
VaultAPI.add_middleware(
CORSMiddleware, # noqa: PyTypeChecker
allow_origins=origins,
@@ -55,10 +61,8 @@ def start(**kwargs) -> None:
rate_limit: List of dictionaries with ``max_requests`` and ``seconds`` to apply as rate limit.
log_config: Logging configuration as a dict or a FilePath. Supports .yaml/.yml, .json or .ini formats.
"""
- models.env = squire.load_env(**kwargs)
- models.session.fernet = Fernet(models.env.secret)
- models.database = models.Database(models.env.database)
- models.database.create_table("default", ["key", "value"])
+ __init__(**kwargs)
+ database.create_table("default", ["key", "value"])
module_name = pathlib.Path(__file__)
enable_cors()
VaultAPI.routes.extend(routes.get_all_routes())
diff --git a/vaultapi/models.py b/vaultapi/models.py
index d784b98..8ffa3f6 100644
--- a/vaultapi/models.py
+++ b/vaultapi/models.py
@@ -2,7 +2,7 @@
import re
import socket
import sqlite3
-from typing import Any, Dict, List, Set, Tuple
+from typing import Any, Dict, List, Set
from cryptography.fernet import Fernet
from pydantic import (
@@ -83,20 +83,6 @@ def __init__(self, filepath: FilePath | str, timeout: int = 10):
database=filepath, check_same_thread=False, timeout=timeout
)
- def create_table(self, table_name: str, columns: List[str] | Tuple[str]) -> None:
- """Creates the table with the required columns.
-
- Args:
- table_name: Name of the table that has to be created.
- columns: List of columns that has to be created.
- """
- with self.connection:
- cursor = self.connection.cursor()
- # Use f-string or %s as table names cannot be parametrized
- cursor.execute(
- f"CREATE TABLE IF NOT EXISTS {table_name!r} ({', '.join(columns)})"
- )
-
database: Database = Database # noqa: PyTypeChecker
@@ -150,8 +136,8 @@ class EnvConfig(BaseSettings):
@field_validator("endpoints", mode="after", check_fields=True)
def parse_endpoints(
- cls, value: HttpUrl | List[HttpUrl]
- ) -> List[HttpUrl]: # noqa: PyMethodParameters
+ cls, value: HttpUrl | List[HttpUrl] # noqa: PyMethodParameters
+ ) -> List[HttpUrl]:
"""Validate endpoints to enable CORS policy."""
if isinstance(value, list):
return value
@@ -169,8 +155,8 @@ def parse_apikey(cls, value: str | None) -> str | None: # noqa: PyMethodParamet
@field_validator("secret", mode="after")
def parse_api_secret(
- cls, value: str | None
- ) -> str | None: # noqa: PyMethodParameters
+ cls, value: str | None # noqa: PyMethodParameters
+ ) -> str | None:
"""Parse API secret to validate complexity."""
if value:
try:
diff --git a/vaultapi/payload.py b/vaultapi/payload.py
index a233a51..c0945f6 100644
--- a/vaultapi/payload.py
+++ b/vaultapi/payload.py
@@ -1,3 +1,5 @@
+from typing import Dict
+
from pydantic import BaseModel
@@ -15,10 +17,21 @@ class DeleteSecret(BaseModel):
class PutSecret(BaseModel):
"""Payload for put-secret API call.
- >>> DeleteSecret
+ >>> PutSecret
"""
key: str
value: str
table_name: str = "default"
+
+
+class PutSecrets(BaseModel):
+ """Payload for put-secrets API call.
+
+ >>> PutSecret
+
+ """
+
+ secrets: Dict[str, str]
+ table_name: str = "default"
diff --git a/vaultapi/routes.py b/vaultapi/routes.py
index 846fadf..df60a34 100644
--- a/vaultapi/routes.py
+++ b/vaultapi/routes.py
@@ -213,6 +213,33 @@ async def put_secret(
)
+async def put_secrets(
+ request: Request,
+ data: payload.PutSecrets,
+ apikey: HTTPAuthorizationCredentials = Depends(security),
+):
+ """**API function to add multiple secrets to a table in the database.**
+
+ **Args:**
+
+ request: Reference to the FastAPI request object.
+ data: Payload with ``key``, ``value``, and ``table_name`` as body.
+ apikey: API Key to authenticate the request.
+
+ **Raises:**
+
+ APIResponse:
+ Raises the HTTPStatus object with a status code and detail as response.
+ """
+ await auth.validate(request, apikey)
+ for key, value in data.secrets.items():
+ encrypted = models.session.fernet.encrypt(value.encode(encoding="UTF-8"))
+ database.put_secret(key=key, value=encrypted, table_name=data.table_name)
+ raise exceptions.APIResponse(
+ status_code=HTTPStatus.OK.real, detail=HTTPStatus.OK.phrase
+ )
+
+
async def delete_secret(
request: Request,
data: payload.DeleteSecret,
@@ -265,7 +292,7 @@ async def create_table(
"""
await auth.validate(request, apikey)
try:
- models.database.create_table(table_name, ["key", "value"])
+ database.create_table(table_name, ["key", "value"])
except sqlite3.OperationalError as error:
LOGGER.error(error)
raise exceptions.APIResponse(
diff --git a/vaultapi/util.py b/vaultapi/util.py
new file mode 100644
index 0000000..1f039e6
--- /dev/null
+++ b/vaultapi/util.py
@@ -0,0 +1,54 @@
+import importlib
+import logging
+import sqlite3
+
+from dotenv import dotenv_values
+
+from . import database, main, models
+
+importlib.reload(logging)
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+HANDLER = logging.StreamHandler()
+DEFAULT_FORMATTER = logging.Formatter(
+ datefmt="%b-%d-%Y %I:%M:%S %p",
+ fmt="%(asctime)s - %(levelname)s - [%(module)s:%(lineno)d] - %(funcName)s - %(message)s",
+)
+HANDLER.setFormatter(DEFAULT_FORMATTER)
+LOGGER.addHandler(HANDLER)
+
+
+def dotenv_to_table(
+ table_name: str, dotenv_file: str, drop_existing: bool = False, **kwargs
+) -> None:
+ """Store all the env vars from a .env file into the database.
+
+ Args:
+ table_name: Name of the table to store secrets.
+ dotenv_file: Dot env filename.
+ drop_existing: Boolean flag to drop existing table.
+ """
+ main.__init__(**kwargs)
+ if drop_existing:
+ LOGGER.info("Dropping table '%s' if available", table_name)
+ database.drop_table(table_name)
+ database.create_table(table_name, ["key", "value"])
+ else:
+ try:
+ if existing := database.get_table(table_name):
+ LOGGER.warning(
+ "Table '%s' exists already. %d secrets will be overwritten",
+ table_name,
+ len(existing),
+ )
+ except sqlite3.OperationalError as error:
+ if str(error) == f"no such table: {table_name}":
+ LOGGER.info("Creating a new table %s", table_name)
+ database.create_table(table_name, ["key", "value"])
+ else:
+ raise
+ env_vars = dotenv_values(dotenv_file)
+ for key, value in env_vars.items():
+ encrypted = models.session.fernet.encrypt(value.encode(encoding="UTF-8"))
+ database.put_secret(key, encrypted, table_name)
+ LOGGER.info("%d secrets have been stored to the database.", len(env_vars))