Improve Dynu env handling and document secrets/dynu.env
This commit is contained in:
@@ -24,6 +24,18 @@ This repository includes a **read-only** Dynu DNS inventory workflow for `lan.dd
|
|||||||
- `DYNU_BASE_URL` (optional, defaults to `https://api.dynu.com`)
|
- `DYNU_BASE_URL` (optional, defaults to `https://api.dynu.com`)
|
||||||
- `DYNU_READ_ONLY` (**must** be `true`)
|
- `DYNU_READ_ONLY` (**must** be `true`)
|
||||||
|
|
||||||
|
Recommended local secrets file (not committed): `secrets/dynu.env`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DYNU_API_KEY=replace-with-real-api-key
|
||||||
|
DYNU_READ_ONLY=true
|
||||||
|
DYNU_BASE_URL=https://api.dynu.com
|
||||||
|
```
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- Keep values unquoted unless required by your shell.
|
||||||
|
- `scripts/dynu/build_dns_inventory.sh` will auto-load `secrets/dynu.env` when present.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
Run directly:
|
Run directly:
|
||||||
@@ -36,7 +48,7 @@ DYNU_READ_ONLY=true python3 scripts/dynu/correlate_dynu_with_traefik.py
|
|||||||
Or run the wrapper:
|
Or run the wrapper:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
DYNU_READ_ONLY=true DYNU_API_KEY=... scripts/dynu/build_dns_inventory.sh
|
scripts/dynu/build_dns_inventory.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Artifacts
|
## Artifacts
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ For machine-readable inventory metadata, use [`../secrets/inventory.json`](../se
|
|||||||
|
|
||||||
- Canonical example template: [`../secrets/.env.secrets.example`](../secrets/.env.secrets.example)
|
- Canonical example template: [`../secrets/.env.secrets.example`](../secrets/.env.secrets.example)
|
||||||
- Runtime-loaded secret env file (local, non-committed): `../secrets/stack-secrets.env`
|
- Runtime-loaded secret env file (local, non-committed): `../secrets/stack-secrets.env`
|
||||||
|
- Dynu DNS inventory env file (local, non-committed): `../secrets/dynu.env`
|
||||||
- Docker secret files (local, non-committed): `../secrets/*.txt`
|
- Docker secret files (local, non-committed): `../secrets/*.txt`
|
||||||
|
|
||||||
Treat the example template as the canonical shape for expected environment variables.
|
Treat the example template as the canonical shape for expected environment variables.
|
||||||
@@ -20,9 +21,11 @@ Treat the example template as the canonical shape for expected environment varia
|
|||||||
- Document expected variable names and usage expectations.
|
- Document expected variable names and usage expectations.
|
||||||
2. **Local runtime env file (`stack-secrets.env`)**
|
2. **Local runtime env file (`stack-secrets.env`)**
|
||||||
- Holds local runtime secret values loaded during compose rendering.
|
- Holds local runtime secret values loaded during compose rendering.
|
||||||
3. **Local Docker secret files (`*.txt`)**
|
3. **Local Dynu env file (`dynu.env`)**
|
||||||
|
- Holds `DYNU_*` values used by read-only Dynu DNS inventory scripts.
|
||||||
|
4. **Local Docker secret files (`*.txt`)**
|
||||||
- Hold password/token material consumed via `*_FILE` style configuration.
|
- Hold password/token material consumed via `*_FILE` style configuration.
|
||||||
4. **Externally managed secret inputs**
|
5. **Externally managed secret inputs**
|
||||||
- Some values are managed outside shared templates and provided through file mounts or environment substitution.
|
- Some values are managed outside shared templates and provided through file mounts or environment substitution.
|
||||||
|
|
||||||
## Machine-readable inventory
|
## Machine-readable inventory
|
||||||
@@ -41,6 +44,7 @@ Before running compose operations, follow [`./deployment-prerequisites.md`](./de
|
|||||||
Never commit:
|
Never commit:
|
||||||
|
|
||||||
- `secrets/stack-secrets.env`
|
- `secrets/stack-secrets.env`
|
||||||
|
- `secrets/dynu.env`
|
||||||
- real `secrets/*.txt` secret files
|
- real `secrets/*.txt` secret files
|
||||||
- real Terraform `.tfvars` files containing credentials
|
- real Terraform `.tfvars` files containing credentials
|
||||||
- Terraform state files with sensitive runtime metadata
|
- Terraform state files with sensitive runtime metadata
|
||||||
|
|||||||
@@ -4,10 +4,23 @@ set -euo pipefail
|
|||||||
# This integration is intentionally read-only.
|
# This integration is intentionally read-only.
|
||||||
# No Dynu mutations are permitted in this repo at this stage.
|
# No Dynu mutations are permitted in this repo at this stage.
|
||||||
|
|
||||||
|
# Optional convenience: auto-load local Dynu env file when variables are unset.
|
||||||
|
if [[ -f "secrets/dynu.env" ]]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "secrets/dynu.env"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "${DYNU_READ_ONLY:-}" != "true" ]]; then
|
if [[ "${DYNU_READ_ONLY:-}" != "true" ]]; then
|
||||||
echo "Refusing to run: DYNU_READ_ONLY must be exactly 'true'." >&2
|
echo "Refusing to run: DYNU_READ_ONLY must be exactly 'true'." >&2
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${DYNU_API_KEY:-}" ]]; then
|
||||||
|
echo "Missing DYNU_API_KEY. Set it in env or secrets/dynu.env." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
python3 scripts/dynu/fetch_dynu_dns.py
|
python3 scripts/dynu/fetch_dynu_dns.py
|
||||||
python3 scripts/dynu/correlate_dynu_with_traefik.py
|
python3 scripts/dynu/correlate_dynu_with_traefik.py
|
||||||
|
|||||||
@@ -54,7 +54,13 @@ def get_json(base_url: str, api_key: str, path: str, query: Optional[Dict[str, A
|
|||||||
body = resp.read().decode("utf-8")
|
body = resp.read().decode("utf-8")
|
||||||
except HTTPError as exc:
|
except HTTPError as exc:
|
||||||
detail = exc.read().decode("utf-8", errors="replace")
|
detail = exc.read().decode("utf-8", errors="replace")
|
||||||
raise RuntimeError(f"Dynu API GET failed at {path}: HTTP {exc.code} {detail}") from exc
|
hint = ""
|
||||||
|
if exc.code == 401:
|
||||||
|
hint = (
|
||||||
|
" Check DYNU_API_KEY from secrets/dynu.env, verify it is a valid Dynu API key, "
|
||||||
|
"and ensure DYNU_BASE_URL points to the Dynu API endpoint."
|
||||||
|
)
|
||||||
|
raise RuntimeError(f"Dynu API GET failed at {path}: HTTP {exc.code} {detail}.{hint}") from exc
|
||||||
except URLError as exc:
|
except URLError as exc:
|
||||||
raise RuntimeError(f"Dynu API GET failed at {path}: {exc}") from exc
|
raise RuntimeError(f"Dynu API GET failed at {path}: {exc}") from exc
|
||||||
|
|
||||||
@@ -177,8 +183,12 @@ def main() -> int:
|
|||||||
if not api_key:
|
if not api_key:
|
||||||
print("Missing DYNU_API_KEY. Refusing to call Dynu API.", file=sys.stderr)
|
print("Missing DYNU_API_KEY. Refusing to call Dynu API.", file=sys.stderr)
|
||||||
return 2
|
return 2
|
||||||
|
api_key = api_key.strip().strip("'").strip('"')
|
||||||
|
if not api_key:
|
||||||
|
print("DYNU_API_KEY is empty after trimming quotes/whitespace.", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
base_url = os.environ.get("DYNU_BASE_URL", DEFAULT_BASE_URL)
|
base_url = os.environ.get("DYNU_BASE_URL", DEFAULT_BASE_URL).strip().strip("'").strip('"')
|
||||||
|
|
||||||
domains = list_domains(base_url, api_key)
|
domains = list_domains(base_url, api_key)
|
||||||
target = [d for d in domains if str(d.get("name", "")).strip(".").lower() == BASE_DOMAIN]
|
target = [d for d in domains if str(d.get("name", "")).strip(".").lower() == BASE_DOMAIN]
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"scope_and_authority": {
|
"scope_and_authority": {
|
||||||
"canonical_example_template": "secrets/.env.secrets.example",
|
"canonical_example_template": "secrets/.env.secrets.example",
|
||||||
"runtime_loaded_secret_env_file": "secrets/stack-secrets.env",
|
"runtime_loaded_secret_env_file": "secrets/stack-secrets.env",
|
||||||
|
"dns_inventory_secret_env_file": "secrets/dynu.env",
|
||||||
"docker_secret_files_pattern": "secrets/*.txt"
|
"docker_secret_files_pattern": "secrets/*.txt"
|
||||||
},
|
},
|
||||||
"env_template_variables": [
|
"env_template_variables": [
|
||||||
@@ -140,6 +141,7 @@
|
|||||||
],
|
],
|
||||||
"commit_safety_rules": [
|
"commit_safety_rules": [
|
||||||
"Never commit secrets/stack-secrets.env.",
|
"Never commit secrets/stack-secrets.env.",
|
||||||
|
"Never commit secrets/dynu.env.",
|
||||||
"Never commit real secrets/*.txt files.",
|
"Never commit real secrets/*.txt files.",
|
||||||
"Never commit real Terraform .tfvars containing credentials.",
|
"Never commit real Terraform .tfvars containing credentials.",
|
||||||
"Never commit Terraform state files with sensitive runtime metadata."
|
"Never commit Terraform state files with sensitive runtime metadata."
|
||||||
|
|||||||
Reference in New Issue
Block a user