ข้ามไปยังเนื้อหา

สาธิต

คู่มือนี้จะพาคุณผ่าน แบบฝึกหัด Client-Side Defense แบบครบวงจร บน F5 Distributed Cloud โดยใช้ API — จัดโครงสร้างเป็นสี่เฟสที่ผู้ช่วย AI หรือผู้ดำเนินการมนุษย์สามารถดำเนินการได้ตั้งแต่ต้นจนจบ แต่ละขั้นตอนมีคำสั่ง curl พร้อมใช้งานพร้อมค่า placeholder ที่คุณสามารถปรับแต่งได้โดยใช้แบบฟอร์มที่ด้านบนของหน้า, ไฟล์ .env หรือเครื่องมืออัตโนมัติใดๆ

เฟสเป้าหมายขั้นตอน
เฟส 1 — สร้างปรับใช้และตรวจสอบโครงสร้างพื้นฐาน CSD ทั้งหมดขั้นตอน 1–7
เฟส 2 — โจมตีสร้างทราฟฟิกการโจมตีจำลองและยืนยันว่า CSD ตรวจพบขั้นตอน 8–9
เฟส 3 — บรรเทาหลักฐานก่อน/หลังการบรรเทา — รันการโจมตี, ใช้การบรรเทา, รันการโจมตีอีกครั้ง, เปรียบเทียบขั้นตอน 1–6
เฟส 4 — รื้อถอนลบออบเจ็กต์การปรับใช้ทั้งหมดหลังจากได้รับการยืนยันอย่างชัดแจ้งรื้อถอน

ก่อนเริ่มเฟส 1 ให้ตรวจสอบว่าสภาพแวดล้อมสะอาด รันการตรวจสอบ API เหล่านี้เพื่อพิจารณาว่ามีออบเจ็กต์ที่เหลือจากการรันก่อนหน้าหรือไม่:

