Setting the file. One moment.
Widget Create · Turnstile Spin · cloudflare/skills · Skills Docs
ContentsBack to the top of the page 11.11
README
(opens in a new tab)
scripts/ widget-create.sh
Shell · 121 lines · 4 KB
"
>&2
10 exit 2
11 fi
12 }
13
14 MODE = "managed"
15 ACCOUNT_ID = ""
16 NAME = ""
17 DOMAINS = ""
18
19 while [[ $# -gt 0 ]]; do
20 case " $1 " in
21 --account-id ) need_arg " $1 " " ${2 - } " ; ACCOUNT_ID = " $2 " ; shift 2 ;;
22 --name ) need_arg " $1 " " ${2 - } " ; NAME = " $2 " ; shift 2 ;;
23 --domains ) need_arg " $1 " " ${2 - } " ; DOMAINS = " $2 " ; shift 2 ;;
24 --mode ) need_arg " $1 " " ${2 - } " ; MODE = " $2 " ; shift 2 ;;
25 *) echo "widget-create: unknown arg $1 " >&2 ; exit 2 ;;
26 esac
27 done
28
29 : "${ CLOUDFLARE_API_TOKEN :? CLOUDFLARE_API_TOKEN must be set }"
30 API_TOKEN = " $CLOUDFLARE_API_TOKEN "
31 unset CLOUDFLARE_API_TOKEN
32 [[ -n " $ACCOUNT_ID " ]] || { echo "widget-create: --account-id required" >&2 ; exit 2 ; }
33 [[ -n " $NAME " ]] || { echo "widget-create: --name required" >&2 ; exit 2 ; }
34 [[ -n " $DOMAINS " ]] || { echo "widget-create: --domains required" >&2 ; exit 2 ; }
35 [[ " $API_TOKEN " =~ ^[A-Za-z0-9_-]+$ ]] || {
36 echo "widget-create: CLOUDFLARE_API_TOKEN has an invalid format" >&2
37 exit 1
38 }
39 case " $MODE " in
40 managed | invisible | non-interactive ) ;;
41 *) echo "widget-create: unsupported mode" >&2 ; exit 2 ;;
42 esac
43
44 for command_name in curl python3 ; do
45 command -v " $command_name " > /dev/null 2>&1 || {
46 echo "widget-create: $command_name is required" >&2
47 exit 1
48 }
49 done
50
51 BODY_JSON = "$( python3 -I -c '
52 import json, sys
53 name, domains_csv, mode = sys.argv[1], sys.argv[2], sys.argv[3]
54 domains = [domain.strip() for domain in domains_csv.split(",") if domain.strip()]
55 if not domains:
56 raise SystemExit(2)
57 print(json.dumps({"name": name, "domains": domains, "mode": mode}))
58 ' " $NAME " " $DOMAINS " " $MODE ")" || {
59 echo "widget-create: --domains must include at least one domain" >&2
60 exit 2
61 }
62 ACCOUNT_ENCODED = "$( python3 -I -c 'import sys,urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' " $ACCOUNT_ID ")"
63
64 if ! API_RESPONSE = "$(
65 printf 'header = "Authorization: Bearer %s"\n' " $API_TOKEN " |
66 curl --disable --config - --silent --show-error --write-out $' \n %{http_code}' -X POST \
67 "https://api.cloudflare.com/client/v4/accounts/ $ACCOUNT_ENCODED /challenges/widgets" \
68 -H "Content-Type: application/json" \
69 --data " $BODY_JSON "
70 )" ; then
71 echo "widget-create: Cloudflare API request failed" >&2
72 echo '{"status":"error","code":0,"message":"Cloudflare API request failed"}'
73 exit 1
74 fi
75 unset BODY_JSON
76 unset API_TOKEN
77
78 HTTP_CODE = "${ API_RESPONSE ##* $' \n '}"
79 RESPONSE_BODY = "${ API_RESPONSE % $' \n ' * }"
80 unset API_RESPONSE
81
82 if ! printf '%s' " $RESPONSE_BODY " | python3 -I -c '
83 import json
84 import re
85 import sys
86
87 http_code = sys.argv[1]
88 try:
89 data = json.load(sys.stdin)
90 except Exception:
91 print(f"widget-create: non-JSON response (HTTP {http_code})", file=sys.stderr)
92 print(json.dumps({"status":"error","code":0,"message":"Cloudflare API returned an invalid response"}))
93 raise SystemExit(1)
94
95 errors = data.get("errors") if isinstance(data, dict) else []
96 first = errors[0] if isinstance(errors, list) and errors and isinstance(errors[0], dict) else {}
97 code = first.get("code", 0)
98 if not isinstance(data, dict) or data.get("success") is not True:
99 print(f"widget-create: request failed (HTTP {http_code}, code={code})", file=sys.stderr)
100 print(json.dumps({"status":"error","code":code,"message":"Cloudflare API request failed"}))
101 raise SystemExit(1)
102
103 result = data.get("result")
104 sitekey = result.get("sitekey") if isinstance(result, dict) else None
105 secret = result.get("secret") if isinstance(result, dict) else None
106 if not (
107 isinstance(sitekey, str)
108 and re.fullmatch(r"\S{1,256}", sitekey)
109 and isinstance(secret, str)
110 and re.fullmatch(r"\S{1,1024}", secret)
111 ):
112 print("widget-create: API returned invalid widget credentials", file=sys.stderr)
113 print(json.dumps({"status":"error","code":0,"message":"Cloudflare API returned invalid widget credentials"}))
114 raise SystemExit(1)
115
116 print(json.dumps({"status":"ok","sitekey":sitekey,"secret":secret}))
117 ' " $HTTP_CODE " ; then
118 unset RESPONSE_BODY
119 exit 1
120 fi
121 unset RESPONSE_BODY