@auth-craft/aws-cf-stack 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env.example CHANGED
@@ -75,6 +75,15 @@ CF_WORKER_ROUTE_PREFIX_CUSTOMER=/customer
75
75
  CF_WORKER_CUSTOM_DOMAIN_SYSTEM=
76
76
  CF_WORKER_CUSTOM_DOMAIN_TENANT=
77
77
  CF_WORKER_CUSTOM_DOMAIN_CUSTOMER=
78
+ # Disable the public worker URL — turns off BOTH workers.dev AND preview URLs (Pages-proxy
79
+ # / Service-Binding deploys reach the worker in-network, so no public URL should be
80
+ # exposed; CF won't drop preview URLs just for workers.dev being off). Truthy: 1/true/yes.
81
+ # CF_WORKER_DISABLE_PUBLIC_URL is the shared default; override one scope with the
82
+ # per-scope var. Ignored when a custom domain is set for that scope.
83
+ CF_WORKER_DISABLE_PUBLIC_URL= # shared default (e.g. true to disable all)
84
+ CF_WORKER_DISABLE_PUBLIC_URL_SYSTEM= # e.g. true — admin app via Pages proxy
85
+ CF_WORKER_DISABLE_PUBLIC_URL_TENANT=
86
+ CF_WORKER_DISABLE_PUBLIC_URL_CUSTOMER=
78
87
 
79
88
  # ─── Internal service JWT (optional — enables /internal/* + service worker verify) ─
80
89
  LAMBDA_INTERNAL_JWT_PUBLIC_KEY= # optional — also fed to workers as SERVICE_JWT_PUBLIC_KEY
package/README.md CHANGED
@@ -218,6 +218,18 @@ billed as a second request). If you can't use a binding, set `AUTH_GATEWAY_URL`
218
218
  gateway URL from `outputs.gatewayUrls.<scope>` instead — that path is a normal billable
219
219
  request. See [@auth-craft/pages-auth-proxy](../pages-auth-proxy/README.md).
220
220
 
221
+ **Disable the public worker URL.** With a Service Binding the worker is reached in-network,
222
+ so its public `workers.dev` URL only widens the attack surface (and bypasses the Pages
223
+ same-origin path). Set `CF_WORKER_DISABLE_PUBLIC_URL=true` (or per scope, e.g.
224
+ `CF_WORKER_DISABLE_PUBLIC_URL_SYSTEM=true`) and the deploy ships the worker with
225
+ `workers_dev = false` **and** `preview_urls = false` — turning off both the production
226
+ `workers.dev` subdomain **and** the per-version preview URLs (Cloudflare does *not* drop
227
+ preview URLs just because `workers.dev` is off, so both must be set; the deploy does this
228
+ for you). The worker then stays reachable only via its Service Binding (and any custom
229
+ domain). This applies only when no `CF_WORKER_CUSTOM_DOMAIN_<SCOPE>` is set for the scope;
230
+ if you're using `AUTH_GATEWAY_URL` (no binding) leave it off, since that path needs the
231
+ public URL.
232
+
221
233
  ### Per-scope token transport
222
234
 
223
235
  `REFRESH_TOKEN_STRATEGY` sets the transport for every scope. To mix, use the per-scope
@@ -30,6 +30,21 @@ custom_domain_for() {
30
30
  echo "${!var:-}"
31
31
  }
32
32
 
33
+ # Resolve whether to disable the public workers.dev URL for a scope (Pages-proxy /
34
+ # Service-Binding deploys reach the worker in-network and don't need a public URL).
35
+ # Precedence: CF_WORKER_DISABLE_PUBLIC_URL_<SCOPE> > CF_WORKER_DISABLE_PUBLIC_URL > '' (off).
36
+ # Truthy values: 1 / true / yes (case-insensitive). Ignored when a custom domain is set.
37
+ disable_public_url_for() {
38
+ local scope="$1" upper var val
39
+ upper="$(echo "$scope" | tr '[:lower:]' '[:upper:]')"
40
+ var="CF_WORKER_DISABLE_PUBLIC_URL_${upper}"
41
+ val="${!var:-${CF_WORKER_DISABLE_PUBLIC_URL:-}}"
42
+ case "$(echo "$val" | tr '[:upper:]' '[:lower:]')" in
43
+ 1 | true | yes) echo 1 ;;
44
+ *) echo '' ;;
45
+ esac
46
+ }
47
+
33
48
  # Resolve per-scope static CORS origins. Precedence:
34
49
  # CF_ALLOWED_ORIGINS_<SCOPE> > CF_ALLOWED_ORIGINS > LAMBDA_CORS_ORIGINS > '*'.