Terminal window
# Check all Phase 1 objects and compute environment status
HTTP_LB=$(curl -s -o /dev/null -w '%\{http_code\}' \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http")
HTTPS_LB=$(curl -s -o /dev/null -w '%\{http_code\}' \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https")
ORIGIN=$(curl -s -o /dev/null -w '%\{http_code\}' \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/xF5XC_ORIGIN_POOLx")
HC=$(curl -s -o /dev/null -w '%\{http_code\}' \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks/xF5XC_HC_NAMEx")
PD_COUNT=$(curl -s -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains" \
| jq '[.items // [] | .[] | select(.metadata.name != null)] | length')
MD_COUNT=$(curl -s -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains" \
| jq '[.items // [] | .[] | select(.metadata.name != null)] | length')
# If HTTPS LB exists, fetch body to detect skeleton state
HTTPS_IS_SKELETON="false"
if [ "$HTTPS_LB" = "200" ]; then
HTTPS_LB_BODY=$(curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https")
HTTPS_IS_SKELETON=$(echo "$HTTPS_LB_BODY" | jq '
((.spec.default_route_pools // []) | length == 0) and
(.spec.client_side_defense == null)
')
fi
# Compute deterministic environment status
jq -n \
--argjson http_lb "$HTTP_LB" \
--argjson https_lb "$HTTPS_LB" \
--argjson origin "$ORIGIN" \
--argjson hc "$HC" \
--argjson pd "$PD_COUNT" \
--argjson md "$MD_COUNT" \
--argjson https_skeleton "$HTTPS_IS_SKELETON" \
'{
objects: [
{ name: "http_lb", http_code: $http_lb, exists: ($http_lb == 200) },
{ name: "https_lb", http_code: $https_lb, exists: ($https_lb == 200), is_skeleton: $https_skeleton },
{ name: "origin_pool", http_code: $origin, exists: ($origin == 200) },
{ name: "healthcheck", http_code: $hc, exists: ($hc == 200) },
{ name: "protected_domains", count: $pd, exists: ($pd > 0) },
{ name: "mitigated_domains", count: $md, exists: ($md > 0) }
],
any_infra_exists: ($http_lb == 200 or ($https_lb == 200 and ($https_skeleton | not)) or $origin == 200 or $hc == 200),
any_csd_exists: ($pd > 0 or $md > 0),
status: (
if ($http_lb == 404 and $https_lb == 404 and $origin == 404 and $hc == 404 and $pd == 0 and $md == 0) then "CLEAN"
elif ($https_lb == 200 and $https_skeleton and $http_lb == 404 and $origin == 404 and $hc == 404 and $pd == 0 and $md == 0) then "HTTPS_SKELETON"
elif ($http_lb == 200 and $origin == 200) then "ALL_EXIST"
elif ($http_lb == 200 or ($https_lb == 200 and ($https_skeleton | not)) or $origin == 200 or $hc == 200) then "TEARDOWN_NEEDED"
elif ($md > 0 and $http_lb == 404 and ($https_lb == 404 or ($https_lb == 200 and $https_skeleton)) and $origin == 404 and $hc == 404) then "MITIGATIONS_ONLY"
else "TEARDOWN_NEEDED"
end
),
action: (
if ($http_lb == 404 and $https_lb == 404 and $origin == 404 and $hc == 404 and $pd == 0 and $md == 0) then "Proceed to Phase 1"
elif ($https_lb == 200 and $https_skeleton and $http_lb == 404 and $origin == 404 and $hc == 404 and $pd == 0 and $md == 0) then "Proceed to Phase 1 (HTTPS LB skeleton will be restored via PUT)"
elif ($http_lb == 200 and $origin == 200) then "All Phase 1 objects exist — verify health, optionally skip to Phase 2"
elif ($http_lb == 200 or ($https_lb == 200 and ($https_skeleton | not)) or $origin == 200 or $hc == 200) then "Run Phase 4 Teardown first, then re-check"
elif ($md > 0 and $http_lb == 404 and ($https_lb == 404 or ($https_lb == 200 and $https_skeleton)) and $origin == 404 and $hc == 404) then "Delete mitigated domains inline, then proceed"
else "Run Phase 4 Teardown first, then re-check"
end
)
}'

เมื่อออบเจ็กต์เฟส 1 ทั้งหมดมีอยู่ (200) และคุณวางแผนจะข้ามไปเฟส 2 ให้รัน คำสั่งตรวจสอบขั้นตอนที่ 7 ของเฟส 1 เพื่อยืนยันสุขภาพโครงสร้างพื้นฐาน ก่อนข้าม ใช้คำสั่งที่แน่นอนจาก เฟส 1 — ขั้นตอนที่ 7: ตรวจสอบ:

  1. การแก้ไข DNS: dig +short xF5XC_DOMAINNAMEx A
  2. สถานะ HTTP LB: GET .../http_loadbalancers/xF5XC_LB_NAMEx-http ส่งต่อไปยัง jq '{state: .spec.state}' — ต้องแสดง VIRTUAL_HOST_READY
  3. การกำหนดค่า CSD JS: GET .../js_configuration — ต้องมี scriptTag
  4. สถานะ CSD: GET .../status ส่งต่อไปยัง jq '{configured: .isConfigured, enabled: .isEnabled}' — ทั้งสองต้องเป็น true

การตรวจสอบที่จำเป็นทั้งหมด (DNS-1, LB-1, CSD-1, CSD-2) ต้อง PASS ก่อน ข้ามไปเฟส 2 หากการตรวจสอบใดล้มเหลว ให้ดำเนินการเฟส 1 เริ่มจาก ขั้นตอนที่ล้มเหลว

การตรวจสอบก่อนเริ่มต้นด้านบนจะยืนยันว่าสภาพแวดล้อม สะอาด ตารางความพร้อมด้านล่างจะยืนยันว่าสภาพแวดล้อม มีความสามารถ — ว่าข้อกำหนดเบื้องต้น โควตา การเชื่อมต่อ และบริการแพลตฟอร์มทั้งหมดพร้อมสำหรับการสาธิตที่ประสบความสำเร็จ รันตารางนี้ก่อนการประชุมทุกครั้งเป็นส่วนหนึ่งของขั้นตอนเตรียมการ

การตรวจสอบแต่ละรายการมี test ID, ระดับ (T0–T5), เกณฑ์ PASS/FAIL/WARN และเส้นทางการแก้ไข ระดับเป็นลำดับ — การ FAIL ในระดับก่อนหน้าจะบล็อกระดับถัดไปจากการทำงาน

ระดับหมวดหมู่บล็อกการสาธิต?วัตถุประสงค์
T0การเชื่อมต่อ & การยืนยันตัวตนใช่เราสามารถเข้าถึงแพลตฟอร์มและยืนยันตัวตนได้หรือไม่?
T1โควตา & ความจุใช่ (หากถึงขีดจำกัด)มีพื้นที่เพียงพอสำหรับสร้างออบเจ็กต์สาธิตหรือไม่?
T2ข้อกำหนดเบื้องต้นแพลตฟอร์มใช่บริการระดับ tenant ได้รับการกำหนดค่าแล้วหรือไม่?
T3สุขภาพ Originเตือนแอปพลิเคชันแบ็คเอนด์ตอบสนองหรือไม่?
T4สภาพแวดล้อมสะอาดแก้ไขอัตโนมัติมีออบเจ็กต์ที่เหลือจากการรันก่อนหน้าหรือไม่?
T5ความพร้อมของใบรับรองข้อมูลHTTPS จะทำงานหรือเราควรวางแผนสำหรับ HTTP เท่านั้น?

การตรวจสอบเหล่านี้ยืนยันว่าเครื่องปฏิบัติการสามารถเข้าถึง F5 XC API และข้อมูลประจำตัวถูกต้อง

Terminal window
HTTP_CODE=$(curl -s -o /dev/null -w '%\{http_code\}' --connect-timeout 10 --max-time 15 \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/web/namespaces")
echo "{\"http_code\": $HTTP_CODE}" | jq '{
check: "PF-T0-1",
http_code: .http_code,
status: (
if .http_code == 200 then "PASS"
elif .http_code == 401 then "FAIL"
else "FAIL"
end
),
detail: (
if .http_code == 200 then "API reachable, token valid"
elif .http_code == 401 then "Token expired or invalid — regenerate under Administration > Credentials > API Credentials"
elif .http_code == 0 then "Network unreachable — check connectivity, VPN, or TLS compatibility (try --tlsv1.2 --tls-max 1.2)"
else "Unexpected HTTP \(.http_code)"
end
)
}'
Terminal window
HTTP_CODE=$(curl -s -o /dev/null -w '%\{http_code\}' \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers")
echo "{\"http_code\": $HTTP_CODE}" | jq '{
check: "PF-T0-2",
http_code: .http_code,
status: (
if .http_code == 200 then "PASS"
elif .http_code == 404 then "WARN"
else "FAIL"
end
),
detail: (
if .http_code == 200 then "Token has namespace access"
elif .http_code == 403 then "Token lacks permissions for namespace — check role bindings"
elif .http_code == 404 then "Namespace does not exist — will be created in Phase 1 Step 0"
else "Unexpected HTTP \(.http_code)"
end
)
}'
Terminal window
HTTP_CODE=$(curl -s -o /dev/null -w '%\{http_code\}' \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/status")
echo "{\"http_code\": $HTTP_CODE}" | jq '{
check: "PF-T0-3",
http_code: .http_code,
status: (
if .http_code == 200 then "PASS"
elif .http_code == 404 then "WARN"
else "FAIL"
end
),
detail: (
if .http_code == 200 then "Token has CSD/Shape API permissions"
elif .http_code == 403 then "Token lacks CSD role binding — contact tenant administrator"
elif .http_code == 404 then "Namespace does not exist — CSD access will be verified after namespace creation in Phase 1"
else "Unexpected HTTP \(.http_code)"
end
)
}'

การตรวจสอบที่ไม่ทำลายจะทดสอบสิทธิ์การอ่านและเขียนสำหรับออบเจ็กต์ทุกประเภทที่การสาธิตต้องการ การอ่านทดสอบผ่าน GET บน list endpoints การเขียนทดสอบผ่าน DELETE บนออบเจ็กต์ที่ไม่มีอยู่จริง — API คืนค่า 403 หาก RBAC ปฏิเสธการดำเนินการ หรือ 404 หากการดำเนินการได้รับอนุญาตแต่ออบเจ็กต์ไม่มีอยู่ เทคนิคที่ไม่มีผลข้างเคียงนี้หลีกเลี่ยงการสร้างออบเจ็กต์ probe ชั่วคราว

Terminal window
PROBE_NAME="rbac-probe-nonexistent"
# Read probes
NS_R=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/web/namespaces/xF5XC_NAMESPACEx")
HC_R=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks")
OP_R=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools")
LB_R=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers")
CSD_R=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/status")
PD_R=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains")
MD_R=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains")
# Write probes (non-destructive: DELETE/cascade_delete on non-existent objects)
NS_W=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-X POST -H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d "{\"name\":\"$PROBE_NAME\"}" \
"xF5XC_API_URLx/api/web/namespaces/$PROBE_NAME/cascade_delete")
HC_W=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks/$PROBE_NAME")
OP_W=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/$PROBE_NAME")
LB_W=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/$PROBE_NAME")
PD_W=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains/$PROBE_NAME.example.com")
MD_W=$(curl -s -o /dev/null -w '%\{http_code\}' --max-time 10 \
-X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains/$PROBE_NAME.example.com")
# Compute deterministic permission matrix
jq -n \
--argjson ns_r "$NS_R" --argjson ns_w "$NS_W" \
--argjson hc_r "$HC_R" --argjson hc_w "$HC_W" \
--argjson op_r "$OP_R" --argjson op_w "$OP_W" \
--argjson lb_r "$LB_R" --argjson lb_w "$LB_W" \
--argjson csd_r "$CSD_R" \
--argjson pd_r "$PD_R" --argjson pd_w "$PD_W" \
--argjson md_r "$MD_R" --argjson md_w "$MD_W" \
'{
check: "PF-T0-4",
permissions: [
{ object: "namespace", read: ($ns_r != 403), write: ($ns_w != 403), required: false, note: "conditional — only if ns must be created" },
{ object: "healthcheck", read: ($hc_r != 403), write: ($hc_w != 403), required: false, note: "optional for CSD" },
{ object: "origin_pool", read: ($op_r != 403), write: ($op_w != 403), required: true, note: "" },
{ object: "http_loadbalancer", read: ($lb_r != 403), write: ($lb_w != 403), required: true, note: "" },
{ object: "csd_status", read: ($csd_r != 403), write: true, required: true, note: "read-only check" },
{ object: "protected_domain", read: ($pd_r != 403), write: ($pd_w != 403), required: true, note: "" },
{ object: "mitigated_domain", read: ($md_r != 403), write: ($md_w != 403), required: false, note: "Phase 3 only" }
],
status: (
if [
($op_r == 403), ($op_w == 403),
($lb_r == 403), ($lb_w == 403),
($csd_r == 403),
($pd_r == 403), ($pd_w == 403)
] | any then "FAIL"
elif ($ns_w == 403 or $hc_w == 403 or $md_w == 403) then "WARN"
else "PASS"
end
),
detail: (
[
(if ($op_r == 403 or $op_w == 403) then "Origin pool: permission denied" else null end),
(if ($lb_r == 403 or $lb_w == 403) then "Load balancer: permission denied" else null end),
(if $csd_r == 403 then "CSD API: permission denied — CSD may not be enabled for this namespace" else null end),
(if ($pd_r == 403 or $pd_w == 403) then "Protected domain: permission denied" else null end),
(if $ns_w == 403 then "Namespace: write denied — namespace must already exist (cannot create)" else null end),
(if $hc_w == 403 then "Healthcheck: write denied — will skip healthcheck creation" else null end),
(if $md_w == 403 then "Mitigated domain: write denied — Phase 3 mitigation will be skipped" else null end)
] | map(select(. != null)) | join("; ")
)
}'

การตรวจสอบเหล่านี้สอบถาม Quota Usage API ของ tenant เพื่อพิจารณาขีดจำกัด การใช้งานปัจจุบัน และความจุที่เหลือสำหรับออบเจ็กต์แต่ละชนิดที่การสาธิตต้องการ ซึ่งแทนที่การทดสอบแบบ probe-and-delete ด้วย API call แบบอ่านอย่างเดียวครั้งเดียวที่รายงานตัวเลขที่แน่นอน

สอบถาม endpoint การใช้โควตาระดับ tenant และคำนวณสถานะ PASS/WARN/FAIL แบบกำหนดได้สำหรับออบเจ็กต์แต่ละชนิดที่การสาธิตต้องการ endpoint นี้ต้องใช้ namespace system API call เดียวตรวจสอบโควตาระดับแพลตฟอร์มทั้งหมดพร้อมกัน

เกตกำหนดอาร์เรย์ demo_needs ที่ระบุจำนวนออบเจ็กต์แต่ละชนิดที่การสาธิตจะใช้ ว่าชนิดนั้นจำเป็นหรือไม่ และจำนวนขั้นต่ำที่จำเป็นเพื่อให้การสาธิตดำเนินการต่อได้ ตัวกรอง jq เปรียบเทียบ remaining กับ needed และคำนวณฟิลด์ status แบบกำหนดได้ — ไม่จำเป็นต้องมีผู้ดำเนินการตีความ

Terminal window
# Step 1: Fetch quota data
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/web/namespaces/system/quota/usage?namespace=system" \
> /tmp/quota.json
# Step 2: Compute gate status
jq '
. as $data |
[
{ kind: "healthcheck", needed: 1, required: false, min_proceed: 0 },
{ kind: "origin_pool", needed: 1, required: true, min_proceed: 1 },
{ kind: "endpoint", needed: 1, required: true, min_proceed: 1 },
{ kind: "http_loadbalancer", needed: 2, required: true, min_proceed: 1 }
] | map(
. as $req |
$data.objects[$req.kind] as $obj |
$obj.limit.maximum as $limit |
$obj.usage.current as $usage |
(if $limit == -1 then null else ($limit - $usage) end) as $remaining |
{
kind: $req.kind,
limit: (if $limit == -1 then "unlimited" else $limit end),
usage: $usage,
remaining: (if $remaining == null then "unlimited" else $remaining end),
needed: $req.needed,
status: (
if $remaining == null then "PASS"
elif $remaining >= $req.needed then "PASS"
elif $remaining >= $req.min_proceed then "WARN"
else
(if $req.required then "FAIL" else "WARN" end)
end
)
}
)
| {
checks: .,
gate: (if any(.[]; .status == "FAIL") then "FAIL"
elif any(.[]; .status == "WARN") then "WARN"
else "PASS" end)
}
' /tmp/quota.json

ผลลัพธ์เกต — ฟิลด์ gate คือผลตัดสินแบบกำหนดได้เดียว:

  • PASS — ออบเจ็กต์ทุกชนิดมี remaining >= needed การสาธิตสามารถดำเนินการต่อได้
  • WARN — อย่างน้อยหนึ่งชนิดมีความจุลดลงแต่ขั้นต่ำที่จะดำเนินการต่อได้ถูกบรรลุ (เช่น มีช่อง LB ว่างเพียง 1 แทนที่จะเป็น 2 หรือโควตา healthcheck หมด) การสาธิตสามารถดำเนินการต่อได้แต่มีข้อจำกัด
  • FAIL — อย่างน้อยหนึ่งชนิดที่จำเป็นมี remaining < min_proceed การสาธิตไม่สามารถดำเนินการต่อได้จนกว่าจะเพิ่มโควตา

ผลลัพธ์ตัวอย่าง (WARN — endpoint เต็มความจุ, healthcheck เกือบเต็ม):

{
"checks": [
{ "kind": "healthcheck", "limit": 150, "usage": 149, "remaining": 1, "needed": 1, "status": "PASS" },
{ "kind": "origin_pool", "limit": "unlimited", "usage": 420, "remaining": "unlimited", "needed": 1, "status": "PASS" },
{ "kind": "endpoint", "limit": 500, "usage": 500, "remaining": 0, "needed": 1, "status": "FAIL" },
{ "kind": "http_loadbalancer", "limit": "unlimited", "usage": 116, "remaining": "unlimited", "needed": 2, "status": "PASS" }
],
"gate": "FAIL"
}
ค่า gateการดำเนินการ
PASSดำเนินการต่อไปยัง PF-T1-4 (การตรวจสอบ protected domain) แล้วไป T2
WARNบันทึกข้อจำกัดในรายงานความพร้อม ดำเนินการต่อด้วยความสามารถที่ลดลง
FAILหยุด — รายงานชนิดที่หมดและขั้นตอนการแก้ไขด้านล่าง

การแก้ไขตามชนิด:

ชนิดการแก้ไข
healthcheckลบ healthcheck ที่ไม่ได้ใช้เพื่อเพิ่มความจุ การสาธิตดำเนินต่อได้โดยไม่มี healthcheck (CSD ไม่ต้องการ)
origin_poolลบ origin pool ที่ไม่ได้ใช้หรือติดต่อผู้ดูแลระบบเพื่อเพิ่มขีดจำกัดของ tenant
endpointลบ origin pool ที่ไม่ได้ใช้ใน namespace อื่นเพื่อเพิ่มความจุ endpoint (endpoint เป็นออบเจ็กต์ย่อยของ origin pool) หรือติดต่อผู้ดูแลระบบ
http_loadbalancerลบ load balancer ที่ไม่ได้ใช้หรือติดต่อผู้ดูแลระบบ หากมีเพียง 1 ช่องว่าง HTTP LB (หลัก) จะถูกสร้างแต่ HTTPS LB (รอง) จะถูกข้าม

CSD protected domain ไม่ปรากฏใน Quota Usage API ของแพลตฟอร์ม ใช้การตรวจสอบแบบ probe: สร้างและลบ probe protected domain ทันที

Terminal window
# Create probe and capture both HTTP code and response body
PROBE_BODY=$(curl -s -w '\n%\{http_code\}' -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"metadata": {
"name": "preflight-probe.example.com",
"namespace": "xF5XC_NAMESPACEx"
},
"spec": {
"protected_domain": "example.com"
}
}' \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains")
PROBE_HTTP=$(echo "$PROBE_BODY" | tail -1)
PROBE_JSON=$(echo "$PROBE_BODY" | sed '$d')
# Compute status
echo "$PROBE_JSON" | jq --argjson http "$PROBE_HTTP" '{
check: "PF-T1-4",
http_code: $http,
status: (
if $http == 409 then "PASS"
elif (.code // 0) == 8 then "FAIL"
elif .metadata.name then "PASS"
else "FAIL"
end
),
detail: (
if $http == 409 then "example.com already registered — quota not exhausted"
elif (.code // 0) == 8 then "Protected domain quota exhausted — delete unused protected domains"
elif .metadata.name then "Probe created — quota available"
else "Unexpected response"
end
)
}'
# Cleanup probe (404 is expected if 409 occurred)
curl -s -X DELETE \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains/preflight-probe.example.com" \
> /dev/null

หาก PF-T1-0 ล้มเหลว (Quota Usage API คืนค่า 403, 404 หรือรูปแบบที่ไม่คาดคิด) ให้ใช้การตรวจสอบแบบ probe-and-delete สำรองสำหรับโควตา healthcheck, origin pool, endpoint และ load balancer การตรวจสอบเหล่านี้สร้างออบเจ็กต์ชั่วคราวและลบทันที — หากการสร้างคืนค่า error code 8 พร้อม “exhausted limits” แสดงว่าโควตาเต็ม

แต่ละ fallback probe ใช้รูปแบบเดียวกัน: สร้างออบเจ็กต์ชั่วคราว คำนวณสถานะแบบกำหนดได้จากการตอบกลับ จากนั้นลบ probe ฟิลด์ status เป็น PASS หากออบเจ็กต์ถูกสร้าง (มี .metadata.name), WARN หรือ FAIL หาก error code 8 (exhausted limits) ขึ้นอยู่กับว่าชนิดนั้นจำเป็นหรือไม่

Probe ของ Healthcheck (WARN หากหมด — healthcheck เป็นตัวเลือกสำหรับ CSD):

Terminal window
RESULT=$(curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"metadata": {
"name": "preflight-quota-probe",
"namespace": "xF5XC_NAMESPACEx"
},
"spec": {
"http_health_check": {
"use_origin_server_name": {},
"path": "/",
"use_http2": false
},
"timeout": 3,
"interval": 15,
"unhealthy_threshold": 1,
"healthy_threshold": 3
}
}' \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks")
echo "$RESULT" | jq '{
check: "fallback-healthcheck",
status: (if .metadata.name then "PASS" elif (.code // 0) == 8 then "WARN" else "FAIL" end),
detail: (if .metadata.name then "Quota available" elif (.code // 0) == 8 then "Quota full — healthcheck optional, demo proceeds" else "Unexpected: \(.message // "unknown error")" end)
}'
curl -s -X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks/preflight-quota-probe" \
> /dev/null

Probe ของ Origin pool & endpoint (FAIL หากหมด — ทั้งสองจำเป็น):

Terminal window
RESULT=$(curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"metadata": {
"name": "preflight-origin-probe",
"namespace": "xF5XC_NAMESPACEx"
},
"spec": {
"origin_servers": [{
"public_ip": { "ip": "192.0.2.1" },
"labels": {}
}],
"no_tls": {},
"port": 80,
"same_as_endpoint_port": {},
"healthcheck": [],
"loadbalancer_algorithm": "LB_OVERRIDE",
"endpoint_selection": "LOCAL_PREFERRED"
}
}' \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools")
echo "$RESULT" | jq '{
check: "fallback-origin-pool",
status: (if .metadata.name then "PASS" elif (.code // 0) == 8 then "FAIL" else "FAIL" end),
detail: (if .metadata.name then "Quota available" elif (.code // 0) == 8 then "Quota exhausted — \(.message // "limit reached")" else "Unexpected: \(.message // "unknown error")" end)
}'
curl -s -X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/preflight-origin-probe" \
> /dev/null

Probe ของ HTTP load balancer (FAIL หากหมด — LB จำเป็น):

Terminal window
RESULT=$(curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"metadata": {
"name": "preflight-lb-probe",
"namespace": "xF5XC_NAMESPACEx",
"disable": false
},
"spec": {
"domains": ["preflight-probe.example.com"],
"http": {
"dns_volterra_managed": false,
"port": 80
},
"advertise_on_public_default_vip": {},
"default_route_pools": [],
"disable_rate_limit": {},
"no_service_policies": {},
"round_robin": {},
"disable_waf": {},
"no_challenge": {},
"disable_bot_defense": {},
"disable_api_definition": {},
"disable_api_discovery": {},
"disable_ip_reputation": {},
"disable_malicious_user_detection": {},
"single_lb_app": {
"disable_discovery": {},
"disable_ddos_detection": {},
"disable_malicious_user_detection": {}
},
"disable_trust_client_ip_headers": {},
"user_id_client_ip": {},
"disable_threat_mesh": {},
"l7_ddos_action_default": {},
"system_default_timeouts": {},
"default_sensitive_data_policy": {},
"disable_malware_protection": {},
"disable_api_testing": {}
}
}' \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers")
echo "$RESULT" | jq '{
check: "fallback-http-lb",
status: (if .metadata.name then "PASS" elif (.code // 0) == 8 then "FAIL" else "FAIL" end),
detail: (if .metadata.name then "Quota available" elif (.code // 0) == 8 then "Quota exhausted — \(.message // "limit reached")" else "Unexpected: \(.message // "unknown error")" end)
}'
curl -s -X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/preflight-lb-probe" \
> /dev/null

การตรวจสอบเหล่านี้ยืนยันบริการระดับ tenant ที่การสาธิตต้องพึ่งพา

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/status" \
| jq '{
check: "PF-T2-1",
configured: .isConfigured,
enabled: .isEnabled,
status: (if .isConfigured and .isEnabled then "PASS" else "FAIL" end),
detail: (
if .isConfigured and .isEnabled then "CSD is active"
elif (.isConfigured | not) then "CSD not enabled at tenant level — contact F5 XC administrator"
else "CSD configured but not active — contact administrator"
end
)
}'
Terminal window
HTTP_CODE=$(curl -s -o /dev/null -w '%\{http_code\}' \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/dns/namespaces/system/dns_zones/xF5XC_ROOT_DOMAINx")
echo "{\"http_code\": $HTTP_CODE}" | jq '{
check: "PF-T2-2",
http_code: .http_code,
status: (
if .http_code == 200 then "PASS"
elif .http_code == 404 then "WARN"
elif .http_code == 403 then "WARN"
else "FAIL"
end
),
detail: (
if .http_code == 200 then "DNS zone exists in F5 XC"
elif .http_code == 404 then "No F5 XC DNS zone — external DNS may be in use"
elif .http_code == 403 then "Token lacks DNS zone read access (system namespace)"
else "Unexpected HTTP \(.http_code)"
end
)
}'

รันเฉพาะเมื่อ PF-T2-2 คืนค่า 200 (มี F5 XC DNS zone)

ตรวจสอบสถานะปัจจุบัน:

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/dns/namespaces/system/dns_zones/xF5XC_ROOT_DOMAINx" \
| jq '{
check: "PF-T2-3",
managed_records: (.spec.primary.allow_http_lb_managed_records // false),
status: (if .spec.primary.allow_http_lb_managed_records == true then "PASS" else "WARN" end),
detail: (if .spec.primary.allow_http_lb_managed_records == true then "LB-managed DNS records enabled" else "Managed records not enabled — auto-remediation may be needed" end)
}'

แก้ไขอัตโนมัติหากจำเป็น: หาก status เป็น WARN และ PF-T2-4 แสดง nameserver ของ F5 XC (ns1.f5clouddns.com, ns2.f5clouddns.com) ให้เปิดใช้งาน managed records อัตโนมัติโดยใช้ GET+PUT:

Terminal window
# Get current zone config
ZONE_CONFIG=$(curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/dns/namespaces/system/dns_zones/xF5XC_ROOT_DOMAINx")
# Update with managed records enabled
echo "$ZONE_CONFIG" \
| jq '.spec.primary.allow_http_lb_managed_records = true' \
| curl -s -X PUT \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d @- \
"xF5XC_API_URLx/api/config/dns/namespaces/system/dns_zones/xF5XC_ROOT_DOMAINx" \
| jq .

จากนั้นตรวจสอบอีกครั้งเพื่อยืนยันว่าการอัปเดตมีผล:

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/dns/namespaces/system/dns_zones/xF5XC_ROOT_DOMAINx" \
| jq '.spec.primary.allow_http_lb_managed_records'
ผลลัพธ์DNS Authorityสถานะการแก้ไข
trueใดก็ได้PASSLB-managed DNS records จะถูกสร้างอัตโนมัติ
false/nullF5 XCแก้ไขอัตโนมัติเปิดใช้งานผ่าน GET+PUT, ตรวจสอบ, รายงานผลลัพธ์
false/nullภายนอกINFOManaged records ไม่ใช้ได้กับ DNS ภายนอก — ขั้นตอนที่ 4 ของเฟส 1 จะใช้ ตัวเลือก B (สร้าง record ด้วยตนเอง)
การแก้ไขอัตโนมัติล้มเหลวF5 XCFAILToken อาจไม่มีสิทธิ์เขียน system namespace — ติดต่อผู้ดูแลระบบ tenant
Terminal window
NS_RECORDS=$(dig +short NS xF5XC_ROOT_DOMAINx)
echo "$NS_RECORDS" | jq -Rs '{
check: "PF-T2-4",
nameservers: (split("\n") | map(select(length > 0))),
status: (
if (split("\n") | map(select(length > 0)) | length) == 0 then "FAIL"
elif test("f5clouddns\\.com") then "PASS"
else "INFO"
end
),
detail: (
if (split("\n") | map(select(length > 0)) | length) == 0 then "No NS records — DNS is broken for this domain"
elif test("f5clouddns\\.com") then "F5 XC is authoritative — automatic DNS management available"
else "External DNS provider — Phase 1 Step 4 will use Option B (manual record creation)"
end
)
}'

การตรวจสอบเหล่านี้ยืนยันว่าแอปพลิเคชันแบ็คเอนด์สามารถเข้าถึงได้

การตรวจสอบเงื่อนไขข้าม: คำนวณว่า origin IP เป็นที่อยู่ RFC 5737 TEST-NET หรือไม่ก่อนรันการทดสอบการเชื่อมต่อ:

Terminal window
echo "xF5XC_ORIGIN_IPx" | jq -Rs '{
check: "PF-T3-skip",
origin_ip: (rtrimstr("\n")),
is_test_net: (rtrimstr("\n") | test("^192\\.0\\.2\\.|^198\\.51\\.100\\.|^203\\.0\\.113\\.")),
status: (if (rtrimstr("\n") | test("^192\\.0\\.2\\.|^198\\.51\\.100\\.|^203\\.0\\.113\\.")) then "SKIP" else "CONTINUE" end),
detail: (if (rtrimstr("\n") | test("^192\\.0\\.2\\.|^198\\.51\\.100\\.|^203\\.0\\.113\\.")) then "RFC 5737 TEST-NET address — not routable, connectivity testing skipped" else "Routable IP — proceed with connectivity tests" end)
}'

หาก status เป็น SKIP ให้บันทึก PF-T3-1 และ PF-T3-2 เป็น SKIP และไปยัง T4 มิฉะนั้นให้รันการตรวจสอบด้านล่าง

Terminal window
HTTP_CODE=$(curl -s -o /dev/null -w '%\{http_code\}' --connect-timeout 10 --max-time 15 \
"http://xF5XC_ORIGIN_IPx:xF5XC_ORIGIN_PORTx/")
echo "{\"http_code\": $HTTP_CODE}" | jq '{
check: "PF-T3-1",
http_code: .http_code,
status: (if .http_code >= 200 and .http_code < 600 then "PASS" elif .http_code == 0 then "WARN" else "WARN" end),
detail: (
if .http_code >= 200 and .http_code < 600 then "Origin responding with HTTP \(.http_code)"
elif .http_code == 0 then "Origin unreachable from this network — LB may use a different path"
else "Unexpected response code \(.http_code)"
end
)
}'

รันเฉพาะเมื่อ PF-T3-1 คืนค่า HTTP status ที่ถูกต้อง:

Terminal window
curl -s --max-time 10 "http://xF5XC_ORIGIN_IPx:xF5XC_ORIGIN_PORTx/" \
| grep -qi '</html>' && echo "PASS: HTML content" || echo "WARN: No HTML detected"
ผลลัพธ์สถานะการแก้ไข
PASS: HTML contentPASSOrigin ให้บริการหน้า HTML (จำเป็นสำหรับการฉีด CSD JS)
WARN: No HTML detectedWARNOrigin อาจเป็นบริการ API เท่านั้นหรือคืนค่าที่ไม่ใช่ HTML — การฉีด CSD JS ต้องการการตอบกลับหน้า HTML

การตรวจสอบเหล่านี้ยืนยันว่าไม่มี ออบเจ็กต์การกำหนดค่า F5 XC ที่มีชื่อ เหลือจากการรันสาธิตก่อนหน้า — HTTP load balancer, HTTPS load balancer, origin pool, healthcheck, protected domain และ mitigated domain T4 เกี่ยวกับการทำความสะอาดระดับออบเจ็กต์: ว่าออบเจ็กต์ API ที่จะขัดแย้งกับการสร้างเฟส 1 ยังคงมีอยู่หรือไม่ มันไม่ทดสอบที่อยู่ IP การเชื่อมต่อเครือข่าย หรือสุขภาพ origin (ข้อกังวลเหล่านั้นอยู่ใน T3)

รันคำสั่ง pre-flight ทั้งหกจากส่วน การตรวจสอบก่อนเริ่มต้น ด้านบน ใช้ ตรรกะการตัดสินใจ เพื่อกำหนดขั้นตอนถัดไป หากมีออบเจ็กต์อยู่ การรื้อถอนอัตโนมัติจะดำเนินการในขั้นตอนเตรียมการ (ไม่ต้องมีการยืนยัน)

ตรวจสอบและลบออบเจ็กต์ probe ค้างจากการรัน pre-flight ที่ถูกขัดจังหวะก่อนหน้าด้วย probe เหล่านี้สร้างขึ้นเฉพาะเมื่อ Quota Usage API ไม่สามารถใช้งานได้และมีการใช้ การตรวจสอบแบบ probe สำรอง หรือสำหรับ protected domain probe (PF-T1-4) ซึ่งใช้การตรวจสอบแบบ probe เสมอ:

Terminal window
# Stale probe cleanup (delete in any order — probes have no dependencies)
curl -s -X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks/preflight-quota-probe" \
> /dev/null
curl -s -X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/preflight-lb-probe" \
> /dev/null
curl -s -X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/preflight-origin-probe" \
> /dev/null
curl -s -X DELETE -H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains/preflight-probe.example.com" \
> /dev/null

DELETE แต่ละรายการคืนค่า 200 ({} ว่าง) หากออบเจ็กต์มีอยู่ หรือ 404 หากไม่มี — ทั้งสองเป็นสิ่งที่คาดหวัง

การตรวจสอบเหล่านี้ประเมินว่า HTTPS จะทำงานหรือการสาธิตควรวางแผนสำหรับ HTTP เท่านั้น

ตรวจสอบว่ามีการออกใบรับรอง Let’s Encrypt สำหรับโดเมนสาธิตเมื่อเร็วๆ นี้หรือไม่ วงจรสร้าง/ทำลายบ่อยๆ อาจทำให้ถึงขีดจำกัดอัตรารายสัปดาห์ (5 ใบรับรองซ้ำต่อสัปดาห์ต่อโดเมน)

รันเฉพาะเมื่อมี HTTPS LB จากการรันก่อนหน้า (PF-T4 พบออบเจ็กต์):

Terminal window
CERT_BODY=$(curl -s -w '\n%\{http_code\}' \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https")
CERT_HTTP=$(echo "$CERT_BODY" | tail -1)
CERT_JSON=$(echo "$CERT_BODY" | sed '$d')
if [ "$CERT_HTTP" = "404" ]; then
echo '{"check":"PF-T5-2","cert_state":null,"status":"SKIP","detail":"No HTTPS LB — certificate state assessed after Phase 1 Step 3"}'
else
echo "$CERT_JSON" | jq '{
check: "PF-T5-2",
cert_state: .spec.cert_state,
status: (
if .spec.cert_state == "CertificateValid" then "PASS"
elif .spec.cert_state == "AutoCertDomainRateLimited" then "INFO"
elif (.spec.cert_state | test("Pending|Started")) then "INFO"
else "INFO"
end
),
detail: (
if .spec.cert_state == "CertificateValid" then "Certificate healthy — HTTPS will work"
elif .spec.cert_state == "AutoCertDomainRateLimited" then "Let'\''s Encrypt rate limit hit — plan for HTTP-only demo"
elif (.spec.cert_state | test("Pending|Started")) then "Certificate provisioning in progress"
else "Certificate state: \(.spec.cert_state // "unknown")"
end
)
}'
fi

หลังจากรันทุกระดับแล้ว ให้นำเสนอรายงานความพร้อมรวม:

## ความพร้อมสาธิต: พร้อม / ไม่พร้อม / พร้อมพร้อมคำเตือน
### T0: การเชื่อมต่อ & การยืนยันตัวตน
| การตรวจสอบ | ผลลัพธ์ | สถานะ |
|---|---|---|
| PF-T0-1: API Connectivity | 200 | PASS |
| PF-T0-2: Namespace Access | 200 | PASS |
| PF-T0-3: CSD API Access | 200 | PASS |
### T1: โควตา & ความจุ
| การตรวจสอบ | ชนิด | ขีดจำกัด | การใช้งาน | เหลือ | ต้องการ | สถานะ |
|---|---|---|---|---|---|---|
| PF-T1-0: Quota Usage Gate | `healthcheck` | 150 | 148 | 2 | 1 | PASS |
| PF-T1-0: Quota Usage Gate | `origin_pool` | unlimited | 420 | unlimited | 1 | PASS |
| PF-T1-0: Quota Usage Gate | `endpoint` | 500 | 498 | 2 | 1 | PASS |
| PF-T1-0: Quota Usage Gate | `http_loadbalancer` | unlimited | 116 | unlimited | 2 | PASS |
| PF-T1-0: Quota Usage Gate | **gate** | — | — | — | — | **PASS** |
| PF-T1-4: Protected Domain | — | — | — | — | 1 | PASS (probe) |
### T2: ข้อกำหนดเบื้องต้นแพลตฟอร์ม
| การตรวจสอบ | ผลลัพธ์ | สถานะ |
|---|---|---|
| PF-T2-1: CSD Tenant Status | configured + enabled | PASS |
| PF-T2-2: DNS Zone Exists | 200 | PASS |
| PF-T2-3: DNS Managed Records | true | PASS |
| PF-T2-4: DNS Nameserver Authority | f5clouddns.com | PASS |
### T3: สุขภาพ Origin
| การตรวจสอบ | ผลลัพธ์ | สถานะ |
|---|---|---|
| PF-T3-1: Origin Connectivity | TEST-NET address (192.0.2.1) | SKIP |
| PF-T3-2: HTML Content | TEST-NET address | SKIP |
### T4: สภาพแวดล้อมสะอาด
| การตรวจสอบ | ผลลัพธ์ | สถานะ |
|---|---|---|
| HTTP LB | 404 | PASS |
| HTTPS LB | 404 | PASS |
| Origin Pool | 404 | PASS |
| Healthcheck | 404 | PASS |
| Protected Domains | 0 | PASS |
| Mitigated Domains | 0 | PASS |
### T5: ความพร้อมของใบรับรอง
| การตรวจสอบ | ผลลัพธ์ | สถานะ |
|---|---|---|
| PF-T5-2: Cert State | SKIP (no HTTPS LB) | INFO |
### คำเตือน
- (ระบุรายการ WARN หรือ INFO พร้อมบริบท)

กฎสถานะโดยรวม:

เงื่อนไขสถานะ
การตรวจสอบ T0–T4 ทั้งหมด PASSพร้อม
การตรวจสอบ T0–T4 ทั้งหมด PASS แต่ T3 หรือ T5 มี WARN/INFOพร้อมพร้อมคำเตือน
การตรวจสอบ T0, T1 หรือ T2 ใดเป็น FAILไม่พร้อม — แก้ไขก่อนดำเนินการต่อ
T4 มีออบเจ็กต์ที่เหลือแก้ไขอัตโนมัติ (รื้อถอน) จากนั้นตรวจสอบอีกครั้ง

ส่วนนี้กำหนด ขั้นตอนการทำงานแบบกำหนดได้ สำหรับผู้ช่วย AI (Claude Code, Copilot ฯลฯ) ที่ดำเนินการขั้นตอนอัตโนมัติ API การปฏิบัติตามโปรโตคอลนี้ขจัดการคาดเดา — จุดตัดสินใจทุกจุดมีเส้นทางการแก้ไขที่กำหนดไว้

แก้ไขตัวแปรแต่ละตัวตามลำดับที่แน่นอนนี้ หยุดที่แหล่งแรกที่ให้ค่าที่ไม่ใช่ placeholder:

  1. ตรวจสอบไฟล์ .env — มองหา .env ในรูทของ repository หากมีอยู่ ให้แยกวิเคราะห์คู่ KEY=VALUE ทั้งหมด
  2. ตรวจสอบ shell environment — รัน env | grep F5XC_ เพื่อหาค่าที่ export แล้วในเซสชันปัจจุบัน
  3. ระบุค่าที่ขาด — เปรียบเทียบค่าที่แก้ไขแล้วกับตารางจำเป็น/ตัวเลือกด้านล่าง ค่าจะ “ขาด” หากไม่มี ว่างเปล่า หรือยังคงตั้งค่าเป็น placeholder เริ่มต้น (เช่น example-api-token, example-tenant, example-namespace, app.example.com, user@example.com)
  4. ถามผู้ดำเนินการ — สำหรับตัวแปร จำเป็น ที่ขาดแต่ละตัว ให้ถามผู้ดำเนินการเพื่อให้ค่า อย่าดำเนินการต่อจนกว่าตัวแปรจำเป็นทั้งหมดจะได้รับการแก้ไข
  5. ใช้ค่าเริ่มต้น — สำหรับตัวแปร ตัวเลือก ที่ขาดแต่ละตัว ใช้ค่าเริ่มต้นจากตารางด้านล่างโดยไม่ต้องถาม

สตริงว่าง = ขาด: ตัวแปรที่ export ด้วยค่าว่าง (เช่น F5XC_HC_NAME="") ถูกถือเสมือนตัวแปรที่ไม่ได้ตั้งค่า — ใช้ค่าเริ่มต้น ใช้ shell parameter expansion (${F5XC_HC_NAME:-csd-hc}) เพื่อใช้ค่าเริ่มต้นในขั้นตอนเดียว

  1. แสดงการยืนยัน — แสดงตารางตัวแปรที่แก้ไขแล้วให้ผู้ดำเนินการดูและรอการอนุมัติก่อนดำเนินการ API call ใดๆ

การ override ขั้นตอนเตรียมการ: ระหว่างขั้นตอนที่ 1 เตรียมการ ให้ข้ามการรอใน ขั้นตอนที่ 6 แสดงตารางตัวแปรที่แก้ไขแล้วเพื่อบันทึก จากนั้น ดำเนินการต่อทันที ขั้นตอนที่ 1–5 ยังคงใช้ได้ — หากตัวแปรจำเป็นใดขาด หลังจากตรวจสอบ .env และ shell ให้หยุดและรายงาน ตัวแปรที่ขาด

ตัวแปรจำเป็นค่าเริ่มต้นPlaceholder (ถือว่าขาด)
F5XC_API_TOKENใช่example-api-token
F5XC_API_URLใช่https://example-tenant.console.ves.volterra.io
F5XC_NAMESPACEใช่example-namespace
F5XC_DOMAINNAMEใช่app.example.com
F5XC_ROOT_DOMAINใช่example.com
F5XC_LB_NAMEใช่example-lb-name, example-lb
F5XC_EMAILใช่user@example.com
F5XC_HC_NAMEตัวเลือกcsd-hc
F5XC_ORIGIN_IPตัวเลือก44.232.69.192
F5XC_ORIGIN_POOLตัวเลือกcsd-origin
F5XC_ORIGIN_PORTตัวเลือก3000

ผู้ช่วย AI ทำงานในหนึ่งในสามโหมดระหว่างการสาธิต:

โหมดเมื่อใช้งานพฤติกรรม
ปกติค่าเริ่มต้นระหว่างเตรียมการ, ดำเนินการ, รื้อถอนคำสั่งที่บันทึกไว้เท่านั้น
ดีบักเปิดอัตโนมัติเมื่อเกิดข้อผิดพลาดการแก้ไขปัญหาอย่างสร้างสรรค์, อัปเดตเอกสาร
ถาม-ตอบระหว่างขั้นตอนถาม-ตอบด้นสด — อนุญาตคำสั่ง ad-hoc เพื่อตอบคำถามผู้ชม

โหมดปกติ (ค่าเริ่มต้น):

  • API call, คำค้นตรวจสอบ และคำสั่ง shell ทุกรายการ ต้องมาจาก ไฟล์เฟสโดยตรง (เฟส 1–4) หรือจากส่วนการตรวจสอบก่อนเริ่มต้นด้านบน
  • แทนที่เฉพาะ placeholder xTOKENx ด้วยค่าตัวแปรที่แก้ไขแล้ว
  • อย่าสร้าง API endpoint, jq filter หรือคำสั่ง cURL จาก ความรู้ทั่วไปหรือการอนุมาน
  • หากคำสั่งที่จำเป็นไม่ได้บันทึกไว้ ให้หยุดและรายงานให้ผู้ดำเนินการ: “ขั้นตอนการตรวจสอบนี้ไม่ครอบคลุมในเอกสารเฟส”

โหมดดีบัก (เปิดอัตโนมัติเมื่อเกิดข้อผิดพลาด):

  • เปิดอัตโนมัติเมื่อคำสั่งที่บันทึกไว้ให้ผลลัพธ์ที่ไม่คาดคิด: HTTP response ที่ไม่ใช่ 2xx, jq parse error, command timeout หรือ response body ที่ขัดแย้งกับตารางหลักฐาน
  • ในโหมดดีบัก ผู้ช่วย AI อาจสร้างคำสั่งวินิจฉัย ตรวจสอบ API response ดิบ ทดสอบ endpoint ที่แตกต่าง และใช้ การแก้ไขปัญหาอย่างสร้างสรรค์เพื่อหาสาเหตุ
  • นำหน้าผลลัพธ์ดีบักทั้งหมดด้วย [DEBUG] เพื่อให้ผู้ดำเนินการสามารถ แยกแยะกิจกรรมวินิจฉัยจากการดำเนินการปกติ
  • บันทึกสิ่งที่เรียนรู้: หลังจากแก้ไขปัญหาแล้ว ให้อัปเดต ไฟล์เฟสที่เกี่ยวข้องหรือส่วนการแก้ไขปัญหาด้วย:
    1. สถานการณ์ความล้มเหลว (อะไรผิดพลาด)
    2. สิ่งที่ลองแล้วไม่ได้ผล (เพื่อให้การรันในอนาคตไม่ต้องทำซ้ำ)
    3. การแก้ไขที่ทำงาน (คำสั่งหรือการแก้ไขที่แก้ปัญหาได้)
  • เป้าหมายของโหมดดีบักคือ ขจัดตัวเอง — ทุกเซสชันดีบัก ควรสร้างการอัปเดตเอกสารที่ทำให้การดำเนินการครั้งถัดไป เป็นแบบกำหนดได้อย่างสมบูรณ์
  • เมื่อเอกสารได้รับการอัปเดตและปัญหาได้รับการแก้ไขแล้ว ให้กลับ ไปโหมดปกติและดำเนินการต่อจากขั้นตอนที่บันทึกไว้สำเร็จล่าสุด
  • หากโหมดดีบักไม่สามารถแก้ไขปัญหาได้ ให้รายงานผลการค้นพบให้ ผู้ดำเนินการและหยุด — อย่าดำเนินการต่อไปยังเฟสถัดไป

โหมดถาม-ตอบ (ระหว่างขั้นตอนถาม-ตอบ):

  • ใช้งานเฉพาะระหว่างขั้นตอนถาม-ตอบของการประชุม หลังจากสรุปการสาธิต
  • ผู้ช่วย AI อาจสร้าง API call แบบ ad-hoc, รันคำสั่ง วินิจฉัย, นำทางไปยังหน้าที่ไม่ได้เตรียมสคริปต์ไว้ และแก้ไข สภาพแวดล้อมสาธิตสดเพื่อแสดงคำตอบสำหรับคำถามของผู้ชม
  • ไม่มีนำหน้า [DEBUG] — นี่เป็นพฤติกรรมด้นสดที่ตั้งใจ ไม่ใช่การกู้คืนข้อผิดพลาด
  • ใช้ส่วน CSD Product Expertise ใน DEMO_EXECUTOR.md เป็น ฐานความรู้สำหรับคำถามเกี่ยวกับผลิตภัณฑ์

การสะสม initScript เป็นสาเหตุทั่วไปของความล้มเหลวในการสาธิต การเรียก navigate_page แต่ละครั้งพร้อมพารามิเตอร์ initScript จะเพิ่มสคริปต์ไปยัง รายการถาวรที่ทำงานทุกครั้งที่โหลดเอกสารในภายหลัง ปฏิบัติตาม กฎเหล่านี้:

  • นำทางไปยัง about:blank เสมอ ก่อนการนำทางใดๆ ที่มี initScript เพื่อล้างสคริปต์ที่สะสมจากการรันก่อนหน้า
  • ใช้ new_page พร้อม isolatedContext เมื่อสลับระหว่าง เฟสสาธิต (เช่น เฟส 2 → เฟส 3) เพื่อให้แน่ใจว่ามีสถานะเบราว์เซอร์ ที่สะอาดสมบูรณ์
  • การกู้คืนจากหน้าที่ไม่ตอบสนอง — หากเกิด timeout ของ take_screenshot หรือ take_snapshot แสดงว่า browser context ใช้ ทรัพยากรหมด ใช้ new_page พร้อม isolatedContext เพื่อสร้าง context ใหม่ จากนั้นลองอีกครั้งจากขั้นตอนนำทาง about:blank
  • ดู aside ของ การจำลองการโจมตีเฟส 2 สำหรับ คำแนะนำโดยละเอียดเกี่ยวกับข้อผิดพลาด origin ชั่วคราวและการกู้คืนจาก ทรัพยากรหมด

หลังจาก API call ทุกครั้ง ผู้ช่วย AI ต้องนำเสนอหลักฐานที่มีโครงสร้างให้ผู้ดำเนินการโดยใช้รูปแบบนี้:

ขั้นตอนการสร้าง (POST):

ฟิลด์ค่าสถานะ
HTTP Status200PASS
Object Namecsd-origin
Key Property(แยกผ่าน jq)

หลังจากแต่ละขั้นตอนการสร้าง ให้รัน GET เพื่อยืนยันว่าออบเจ็กต์มีอยู่และแสดงคุณสมบัติหลัก หาก GET คืนค่า 404 ให้รายงาน FAIL และหยุด

ขั้นตอนการตรวจสอบ (GET/dig):

การทดสอบผลลัพธ์สถานะ
DNS-1: A Record198.51.100.10PASS
LB-1: HTTP LB StateVIRTUAL_HOST_READYPASS
LB-2: HTTPS LB StateVIRTUAL_HOST_READYINFO (ตัวเลือก)
TLS-1: Cert StateCertificateValidINFO (ตัวเลือก)
CSD-1: JS Tagมี scriptTagPASS

อ้างอิง test case ID ของ การวินิจฉัย & การตรวจสอบ (DNS-1, TLS-1, LB-1, CSD-1 ฯลฯ) เป็นมาตรฐานการตรวจสอบสำหรับแต่ละชั้น

การดำเนินการเฟสเป็นลำดับและมีเกต: แต่ละเฟสต้อง PASS ในการตรวจสอบที่จำเป็นทั้งหมดก่อนเฟสถัดไปจะเริ่ม การสาธิตปฏิบัติตามวงจรชีวิตการประชุมสี่ขั้นตอน — ดูส่วน Meeting Stages ใน DEMO_EXECUTOR.md สำหรับวลีกระตุ้นและกฎพฤติกรรม

ผู้ช่วย AI ปฏิบัติตามลำดับนี้:

  1. เตรียมการ — แก้ไขตัวแปร, รันการตรวจสอบ pre-flight, ยืนยันสภาพแวดล้อมสะอาด (สามารถรันแยกก่อนการประชุม)
  2. แนะนำ — SE แนะนำตัวเองและระบุเป้าหมายผลลัพธ์ (การมองเห็นภัยคุกคามฝั่งไคลเอนต์, การปฏิบัติตาม PCI, การตรวจจับแบบเรียลไทม์)
  3. ดำเนินการเฟส 1 (ขั้นตอน 1–7) — การสร้างและตรวจสอบโครงสร้างพื้นฐาน; การตรวจสอบเฟส 1 ทั้งหมดต้อง PASS ก่อนดำเนินการต่อ
  4. ดำเนินการเฟส 2 (ขั้นตอน 8–9) — การจำลองการโจมตีและการตรวจสอบการตรวจจับผ่าน API; ผู้ช่วย AI ที่มีระบบอัตโนมัติเบราว์เซอร์จะดำเนินการขั้นตอนเบราว์เซอร์โดยตรง ผู้ดำเนินการที่ไม่มีเครื่องมือเบราว์เซอร์จะดำเนินการด้วยตนเอง
  5. ดำเนินการเฟส 3 — ยืนยัน baseline ที่สะอาด, รันการโจมตี (หลักฐานก่อน), POST แต่ละโดเมนไปยัง /mitigated_domains, ตรวจสอบว่ามีการใช้ mitigation, รันการโจมตีอีกครั้งโดยใช้ URL http:// (หลักฐานหลัง), นำเสนอการเปรียบเทียบก่อน/หลัง
  6. สรุป — ย้ำเป้าหมายผลลัพธ์, สรุปหลักฐานจากแต่ละเฟส, เน้นการตรวจจับและ mitigation สำคัญ
  7. ถาม-ตอบ — ขั้นตอนด้นสด, การสาธิตยังคงเปิดอยู่, SE ตอบคำถามผู้ชมและถามคำถามกลับ
  8. รื้อถอน (หลังการประชุม) — เฟส 4, ต้องมีการยืนยันจากผู้ดำเนินการอย่างชัดแจ้ง, ลบออบเจ็กต์ทั้งหมดตามลำดับย้อนกลับของ dependency, ยืนยันสภาพแวดล้อมสะอาด

หากขั้นตอนใดคืนค่า FAIL ให้หยุดและรายงานความล้มเหลวพร้อมลิงก์ส่วนการแก้ไขปัญหาที่เกี่ยวข้องก่อนดำเนินการต่อ

  • F5 XC API token — สร้างได้ที่ AdministrationCredentialsAPI Credentials
  • ติดตั้ง curl และ jq ในเครื่อง
  • namespace ที่มีสิทธิ์สร้าง healthcheck, origin pool และ HTTP load balancer

สร้างไฟล์ .env พร้อมค่าสภาพแวดล้อมของคุณ มีเทมเพลตในที่เก็บข้อมูล:

Terminal window
cp .env.example .env

แก้ไข .env ด้วยค่าจริงของคุณ:

.env
# Required — your environment
F5XC_API_TOKEN=example-api-token
F5XC_API_URL=https://example-tenant.console.ves.volterra.io
F5XC_DOMAINNAME=app.example.com
F5XC_EMAIL=user@example.com
F5XC_LB_NAME=example-lb-name
F5XC_NAMESPACE=example-namespace
F5XC_ROOT_DOMAIN=example.com
# Optional — Juice Shop demo defaults are used when not set
# F5XC_HC_NAME=csd-hc
# F5XC_ORIGIN_IP=44.232.69.192
# F5XC_ORIGIN_POOL=csd-origin
# F5XC_ORIGIN_PORT=3000

Source ไฟล์เพื่อโหลดตัวแปรเข้า shell session ของคุณ:

Terminal window
set -a && source .env && set +a

placeholder xTOKENx แต่ละตัวในคำสั่ง curl แมปโดยตรงกับตัวแปรสภาพแวดล้อม — ตัวอย่างเช่น xF5XC_API_TOKENx ตรงกับ $F5XC_API_TOKEN คุณสามารถแทนที่ค่าเหล่านี้ได้โดยใช้แบบฟอร์มแบบโต้ตอบที่ด้านบนของหน้า หรือให้ผู้ช่วย AI เช่น Claude Code อ่าน .env ของคุณและสร้างคำสั่งให้

โทเค็นค่าเริ่มต้นคำอธิบาย
xF5XC_API_URLxhttps://example-tenant.console.ves.volterra.ioURL ของ XC Console API
xF5XC_API_TOKENxexample-api-tokenโทเค็นข้อมูลประจำตัว API
xF5XC_EMAILxuser@example.comที่อยู่อีเมลการแจ้งเตือน CSD
xF5XC_NAMESPACExexample-namespaceNamespace
xF5XC_LB_NAMExexample-lbชื่อฐานของ HTTP Load Balancer (สร้าง ${name}-http และ ${name}-https)
xF5XC_DOMAINNAMExapp.example.comFQDN ที่จะปกป้อง
xF5XC_ROOT_DOMAINxexample.comโดเมนราก (eTLD+1) สำหรับ CSD protected domain
xF5XC_ORIGIN_POOLxcsd-originชื่อ origin pool
xF5XC_ORIGIN_IPx44.232.69.192IP ของเซิร์ฟเวอร์ origin
xF5XC_ORIGIN_PORTx3000พอร์ตของเซิร์ฟเวอร์ origin
xF5XC_HC_NAMExcsd-hcชื่อ healthcheck

ส่วนนี้สรุปขั้นตอนการทำงานทั้งหมดของแบบฝึกหัดสำหรับการเขียนสคริปต์หรือระบบอัตโนมัติ

  1. Clone repository และคัดลอกเทมเพลตสภาพแวดล้อม: cp .env.example .env
  2. แก้ไข .env ด้วย tenant URL, API token, namespace และค่าโดเมนของคุณ
  3. Source สภาพแวดล้อม: set -a && source .env && set +a
  4. ดำเนินการแต่ละเฟสตามลำดับ ตรวจสอบ PASS ในแต่ละบล็อกหลักฐานก่อนดำเนินการเฟสถัดไป

ค่าจะถูกแก้ไขโดยใช้โปรโตคอลแบบกำหนดได้ที่กำหนดใน โปรโตคอลการดำเนินการของผู้ช่วย AI:

  1. ไฟล์ .env — แยกวิเคราะห์คู่ KEY=VALUE จากรูทของ repository
  2. Shell environment — ตรวจสอบ env | grep F5XC_ สำหรับค่าที่ export
  3. การตรวจจับ placeholder — ทำเครื่องหมายค่าที่ตรงกับ placeholder เริ่มต้น (เช่น example-api-token, example-namespace) ว่าขาด
  4. ถามผู้ดำเนินการ — ถามสำหรับตัวแปร จำเป็น ที่ขาดแต่ละตัว
  5. ใช้ค่าเริ่มต้น — ใช้ค่าเริ่มต้นในตัวสำหรับตัวแปร ตัวเลือก ที่ขาด
  6. ยืนยัน — แสดงตารางตัวแปรที่แก้ไขแล้วและรอการอนุมัติจากผู้ดำเนินการ
  1. เฟส 1 — สร้าง: ปรับใช้โครงสร้างพื้นฐาน (healthcheck, origin pool, HTTP LB + HTTPS LB), กำหนดค่า DNS, เปิดใช้งาน CSD, ลงทะเบียน protected domain, ตรวจสอบส่วนประกอบทั้งหมด HTTP LB เป็นเป้าหมายสาธิตหลัก; HTTPS LB เป็นตัวเลือก
  2. เฟส 2 — โจมตี: รันการจำลองการโจมตีในเบราว์เซอร์โดยใช้ URL http://, รอ 5–10 นาที, ตรวจสอบการตรวจจับผ่าน API (/scripts, /detected_domains, /formFields)
  3. เฟส 3 — บรรเทา: ยืนยัน baseline ที่สะอาด, รันการโจมตี (หลักฐานก่อน), POST แต่ละโดเมนไปยัง /mitigated_domains, ตรวจสอบว่ามีการใช้ mitigation, รันการโจมตีอีกครั้งโดยใช้ URL http:// (หลักฐานหลัง), นำเสนอการเปรียบเทียบก่อน/หลัง
  4. เฟส 4 — รื้อถอน (ต้องมีการยืนยันจากมนุษย์อย่างชัดแจ้ง): ลบ HTTPS LB → HTTP LB → origin pool → ทำความสะอาด DNS zone (record ที่สร้างด้วยตนเองเท่านั้น) → healthcheck → protected domain อย่าลบ DNS zone
โทเค็นคำอธิบายค่าเริ่มต้น
xF5XC_API_URLxURL ของ XC Console APIhttps://example-tenant.console.ves.volterra.io
xF5XC_API_TOKENxโทเค็นข้อมูลประจำตัว API(ผู้ใช้ระบุ)
xF5XC_EMAILxอีเมลการแจ้งเตือน CSDuser@example.com
xF5XC_NAMESPACExNamespaceexample-namespace
xF5XC_LB_NAMExชื่อฐานของ HTTP Load Balancer (สร้าง ${name}-http และ ${name}-https)example-lb
xF5XC_DOMAINNAMExFQDN ที่จะปกป้องapp.example.com
xF5XC_ROOT_DOMAINxโดเมนราก (eTLD+1)example.com
xF5XC_ORIGIN_POOLxชื่อ origin poolcsd-origin
xF5XC_ORIGIN_IPxIP ของเซิร์ฟเวอร์ origin44.232.69.192
xF5XC_ORIGIN_PORTxพอร์ตของเซิร์ฟเวอร์ origin3000
xF5XC_HC_NAMExชื่อ healthcheckcsd-hc

spec ของ HTTP Load Balancer ใช้กลุ่มตัวเลือก oneOf ที่ต้องตั้งค่าตัวเลือกเดียวต่อกลุ่ม การตั้งค่าศูนย์หรือมากกว่าหนึ่งตัวเลือกในกลุ่มจะทำให้เกิดข้อผิดพลาด 422

ตัวเลือกที่เกี่ยวข้องกับ CSD ที่สำคัญ:

กลุ่มตัวเลือกตัวเลือกค่าเริ่มต้น CSD
client_side_defense_choiceclient_side_defense, disable_client_side_defenseclient_side_defense
java_script_choice (ซ้อนใน CSD)disable_js_insert, js_insert_all_pages, js_insert_all_pages_except, js_insertion_rulesjs_insert_all_pages

ตัวเลือกประเภท listener (HTTP vs HTTPS):

การสาธิตสร้าง LB สองตัวที่มีการกำหนดค่า listener แตกต่างกัน:

LBตัวเลือก Listenerการกำหนดค่า
${F5XC_LB_NAME}-http (หลัก)http"http": { "dns_volterra_managed": true, "port": 80 }
${F5XC_LB_NAME}-https (รอง)https_auto_cert"https_auto_cert": { "http_redirect": true, "port": 443, ... }

คีย์ http และ https_auto_cert เป็นแบบ mutually exclusive — LB แต่ละตัวใช้เพียงตัวเดียว

ตัวเลือกซ้อนของ HTTPS auto-cert (LB รองเท่านั้น):

กลุ่มตัวเลือกตัวเลือกค่าเริ่มต้น
portport (number)443
server_header_choicedefault_header, server_name, append_server_namedefault_header
path_normalize_choiceenable_path_normalize, disable_path_normalizeenable_path_normalize
mtls_choiceno_mtls, use_mtlsno_mtls
default_loadbalancer_choicedefault_loadbalancer, non_default_loadbalancerdefault_loadbalancer

ตัวเลือกซ้อนของ single_lb_app (การกำหนดค่า ML):

ออบเจ็กต์ single_lb_app มีกลุ่ม oneOf ที่จำเป็นของตัวเอง การตั้งค่า single_lb_app: \{\} โดยไม่มีตัวเลือกซ้อนเหล่านี้จะทำให้เกิดข้อผิดพลาด 400

กลุ่มตัวเลือกตัวเลือกค่าเริ่มต้น
api_discovery_choicedisable_discovery, enable_discoverydisable_discovery
ddos_detection_choicedisable_ddos_detection, enable_ddos_detectiondisable_ddos_detection
malicious_user_detection_choicedisable_malicious_user_detection, enable_malicious_user_detectiondisable_malicious_user_detection

ตัวเลือกระดับ LB อื่นๆ (ทั้งหมดตั้งเป็น disable/default):

disable_rate_limit · no_service_policies · round_robin · disable_waf · no_challenge · disable_bot_defense · disable_api_definition · disable_api_discovery · disable_ip_reputation · disable_malicious_user_detection · single_lb_app · disable_trust_client_ip_headers · user_id_client_ip · disable_threat_mesh · l7_ddos_action_default · system_default_timeouts · default_sensitive_data_policy · disable_malware_protection · disable_api_testing

  • 401 Unauthorized — API token ไม่ถูกต้องหรือหมดอายุ สร้างใหม่ที่ AdministrationCredentials
  • 403 Forbidden — token ขาดสิทธิ์สำหรับ namespace ตรวจสอบ role bindings
  • 404 Not Found — namespace หรือชื่อออบเจ็กต์ไม่ถูกต้อง แสดงรายการออบเจ็กต์ด้วย GET /api/config/namespaces/\{namespace\}/\{object_type\}
  • 409 Conflict — ออบเจ็กต์มีอยู่แล้ว สำหรับ protected domain, 409 พร้อม “domain already exists (in uriList)” หมายความว่าโดเมนรากถูกลงทะเบียนแล้วบน tenant — นี่คือเงื่อนไขสำเร็จ ไม่ใช่ข้อผิดพลาด สำหรับออบเจ็กต์อื่น ให้ลบก่อนหรือใช้ PUT เพื่ออัปเดต
  • 422 Unprocessable Entity — การตรวจสอบ JSON schema ล้มเหลว สาเหตุทั่วไป: ขาดตัวเลือก oneOf, ตั้งหลายตัวเลือกในกลุ่มเดียวกัน, ประเภทฟิลด์ผิด ตรวจสอบข้อความข้อผิดพลาดสำหรับฟิลด์ที่เฉพาะเจาะจง
  • โควตาออบเจ็กต์หมด (error code 8, ข้อความ "Object kind {kind} has exhausted limits({N})") — tenant ถึงขีดจำกัดโควตาออบเจ็กต์ API คืนค่า HTTP 200 พร้อม JSON error body ที่มี "code": 8 ไม่ใช่ HTTP 429 คุณสามารถตรวจสอบความจุโควตาเชิงรุกก่อนพบข้อผิดพลาดนี้โดยใช้ Quota Usage API (GET /api/web/namespaces/system/quota/usage?namespace=system) พฤติกรรมขึ้นอยู่กับประเภทออบเจ็กต์:
    • Healthcheck (ขีดจำกัด ~150): ไม่บล็อก — ข้ามขั้นตอนที่ 1 ของเฟส 1 และสร้าง origin pool โดยไม่มีการอ้างอิง healthcheck CSD ไม่ต้องพึ่งพาการตรวจสอบสุขภาพ
    • Endpoint (ขีดจำกัด ~500): บล็อก — endpoint เป็นออบเจ็กต์ย่อยที่สร้างภายใน origin pool หากถึงขีดจำกัดนี้ การสร้าง origin pool จะล้มเหลว ลบ origin pool ที่ไม่ได้ใช้ (ซึ่งจะปลดปล่อยออบเจ็กต์ย่อย endpoint) หรือติดต่อผู้ดูแลระบบเพื่อเพิ่มขีดจำกัดของ tenant
    • Origin pool: บล็อก — ลบ origin pool ที่ไม่ได้ใช้หรือติดต่อผู้ดูแลระบบ
    • HTTP load balancer: บล็อก — ลบ load balancer ที่ไม่ได้ใช้หรือติดต่อผู้ดูแลระบบ
    • Protected domain: บล็อก — ลบ protected domain ที่ไม่ได้ใช้หรือติดต่อผู้ดูแลระบบ

หากขั้นตอนที่ 2 ของเฟส 1 (ตรวจสอบว่า Healthcheck เชื่อมต่อ) แสดงอาร์เรย์ว่าง []:

  1. ลบ origin pool: DELETE /api/config/namespaces/{namespace}/origin_pools/{pool_name}
  2. ตรวจสอบว่า healthcheck มีอยู่: GET /api/config/namespaces/{namespace}/healthchecks/{hc_name}
  3. สร้าง origin pool ใหม่ด้วยการอ้างอิง healthcheck ที่ถูกต้อง

หากสถานะ state ของ load balancer ยังคงเป็น VIRTUAL_HOST_PENDING_A_RECORD หลังจากขั้นตอนที่ 4 ของเฟส 1:

  1. ตรวจสอบว่ามี DNS zone (F5 XC managed DNS เท่านั้น):

    Terminal window
    curl -s \
    -H "Authorization: APIToken xF5XC_API_TOKENx" \
    "xF5XC_API_URLx/api/config/dns/namespaces/system/dns_zones/xF5XC_ROOT_DOMAINx" \
    | jq '.metadata.name'

    404 หมายความว่า DNS zone ยังไม่ได้ถูกสร้างใน F5 XC

  2. ตรวจสอบ allow_http_lb_managed_records — หาก zone มีอยู่แต่ LB กำลังรออยู่ managed records อาจถูกปิดใช้งาน:

    Terminal window
    curl -s \
    -H "Authorization: APIToken xF5XC_API_TOKENx" \
    "xF5XC_API_URLx/api/config/dns/namespaces/system/dns_zones/xF5XC_ROOT_DOMAINx" \
    | jq '.spec.primary.allow_http_lb_managed_records'

    หากเป็น false หรือ null ให้เปิดใช้งานโดยใช้คำสั่ง PUT ใน ขั้นตอนที่ 4 ของเฟส 1, ตัวเลือก A

  3. DNS ภายนอก — หาก F5 XC ไม่ใช่ authoritative ให้สร้าง A record และ ACME CNAME record ด้วยตนเองที่ผู้ให้บริการ DNS ของคุณ (ดู ขั้นตอนที่ 4 ของเฟส 1, ตัวเลือก B)

  4. ตรวจสอบการ resolve — หลังจากแก้ไข DNS ให้ยืนยัน:

    Terminal window
    dig +short xF5XC_DOMAINNAMEx A

    หาก A record resolve ได้ LB จะเปลี่ยนเป็น VIRTUAL_HOST_READY ตรวจสอบทุก 30 วินาที สูงสุด 4 รอบ (รวม 2 นาที) หากยังคงเป็น VIRTUAL_HOST_PENDING_A_RECORD หลัง 2 นาที ให้ตรวจสอบการเผยแพร่ DNS อีกครั้งและรายงานให้ผู้ดำเนินการ

CSD ต้องเปิดใช้งานที่ระดับ tenant ติดต่อผู้ดูแลระบบ F5 XC ของคุณเพื่อเปิดใช้งาน Client-Side Defense สำหรับ tenant ของคุณ นี่เป็นการตั้งค่าระดับ tenant ที่ไม่สามารถกำหนดค่าผ่าน API

  1. ตรวจสอบว่า CSD เปิดใช้งานที่ระดับ tenant (ขั้นตอนที่ 5 ของเฟส 1)
  2. ยืนยันว่า load balancer มี client_side_defense ตั้งค่าใน spec
  3. ตรวจสอบว่า JS configuration endpoint คืนค่า scriptTag
  4. เข้าชม protected domain ในเบราว์เซอร์และดู page source เพื่อยืนยันว่าสคริปต์ถูกฉีด

409 พร้อม “domain already exists (in uriList)” หมายความว่าโดเมนรากถูกลงทะเบียนแล้วบน tenant Protected domain เป็น ขอบเขตระดับ tenant — ไม่ได้เป็นของ namespace ใดโดยเฉพาะ นี่คือเงื่อนไขสำเร็จ: โดเมนได้รับการปกป้องแล้วและไม่จำเป็นต้องดำเนินการเพิ่มเติม ดำเนินการต่อไปขั้นตอนที่ 7 ของเฟส 1

หาก cert_state ของ HTTPS LB แสดง AutoCertDomainRateLimited หมายความว่า Let’s Encrypt ได้จำกัดอัตราการออกใบรับรองสำหรับโดเมนนี้ นี่ คาดหวังในสภาพแวดล้อมสาธิต ที่มีการสร้างและทำลายโครงสร้างพื้นฐานบ่อยครั้ง

ผลกระทบ: HTTPS LB จะไม่ให้บริการทราฟฟิกจนกว่าขีดจำกัดอัตราจะรีเซ็ต (โดยทั่วไป 1 ชั่วโมง) HTTP LB ไม่ได้รับผลกระทบเลย — ทราฟฟิกสาธิตทั้งหมดดำเนินการตามปกติผ่าน http://

การแก้ไข: ไม่ต้องดำเนินการใดๆ สำหรับความคืบหน้าของการสาธิต HTTP LB (${F5XC_LB_NAME}-http) เป็นเป้าหมายสาธิตหลักและไม่ต้องพึ่งพาการจัดเตรียมใบรับรอง หากต้องการ HTTPS ให้รอจนกว่าขีดจำกัดอัตราจะรีเซ็ตและใบรับรองจะจัดเตรียมอัตโนมัติ

ใบรับรองค้าง — การสร้างใหม่ที่สะอาด (ตัวเลือก)

หัวข้อที่มีชื่อว่า “ใบรับรองค้าง — การสร้างใหม่ที่สะอาด (ตัวเลือก)”

เมื่อใบรับรอง HTTPS LB ค้างใน DomainChallengePending หรือ PreDomainChallengePending นานกว่า 15 นาที เส้นทางการกู้คืนที่เร็วที่สุดคือลบ HTTPS LB และสร้างใหม่ ด้วย DNS zone ที่กำหนดค่าแล้ว (เปิดใช้งาน managed records) การสร้างใหม่ที่สะอาดมักจะได้ CertificateValid ใน 5–7 นาที — เว้นแต่จะถูกจำกัดอัตรา

  1. ลบ HTTPS Load Balancer: DELETE .../http_loadbalancers/${F5XC_LB_NAME}-https
  2. รอ 30 วินาทีสำหรับการทำความสะอาดแพลตฟอร์ม
  3. สร้าง HTTPS Load Balancer ใหม่ (ขั้นตอนที่ 3 ของเฟส 1)
  4. ตรวจสอบสถานะใบรับรอง (ขั้นตอนที่ 7 ของเฟส 1) — คาดหวัง CertificateValid ภายใน 5–10 นาที

ข้อกำหนด API F5 Distributed Cloud อย่างเป็นทางการมีให้ที่:

https://docs.cloud.f5.com/docs-v2/downloads/f5-distributed-cloud-open-api.zip

ZIP นี้มี OpenAPI 3.0 spec สำหรับกลุ่ม API ทั้งหมดรวมถึง ves.io.schema.views.http_loadbalancer, ves.io.schema.healthcheck, ves.io.schema.origin_pool และ ves.io.schema.shape.csd ใช้ spec เหล่านี้เพื่อตรวจสอบ JSON payload และค้นพบฟิลด์เพิ่มเติม