diff --git a/README.md b/README.md index b272c0d..abaf3dd 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ The document will go over all the Github Actions that currently automate a coupl * [Push templates to review firm (push_to_review_firm.yml)](#push-templates-to-review-firm-push_to_review_firmyml) * [Liquid sampler](#liquid-sampler) * [Run liquid sampler (run_sampler.yml)](#run-liquid-sampler-run_sampleryml) + * [Authorizing a partner for staging (scripts/authorize-partner-secret.sh)](#authorizing-a-partner-for-staging-scriptsauthorize-partner-secretsh) ## Overview @@ -284,4 +285,60 @@ _Prerequisites:_ * `SF_API_CLIENT_ID`, `SF_API_SECRET`, `PARTNER_CONFIG_JSON` (per-partner secret resolved by the caller) and `REPO_ACCESS_TOKEN` (repo-scoped write PAT, for the token write-back) available to the caller. * `SF_BASIC_AUTH` if the partner's host is a `*.staging.getsilverfin.com` gateway. -* The partner must already be authorized with the Silverfin CLI (`silverfin authorize-partner`) and its `config.json` stored as the `PARTNER_CONFIG_JSON_` secret. \ No newline at end of file +* The partner must already be authorized with the Silverfin CLI (`silverfin authorize-partner`) and its `config.json` stored as the `PARTNER_CONFIG_JSON_` secret. + +#### Authorizing a partner for staging (`scripts/authorize-partner-secret.sh`) + +_Description:_ +One-off setup script that authorizes a partner `api_key` against staging and stores the result as that partner's `PARTNER_CONFIG_JSON_` GitHub secret — the secret [`run_sampler.yml`](#run-liquid-sampler-run_sampleryml) reads from. Run this once per partner, and again any time a partner's staging token is lost for good (see _When you need to re-run this_ below) — day-to-day token rotation during sampler runs is handled automatically by the workflow itself and does **not** need this script. + +_Prerequisites:_ + +* `silverfin` CLI installed and on `PATH`. +* `gh` CLI installed and authenticated (`gh auth login`), with write access to the target market repo's secrets. +* A fresh partner `api_key`, obtained via the staging login flow below. Get this **right before** running the script — the token is shown once, in a banner, and you paste it straight into the prompt. + +_Getting the partner `api_key` (staging login flow):_ + +By default your browser is logged into production (`https://live.getsilverfin.com`). To fetch a staging partner token: + +1. In your browser, change the URL from `https://live.getsilverfin.com` to `https://bso-staging-beta.staging.getsilverfin.com`. +2. A basic-auth popup appears — log in with the **"Silverfin staging basic-auth"** credentials from 1Password. (This is the staging gateway's basic auth, not your Silverfin login.) +3. Adjust the URL again to `https://bso-staging-beta.staging.getsilverfin.com/partners`. +4. Log in with your normal partner credentials for the specific partner id you want to authorize. +5. In that partner env, click **"Configuration partners"** in the header. +6. Click the red **"Refresh API token"** button. +7. A banner appears with the token — copy it. Then immediately run the script (below) and paste the token when it prompts for the api key. +8. **Repeat steps 3–7 for every partner env** you need to authorize — each partner has its own login and its own token. + +_Usage:_ + +```bash +./scripts/authorize-partner-secret.sh [host] +``` + +* `` — numeric partner environment id, e.g. `2`. +* `` — either a short code (`nl`, `be`, `lu`, `uk`, mapped to `silverfin/_market` in the script's `MARKET_REPOS` table) or a full `owner/repo`. +* `[host]` — optional. Defaults to `https://bso-staging-beta.staging.getsilverfin.com` (the same staging beta host used in the login flow above). Pass an explicit URL to target a different environment, or edit the `HOST` default in the script if you're permanently moving to a new environment. + +Examples: + +```bash +./scripts/authorize-partner-secret.sh 2 nl +./scripts/authorize-partner-secret.sh 11 lu +./scripts/authorize-partner-secret.sh 1 silverfin/be_market +./scripts/authorize-partner-secret.sh 2 nl https://some-other-staging-host.example.com +``` + +_What it does:_ + +* Prompts for the api key (hidden input). +* Creates a throwaway `HOME` directory so the authorization doesn't touch your real `~/.silverfin/config.json`. +* Runs `silverfin config --set-host ` and `silverfin authorize-partner -i -k -n partner-` inside that throwaway `HOME`. +* Pushes the resulting `config.json` straight to the `PARTNER_CONFIG_JSON_` secret on the target repo via `gh secret set`. +* Deletes the throwaway `HOME` on exit (success or failure), via a `trap`. + +_When you need to re-run this:_ + +* **Not needed for normal 401s.** A partner token that's simply gone stale (>24h old) self-heals — the sampler workflow's own refresh call authenticates on a digest match, not the token's age, so it mints a fresh token automatically mid-run and writes it back itself. +* **Re-run this script only after a staging DB snapshot/reset**, which overwrites the partner's stored credentials server-side — that invalidates any token you're holding client-side, including the refresh path, so the sampler workflow's automatic 401 recovery also fails. Signature: a partner token fails on first use *and* on the workflow's automatic refresh attempt in the same run. Get a backend/console regeneration of the partner's api_key first, then re-run this script with the new key. \ No newline at end of file diff --git a/scripts/authorize-partner-secret.sh b/scripts/authorize-partner-secret.sh new file mode 100755 index 0000000..8526633 --- /dev/null +++ b/scripts/authorize-partner-secret.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# Authorize a Silverfin partner api_key against an isolated throwaway HOME, +# then push the resulting config.json straight to a market repo's +# PARTNER_CONFIG_JSON_ GitHub secret. Cleans up after itself. +# +# Usage: +# ./authorize-partner-secret.sh [host] +# +# is either a short code (nl, be, lu, uk) or a full "owner/repo". +# +# Examples: +# ./authorize-partner-secret.sh 2 nl +# ./authorize-partner-secret.sh 11 lu +# ./authorize-partner-secret.sh 1 silverfin/be_market +# +# Prompts for the api_key with hidden input (never as an argv, so it never +# lands in shell history). Re-run once per partner after each staging reset. + +set -euo pipefail + +declare -A MARKET_REPOS=( + [nl]="silverfin/nl_market" + [be]="silverfin/be_market" + [lu]="silverfin/lu_market" + [uk]="silverfin/uk_market" +) + +PARTNER_ID="${1:?Usage: $0 [host]}" +MARKET="${2:?Usage: $0 [host]}" +HOST="${3:-https://bso-staging-beta.staging.getsilverfin.com}" + +if [[ -n "${MARKET_REPOS[$MARKET]:-}" ]]; then + REPO="${MARKET_REPOS[$MARKET]}" +else + REPO="$MARKET" +fi + +printf '%s' "API key for partner ${PARTNER_ID} (${REPO}): " +read -rs API_KEY +echo + +TMP_HOME=$(mktemp -d) +trap 'rm -rf "$TMP_HOME"' EXIT + +HOME="$TMP_HOME" silverfin config --set-host "$HOST" +HOME="$TMP_HOME" silverfin authorize-partner -i "$PARTNER_ID" -k "$API_KEY" -n "partner-${PARTNER_ID}" + +gh secret set "PARTNER_CONFIG_JSON_${PARTNER_ID}" --repo "$REPO" < "$TMP_HOME/.silverfin/config.json" + +echo "Done: PARTNER_CONFIG_JSON_${PARTNER_ID} updated on ${REPO}."