35
50
  allowed_origins_for() {
@@ -100,7 +115,7 @@ deploy_gateway() {
100
115
 
101
116
  GATEWAY_URLS=()
102
117
  local scope worker_name route_prefix custom_domain url
103
- local allowed_origins origin_suffixes cors_kv_id config_file
118
+ local allowed_origins origin_suffixes cors_kv_id config_file disable_public_url
104
119
  for scope in system tenant customer; do
105
120
  worker_name="${APP_NAME}-${STAGE}-${scope}"
106
121
  route_prefix="$(route_prefix_for "$scope")"
@@ -108,23 +123,46 @@ deploy_gateway() {
108
123
  allowed_origins="$(allowed_origins_for "$scope")"
109
124
  origin_suffixes="$(origin_suffixes_for "$scope")"
110
125
  cors_kv_id="$(cors_kv_id_for "$scope")"
126
+ # A custom domain always needs the worker reachable, so the disable flag is ignored there.
127
+ disable_public_url=""
128
+ [[ -z "$custom_domain" ]] && disable_public_url="$(disable_public_url_for "$scope")"
111
129
 
112
130
  info "Deploying $worker_name (scope=$scope route_prefix=$route_prefix)…"
113
131
 
114
- # When a CORS KV id is set for this scope (typically customer), deploy with a
115
- # temp config that appends a [[kv_namespaces]] binding (CORS_KV) — a binding can't
116
- # be set via --var. Otherwise use the shipped config unchanged (KV disabled).
132
+ # A temp config is needed when either (a) a CORS KV id is set (a binding can't be
133
+ # set via --var) or (b) the public URL must be disabled (workers_dev/preview_urls are
134
+ # top-level config keys, not vars, and CF won't disable preview URLs just because
135
+ # workers.dev is off — both must be set explicitly). Otherwise use the shipped config.
117
136
  config_file="$WRANGLER_DIR/wrangler.toml"
118
- if [[ -n "$cors_kv_id" ]]; then
137
+ if [[ -n "$cors_kv_id" || -n "$disable_public_url" ]]; then
119
138
  config_file="$(mktemp "${TMPDIR:-/tmp}/wrangler-${scope}.XXXXXX.toml")"
120
- cat "$WRANGLER_DIR/wrangler.toml" >"$config_file"
121
- {
122
- echo ''
123
- echo '[[kv_namespaces]]'
124
- echo 'binding = "CORS_KV"'
125
- echo "id = \"$cors_kv_id\""
126
- } >>"$config_file"
127
- info " dynamic CORS: KV binding CORS_KV → $cors_kv_id"
139
+ if [[ -n "$disable_public_url" ]]; then
140
+ # Turn off the workers.dev URL *and* the per-version preview URLs in a single
141
+ # deploy (no REST API round-trip; CF won't drop preview URLs just for workers_dev
142
+ # being off, so both are set explicitly). These are ROOT keys: they must precede
143
+ # any [table] header or TOML scopes them under it (e.g. [build]). We drop the
144
+ # shipped `workers_dev = true` (TOML forbids duplicate keys) and inject both flags
145
+ # immediately after the first root key (`name = …`), before [build].
146
+ awk '
147
+ /^[[:space:]]*workers_dev[[:space:]]*=/ { next } # drop original (anywhere)
148
+ { print }
149
+ !injected && /^[[:space:]]*name[[:space:]]*=/ {
150
+ print "workers_dev = false"; print "preview_urls = false"; injected = 1
151
+ }
152
+ ' "$WRANGLER_DIR/wrangler.toml" >"$config_file"
153
+ info " public URL disabled: workers.dev + preview URLs off (Pages-proxy / Service Binding only)"
154
+ else
155
+ cat "$WRANGLER_DIR/wrangler.toml" >"$config_file"
156
+ fi
157
+ if [[ -n "$cors_kv_id" ]]; then
158
+ {
159
+ echo ''
160
+ echo '[[kv_namespaces]]'
161
+ echo 'binding = "CORS_KV"'
162
+ echo "id = \"$cors_kv_id\""
163
+ } >>"$config_file"
164
+ info " dynamic CORS: KV binding CORS_KV → $cors_kv_id"
165
+ fi
128
166
  fi
129
167
 
130
168
  # Deploy the prebuilt bundle with per-scope vars (flags override the toml).
@@ -144,7 +182,7 @@ deploy_gateway() {
144
182
  --var "SERVICE_JWT_ISSUER:$svc_iss" \
145
183
  --var "SERVICE_JWT_ALLOWED_ALGORITHMS:$svc_alg" >/dev/null
146
184
 
147
- # Clean up the temp config (only created when KV was bound).
185
+ # Clean up the temp config (only created when KV was bound or public URL disabled).
148
186
  [[ "$config_file" != "$WRANGLER_DIR/wrangler.toml" ]] && rm -f "$config_file"
149
187
 
150
188
  # Secrets (piped via stdin).
@@ -158,6 +196,10 @@ deploy_gateway() {
158
196
  if [[ -n "$custom_domain" ]]; then
159
197
  url="https://$custom_domain"
160
198
  info " custom domain: $custom_domain (configure DNS/route separately)"
199
+ elif [[ -n "$disable_public_url" ]]; then
200
+ # workers.dev + preview URLs were turned off in the deploy config above; the worker
201
+ # is reachable only via its Service Binding (Pages proxy) — no public URL to print.
202
+ url="(no public URL — reached via Pages proxy / Service Binding)"
161
203
  else
162
204
  enable_workers_dev "$worker_name"
163
205
  if [[ -n "${CF_WORKERS_SUBDOMAIN:-}" ]]; then
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@auth-craft/aws-cf-stack",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Self-contained, versioned distribution of the Auth Craft AWS (DynamoDB + Lambda) + Cloudflare gateway stack. Bundles prebuilt Lambda/worker artifacts + CDK app so consumers deploy without cloning auth-craft.",
5
5
  "type": "module",
6
6
  "bin": {