Source code for openpois.io.credentials
# -------------------------------------------------------------
# Copyright (c) Henry Spatial Analysis. All rights reserved.
# Licensed under the MIT License. See LICENSE in project root for information.
# -------------------------------------------------------------
"""
Load Source Cooperative temporary AWS credentials from a local .env.json file.
Source Coop credentials are short-lived (issued via the dashboard and scoped to
a single repository prefix). The file format is the JSON payload shown in the
Source Coop UI — four keys:
{
"aws_access_key_id": "ASIA...",
"aws_secret_access_key": "...",
"aws_session_token": "...",
"region_name": "us-west-2"
}
If the file has not been touched recently we warn the caller (but do not fail);
STS tokens typically last an hour or so.
"""
from __future__ import annotations
import json
import time
from pathlib import Path
REQUIRED_KEYS = (
"aws_access_key_id",
"aws_secret_access_key",
"aws_session_token",
"region_name",
)
REFRESH_HINT = (
"Regenerate temporary credentials at "
"https://source.coop/repositories/henryspatialanalysis/openpois/manage "
"and write them to .env.json at the repo root."
)
STALE_SECONDS = 60 * 60 # Source Coop tokens usually last ~1 hour.
[docs]
def load_source_coop_credentials(env_file: Path | str | None = None) -> dict:
"""Read Source Coop temporary AWS credentials from ``.env.json``.
``env_file`` defaults to ``~/repos/openpois/.env.json``.
Raises ``FileNotFoundError`` or ``ValueError`` with a refresh hint if the
file is missing or malformed. Prints a warning if the file's mtime is
older than ~1 hour (tokens may have expired).
"""
if env_file is None:
env_file = Path.home() / "repos" / "openpois" / ".env.json"
env_file = Path(env_file).expanduser()
if not env_file.exists():
raise FileNotFoundError(
f"Source Coop credentials file not found at {env_file}. "
f"{REFRESH_HINT}"
)
with env_file.open() as f:
creds = json.load(f)
missing = [k for k in REQUIRED_KEYS if k not in creds]
if missing:
raise ValueError(
f"Source Coop credentials file {env_file} is missing keys: "
f"{missing}. {REFRESH_HINT}"
)
mtime_age = time.time() - env_file.stat().st_mtime
if mtime_age > STALE_SECONDS:
minutes = int(mtime_age // 60)
print(
f"⚠️ {env_file} was last updated ~{minutes} minutes ago. "
"Source Coop tokens usually expire within an hour — if uploads "
f"fail with ExpiredToken, {REFRESH_HINT}"
)
return {k: creds[k] for k in REQUIRED_KEYS}