lambdavault 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lambdavault-0.1.0/PKG-INFO +41 -0
- lambdavault-0.1.0/README.md +20 -0
- lambdavault-0.1.0/lambdavault/__init__.py +4 -0
- lambdavault-0.1.0/lambdavault/__main__.py +3 -0
- lambdavault-0.1.0/lambdavault/cli.py +87 -0
- lambdavault-0.1.0/lambdavault.egg-info/PKG-INFO +41 -0
- lambdavault-0.1.0/lambdavault.egg-info/SOURCES.txt +10 -0
- lambdavault-0.1.0/lambdavault.egg-info/dependency_links.txt +1 -0
- lambdavault-0.1.0/lambdavault.egg-info/entry_points.txt +2 -0
- lambdavault-0.1.0/lambdavault.egg-info/top_level.txt +1 -0
- lambdavault-0.1.0/pyproject.toml +35 -0
- lambdavault-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lambdavault
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: HashiCorp Vault on AWS Lambda + S3 + KMS, ≈ $0 when idle. The vault CLI, hvac and the Terraform vault provider talk to it unchanged; this package is the helper: status, output.
|
|
5
|
+
Author: Frank Zhang
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/cloudformer/lambdavault
|
|
8
|
+
Project-URL: Repository, https://github.com/cloudformer/lambdavault
|
|
9
|
+
Project-URL: Deploy, https://github.com/cloudformer/lambdavault#quick-start
|
|
10
|
+
Project-URL: Compatibility, https://github.com/cloudformer/lambdavault/blob/main/tests/compat/REPORT.md
|
|
11
|
+
Project-URL: Changelog, https://github.com/cloudformer/lambdavault/blob/main/CHANGELOG.md
|
|
12
|
+
Project-URL: Issues, https://github.com/cloudformer/lambdavault/issues
|
|
13
|
+
Keywords: serverless,aws,lambda,vault,hashicorp-vault,secrets,kms
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Topic :: Security
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# lambdavault
|
|
23
|
+
|
|
24
|
+
**HashiCorp Vault, truly serverless: the official Vault binary on AWS Lambda, data in S3, auto-unseal by KMS,
|
|
25
|
+
≈ $1 a month when idle.** Part of [Redefine AWS Serverless](https://github.com/topics/redefine-aws-serverless).
|
|
26
|
+
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+
The vault CLI, hvac and the Terraform vault provider are the clients — unchanged, only `VAULT_ADDR` points at
|
|
30
|
+
the Lambda. This package is the helper around a deployment:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install lambdavault
|
|
34
|
+
lambdavault status # initialized / sealed / version / latency (address from terraform output)
|
|
35
|
+
eval "$(lambdavault output)" # export VAULT_ADDR for the vault CLI
|
|
36
|
+
vault operator init -recovery-shares=1 -recovery-threshold=1 # once
|
|
37
|
+
vault kv get kvv2/app
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Deploy the server from the [main repository](https://github.com/cloudformer/lambdavault) with Terraform.
|
|
41
|
+
Compatibility with a normal Vault: [REPORT.md](https://github.com/cloudformer/lambdavault/blob/main/tests/compat/REPORT.md).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# lambdavault
|
|
2
|
+
|
|
3
|
+
**HashiCorp Vault, truly serverless: the official Vault binary on AWS Lambda, data in S3, auto-unseal by KMS,
|
|
4
|
+
≈ $1 a month when idle.** Part of [Redefine AWS Serverless](https://github.com/topics/redefine-aws-serverless).
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
The vault CLI, hvac and the Terraform vault provider are the clients — unchanged, only `VAULT_ADDR` points at
|
|
9
|
+
the Lambda. This package is the helper around a deployment:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install lambdavault
|
|
13
|
+
lambdavault status # initialized / sealed / version / latency (address from terraform output)
|
|
14
|
+
eval "$(lambdavault output)" # export VAULT_ADDR for the vault CLI
|
|
15
|
+
vault operator init -recovery-shares=1 -recovery-threshold=1 # once
|
|
16
|
+
vault kv get kvv2/app
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Deploy the server from the [main repository](https://github.com/cloudformer/lambdavault) with Terraform.
|
|
20
|
+
Compatibility with a normal Vault: [REPORT.md](https://github.com/cloudformer/lambdavault/blob/main/tests/compat/REPORT.md).
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""lambdavault: the helper around a deployment. Day-to-day work (and `vault operator init`) is the vault CLI.
|
|
2
|
+
|
|
3
|
+
lambdavault output export VAULT_ADDR=...: eval "$(lambdavault output)"
|
|
4
|
+
lambdavault status is it up: initialized / sealed / version, and how long one call took
|
|
5
|
+
|
|
6
|
+
The address comes from the deployment's local Terraform state (`terraform -chdir=terraform output -json`, run
|
|
7
|
+
from the repo root), or from --addr / $VAULT_ADDR. Nothing is stored anywhere else.
|
|
8
|
+
"""
|
|
9
|
+
import argparse
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
import subprocess
|
|
13
|
+
import sys
|
|
14
|
+
import time
|
|
15
|
+
import urllib.error
|
|
16
|
+
import urllib.request
|
|
17
|
+
|
|
18
|
+
from . import __version__
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def address(args):
|
|
22
|
+
if args.addr:
|
|
23
|
+
return args.addr.rstrip("/")
|
|
24
|
+
try:
|
|
25
|
+
r = subprocess.run(["terraform", f"-chdir={args.dir}", "output", "-json"], capture_output=True, text=True)
|
|
26
|
+
except FileNotFoundError:
|
|
27
|
+
r = None
|
|
28
|
+
if r is None or r.returncode:
|
|
29
|
+
sys.exit(f"no address: run from the repo root after terraform apply, or give --addr / VAULT_ADDR "
|
|
30
|
+
f"({(r.stderr.strip()[:200] if r else 'terraform not found')})")
|
|
31
|
+
out = json.loads(r.stdout or "{}")
|
|
32
|
+
if "vault_addr" not in out:
|
|
33
|
+
sys.exit(f"terraform output in {args.dir} has no vault_addr: deploy first (terraform -chdir={args.dir} apply)")
|
|
34
|
+
return out["vault_addr"]["value"]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def call(addr, path, tries=5):
|
|
38
|
+
"""GET one Vault API path. A cold start can take seconds and a busy function answers 429: wait and retry."""
|
|
39
|
+
for attempt in range(tries):
|
|
40
|
+
try:
|
|
41
|
+
with urllib.request.urlopen(addr + path, timeout=60) as r:
|
|
42
|
+
return r.status, json.loads(r.read() or b"{}")
|
|
43
|
+
except urllib.error.HTTPError as e:
|
|
44
|
+
if e.code in (429, 502, 503) and attempt < tries - 1:
|
|
45
|
+
time.sleep(1 + attempt)
|
|
46
|
+
continue
|
|
47
|
+
raw = e.read()
|
|
48
|
+
try:
|
|
49
|
+
return e.code, json.loads(raw)
|
|
50
|
+
except ValueError:
|
|
51
|
+
return e.code, {"errors": [raw.decode(errors="replace")[:200]]}
|
|
52
|
+
raise AssertionError("unreachable")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def cmd_status(args):
|
|
56
|
+
addr = address(args)
|
|
57
|
+
t0 = time.time()
|
|
58
|
+
status, health = call(addr, "/v1/sys/health?uninitcode=200&sealedcode=200")
|
|
59
|
+
ms = (time.time() - t0) * 1000
|
|
60
|
+
if status != 200:
|
|
61
|
+
sys.exit(f"{addr} answered {status}: {health}")
|
|
62
|
+
print(f"{addr}\n"
|
|
63
|
+
f" initialized {health.get('initialized')} · sealed {health.get('sealed')} · Vault {health.get('version')}\n"
|
|
64
|
+
f" one call: {ms:.0f} ms (seconds after idle = a cold start) · UI: {addr}/ui/")
|
|
65
|
+
if not health.get("initialized"):
|
|
66
|
+
print(f"next: VAULT_ADDR={addr} vault operator init -recovery-shares=1 -recovery-threshold=1")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def cmd_output(args):
|
|
70
|
+
print(f"export VAULT_ADDR={address(args)}")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def main(argv=None):
|
|
74
|
+
p = argparse.ArgumentParser(prog="lambdavault", description=__doc__.split("\n\n")[0])
|
|
75
|
+
p.add_argument("--version", action="version", version=f"lambdavault {__version__}")
|
|
76
|
+
common = argparse.ArgumentParser(add_help=False)
|
|
77
|
+
common.add_argument("--dir", default="terraform", help="the Terraform directory (default terraform, from the repo root)")
|
|
78
|
+
common.add_argument("--addr", default=os.environ.get("VAULT_ADDR"), help="the Vault address instead of terraform output")
|
|
79
|
+
sub = p.add_subparsers(dest="command", required=True)
|
|
80
|
+
sub.add_parser("output", parents=[common], help="print export VAULT_ADDR=... (eval it)").set_defaults(func=cmd_output)
|
|
81
|
+
sub.add_parser("status", parents=[common], help="initialized / sealed / version / latency").set_defaults(func=cmd_status)
|
|
82
|
+
args = p.parse_args(argv)
|
|
83
|
+
args.func(args)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if __name__ == "__main__":
|
|
87
|
+
main()
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lambdavault
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: HashiCorp Vault on AWS Lambda + S3 + KMS, ≈ $0 when idle. The vault CLI, hvac and the Terraform vault provider talk to it unchanged; this package is the helper: status, output.
|
|
5
|
+
Author: Frank Zhang
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/cloudformer/lambdavault
|
|
8
|
+
Project-URL: Repository, https://github.com/cloudformer/lambdavault
|
|
9
|
+
Project-URL: Deploy, https://github.com/cloudformer/lambdavault#quick-start
|
|
10
|
+
Project-URL: Compatibility, https://github.com/cloudformer/lambdavault/blob/main/tests/compat/REPORT.md
|
|
11
|
+
Project-URL: Changelog, https://github.com/cloudformer/lambdavault/blob/main/CHANGELOG.md
|
|
12
|
+
Project-URL: Issues, https://github.com/cloudformer/lambdavault/issues
|
|
13
|
+
Keywords: serverless,aws,lambda,vault,hashicorp-vault,secrets,kms
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Topic :: Security
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# lambdavault
|
|
23
|
+
|
|
24
|
+
**HashiCorp Vault, truly serverless: the official Vault binary on AWS Lambda, data in S3, auto-unseal by KMS,
|
|
25
|
+
≈ $1 a month when idle.** Part of [Redefine AWS Serverless](https://github.com/topics/redefine-aws-serverless).
|
|
26
|
+
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+
The vault CLI, hvac and the Terraform vault provider are the clients — unchanged, only `VAULT_ADDR` points at
|
|
30
|
+
the Lambda. This package is the helper around a deployment:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install lambdavault
|
|
34
|
+
lambdavault status # initialized / sealed / version / latency (address from terraform output)
|
|
35
|
+
eval "$(lambdavault output)" # export VAULT_ADDR for the vault CLI
|
|
36
|
+
vault operator init -recovery-shares=1 -recovery-threshold=1 # once
|
|
37
|
+
vault kv get kvv2/app
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Deploy the server from the [main repository](https://github.com/cloudformer/lambdavault) with Terraform.
|
|
41
|
+
Compatibility with a normal Vault: [REPORT.md](https://github.com/cloudformer/lambdavault/blob/main/tests/compat/REPORT.md).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
lambdavault/__init__.py
|
|
4
|
+
lambdavault/__main__.py
|
|
5
|
+
lambdavault/cli.py
|
|
6
|
+
lambdavault.egg-info/PKG-INFO
|
|
7
|
+
lambdavault.egg-info/SOURCES.txt
|
|
8
|
+
lambdavault.egg-info/dependency_links.txt
|
|
9
|
+
lambdavault.egg-info/entry_points.txt
|
|
10
|
+
lambdavault.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
lambdavault
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "lambdavault"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "HashiCorp Vault on AWS Lambda + S3 + KMS, ≈ $0 when idle. The vault CLI, hvac and the Terraform vault provider talk to it unchanged; this package is the helper: status, output."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Frank Zhang" }]
|
|
13
|
+
keywords = ["serverless", "aws", "lambda", "vault", "hashicorp-vault", "secrets", "kms"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Security",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [] # standard library only
|
|
22
|
+
|
|
23
|
+
[project.scripts]
|
|
24
|
+
lambdavault = "lambdavault.cli:main"
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://github.com/cloudformer/lambdavault"
|
|
28
|
+
Repository = "https://github.com/cloudformer/lambdavault"
|
|
29
|
+
Deploy = "https://github.com/cloudformer/lambdavault#quick-start"
|
|
30
|
+
Compatibility = "https://github.com/cloudformer/lambdavault/blob/main/tests/compat/REPORT.md"
|
|
31
|
+
Changelog = "https://github.com/cloudformer/lambdavault/blob/main/CHANGELOG.md"
|
|
32
|
+
Issues = "https://github.com/cloudformer/lambdavault/issues"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools]
|
|
35
|
+
packages = ["lambdavault"]
|