Skip to content

Commit 7cfd5b7

Browse files
authored
Added a script to generate provisioning tokens (#15)
1 parent 5dfe06e commit 7cfd5b7

2 files changed

Lines changed: 249 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ A Helm chart for deploying Kentik Universal Agent (kagent) with support for mult
77
- Kubernetes 1.20+
88
- Helm 3.x
99
- Kentik account with API access
10+
- A provisioning token (if you cloned this repo, see `./generate-provisioning-token.sh --help`)
1011

1112
## Quick Start
1213

generate-provisioning-token.sh

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
#!/bin/bash
2+
3+
# Script to create a Kentik provisioning token for kagent Helm chart deployment
4+
# Usage: ./generate-provisioning-token.sh --name <token-name> [options]
5+
#
6+
# Kentik API (flags override environment variables):
7+
# --api-root <host> API host (or K_API_ROOT env var; default: grpc.api.kentik.com)
8+
# --api-email <email> Kentik account email (or K_API_EMAIL env var)
9+
# --api-token <token> Kentik API token (or K_API_TOKEN env var)
10+
#
11+
# Token Configuration:
12+
# --name <name> Required. User-friendly name for the token.
13+
# --max-usage <count> Max agents that can use this token (default: 1)
14+
# --expires-at <ISO-8601> Token expiration time (default: API default)
15+
# --auto-approve Skip manual approval (default: requires approval)
16+
# --site-id <id> Site ID to assign to registered agents
17+
18+
set -euo pipefail
19+
20+
# ============================================================================
21+
# Defaults
22+
# ============================================================================
23+
K_API_EMAIL="${K_API_EMAIL:-}"
24+
K_API_TOKEN="${K_API_TOKEN:-}"
25+
API_ROOT="${K_API_ROOT:-grpc.api.kentik.com}"
26+
TOKEN_NAME=""
27+
MAX_USAGE_COUNT=""
28+
EXPIRES_AT=""
29+
REQUIRES_APPROVAL="true"
30+
SITE_ID=""
31+
32+
# ============================================================================
33+
# Functions
34+
# ============================================================================
35+
36+
usage() {
37+
cat <<EOF
38+
Usage: $0 --name <token-name> [options]
39+
40+
Create a Kentik provisioning token for kagent Helm chart deployment.
41+
42+
Kentik API (flags override environment variables):
43+
--api-root <host> API host (or K_API_ROOT env var; default: grpc.api.kentik.com)
44+
--api-email <email> Kentik account email (or K_API_EMAIL env var)
45+
--api-token <token> Kentik API token (or K_API_TOKEN env var)
46+
47+
Token Configuration:
48+
--name <name> Required. User-friendly name for the token.
49+
--max-usage <count> Max agents that can use this token (default: 1)
50+
NOTE: must match the number of replicas you intend to deploy
51+
--expires-at <ISO-8601> Token expiration time (default: API default)
52+
--auto-approve Skip manual approval (default: requires approval)
53+
--site-id <id> Site ID to assign to registered agents
54+
55+
Examples:
56+
# Minimal (uses env vars for auth):
57+
export K_API_EMAIL=user@company.com
58+
export K_API_TOKEN=abc123
59+
$0 --name "production-agents"
60+
61+
# Full options with CLI auth:
62+
$0 --api-root grpc.api.kentik.eu \\
63+
--api-email user@co.com --api-token abc123 \\
64+
--name "staging-fleet" \\
65+
--max-usage 10
66+
EOF
67+
exit "${1:-0}"
68+
}
69+
70+
die() {
71+
printf 'Error: %b\n' "$1" >&2
72+
exit 1
73+
}
74+
75+
check_curl() {
76+
if ! command -v curl &>/dev/null; then
77+
die "curl is required but not found. Please install curl."
78+
fi
79+
}
80+
81+
check_jq() {
82+
if ! command -v jq &>/dev/null; then
83+
die "jq is required but not found. Please install jq."
84+
fi
85+
}
86+
87+
88+
build_request_body() {
89+
local body
90+
body=$(jq -n --arg name "$TOKEN_NAME" '{name: $name}')
91+
92+
if [[ -n "$MAX_USAGE_COUNT" ]]; then
93+
body=$(echo "$body" | jq --argjson v "$MAX_USAGE_COUNT" '. + {maxUsageCount: $v}')
94+
fi
95+
96+
if [[ -n "$EXPIRES_AT" ]]; then
97+
body=$(echo "$body" | jq --arg v "$EXPIRES_AT" '. + {expiresAt: $v}')
98+
fi
99+
100+
if [[ "$REQUIRES_APPROVAL" == "true" ]]; then
101+
body=$(echo "$body" | jq '. + {requiresApproval: true}')
102+
else
103+
body=$(echo "$body" | jq '. + {requiresApproval: false}')
104+
fi
105+
106+
if [[ -n "$SITE_ID" ]]; then
107+
body=$(echo "$body" | jq --arg v "$SITE_ID" '. + {config: {siteId: $v}}')
108+
fi
109+
110+
echo "$body"
111+
}
112+
113+
do_post() {
114+
local url="$1"
115+
local body="$2"
116+
117+
curl -sS -w "\n%{http_code}" \
118+
-X POST \
119+
-H "Content-Type: application/json" \
120+
-H "X-CH-Auth-Email: $K_API_EMAIL" \
121+
-H "X-CH-Auth-API-Token: $K_API_TOKEN" \
122+
-d "$body" \
123+
"$url"
124+
}
125+
126+
# ============================================================================
127+
# Parse Arguments
128+
# ============================================================================
129+
130+
while [[ $# -gt 0 ]]; do
131+
if [[ "$1" =~ ^--(api-email|api-token|name|max-usage|expires-at|site-id|api-root)$ ]]; then
132+
if [[ $# -lt 2 || "${2:-}" == --* ]]; then
133+
die "Missing value for $1"
134+
fi
135+
fi
136+
case "$1" in
137+
--api-email)
138+
K_API_EMAIL="$2"
139+
shift 2
140+
;;
141+
--api-token)
142+
K_API_TOKEN="$2"
143+
shift 2
144+
;;
145+
--name)
146+
TOKEN_NAME="$2"
147+
shift 2
148+
;;
149+
--max-usage)
150+
MAX_USAGE_COUNT="$2"
151+
shift 2
152+
;;
153+
--expires-at)
154+
EXPIRES_AT="$2"
155+
shift 2
156+
;;
157+
--auto-approve)
158+
REQUIRES_APPROVAL="false"
159+
shift
160+
;;
161+
--site-id)
162+
SITE_ID="$2"
163+
shift 2
164+
;;
165+
--api-root)
166+
API_ROOT="$2"
167+
shift 2
168+
;;
169+
--help|-h)
170+
usage 0
171+
;;
172+
*)
173+
die "Unknown option: $1. Use --help for usage."
174+
;;
175+
esac
176+
done
177+
178+
# ============================================================================
179+
# Validate Inputs
180+
# ============================================================================
181+
182+
check_curl
183+
check_jq
184+
185+
[[ -z "$K_API_EMAIL" ]] && die "Kentik email is required. Use --api-email or set K_API_EMAIL env var."
186+
[[ -z "$K_API_TOKEN" ]] && die "Kentik API token is required. Use --api-token or set K_API_TOKEN env var."
187+
[[ -z "$TOKEN_NAME" ]] && die "Token name is required. Use --name <name>."
188+
189+
if [[ -n "$MAX_USAGE_COUNT" ]]; then
190+
if ! [[ "$MAX_USAGE_COUNT" =~ ^[0-9]+$ ]] || [[ "$MAX_USAGE_COUNT" -lt 1 ]]; then
191+
die "--max-usage must be a positive integer."
192+
fi
193+
fi
194+
195+
# ============================================================================
196+
# Create Token
197+
# ============================================================================
198+
199+
API_ROOT="${API_ROOT#https://}"
200+
API_ROOT="${API_ROOT#http://}"
201+
API_ROOT="${API_ROOT%/}"
202+
URL="https://${API_ROOT}/kagent/v202401/provisioning-tokens"
203+
BODY=$(build_request_body)
204+
205+
echo "Creating provisioning token..."
206+
echo " API: $API_ROOT"
207+
echo " Name: $TOKEN_NAME"
208+
echo ""
209+
210+
RESPONSE=$(do_post "$URL" "$BODY") || die "curl request failed. Check network connectivity and API host: $URL"
211+
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
212+
RESPONSE_BODY=$(echo "$RESPONSE" | sed '$d')
213+
214+
if [[ -z "$HTTP_CODE" || "$HTTP_CODE" -ne 200 ]]; then
215+
echo "API request failed (HTTP $HTTP_CODE):" >&2
216+
if echo "$RESPONSE_BODY" | jq . >/dev/null 2>&1; then
217+
echo "$RESPONSE_BODY" | jq . >&2
218+
else
219+
echo "$RESPONSE_BODY" >&2
220+
fi
221+
exit 1
222+
fi
223+
224+
# Extract token value
225+
PROV_TOKEN=$(echo "$RESPONSE_BODY" | jq -r '.token.token')
226+
TOKEN_EXPIRES=$(echo "$RESPONSE_BODY" | jq -r '.token.expiresAt // "N/A"')
227+
TOKEN_MAX_USAGE=$(echo "$RESPONSE_BODY" | jq -r '.token.maxUsageCount // 1')
228+
229+
if [[ -z "$PROV_TOKEN" || "$PROV_TOKEN" == "null" ]]; then
230+
die "Failed to extract token from API response. Full response:\n$RESPONSE_BODY"
231+
fi
232+
233+
# ============================================================================
234+
# Output
235+
# ============================================================================
236+
237+
echo "✓ Provisioning token created successfully!"
238+
echo ""
239+
echo " Token: $PROV_TOKEN"
240+
echo " Expires: $TOKEN_EXPIRES"
241+
echo " Max Agents: $TOKEN_MAX_USAGE"
242+
echo ""
243+
echo "Use with Helm:"
244+
echo ""
245+
echo " helm install kagent . \\"
246+
echo " --set-string kagent.companyId=YOUR_COMPANY_ID \\"
247+
echo " --set-string kagent.provisioningToken='$PROV_TOKEN'"
248+
echo ""

0 commit comments

Comments
 (0)