- Home
- Client-Side Defense
- demo
- Phase 4 — Teardown
Phase 4 — Teardown
Phase 4 removes all objects created during the exercise in reverse dependency order. This phase requires explicit human confirmation before any destructive operations.
Teardown Order
Section titled “Teardown Order”Remove objects in reverse creation order — delete objects that depend on other objects first:
- Mitigated Domains — delete all CSD mitigated domains created in Phase 3
- HTTPS Load Balancer (
${F5XC_LB_NAME}-https) — strip to skeleton (preserve Let’s Encrypt certificate); full DELETE ifNAMESPACE_CREATED=trueor on explicit request - HTTP Load Balancer (
${F5XC_LB_NAME}-http) — depends on Origin Pool - Origin Pool — depends on Healthcheck (if created)
- DNS zone cleanup — the HTTPS LB skeleton retains its managed A and ACME records (this is desired — it keeps the certificate valid). The HTTP LB’s managed records auto-clean on deletion. Manual records in
default_rr_set_groupneed manual cleanup viaPUT - Healthcheck — only if created in Phase 1 Step 1
- Protected Domain — delete the CSD protected domain registration
- Namespace — only if created during Phase 1 Step 0 (
NAMESPACE_CREATED=true)
Delete Mitigated Domains
Section titled “Delete Mitigated Domains”If Phase 3 was executed, delete all mitigated domains before removing infrastructure objects. The standard simulation creates 6 mitigated domains:
for domain in cdn.jsdelivr.net esm.sh unpkg.com ga.jspm.io httpbin.org jsonplaceholder.typicode.com; do curl -s -X DELETE \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ "xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains/$domain"doneVerify: List mitigated domains to confirm the count is 0 (or 1 — see note below):
curl -s \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ "xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains" \ | jq '{count: (.items | length)}'HTTPS Load Balancer
Section titled “HTTPS Load Balancer”The HTTPS LB teardown behavior depends on whether the namespace was created during this demo session (NAMESPACE_CREATED variable from Phase 1 Step 0):
NAMESPACE_CREATED=false(pre-existing namespace) — strip to skeleton state, preserving the Let’s Encrypt certificate for reuseNAMESPACE_CREATED=true(namespace created during demo) — full DELETE, since the namespace itself will be deleted and the certificate cannot be preserved
Path A: Strip to Skeleton (Pre-existing Namespace)
Section titled “Path A: Strip to Skeleton (Pre-existing Namespace)”When the namespace is pre-existing, strip the HTTPS LB to a skeleton state — remove the origin pool reference and CSD configuration while preserving the domain binding, https_auto_cert settings, and the Let’s Encrypt certificate. This avoids triggering a new certificate request on the next demo run (Let’s Encrypt enforces a limit of 5 duplicate certificates per exact identifier set per 7 days).
Step 1 — GET the current HTTPS LB config:
HTTPS_LB_JSON=$(curl -s \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ "xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https")Step 2 — Strip to skeleton via jq and PUT back:
echo "$HTTPS_LB_JSON" | jq '{ metadata: .metadata, spec: (.spec | del(.client_side_defense) | .disable_client_side_defense = {} | .default_route_pools = [])}' | curl -s -X PUT \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ -H "Content-Type: application/json" \ -d @- \ "xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \ | jq .The jq filter preserves the entire spec (domains, https_auto_cert, advertise_on_public_default_vip, and all disabled feature flags) while removing client_side_defense (replaced with disable_client_side_defense: {}) and clearing default_route_pools to an empty array. The certificate and DNS bindings remain intact.
Verify the HTTPS LB is now a skeleton:
curl -s \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ "xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \ | jq '{ name: .metadata.name, domains: .spec.domains, has_origin_pools: ((.spec.default_route_pools // []) | length > 0), has_csd: (.spec.client_side_defense != null), cert_state: .spec.cert_state }'Expected: has_origin_pools: false, has_csd: false, domains still populated, cert_state unchanged (e.g., CertificateValid).
Path B: Full Delete (Namespace Created During Demo)
Section titled “Path B: Full Delete (Namespace Created During Demo)”When the namespace was created during this demo session, the HTTPS LB must be fully deleted — skeleton preservation is unnecessary because the namespace itself will be removed at the end of teardown.
curl -s -X DELETE \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ "xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https"Verify: GET /api/config/namespaces/\{namespace\}/http_loadbalancers should not contain ${F5XC_LB_NAME}-https.
Delete HTTP Load Balancer
Section titled “Delete HTTP Load Balancer”Delete the primary HTTP LB:
curl -s -X DELETE \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ "xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http"Verify: GET /api/config/namespaces/\{namespace\}/http_loadbalancers should not contain ${F5XC_LB_NAME}-http. If the object still appears in the list after DELETE returned 200, wait 30 seconds and re-check once. If still present after the second check, report to operator — do not proceed.
Delete Origin Pool
Section titled “Delete Origin Pool”curl -s -X DELETE \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ "xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/xF5XC_ORIGIN_POOLx"Verify: GET /api/config/namespaces/\{namespace\}/origin_pools should not contain the pool name. If the object still appears in the list after DELETE returned 200, wait 30 seconds and re-check once. If still present after the second check, report to operator.
Delete Healthcheck
Section titled “Delete Healthcheck”curl -s -X DELETE \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ "xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks/xF5XC_HC_NAMEx"Verify: GET /api/config/namespaces/\{namespace\}/healthchecks should not contain the healthcheck name. If the object still appears in the list after DELETE returned 200, wait 30 seconds and re-check once. If still present after the second check, report to operator.
Delete Protected Domain
Section titled “Delete Protected Domain”Delete the CSD protected domain registration. The protected domain is tenant-scoped (not namespace-scoped), but it is a CSD configuration object tied to this deployment — not shared infrastructure like the DNS zone.
curl -s -X DELETE \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ "xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains/xF5XC_ROOT_DOMAINx"Verify: List protected domains to confirm the domain is no longer registered:
curl -s -X GET \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ "xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains" \ | jq '.items // [] | map(.metadata.name)'Delete Namespace (Conditional)
Section titled “Delete Namespace (Conditional)”This step runs only if the namespace was created during Phase 1 Step 0 (NAMESPACE_CREATED=true). If the namespace was pre-existing (NAMESPACE_CREATED=false), skip this step entirely — the namespace is shared infrastructure that must not be deleted.
if [ "$NAMESPACE_CREATED" = "true" ]; then curl -s -X POST \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ -H "Content-Type: application/json" \ -d '{"name": "xF5XC_NAMESPACEx"}' \ "xF5XC_API_URLx/api/web/namespaces/xF5XC_NAMESPACEx/cascade_delete" | jq .fiVerify: Confirm the namespace no longer exists:
curl -s -o /dev/null -w '%\{http_code\}' \ -H "Authorization: APIToken xF5XC_API_TOKENx" \ "xF5XC_API_URLx/api/web/namespaces/xF5XC_NAMESPACEx"Expected: 404 if NAMESPACE_CREATED=true, 200 if NAMESPACE_CREATED=false.
Phase 4 Evidence Summary
Section titled “Phase 4 Evidence Summary”| Object | Delete Status | Verify Status |
|---|---|---|
| Mitigated Domains (6) | All 200 (empty \{\}) or skipped if Phase 3 not run | Count 0 (or 1 phantom) — PASS |
HTTPS Load Balancer (-https) | 200 (skeleton PUT) or 200 (full DELETE if NAMESPACE_CREATED=true) | Skeleton verified or not in list — PASS |
HTTP Load Balancer (-http) | 200 (empty \{\}) | Not in list — PASS |
| Origin Pool | 200 (empty \{\}) | Not in list — PASS |
| Healthcheck | 200 (empty \{\}) or skipped | Not in list — PASS |
| Protected Domain | 200 (empty \{\}) | Not in list — PASS |
| DNS zone | NOT deleted (shared infra) | Zone still exists — PASS |
| Namespace | 200 (cascade delete) if NAMESPACE_CREATED=true, skipped otherwise | 404 if deleted, 200 if preserved — PASS |
Teardown complete. When the namespace was pre-existing (NAMESPACE_CREATED=false), all deployment objects have been removed except the HTTPS LB skeleton, which preserves the Let’s Encrypt certificate and domain binding for the next demo run. When the namespace was created during the demo (NAMESPACE_CREATED=true), all objects including the HTTPS LB and namespace have been fully deleted. The DNS zone and its non-managed records remain intact in both cases.