kong.yml408 lines · main
1_format_version: '2.1'
2_transform: true
3
4###
5### Consumers / Users
6###
7consumers:
8 - username: DASHBOARD
9 - username: anon
10 keyauth_credentials:
11 - key: $BRIVEN_ANON_KEY
12 - key: $BRIVEN_PUBLISHABLE_KEY
13 - username: service_role
14 keyauth_credentials:
15 - key: $BRIVEN_SERVICE_KEY
16 - key: $BRIVEN_SECRET_KEY
17
18###
19### Access Control List
20###
21acls:
22 - consumer: anon
23 group: anon
24 - consumer: service_role
25 group: admin
26
27###
28### Dashboard credentials
29###
30basicauth_credentials:
31 - consumer: DASHBOARD
32 username: '$DASHBOARD_USERNAME'
33 password: '$DASHBOARD_PASSWORD'
34
35###
36### API Routes
37###
38services:
39 ## Open Auth routes
40 - name: auth-v1-open
41 _comment: 'Auth: /auth/v1/verify* -> http://auth:9999/verify*'
42 url: http://auth:9999/verify
43 routes:
44 - name: auth-v1-open
45 strip_path: true
46 paths:
47 - /auth/v1/verify
48 plugins:
49 - name: cors
50 - name: auth-v1-open-callback
51 _comment: 'Auth: /auth/v1/callback* -> http://auth:9999/callback*'
52 url: http://auth:9999/callback
53 routes:
54 - name: auth-v1-open-callback
55 strip_path: true
56 paths:
57 - /auth/v1/callback
58 plugins:
59 - name: cors
60 - name: auth-v1-open-authorize
61 _comment: 'Auth: /auth/v1/authorize* -> http://auth:9999/authorize*'
62 url: http://auth:9999/authorize
63 routes:
64 - name: auth-v1-open-authorize
65 strip_path: true
66 paths:
67 - /auth/v1/authorize
68 plugins:
69 - name: cors
70 - name: auth-v1-open-jwks
71 _comment: 'Auth: /auth/v1/.well-known/jwks.json -> http://auth:9999/.well-known/jwks.json'
72 url: http://auth:9999/.well-known/jwks.json
73 routes:
74 - name: auth-v1-open-jwks
75 strip_path: true
76 paths:
77 - /auth/v1/.well-known/jwks.json
78 plugins:
79 - name: cors
80
81 - name: auth-v1-open-sso-acs
82 url: "http://auth:9999/sso/saml/acs"
83 routes:
84 - name: auth-v1-open-sso-acs
85 strip_path: true
86 paths:
87 - /sso/saml/acs
88 plugins:
89 - name: cors
90
91 - name: auth-v1-open-sso-metadata
92 url: "http://auth:9999/sso/saml/metadata"
93 routes:
94 - name: auth-v1-open-sso-metadata
95 strip_path: true
96 paths:
97 - /sso/saml/metadata
98 plugins:
99 - name: cors
100
101 ## Secure Auth routes
102 - name: auth-v1
103 _comment: 'Auth: /auth/v1/* -> http://auth:9999/*'
104 url: http://auth:9999/
105 routes:
106 - name: auth-v1-all
107 strip_path: true
108 paths:
109 - /auth/v1/
110 plugins:
111 - name: cors
112 - name: key-auth
113 config:
114 hide_credentials: false
115 - name: request-transformer
116 config:
117 add:
118 headers:
119 - "Authorization: $LUA_AUTH_EXPR"
120 replace:
121 headers:
122 - "Authorization: $LUA_AUTH_EXPR"
123 - name: acl
124 config:
125 hide_groups_header: true
126 allow:
127 - admin
128 - anon
129
130 ## Secure PostgREST routes
131 - name: rest-v1
132 _comment: 'PostgREST: /rest/v1/* -> http://rest:3000/*'
133 url: http://rest:3000/
134 routes:
135 - name: rest-v1-all
136 strip_path: true
137 paths:
138 - /rest/v1/
139 plugins:
140 - name: cors
141 - name: key-auth
142 config:
143 hide_credentials: false
144 - name: request-transformer
145 config:
146 add:
147 headers:
148 - "Authorization: $LUA_AUTH_EXPR"
149 replace:
150 headers:
151 - "Authorization: $LUA_AUTH_EXPR"
152 - name: acl
153 config:
154 hide_groups_header: true
155 allow:
156 - admin
157 - anon
158
159 ## Secure GraphQL routes
160 - name: graphql-v1
161 _comment: 'PostgREST: /graphql/v1/* -> http://rest:3000/rpc/graphql'
162 url: http://rest:3000/rpc/graphql
163 routes:
164 - name: graphql-v1-all
165 strip_path: true
166 paths:
167 - /graphql/v1
168 plugins:
169 - name: cors
170 - name: key-auth
171 config:
172 hide_credentials: false
173 - name: request-transformer
174 config:
175 add:
176 headers:
177 - "Content-Profile: graphql_public"
178 - "Authorization: $LUA_AUTH_EXPR"
179 replace:
180 headers:
181 - "Authorization: $LUA_AUTH_EXPR"
182 - name: acl
183 config:
184 hide_groups_header: true
185 allow:
186 - admin
187 - anon
188
189 ## Secure Realtime routes
190 - name: realtime-v1-ws
191 _comment: 'Realtime: /realtime/v1/* -> ws://realtime:4000/socket/*'
192 url: http://realtime-dev.briven-realtime:4000/socket
193 protocol: ws
194 routes:
195 - name: realtime-v1-ws
196 strip_path: true
197 paths:
198 - /realtime/v1/
199 plugins:
200 - name: cors
201 - name: key-auth
202 config:
203 hide_credentials: false
204 - name: request-transformer
205 config:
206 add:
207 headers:
208 - "x-api-key:$LUA_RT_WS_EXPR"
209 replace:
210 querystring:
211 - "apikey:$LUA_RT_WS_EXPR"
212 - name: acl
213 config:
214 hide_groups_header: true
215 allow:
216 - admin
217 - anon
218
219 - name: realtime-v1-rest
220 _comment: 'Realtime: /realtime/v1/api/* -> http://realtime:4000/api/*'
221 url: http://realtime-dev.briven-realtime:4000/api
222 protocol: http
223 routes:
224 - name: realtime-v1-rest
225 strip_path: true
226 paths:
227 - /realtime/v1/api
228 plugins:
229 - name: cors
230 - name: key-auth
231 config:
232 hide_credentials: false
233 - name: request-transformer
234 config:
235 add:
236 headers:
237 - "Authorization: $LUA_AUTH_EXPR"
238 replace:
239 headers:
240 - "Authorization: $LUA_AUTH_EXPR"
241 - name: acl
242 config:
243 hide_groups_header: true
244 allow:
245 - admin
246 - anon
247
248 ## Storage API endpoint (with Authorization header transformation).
249 ## No key-auth — S3 protocol requests don't carry an apikey header.
250 ##
251 ## The request-transformer translates opaque API keys to asymmetric JWTs
252 ## and passes through existing Authorization headers (user JWTs, AWS SigV4).
253 ## When no Authorization or apikey header is present (S3 presigned URLs),
254 ## the Lua expression evaluates to nil which Kong renders as empty string.
255 ## The post-function strips this empty header so Storage's S3 signature
256 ## verification falls through to query-parameter parsing.
257 - name: storage-v1
258 _comment: 'Storage: /storage/v1/* -> http://storage:5000/*'
259 url: http://storage:5000/
260 routes:
261 - name: storage-v1-all
262 strip_path: true
263 paths:
264 - /storage/v1/
265 plugins:
266 - name: cors
267 - name: request-transformer
268 config:
269 add:
270 headers:
271 - "Authorization: $LUA_AUTH_EXPR"
272 replace:
273 headers:
274 - "Authorization: $LUA_AUTH_EXPR"
275 - name: post-function
276 config:
277 access:
278 - |
279 local auth = kong.request.get_header("authorization")
280 if auth == nil or auth == "" or auth:find("^%s*$") then
281 kong.service.request.clear_header("authorization")
282 end
283
284 ## Edge Functions routes
285 - name: functions-v1
286 _comment: 'Edge Functions: /functions/v1/* -> http://functions:9000/*'
287 url: http://functions:9000/
288 read_timeout: 150000
289 routes:
290 - name: functions-v1-all
291 strip_path: true
292 paths:
293 - /functions/v1/
294 plugins:
295 - name: cors
296
297 ## OAuth 2.0 Authorization Server Metadata (RFC 8414)
298 - name: well-known-oauth
299 _comment: 'Auth: /.well-known/oauth-authorization-server -> http://auth:9999/.well-known/oauth-authorization-server'
300 url: http://auth:9999/.well-known/oauth-authorization-server
301 routes:
302 - name: well-known-oauth
303 strip_path: true
304 paths:
305 - /.well-known/oauth-authorization-server
306 plugins:
307 - name: cors
308
309 ## Analytics routes
310 ## Not used - Studio and Vector talk directly to analytics via Docker networking.
311 ## If external access is needed, add routes with key-auth matching Logflare's x-api-key auth.
312 # - name: analytics-v1-api
313 # _comment: 'Analytics: /analytics/v1/api/endpoints/* -> http://logflare:4000/api/endpoints/*'
314 # url: http://analytics:4000/api/endpoints
315 # routes:
316 # - name: analytics-v1-api
317 # strip_path: true
318 # paths:
319 # - /analytics/v1/api/endpoints/
320 # - name: analytics-v1
321 # _comment: 'Analytics: /analytics/v1/* -> http://logflare:4000/*'
322 # url: http://analytics:4000/
323 # routes:
324 # - name: dashboard-v1-all
325 # strip_path: true
326 # paths:
327 # - /analytics/v1
328 # plugins:
329 # - name: cors
330 # - name: basic-auth
331 # config:
332 # hide_credentials: true
333
334 ## Secure Database routes
335 - name: meta
336 _comment: 'pg-meta: /pg/* -> http://pg-meta:8080/*'
337 url: http://meta:8080/
338 routes:
339 - name: meta-all
340 strip_path: true
341 paths:
342 - /pg/
343 plugins:
344 - name: key-auth
345 config:
346 hide_credentials: false
347 - name: acl
348 config:
349 hide_groups_header: true
350 allow:
351 - admin
352
353 ## Block access to /api/mcp
354 - name: mcp-blocker
355 _comment: 'Block direct access to /api/mcp'
356 url: http://studio:3000/api/mcp
357 routes:
358 - name: mcp-blocker-route
359 strip_path: true
360 paths:
361 - /api/mcp
362 plugins:
363 - name: request-termination
364 config:
365 status_code: 403
366 message: "Access is forbidden."
367
368 ## MCP endpoint - local access
369 - name: mcp
370 _comment: 'MCP: /mcp -> http://studio:3000/api/mcp (local access)'
371 url: http://studio:3000/api/mcp
372 routes:
373 - name: mcp
374 strip_path: true
375 paths:
376 - /mcp
377 plugins:
378 # Block access to /mcp by default
379 - name: request-termination
380 config:
381 status_code: 403
382 message: "Access is forbidden."
383 # Enable local access (danger zone!)
384 # 1. Comment out the 'request-termination' section above
385 # 2. Uncomment the entire section below, including 'deny'
386 # 3. Add your local IPs to the 'allow' list
387 #- name: cors
388 #- name: ip-restriction
389 # config:
390 # allow:
391 # - 127.0.0.1
392 # - ::1
393 # deny: []
394
395 ## Protected Dashboard - catch all remaining routes
396 - name: dashboard
397 _comment: 'Studio: /* -> http://studio:3000/*'
398 url: http://studio:3000/
399 routes:
400 - name: dashboard-all
401 strip_path: true
402 paths:
403 - /
404 plugins:
405 - name: cors
406 - name: basic-auth
407 config:
408 hide_credentials: true