diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..930d3ed --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# Dependabot: keep the pinned Python dependency and the CI actions patched. +# Required by the Wherobots Labs charter (automated dependency scanning). +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/aws-step-functions-python-sdk" + schedule: + interval: "weekly" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/aws-step-functions-python-sdk/README.md b/aws-step-functions-python-sdk/README.md index 617cdd4..134fd63 100644 --- a/aws-step-functions-python-sdk/README.md +++ b/aws-step-functions-python-sdk/README.md @@ -76,9 +76,9 @@ cd labs-reference-implementations/aws-step-functions-python-sdk ``` Use a virtual environment so the Wherobots SDK doesn't pollute your system -Python. `requirements.txt` holds the only local dependency -(`wherobots-python-sdk`, used by the upload step — the dashboard server is -stdlib-only, and the Lambdas install the SDK themselves from PyPI): +Python. `requirements.txt` holds the only dependency, pinned +(`wherobots-python-sdk`, used by the upload step and vendored into the +Lambda zips at deploy time — the dashboard server is stdlib-only): ```bash python3 -m venv .venv @@ -143,7 +143,7 @@ python3 scripts/01_upload_job.py # upload job/hello_wherobots_job.py, save s3: 3. The job runs `try: work; post success` / `except: post failure(traceback)`, with a daemon thread posting heartbeats every 60 s. `finally` only stops the heartbeat thread — never posts results. -4. **Happy path**: the success callback (`{building_count: 1084}`) becomes the +4. **Happy path**: the success callback (`{building_count: 1080}`) becomes the state output and **NextStep** runs immediately. **Soft failure**: the failure callback fails the task with the traceback as cause → `JobFailed`. **Hard death (OOM)**: heartbeats stop → `States.Timeout` after @@ -182,12 +182,35 @@ python3 scripts/01_upload_job.py # upload job/hello_wherobots_job.py, save s3: | `scripts/` | Numbered lifecycle scripts (the dashboard runs these) | | `dashboard/` | Local control-plane server + guided UI | +## Security model (read before exposing anything) + +- **The API key never sits in a Lambda env var.** The deploy stores it in + **Secrets Manager**; the Lambdas fetch it at cold start under a role that can + read exactly that one secret. Reading a function's configuration shows only + the secret's ARN. +- **Dependencies are pinned and vendored.** `requirements.txt` pins + `wherobots-python-sdk`, and the deploy vendors it into the Lambda zips — + no network installs at cold start, every instance runs the same code. +- **The callback relay is public by design, throttled, and capability-gated.** + The unguessable single-use task token is the auth; Step Functions rejects + anything else. The token travels as a plain job argument, so anyone who can + read that run's arguments in your Wherobots org (or your Step Functions + execution history) could post a forged callback for that one run — both + surfaces are already inside your trust boundary. The relay caps payload + size, returns generic errors (details go to CloudWatch), and the stage is + throttled (burst 10 / rate 5). For production add an authorizer or WAF. +- **Callback output is treated as untrusted.** The dashboard HTML-escapes + every server-sourced value before rendering it. +- **The dashboard only answers its own page.** Requests must carry a loopback + `Host` and (when present) a same-origin `Origin`; lifecycle scripts run only + via `POST` + `application/json`, so no other website can trigger a deploy, + teardown, or job run while the dashboard is up. + ## Production notes (deliberately out of scope here) -- Bake the SDK into a **Lambda layer** (`pip install wherobots-python-sdk -t python/ && zip -r layer.zip python`) instead of the cold-start pip install. -- Put `WHEROBOTS_API_KEY` in **Secrets Manager**, not a Lambda env var. - Use IaC (Terraform / CDK / SAM) instead of CLI scripts. - Add `Catch` + alerting states around Submit and Poll. +- Put an authorizer (API key / IAM) or WAF in front of the callback route. ## Cost diff --git a/aws-step-functions-python-sdk/dashboard/index.html b/aws-step-functions-python-sdk/dashboard/index.html index 34bb3e4..8a4aeff 100644 --- a/aws-step-functions-python-sdk/dashboard/index.html +++ b/aws-step-functions-python-sdk/dashboard/index.html @@ -7,8 +7,10 @@ - - + +