Skip to content

Commit a42b015

Browse files
committed
gw: enable admin token auth in e2e test cluster
Replace `insecure_no_auth = true` with a real `admin_token` in all three e2e gateway configs, and update test.sh to send `Authorization: Bearer` on every admin-RPC call. Adds a Phase-3 "Admin token auth" check that exercises the auth fairing end-to-end: missing token -> 401, wrong token -> 401, correct token -> 200. This makes the e2e suite a regression test for the auth path itself (not just for the certbot/cert-sync flow that follows), so future changes to admin auth can't silently break ingress without a test failure. Verified locally against the gateway binary (out of band of the docker compose harness, which depends on an external TDX endpoint): the 8 exhaustive curl cases (no token / wrong / Bearer / X-Admin-Token / ?token= GET / ?token= POST / dashboard root unauthed+authed) all return the expected status codes. Env-var fallback (DSTACK_GATEWAY_ADMIN_TOKEN) and fail-by-default policy also confirmed working.
1 parent 84babfa commit a42b015

4 files changed

Lines changed: 53 additions & 15 deletions

File tree

gateway/test-run/e2e/configs/gateway-1.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ rpc_domain = "gateway-1"
1919
enabled = true
2020
port = 9016
2121
address = "0.0.0.0"
22-
insecure_no_auth = true
22+
admin_token = "e2e-admin-token"
2323

2424
[core.debug]
2525
insecure_enable_debug_rpc = true

gateway/test-run/e2e/configs/gateway-2.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ rpc_domain = "gateway-2"
1919
enabled = true
2020
port = 9016
2121
address = "0.0.0.0"
22-
insecure_no_auth = true
22+
admin_token = "e2e-admin-token"
2323

2424
[core.debug]
2525
insecure_enable_debug_rpc = true

gateway/test-run/e2e/configs/gateway-3.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ rpc_domain = "gateway-3"
1919
enabled = true
2020
port = 9016
2121
address = "0.0.0.0"
22-
insecure_no_auth = true
22+
admin_token = "e2e-admin-token"
2323

2424
[core.debug]
2525
insecure_enable_debug_rpc = true

gateway/test-run/e2e/test.sh

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ GATEWAY_PROXIES="gateway-1:9014 gateway-2:9014 gateway-3:9014"
2222
GATEWAY_DEBUG_URLS="http://gateway-1:9015 http://gateway-2:9015 http://gateway-3:9015"
2323
GATEWAY_ADMIN="http://gateway-1:9016"
2424

