All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Implements ReprovisionNotifyHost to migrate a project's email sending from an old notify host to a new one (e.g., from project-name-based to slug-based host). Preserves the project's notify account and send key. - Adds ReprovisionNotifyHost to port.NotifyProvisioner interface - Implements revokeHostAccess on notifyAdminAPI + adminClient - Implements Provisioner.ReprovisionNotifyHost (12-step migration) in provisioner_reprovision.go (split to keep provisioner.go < 500 lines) - Adds NotifyHandler.Reprovision handler (POST /notify/reprovision) - Updates OpenAPI spec with reprovision endpoint Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
560 lines
21 KiB
Bash
Executable File
560 lines
21 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# rdev-cli — credential management CLI for the rdev platform
|
|
#
|
|
# Usage: rdev-cli <command> [subcommand] [flags]
|
|
#
|
|
# Commands:
|
|
# me Show current key identity & access
|
|
# keys list List all API keys (table format)
|
|
# keys get <id> Get a specific key (JSON)
|
|
# keys create --name <n> --scopes <s> Create a new API key
|
|
# keys update <id> [flags] Update a key
|
|
# keys revoke <id> Revoke a key (prompts confirmation)
|
|
# access list <project-id> List keys with access to a project
|
|
# access grant <project-id> <key-id> Grant a key access to a project
|
|
# access revoke <project-id> <key-id> Revoke a key's access to a project
|
|
#
|
|
# Required env vars:
|
|
# RDEV_API_URL — e.g. https://rdev.masq-ops.orchard9.ai
|
|
# RDEV_API_KEY — base64 or rdev_sk_ format
|
|
|
|
set -euo pipefail
|
|
|
|
# ─── colours ────────────────────────────────────────────────────────────────
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
BOLD='\033[1m'
|
|
NC='\033[0m'
|
|
|
|
# ─── env check ──────────────────────────────────────────────────────────────
|
|
|
|
preflight_check() {
|
|
local missing=0
|
|
if [[ -z "${RDEV_API_URL:-}" ]]; then
|
|
echo -e "${RED}Error: RDEV_API_URL is not set${NC}" >&2
|
|
missing=1
|
|
fi
|
|
if [[ -z "${RDEV_API_KEY:-}" ]]; then
|
|
echo -e "${RED}Error: RDEV_API_KEY is not set${NC}" >&2
|
|
missing=1
|
|
fi
|
|
if [[ $missing -ne 0 ]]; then
|
|
echo "" >&2
|
|
echo "Set the required environment variables:" >&2
|
|
echo " export RDEV_API_URL=\"https://rdev.masq-ops.orchard9.ai\"" >&2
|
|
echo " export RDEV_API_KEY=\"<your-api-key>\"" >&2
|
|
echo "" >&2
|
|
echo "Or source your secrets file:" >&2
|
|
echo " source ~/.zshrc" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# ─── api helper ─────────────────────────────────────────────────────────────
|
|
|
|
# api_call METHOD /path [body]
|
|
# Prints JSON response body; exits non-zero on HTTP error.
|
|
api_call() {
|
|
local method="$1"
|
|
local path="$2"
|
|
local body="${3:-}"
|
|
|
|
local tmpfile status_code response_body
|
|
tmpfile=$(mktemp)
|
|
|
|
if [[ -n "$body" ]]; then
|
|
status_code=$(curl -s -o "$tmpfile" -w "%{http_code}" \
|
|
--max-time 30 \
|
|
-X "$method" \
|
|
-H "X-API-Key: $RDEV_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$body" \
|
|
"${RDEV_API_URL}${path}")
|
|
else
|
|
status_code=$(curl -s -o "$tmpfile" -w "%{http_code}" \
|
|
--max-time 30 \
|
|
-X "$method" \
|
|
-H "X-API-Key: $RDEV_API_KEY" \
|
|
"${RDEV_API_URL}${path}")
|
|
fi
|
|
|
|
response_body=$(cat "$tmpfile")
|
|
rm -f "$tmpfile"
|
|
|
|
if [[ "$status_code" -lt 200 || "$status_code" -ge 300 ]]; then
|
|
echo -e "${RED}Error: HTTP $status_code${NC}" >&2
|
|
if [[ -n "$response_body" ]]; then
|
|
echo "$response_body" | jq -r '.message // .error // .' 2>/dev/null >&2 || echo "$response_body" >&2
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
echo "$response_body"
|
|
}
|
|
|
|
# ─── me ─────────────────────────────────────────────────────────────────────
|
|
|
|
cmd_me() {
|
|
local resp
|
|
resp=$(api_call GET "/me")
|
|
|
|
local id name prefix scopes project_access expires_at active
|
|
id=$(echo "$resp" | jq -r '.data.id // .id')
|
|
name=$(echo "$resp" | jq -r '.data.name // .name')
|
|
prefix=$(echo "$resp" | jq -r '.data.key_prefix // .key_prefix')
|
|
scopes=$(echo "$resp" | jq -r '(.data.scopes // .scopes) | join(", ")')
|
|
project_access=$(echo "$resp" | jq -r '.data.project_access // .project_access')
|
|
expires_at=$(echo "$resp" | jq -r '.data.expires_at // .expires_at // "never"')
|
|
active=$(echo "$resp" | jq -r '.data.active // .active')
|
|
|
|
echo ""
|
|
echo -e "${BOLD}Current key identity${NC}"
|
|
echo "────────────────────────────────────"
|
|
printf " %-16s %s\n" "ID:" "$id"
|
|
printf " %-16s %s\n" "Name:" "$name"
|
|
printf " %-16s %s\n" "Prefix:" "$prefix"
|
|
printf " %-16s %s\n" "Scopes:" "$scopes"
|
|
printf " %-16s %s\n" "Access:" "$project_access"
|
|
printf " %-16s %s\n" "Expires:" "$expires_at"
|
|
printf " %-16s %s\n" "Active:" "$active"
|
|
|
|
# Show project list if restricted
|
|
local projects
|
|
projects=$(echo "$resp" | jq -r '(.data.projects // .projects) // []')
|
|
local project_count
|
|
project_count=$(echo "$projects" | jq 'length')
|
|
if [[ "$project_count" -gt 0 ]]; then
|
|
echo ""
|
|
echo " Projects:"
|
|
echo "$projects" | jq -r '.[] | " - \(.id) \(.name) [\(.status)]"'
|
|
fi
|
|
|
|
# Show allowed IPs if set
|
|
local allowed_ips
|
|
allowed_ips=$(echo "$resp" | jq -r '(.data.allowed_ips // .allowed_ips) // []')
|
|
local ip_count
|
|
ip_count=$(echo "$allowed_ips" | jq 'length')
|
|
if [[ "$ip_count" -gt 0 ]]; then
|
|
echo ""
|
|
echo " Allowed IPs:"
|
|
echo "$allowed_ips" | jq -r '.[] | " - \(.)"'
|
|
fi
|
|
echo ""
|
|
}
|
|
|
|
# ─── keys ───────────────────────────────────────────────────────────────────
|
|
|
|
cmd_keys_list() {
|
|
local resp
|
|
resp=$(api_call GET "/keys")
|
|
|
|
local keys
|
|
keys=$(echo "$resp" | jq -r '.data // .')
|
|
|
|
local count
|
|
count=$(echo "$keys" | jq 'length')
|
|
|
|
if [[ "$count" -eq 0 ]]; then
|
|
echo "No API keys found."
|
|
return
|
|
fi
|
|
|
|
echo ""
|
|
printf "${BOLD}%-8s %-30s %-36s %-30s %-12s %-6s${NC}\n" \
|
|
"PREFIX" "NAME" "ID" "SCOPES" "EXPIRES" "ACTIVE"
|
|
printf '%s\n' "────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"
|
|
|
|
echo "$keys" | jq -r '.[] |
|
|
[
|
|
.key_prefix,
|
|
.name,
|
|
.id,
|
|
(.scopes | join(",")),
|
|
(.expires_at // "never"),
|
|
(if .active then "yes" else "no" end)
|
|
] | @tsv' | while IFS=$'\t' read -r prefix name id scopes expires active; do
|
|
# Truncate long fields for readability
|
|
local name_trunc="${name:0:29}"
|
|
local scopes_trunc="${scopes:0:29}"
|
|
local active_color="$GREEN"
|
|
[[ "$active" == "no" ]] && active_color="$RED"
|
|
printf "%-8s %-30s %-36s %-30s %-12s ${active_color}%-6s${NC}\n" \
|
|
"$prefix" "$name_trunc" "$id" "$scopes_trunc" "${expires:0:10}" "$active"
|
|
done
|
|
echo ""
|
|
}
|
|
|
|
cmd_keys_get() {
|
|
local id="${1:-}"
|
|
if [[ -z "$id" ]]; then
|
|
echo -e "${RED}Error: key id required${NC}" >&2
|
|
echo "Usage: rdev-cli keys get <id>" >&2
|
|
exit 1
|
|
fi
|
|
api_call GET "/keys/$id" | jq .
|
|
}
|
|
|
|
cmd_keys_create() {
|
|
local name="" scopes="" expires_in="90d" project_ids_raw="" allowed_ips_raw=""
|
|
|
|
# Parse flags
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--name) name="$2"; shift 2 ;;
|
|
--scopes) scopes="$2"; shift 2 ;;
|
|
--expires) expires_in="$2"; shift 2 ;;
|
|
--project-ids) project_ids_raw="$2"; shift 2 ;;
|
|
--allowed-ips) allowed_ips_raw="$2"; shift 2 ;;
|
|
*) echo -e "${RED}Error: unknown flag: $1${NC}" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$name" ]]; then
|
|
echo -e "${RED}Error: --name is required${NC}" >&2
|
|
echo "Usage: rdev-cli keys create --name <name> --scopes <scope1,scope2,...>" >&2
|
|
exit 1
|
|
fi
|
|
if [[ -z "$scopes" ]]; then
|
|
echo -e "${RED}Error: --scopes is required${NC}" >&2
|
|
echo "Usage: rdev-cli keys create --name <name> --scopes <scope1,scope2,...>" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Convert comma-separated scopes → JSON array
|
|
local scopes_json
|
|
scopes_json=$(echo "$scopes" | tr ',' '\n' | jq -R . | jq -s .)
|
|
|
|
# Convert comma-separated project IDs → JSON array or null
|
|
local project_ids_json="null"
|
|
if [[ -n "$project_ids_raw" && "$project_ids_raw" != "null" && "$project_ids_raw" != '""' ]]; then
|
|
project_ids_json=$(echo "$project_ids_raw" | tr ',' '\n' | jq -R . | jq -s .)
|
|
fi
|
|
|
|
# Convert comma-separated allowed IPs → JSON array
|
|
local allowed_ips_json="[]"
|
|
if [[ -n "$allowed_ips_raw" ]]; then
|
|
allowed_ips_json=$(echo "$allowed_ips_raw" | tr ',' '\n' | jq -R . | jq -s .)
|
|
fi
|
|
|
|
# Build request body
|
|
local body
|
|
body=$(jq -n \
|
|
--arg name "$name" \
|
|
--argjson scopes "$scopes_json" \
|
|
--argjson pids "$project_ids_json" \
|
|
--arg expires "$expires_in" \
|
|
--argjson ips "$allowed_ips_json" \
|
|
'{
|
|
name: $name,
|
|
scopes: $scopes,
|
|
project_ids: $pids,
|
|
expires_in: $expires,
|
|
allowed_ips: $ips
|
|
}')
|
|
|
|
local resp
|
|
resp=$(api_call POST "/keys" "$body")
|
|
|
|
# Extract fields (handles both wrapped .data and flat response)
|
|
local key_id key_name key_scopes key_secret
|
|
key_id=$(echo "$resp" | jq -r '(.data.key.id // .key.id // .id)')
|
|
key_name=$(echo "$resp" | jq -r '(.data.key.name // .key.name // .name)')
|
|
key_scopes=$(echo "$resp" | jq -r '((.data.key.scopes // .key.scopes // .scopes) | join(", "))')
|
|
key_secret=$(echo "$resp" | jq -r '(.data.secret // .secret)')
|
|
|
|
# Secret box
|
|
echo ""
|
|
echo -e "${YELLOW}╔══════════════════════════════════════════════════════════════╗"
|
|
echo "║ NEW API KEY — SAVE THIS SECRET NOW — SHOWN ONCE ║"
|
|
echo "║ ║"
|
|
printf "║ %-10s %-49s║\n" "ID:" "$key_id"
|
|
printf "║ %-10s %-49s║\n" "Name:" "$key_name"
|
|
printf "║ %-10s %-49s║\n" "Scopes:" "${key_scopes:0:48}"
|
|
printf "║ %-10s %-49s║\n" "Secret:" "$key_secret"
|
|
echo "║ ║"
|
|
echo "║ Add to ~/.zshrc or secrets manager before continuing. ║"
|
|
echo -e "╚══════════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
read -r -p "Press [enter] when you have saved the secret..."
|
|
echo ""
|
|
echo -e "${GREEN}✓ Key created — ${key_name} (${key_id:0:8}...)${NC}"
|
|
echo ""
|
|
}
|
|
|
|
cmd_keys_update() {
|
|
local id="${1:-}"
|
|
if [[ -z "$id" ]]; then
|
|
echo -e "${RED}Error: key id required${NC}" >&2
|
|
echo "Usage: rdev-cli keys update <id> [--name <n>] [--scopes <s>] [--expires <e>] [--project-ids <ids>] [--allowed-ips <ips>]" >&2
|
|
exit 1
|
|
fi
|
|
shift
|
|
|
|
local name="" scopes="" expires_in="" project_ids_raw="" allowed_ips_raw=""
|
|
local has_name=0 has_scopes=0 has_expires=0 has_pids=0 has_ips=0
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--name) name="$2"; has_name=1; shift 2 ;;
|
|
--scopes) scopes="$2"; has_scopes=1; shift 2 ;;
|
|
--expires) expires_in="$2"; has_expires=1; shift 2 ;;
|
|
--project-ids) project_ids_raw="$2"; has_pids=1; shift 2 ;;
|
|
--allowed-ips) allowed_ips_raw="$2"; has_ips=1; shift 2 ;;
|
|
*) echo -e "${RED}Error: unknown flag: $1${NC}" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
# Build partial update body using jq null-safe approach
|
|
local body="{}"
|
|
if [[ $has_name -eq 1 ]]; then
|
|
body=$(echo "$body" | jq --arg v "$name" '. + {name: $v}')
|
|
fi
|
|
if [[ $has_scopes -eq 1 ]]; then
|
|
local scopes_json
|
|
scopes_json=$(echo "$scopes" | tr ',' '\n' | jq -R . | jq -s .)
|
|
body=$(echo "$body" | jq --argjson v "$scopes_json" '. + {scopes: $v}')
|
|
fi
|
|
if [[ $has_expires -eq 1 ]]; then
|
|
body=$(echo "$body" | jq --arg v "$expires_in" '. + {expires_in: $v}')
|
|
fi
|
|
if [[ $has_pids -eq 1 ]]; then
|
|
if [[ "$project_ids_raw" == "null" || -z "$project_ids_raw" ]]; then
|
|
body=$(echo "$body" | jq '. + {project_ids: null}')
|
|
else
|
|
local pids_json
|
|
pids_json=$(echo "$project_ids_raw" | tr ',' '\n' | jq -R . | jq -s .)
|
|
body=$(echo "$body" | jq --argjson v "$pids_json" '. + {project_ids: $v}')
|
|
fi
|
|
fi
|
|
if [[ $has_ips -eq 1 ]]; then
|
|
if [[ "$allowed_ips_raw" == "null" || -z "$allowed_ips_raw" ]]; then
|
|
body=$(echo "$body" | jq '. + {allowed_ips: null}')
|
|
else
|
|
local ips_json
|
|
ips_json=$(echo "$allowed_ips_raw" | tr ',' '\n' | jq -R . | jq -s .)
|
|
body=$(echo "$body" | jq --argjson v "$ips_json" '. + {allowed_ips: $v}')
|
|
fi
|
|
fi
|
|
|
|
local resp
|
|
resp=$(api_call PATCH "/keys/$id" "$body")
|
|
|
|
local key_name key_prefix
|
|
key_name=$(echo "$resp" | jq -r '.data.name // .name')
|
|
key_prefix=$(echo "$resp" | jq -r '.data.key_prefix // .key_prefix')
|
|
|
|
echo -e "${GREEN}✓ Updated — ${key_name} (${key_prefix}...)${NC}"
|
|
}
|
|
|
|
cmd_keys_revoke() {
|
|
local id="${1:-}"
|
|
if [[ -z "$id" ]]; then
|
|
echo -e "${RED}Error: key id required${NC}" >&2
|
|
echo "Usage: rdev-cli keys revoke <id>" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Fetch key details for confirmation
|
|
local key_resp
|
|
key_resp=$(api_call GET "/keys/$id")
|
|
local key_name key_prefix active
|
|
key_name=$(echo "$key_resp" | jq -r '.data.name // .name')
|
|
key_prefix=$(echo "$key_resp" | jq -r '.data.key_prefix // .key_prefix')
|
|
active=$(echo "$key_resp" | jq -r '.data.active // .active')
|
|
|
|
echo ""
|
|
echo -e "${YELLOW}About to revoke:${NC}"
|
|
echo " Name: $key_name"
|
|
echo " ID: $id"
|
|
echo " Prefix: $key_prefix"
|
|
echo " Active: $active"
|
|
echo ""
|
|
|
|
local confirm
|
|
read -r -p "Revoke? [y/N] " confirm
|
|
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
|
|
echo "Aborted."
|
|
exit 0
|
|
fi
|
|
|
|
api_call DELETE "/keys/$id" > /dev/null
|
|
echo -e "${GREEN}✓ Revoked — ${key_name} (${key_prefix}...)${NC}"
|
|
echo ""
|
|
}
|
|
|
|
# ─── access ─────────────────────────────────────────────────────────────────
|
|
|
|
cmd_access_list() {
|
|
local project_id="${1:-}"
|
|
if [[ -z "$project_id" ]]; then
|
|
echo -e "${RED}Error: project-id required${NC}" >&2
|
|
echo "Usage: rdev-cli access list <project-id>" >&2
|
|
exit 1
|
|
fi
|
|
|
|
local resp
|
|
resp=$(api_call GET "/projects/$project_id/access")
|
|
|
|
local unrestricted_count
|
|
unrestricted_count=$(echo "$resp" | jq -r '.data.unrestricted_keys // .unrestricted_keys // 0')
|
|
|
|
echo ""
|
|
echo -e "${BOLD}Access for project: $project_id${NC}"
|
|
echo " Unrestricted keys (access all projects): $unrestricted_count"
|
|
echo ""
|
|
|
|
local keys
|
|
keys=$(echo "$resp" | jq -r '.data.keys // .keys // []')
|
|
local key_count
|
|
key_count=$(echo "$keys" | jq 'length')
|
|
|
|
if [[ "$key_count" -eq 0 ]]; then
|
|
echo " No keys explicitly granted access to this project."
|
|
else
|
|
echo " Explicitly granted keys:"
|
|
printf " ${BOLD}%-8s %-30s %-36s %-6s${NC}\n" "PREFIX" "NAME" "ID" "ACTIVE"
|
|
printf ' %s\n' "────────────────────────────────────────────────────────────────────────"
|
|
echo "$keys" | jq -r '.[] | [.key_prefix, .name, .id, (if .active then "yes" else "no" end)] | @tsv' \
|
|
| while IFS=$'\t' read -r prefix name id active; do
|
|
local active_color="$GREEN"
|
|
[[ "$active" == "no" ]] && active_color="$RED"
|
|
printf " %-8s %-30s %-36s ${active_color}%-6s${NC}\n" \
|
|
"$prefix" "${name:0:29}" "$id" "$active"
|
|
done
|
|
fi
|
|
echo ""
|
|
}
|
|
|
|
cmd_access_grant() {
|
|
local project_id="${1:-}" key_id="${2:-}"
|
|
if [[ -z "$project_id" || -z "$key_id" ]]; then
|
|
echo -e "${RED}Error: project-id and key-id required${NC}" >&2
|
|
echo "Usage: rdev-cli access grant <project-id> <key-id>" >&2
|
|
exit 1
|
|
fi
|
|
|
|
local body
|
|
body=$(jq -n --arg kid "$key_id" '{key_id: $kid}')
|
|
|
|
local resp
|
|
resp=$(api_call POST "/projects/$project_id/access" "$body")
|
|
|
|
local status
|
|
status=$(echo "$resp" | jq -r '.data.status // .status')
|
|
|
|
if [[ "$status" == "already_granted" ]]; then
|
|
echo -e "${YELLOW}✓ Already granted — key ${key_id:0:8}... already has access to $project_id${NC}"
|
|
else
|
|
echo -e "${GREEN}✓ Granted — key ${key_id:0:8}... now has access to $project_id${NC}"
|
|
fi
|
|
}
|
|
|
|
cmd_access_revoke() {
|
|
local project_id="${1:-}" key_id="${2:-}"
|
|
if [[ -z "$project_id" || -z "$key_id" ]]; then
|
|
echo -e "${RED}Error: project-id and key-id required${NC}" >&2
|
|
echo "Usage: rdev-cli access revoke <project-id> <key-id>" >&2
|
|
exit 1
|
|
fi
|
|
|
|
api_call DELETE "/projects/$project_id/access/$key_id" > /dev/null
|
|
echo -e "${GREEN}✓ Revoked — key ${key_id:0:8}... no longer has access to $project_id${NC}"
|
|
}
|
|
|
|
# ─── help ───────────────────────────────────────────────────────────────────
|
|
|
|
cmd_help() {
|
|
cat <<'EOF'
|
|
|
|
rdev-cli — rdev credential management CLI
|
|
|
|
Usage:
|
|
rdev-cli me Show current key identity & access
|
|
rdev-cli keys list List all API keys (table format)
|
|
rdev-cli keys get <id> Get a specific key (JSON)
|
|
rdev-cli keys create --name <n> --scopes <s> Create a new API key
|
|
rdev-cli keys update <id> [flags] Update a key
|
|
rdev-cli keys revoke <id> Revoke a key (prompts confirmation)
|
|
rdev-cli access list <project-id> List keys with access to a project
|
|
rdev-cli access grant <project-id> <key-id> Grant a key access to a project
|
|
rdev-cli access revoke <project-id> <key-id> Revoke a key's access to a project
|
|
|
|
Create / Update flags:
|
|
--name <name> Key name (required on create)
|
|
--scopes <s1,s2,...> Comma-separated scopes (required on create)
|
|
--expires <30d|60d|90d|1y|never> Expiration (default: 90d on create)
|
|
--project-ids <id1,id2,...> Restrict to projects (null = unrestricted)
|
|
--allowed-ips <cidr1,...> Restrict to IP ranges (empty = unrestricted)
|
|
|
|
Scopes:
|
|
projects:read projects:execute keys:read keys:write
|
|
audit:read queue:read queue:write webhooks:read
|
|
webhooks:write workers:read workers:write builds:read
|
|
builds:write verify:read verify:write sessions:read
|
|
sessions:execute admin
|
|
|
|
Required env vars:
|
|
RDEV_API_URL e.g. https://rdev.masq-ops.orchard9.ai
|
|
RDEV_API_KEY your API key (base64 or rdev_sk_ format)
|
|
|
|
EOF
|
|
}
|
|
|
|
# ─── router ─────────────────────────────────────────────────────────────────
|
|
|
|
main() {
|
|
local cmd="${1:-}"
|
|
|
|
case "$cmd" in
|
|
me)
|
|
preflight_check
|
|
cmd_me
|
|
;;
|
|
keys)
|
|
preflight_check
|
|
local sub="${2:-}"
|
|
shift 2 2>/dev/null || shift 1 2>/dev/null || true
|
|
case "$sub" in
|
|
list) cmd_keys_list ;;
|
|
get) cmd_keys_get "$@" ;;
|
|
create) cmd_keys_create "$@" ;;
|
|
update) cmd_keys_update "$@" ;;
|
|
revoke) cmd_keys_revoke "$@" ;;
|
|
*)
|
|
echo -e "${RED}Error: unknown keys subcommand: ${sub:-<missing>}${NC}" >&2
|
|
echo "Run 'rdev-cli --help' for usage." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
;;
|
|
access)
|
|
preflight_check
|
|
local sub="${2:-}"
|
|
shift 2 2>/dev/null || shift 1 2>/dev/null || true
|
|
case "$sub" in
|
|
list) cmd_access_list "$@" ;;
|
|
grant) cmd_access_grant "$@" ;;
|
|
revoke) cmd_access_revoke "$@" ;;
|
|
*)
|
|
echo -e "${RED}Error: unknown access subcommand: ${sub:-<missing>}${NC}" >&2
|
|
echo "Run 'rdev-cli --help' for usage." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
;;
|
|
help|--help|-h|"")
|
|
cmd_help
|
|
;;
|
|
*)
|
|
echo -e "${RED}Error: unknown command: $cmd${NC}" >&2
|
|
echo "Run 'rdev-cli --help' for usage." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|