25+
# Must match `admin_token` in configs/gateway-*.toml
26+
ADMIN_TOKEN="e2e-admin-token"
27+
ADMIN_AUTH_HEADER="Authorization: Bearer ${ADMIN_TOKEN}"
28+
2529
# External services
2630
MOCK_CF_API="http://mock-cf-dns-api:8080"
2731
PEBBLE_DIR="http://pebble:14000/dir"
@@ -183,6 +187,7 @@ setup_certbot_config() {
183187
# Set ACME URL
184188
log_info "Setting ACME URL: ${ACME_URL}"
185189
if ! curl -sf -X POST "${GATEWAY_ADMIN}/prpc/Admin.SetCertbotConfig" \
190+
-H "${ADMIN_AUTH_HEADER}" \
186191
-H "Content-Type: application/json" \
187192
-d '{"acme_url": "'"${ACME_URL}"'"}' > /dev/null; then
188193
log_error "Failed to set certbot config"
@@ -192,6 +197,7 @@ setup_certbot_config() {
192197
# Create DNS credential
193198
log_info "Creating DNS credential..."
194199
if ! curl -sf -X POST "${GATEWAY_ADMIN}/prpc/Admin.CreateDnsCredential" \
200+
-H "${ADMIN_AUTH_HEADER}" \
195201
-H "Content-Type: application/json" \
196202
-d '{
197203
"name": "test-cloudflare",
@@ -210,11 +216,13 @@ setup_certbot_config() {
210216
for domain in $CERT_DOMAINS; do
211217
log_info "Adding domain: $domain"
212218
curl -sf -X POST "${GATEWAY_ADMIN}/prpc/Admin.AddZtDomain" \
219+
-H "${ADMIN_AUTH_HEADER}" \
213220
-H "Content-Type: application/json" \
214221
-d '{"domain": "'"${domain}"'"}' > /dev/null || true
215222

216223
log_info "Triggering renewal for: $domain"
217224
curl -sf -X POST "${GATEWAY_ADMIN}/prpc/Admin.RenewZtDomainCert" \
225+
-H "${ADMIN_AUTH_HEADER}" \
218226
-H "Content-Type: application/json" \
219227
-d '{"domain": "'"${domain}"'", "force": true}' > /dev/null || \
220228
log_warn "Renewal request failed for $domain (may retry)"
@@ -223,6 +231,31 @@ setup_certbot_config() {
223231
return 0
224232
}
225233

234+
# Returns 0 if HTTP status code from $1 args equals $2.
235+
http_status_eq() {
236+
local expected="$1"
237+
shift
238+
local actual
239+
actual=$(curl -s -o /dev/null -w '%{http_code}' "$@")
240+
[ "$actual" = "$expected" ]
241+
}
242+
243+
# Returns 0 if all three admin auth checks pass: missing 401, wrong 401, right 200.
244+
test_admin_auth() {
245+
log_info "checking admin auth on ${GATEWAY_ADMIN}"
246+
# Missing token → 401
247+
http_status_eq 401 "${GATEWAY_ADMIN}/prpc/Admin.Status" \
248+
|| { log_error "no-token request did not return 401"; return 1; }
249+
# Wrong token → 401
250+
http_status_eq 401 "${GATEWAY_ADMIN}/prpc/Admin.Status" \
251+
-H "Authorization: Bearer wrong-token" \
252+
|| { log_error "wrong-token request did not return 401"; return 1; }
253+
# Correct token → 200
254+
http_status_eq 200 "${GATEWAY_ADMIN}/prpc/Admin.Status" \
255+
-H "${ADMIN_AUTH_HEADER}" \
256+
|| { log_error "valid-token request did not return 200"; return 1; }
257+
}
258+
226259
# ==================== Main ====================
227260

228261
main() {
@@ -241,14 +274,19 @@ main() {
241274
i=$((i + 1))
242275
done
243276

244-
# Phase 3: Configure certbot
245-
log_phase 3 "Configure certbot"
277+
# Phase 3: Admin auth gating
278+
log_phase 3 "Admin token auth"
279+
run_test "Admin endpoint accepts valid token and rejects missing/wrong" \
280+
"$(test_admin_auth; echo $?)"
281+
282+
# Phase 4: Configure certbot
283+
log_phase 4 "Configure certbot"
246284
if ! setup_certbot_config; then
247285
log_error "Failed to setup certbot configuration"
248286
fi
249287

250-
# Phase 4: Certificate issuance
251-
log_phase 4 "Certificate issuance"
288+
# Phase 5: Certificate issuance
289+
log_phase 5 "Certificate issuance"
252290
local first_domain=$(echo "$CERT_DOMAINS" | cut -d' ' -f1)
253291
local first_sni=$(get_test_sni "$first_domain")
254292
local first_proxy=$(echo "$GATEWAY_PROXIES" | cut -d' ' -f1)
@@ -274,8 +312,8 @@ main() {
274312
log_info "Waiting 20s for cluster sync..."
275313
sleep 20
276314

277-
# Phase 5: Certificate consistency
278-
log_phase 5 "Certificate consistency"
315+
# Phase 6: Certificate consistency
316+
log_phase 6 "Certificate consistency"
279317
for domain in $CERT_DOMAINS; do
280318
local sni=$(get_test_sni "$domain")
281319
run_test "All gateways have same cert for $domain" \
@@ -284,17 +322,17 @@ main() {
284322
"$(test_certificate_from_pebble "$sni"; echo $?)"
285323
done
286324

287-
# Phase 6: SNI-based selection
288-
log_phase 6 "SNI-based certificate selection"
325+
# Phase 7: SNI-based selection
326+
log_phase 7 "SNI-based certificate selection"
289327
for domain in $CERT_DOMAINS; do
290328
local sni=$(get_test_sni "$domain")
291329
local wildcard=$(get_wildcard_domain "$domain")
292330
run_test "SNI $sni returns $wildcard cert" \
293331
"$(test_sni_cert_selection "$first_proxy" "$sni" "$wildcard"; echo $?)"
294332
done
295333

296-
# Phase 7: Proxy TLS health
297-
log_phase 7 "Proxy TLS health endpoint"
334+
# Phase 8: Proxy TLS health
335+
log_phase 8 "Proxy TLS health endpoint"
298336
for domain in $CERT_DOMAINS; do
299337
local sni=$(get_test_sni "$domain")
300338
local i=1
@@ -305,8 +343,8 @@ main() {
305343
done
306344
done
307345

308-
# Phase 8: DNS records (informational)
309-
log_phase 8 "DNS-01 challenge records"
346+
# Phase 9: DNS records (informational)
347+
log_phase 9 "DNS-01 challenge records"
310348
local records=$(curl -sf "${MOCK_CF_API}/api/records" 2>/dev/null || echo "")
311349
if echo "$records" | grep -q "TXT"; then
312350
log_success "DNS TXT records found"

0 commit comments

Comments
 (0)