--- # Source: supabase/templates/analytics/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-analytics labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/auth/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-auth labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/db/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-db labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/functions/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-functions labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/imgproxy/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-imgproxy labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/kong/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-kong labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/meta/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-meta labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/realtime/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-realtime labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/rest/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-rest labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/storage/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-storage labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/studio/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-studio labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/vector/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: supabase-basket-supabase-vector labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm --- # Source: supabase/templates/secret/analytics.yaml apiVersion: v1 kind: Secret metadata: name: supabase-basket-analytics labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm type: Opaque data: publicAccessToken: "eW91ci1zdXBlci1zZWNyZXQtYW5kLWxvbmctbG9nZmxhcmUta2V5LXB1YmxpYw==" privateAccessToken: "eW91ci1zdXBlci1zZWNyZXQtYW5kLWxvbmctbG9nZmxhcmUta2V5LXByaXZhdGU=" --- # Source: supabase/templates/secret/apikey.yaml apiVersion: v1 kind: Secret metadata: name: supabase-basket-apikey labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm type: Opaque data: publishableKey: "" secretKey: "" anonKeyAsymmetric: "" serviceRoleKeyAsymmetric: "" jwtKeys: "" jwtJwks: "" --- # Source: supabase/templates/secret/dashboard.yaml apiVersion: v1 kind: Secret metadata: name: supabase-basket-dashboard labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm type: Opaque data: username: "c3VwYWJhc2U=" password: "dGhpc19wYXNzd29yZF9pc19pbnNlY3VyZV9hbmRfc2hvdWxkX2JlX3VwZGF0ZWQ=" openAiApiKey: "a2V5X3N1cGVyX3NlY3JldA==" --- # Source: supabase/templates/secret/db.yaml apiVersion: v1 kind: Secret metadata: name: supabase-basket-db labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm type: Opaque data: password: "eW91ci1zdXBlci1zZWNyZXQtYW5kLWxvbmctcG9zdGdyZXMtcGFzc3dvcmQ=" database: "cG9zdGdyZXM=" password_encoded: "eW91ci1zdXBlci1zZWNyZXQtYW5kLWxvbmctcG9zdGdyZXMtcGFzc3dvcmQ=" --- # Source: supabase/templates/secret/jwt.yaml apiVersion: v1 kind: Secret metadata: name: supabase-basket-jwt labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm type: Opaque data: anonKey: "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5QWdDaUFnSUNBaWNtOXNaU0k2SUNKaGJtOXVJaXdLSUNBZ0lDSnBjM01pT2lBaWMzVndZV0poYzJVdFpHVnRieUlzQ2lBZ0lDQWlhV0YwSWpvZ01UWTBNVGMyT1RJd01Dd0tJQ0FnSUNKbGVIQWlPaUF4TnprNU5UTTFOakF3Q24wLmRjX1g1aVJfVlBfcVQwenNpeWpfSV9PWjJUOUZ0UlUyQkJOV044QnU0R0U=" serviceKey: "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5QWdDaUFnSUNBaWNtOXNaU0k2SUNKelpYSjJhV05sWDNKdmJHVWlMQW9nSUNBZ0ltbHpjeUk2SUNKemRYQmhZbUZ6WlMxa1pXMXZJaXdLSUNBZ0lDSnBZWFFpT2lBeE5qUXhOelk1TWpBd0xBb2dJQ0FnSW1WNGNDSTZBeE56azVOVE0xTmpBd0NuMC5EYVlsTkVvVXJyRW4ySWc3dHFpYlMtUEhLNXZndXNiY2JvN1gzNlhWdDRR" secret: "eW91ci1zdXBlci1zZWNyZXQtand0LXRva2VuLXdpdGgtYXQtbGVhc3QtMzItY2hhcmFjdGVycy1sb25n" --- # Source: supabase/templates/secret/meta.yaml apiVersion: v1 kind: Secret metadata: name: supabase-basket-meta labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm type: Opaque data: cryptoKey: "eW91ci1lbmNyeXB0aW9uLWtleS0zMi1jaGFycy1taW4=" --- # Source: supabase/templates/secret/minio.yaml apiVersion: v1 kind: Secret metadata: name: supabase-basket-minio labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm type: Opaque data: user: "c3VwYS1zdG9yYWdl" password: "c2VjcmV0MTIzNA==" --- # Source: supabase/templates/secret/realtime.yaml apiVersion: v1 kind: Secret metadata: name: supabase-basket-realtime labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm type: Opaque data: secretKeyBase: "VXBOVm50bjNjRHhISnBxOTlZTWMxVDFBUWdRcGM4a2ZZVHVSZ0JpWWExNUJMcng4ZXRRb1h6M2dadjEvdTJvcQ==" --- # Source: supabase/templates/secret/s3.yaml apiVersion: v1 kind: Secret metadata: name: supabase-basket-s3 labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm type: Opaque data: keyId: "NjI1NzI5YTA4Yjk1YmYxYjdmZjM1MWE2NjNmM2EyM2M=" accessKey: "ODUwMTgxZTQ2NTJkZDAyM2I3YTk4YzU4YWUwZDJkMzRiZDQ4N2VlMGNjMzI1NGFlZDZlZGEzNzMwNzQyNTkwNw==" --- # Source: supabase/templates/secret/smtp.yaml apiVersion: v1 kind: Secret metadata: name: supabase-basket-smtp labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm type: Opaque data: username: "ZmFrZV9tYWlsX3VzZXI=" password: "ZmFrZV9tYWlsX3Bhc3N3b3Jk" --- # Source: supabase/templates/db/initdb.config.yaml kind: ConfigMap apiVersion: v1 metadata: name: supabase-basket-supabase-db-initdb labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm data: 99-jwt.sql: | \set jwt_secret `echo "$JWT_SECRET"` \set jwt_exp `echo "$JWT_EXP"` ALTER DATABASE postgres SET "app.settings.jwt_secret" TO :'jwt_secret'; ALTER DATABASE postgres SET "app.settings.jwt_exp" TO :'jwt_exp'; 99-pooler.sql: | \set pguser `echo "$POSTGRES_USER"` \c _supabase create schema if not exists _supavisor; alter schema _supavisor owner to :pguser; \c postgres 99-logs.sql: | \set pguser `echo "$POSTGRES_USER"` \c _supabase create schema if not exists _analytics; alter schema _analytics owner to :pguser; \c postgres 99-realtime.sql: | \set pguser `echo "$POSTGRES_USER"` create schema if not exists _realtime; alter schema _realtime owner to :pguser; 99-roles.sql: | -- NOTE: change to your own passwords for production environments \set pgpass `echo "$POSTGRES_PASSWORD"` ALTER USER authenticator WITH PASSWORD :'pgpass'; ALTER USER pgbouncer WITH PASSWORD :'pgpass'; ALTER USER supabase_auth_admin WITH PASSWORD :'pgpass'; ALTER USER supabase_functions_admin WITH PASSWORD :'pgpass'; ALTER USER supabase_storage_admin WITH PASSWORD :'pgpass'; 97-_supabase.sql: | \set pguser `echo "$POSTGRES_USER"` CREATE DATABASE _supabase WITH OWNER :pguser; 98-webhooks.sql: | BEGIN; -- Create pg_net extension CREATE EXTENSION IF NOT EXISTS pg_net SCHEMA extensions; -- Create supabase_functions schema CREATE SCHEMA supabase_functions AUTHORIZATION supabase_admin; GRANT USAGE ON SCHEMA supabase_functions TO postgres, anon, authenticated, service_role; ALTER DEFAULT PRIVILEGES IN SCHEMA supabase_functions GRANT ALL ON TABLES TO postgres, anon, authenticated, service_role; ALTER DEFAULT PRIVILEGES IN SCHEMA supabase_functions GRANT ALL ON FUNCTIONS TO postgres, anon, authenticated, service_role; ALTER DEFAULT PRIVILEGES IN SCHEMA supabase_functions GRANT ALL ON SEQUENCES TO postgres, anon, authenticated, service_role; -- supabase_functions.migrations definition CREATE TABLE supabase_functions.migrations ( version text PRIMARY KEY, inserted_at timestamptz NOT NULL DEFAULT NOW() ); -- Initial supabase_functions migration INSERT INTO supabase_functions.migrations (version) VALUES ('initial'); -- supabase_functions.hooks definition CREATE TABLE supabase_functions.hooks ( id bigserial PRIMARY KEY, hook_table_id integer NOT NULL, hook_name text NOT NULL, created_at timestamptz NOT NULL DEFAULT NOW(), request_id bigint ); CREATE INDEX supabase_functions_hooks_request_id_idx ON supabase_functions.hooks USING btree (request_id); CREATE INDEX supabase_functions_hooks_h_table_id_h_name_idx ON supabase_functions.hooks USING btree (hook_table_id, hook_name); COMMENT ON TABLE supabase_functions.hooks IS 'Supabase Functions Hooks: Audit trail for triggered hooks.'; CREATE FUNCTION supabase_functions.http_request() RETURNS trigger LANGUAGE plpgsql AS $function$ DECLARE request_id bigint; payload jsonb; url text := TG_ARGV[0]::text; method text := TG_ARGV[1]::text; headers jsonb DEFAULT '{}'::jsonb; params jsonb DEFAULT '{}'::jsonb; timeout_ms integer DEFAULT 1000; BEGIN IF url IS NULL OR url = 'null' THEN RAISE EXCEPTION 'url argument is missing'; END IF; IF method IS NULL OR method = 'null' THEN RAISE EXCEPTION 'method argument is missing'; END IF; IF TG_ARGV[2] IS NULL OR TG_ARGV[2] = 'null' THEN headers = '{"Content-Type": "application/json"}'::jsonb; ELSE headers = TG_ARGV[2]::jsonb; END IF; IF TG_ARGV[3] IS NULL OR TG_ARGV[3] = 'null' THEN params = '{}'::jsonb; ELSE params = TG_ARGV[3]::jsonb; END IF; IF TG_ARGV[4] IS NULL OR TG_ARGV[4] = 'null' THEN timeout_ms = 1000; ELSE timeout_ms = TG_ARGV[4]::integer; END IF; CASE WHEN method = 'GET' THEN SELECT http_get INTO request_id FROM net.http_get( url, params, headers, timeout_ms ); WHEN method = 'POST' THEN payload = jsonb_build_object( 'old_record', OLD, 'record', NEW, 'type', TG_OP, 'table', TG_TABLE_NAME, 'schema', TG_TABLE_SCHEMA ); SELECT http_post INTO request_id FROM net.http_post( url, payload, params, headers, timeout_ms ); ELSE RAISE EXCEPTION 'method argument % is invalid', method; END CASE; INSERT INTO supabase_functions.hooks (hook_table_id, hook_name, request_id) VALUES (TG_RELID, TG_NAME, request_id); RETURN NEW; END $function$; -- Supabase super admin DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_roles WHERE rolname = 'supabase_functions_admin' ) THEN CREATE USER supabase_functions_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION; END IF; END $$; GRANT ALL PRIVILEGES ON SCHEMA supabase_functions TO supabase_functions_admin; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA supabase_functions TO supabase_functions_admin; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA supabase_functions TO supabase_functions_admin; ALTER USER supabase_functions_admin SET search_path = "supabase_functions"; ALTER table "supabase_functions".migrations OWNER TO supabase_functions_admin; ALTER table "supabase_functions".hooks OWNER TO supabase_functions_admin; ALTER function "supabase_functions".http_request() OWNER TO supabase_functions_admin; GRANT supabase_functions_admin TO postgres; -- Remove unused supabase_pg_net_admin role DO $$ BEGIN IF EXISTS ( SELECT 1 FROM pg_roles WHERE rolname = 'supabase_pg_net_admin' ) THEN REASSIGN OWNED BY supabase_pg_net_admin TO supabase_admin; DROP OWNED BY supabase_pg_net_admin; DROP ROLE supabase_pg_net_admin; END IF; END $$; -- pg_net grants when extension is already enabled DO $$ BEGIN IF EXISTS ( SELECT 1 FROM pg_extension WHERE extname = 'pg_net' ) THEN GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role; ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; END IF; END $$; -- Event trigger for pg_net CREATE OR REPLACE FUNCTION extensions.grant_pg_net_access() RETURNS event_trigger LANGUAGE plpgsql AS $$ BEGIN IF EXISTS ( SELECT 1 FROM pg_event_trigger_ddl_commands() AS ev JOIN pg_extension AS ext ON ev.objid = ext.oid WHERE ext.extname = 'pg_net' ) THEN GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role; ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; END IF; END; $$; COMMENT ON FUNCTION extensions.grant_pg_net_access IS 'Grants access to pg_net'; DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_event_trigger WHERE evtname = 'issue_pg_net_access' ) THEN CREATE EVENT TRIGGER issue_pg_net_access ON ddl_command_end WHEN TAG IN ('CREATE EXTENSION') EXECUTE PROCEDURE extensions.grant_pg_net_access(); END IF; END $$; INSERT INTO supabase_functions.migrations (version) VALUES ('20210809183423_update_grants'); ALTER function supabase_functions.http_request() SECURITY DEFINER; ALTER function supabase_functions.http_request() SET search_path = supabase_functions; REVOKE ALL ON FUNCTION supabase_functions.http_request() FROM PUBLIC; GRANT EXECUTE ON FUNCTION supabase_functions.http_request() TO postgres, anon, authenticated, service_role; COMMIT; --- # Source: supabase/templates/db/migration.config.yaml kind: ConfigMap apiVersion: v1 metadata: name: supabase-basket-supabase-db-migrations labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm data: null --- # Source: supabase/templates/functions/functions.config.yaml apiVersion: v1 kind: ConfigMap metadata: name: supabase-basket-supabase-functions-main labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm data: index.ts: | import * as jose from 'https://deno.land/x/jose@v4.14.4/index.ts' console.log('main function started') const JWT_SECRET = Deno.env.get('JWT_SECRET') const VERIFY_JWT = Deno.env.get('VERIFY_JWT') === 'true' function getAuthToken(req: Request) { const authHeader = req.headers.get('authorization') if (!authHeader) { throw new Error('Missing authorization header') } const [bearer, token] = authHeader.split(' ') if (bearer !== 'Bearer') { throw new Error(`Auth header is not 'Bearer {token}'`) } return token } async function verifyJWT(jwt: string): Promise { const encoder = new TextEncoder() const secretKey = encoder.encode(JWT_SECRET) try { await jose.jwtVerify(jwt, secretKey) } catch (err) { console.error(err) return false } return true } Deno.serve(async (req: Request) => { if (req.method !== 'OPTIONS' && VERIFY_JWT) { try { const token = getAuthToken(req) const isValidJWT = await verifyJWT(token) if (!isValidJWT) { return new Response(JSON.stringify({ msg: 'Invalid JWT' }), { status: 401, headers: { 'Content-Type': 'application/json' }, }) } } catch (e) { console.error(e) return new Response(JSON.stringify({ msg: e.toString() }), { status: 401, headers: { 'Content-Type': 'application/json' }, }) } } const url = new URL(req.url) const { pathname } = url const path_parts = pathname.split('/') const service_name = path_parts[1] if (!service_name || service_name === '') { const error = { msg: 'missing function name in request' } return new Response(JSON.stringify(error), { status: 400, headers: { 'Content-Type': 'application/json' }, }) } const servicePath = `/home/deno/functions/${service_name}` console.error(`serving the request with ${servicePath}`) const memoryLimitMb = 150 const workerTimeoutMs = 1 * 60 * 1000 const noModuleCache = false const importMapPath = null const envVarsObj = Deno.env.toObject() const envVars = Object.keys(envVarsObj).map((k) => [k, envVarsObj[k]]) try { const worker = await EdgeRuntime.userWorkers.create({ servicePath, memoryLimitMb, workerTimeoutMs, noModuleCache, importMapPath, envVars, }) return await worker.fetch(req) } catch (e) { const error = { msg: e.toString() } return new Response(JSON.stringify(error), { status: 500, headers: { 'Content-Type': 'application/json' }, }) } }) --- # Source: supabase/templates/kong/config.yaml apiVersion: v1 kind: ConfigMap metadata: name: supabase-basket-supabase-kong labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm data: kong-entrypoint.sh: | #!/bin/bash set -euo pipefail if [ -n "${SUPABASE_SECRET_KEY:-}" ] && [ -n "${SUPABASE_PUBLISHABLE_KEY:-}" ]; then export LUA_AUTH_EXPR="\$((headers.authorization ~= nil and headers.authorization:sub(1, 10) ~= 'Bearer sb_' and headers.authorization) or (headers.apikey == '${SUPABASE_SECRET_KEY}' and 'Bearer ${SERVICE_ROLE_KEY_ASYMMETRIC}') or (headers.apikey == '${SUPABASE_PUBLISHABLE_KEY}' and 'Bearer ${ANON_KEY_ASYMMETRIC}') or headers.apikey)" export LUA_RT_WS_EXPR="\$((query_params.apikey == '${SUPABASE_SECRET_KEY}' and '${SERVICE_ROLE_KEY_ASYMMETRIC}') or (query_params.apikey == '${SUPABASE_PUBLISHABLE_KEY}' and '${ANON_KEY_ASYMMETRIC}') or query_params.apikey)" else export LUA_AUTH_EXPR="\$((headers.authorization ~= nil and headers.authorization:sub(1, 10) ~= 'Bearer sb_' and headers.authorization) or headers.apikey)" export LUA_RT_WS_EXPR="\$(query_params.apikey)" fi echo "Replacing env placeholders of /usr/local/kong/kong.yml" sed \ -e "s|\${SUPABASE_ANON_KEY}|${SUPABASE_ANON_KEY}|" \ -e "s|\${SUPABASE_SERVICE_KEY}|${SUPABASE_SERVICE_KEY}|" \ -e "s|\${SUPABASE_PUBLISHABLE_KEY}|${SUPABASE_PUBLISHABLE_KEY:-}|" \ -e "s|\${SUPABASE_SECRET_KEY}|${SUPABASE_SECRET_KEY:-}|" \ -e "s|\${ANON_KEY_ASYMMETRIC}|${ANON_KEY_ASYMMETRIC:-}|" \ -e "s|\${SERVICE_ROLE_KEY_ASYMMETRIC}|${SERVICE_ROLE_KEY_ASYMMETRIC:-}|" \ -e "s|\${LUA_AUTH_EXPR}|${LUA_AUTH_EXPR}|" \ -e "s|\${LUA_RT_WS_EXPR}|${LUA_RT_WS_EXPR}|" \ -e "s|\${DASHBOARD_USERNAME}|${DASHBOARD_USERNAME}|" \ -e "s|\${DASHBOARD_PASSWORD}|${DASHBOARD_PASSWORD}|" \ /usr/local/kong/template.yml \ > /usr/local/kong/kong.yml sed -i '/^[[:space:]]*- key:[[:space:]]*$/d' /usr/local/kong/kong.yml exec /entrypoint.sh kong docker-start kong.yml: | _format_version: '2.1' _transform: true consumers: - username: DASHBOARD - username: anon keyauth_credentials: - key: ${SUPABASE_ANON_KEY} - key: ${SUPABASE_PUBLISHABLE_KEY} - username: service_role keyauth_credentials: - key: ${SUPABASE_SERVICE_KEY} - key: ${SUPABASE_SECRET_KEY} acls: - consumer: anon group: anon - consumer: service_role group: admin basicauth_credentials: - consumer: DASHBOARD username: '${DASHBOARD_USERNAME}' password: '${DASHBOARD_PASSWORD}' services: - name: auth-v1-open url: http://supabase-basket-supabase-auth:9999/verify routes: - name: auth-v1-open strip_path: true paths: - /auth/v1/verify plugins: - name: cors - name: auth-v1-open-callback url: http://supabase-basket-supabase-auth:9999/callback routes: - name: auth-v1-open-callback strip_path: true paths: - /auth/v1/callback plugins: - name: cors - name: auth-v1-open-authorize url: http://supabase-basket-supabase-auth:9999/authorize routes: - name: auth-v1-open-authorize strip_path: true paths: - /auth/v1/authorize plugins: - name: cors - name: auth-v1-open-jwks url: http://supabase-basket-supabase-auth:9999/.well-known/jwks.json routes: - name: auth-v1-open-jwks strip_path: true paths: - /auth/v1/.well-known/jwks.json plugins: - name: cors - name: well-known-oauth _comment: 'Auth: /.well-known/oauth-authorization-server -> http://supabase-basket-supabase-auth:9999/.well-known/oauth-authorization-server' url: http://supabase-basket-supabase-auth:9999/.well-known/oauth-authorization-server routes: - name: well-known-oauth strip_path: true paths: - /.well-known/oauth-authorization-server plugins: - name: cors - name: auth-v1-open-sso-acs url: "http://auth:9999/sso/saml/acs" routes: - name: auth-v1-open-sso-acs strip_path: true paths: - /sso/saml/acs plugins: - name: cors - name: auth-v1-open-sso-metadata url: "http://auth:9999/sso/saml/metadata" routes: - name: auth-v1-open-sso-metadata strip_path: true paths: - /sso/saml/metadata plugins: - name: cors - name: auth-v1 _comment: "GoTrue: /auth/v1/* -> http://supabase-basket-supabase-auth:9999/*" url: http://supabase-basket-supabase-auth:9999 routes: - name: auth-v1-all strip_path: true paths: - /auth/v1/ plugins: - name: cors - name: key-auth config: hide_credentials: false - name: request-transformer config: add: headers: - "Authorization: ${LUA_AUTH_EXPR}" replace: headers: - "Authorization: ${LUA_AUTH_EXPR}" - name: acl config: hide_groups_header: true allow: - admin - anon - name: rest-v1 _comment: "PostgREST: /rest/v1/* -> http://supabase-basket-supabase-rest:3000/*" url: http://supabase-basket-supabase-rest:3000/ routes: - name: rest-v1-all strip_path: true paths: - /rest/v1/ plugins: - name: cors - name: key-auth config: hide_credentials: false - name: request-transformer config: add: headers: - "Authorization: ${LUA_AUTH_EXPR}" replace: headers: - "Authorization: ${LUA_AUTH_EXPR}" - name: acl config: hide_groups_header: true allow: - admin - anon - name: graphql-v1 _comment: 'PostgREST: /graphql/v1/* -> http://supabase-basket-supabase-rest:3000/rpc/graphql' url: http://supabase-basket-supabase-rest:3000/rpc/graphql routes: - name: graphql-v1-all strip_path: true paths: - /graphql/v1 plugins: - name: cors - name: key-auth config: hide_credentials: false - name: request-transformer config: add: headers: - "Content-Profile: graphql_public" - "Authorization: ${LUA_AUTH_EXPR}" replace: headers: - "Authorization: ${LUA_AUTH_EXPR}" - name: acl config: hide_groups_header: true allow: - admin - anon - name: realtime-v1-ws _comment: "Realtime: /realtime/v1/* -> ws://supabase-basket-supabase-realtime:4000/socket/*" url: http://supabase-basket-supabase-realtime:4000/socket protocol: ws routes: - name: realtime-v1-ws strip_path: true paths: - /realtime/v1/ plugins: - name: cors - name: key-auth config: hide_credentials: false - name: request-transformer config: add: headers: - "x-api-key:${LUA_RT_WS_EXPR}" replace: querystring: - "apikey:${LUA_RT_WS_EXPR}" - name: acl config: hide_groups_header: true allow: - admin - anon - name: realtime-v1-rest _comment: 'Realtime: /realtime/v1/* -> http://supabase-basket-supabase-realtime:4000/api/*' url: http://supabase-basket-supabase-realtime:4000/api protocol: http routes: - name: realtime-v1-rest strip_path: true paths: - /realtime/v1/api plugins: - name: cors - name: key-auth config: hide_credentials: false - name: request-transformer config: add: headers: - "Authorization: ${LUA_AUTH_EXPR}" replace: headers: - "Authorization: ${LUA_AUTH_EXPR}" - name: acl config: hide_groups_header: true allow: - admin - anon - name: storage-v1 _comment: "Storage: /storage/v1/* -> http://supabase-basket-supabase-storage:5000/*" url: http://supabase-basket-supabase-storage:5000/ routes: - name: storage-v1-all strip_path: true paths: - /storage/v1/ plugins: - name: cors - name: request-transformer config: add: headers: - "Authorization: ${LUA_AUTH_EXPR}" replace: headers: - "Authorization: ${LUA_AUTH_EXPR}" - name: post-function config: access: - | local auth = kong.request.get_header("authorization") if auth == nil or auth == "" or auth:find("^%s*$") then kong.service.request.clear_header("authorization") end - name: functions-v1 _comment: 'Edge Functions: /functions/v1/* -> http://supabase-basket-supabase-functions:9000/*' url: http://supabase-basket-supabase-functions:9000/ read_timeout: 150000 routes: - name: functions-v1-all strip_path: true paths: - /functions/v1/ plugins: - name: cors - name: meta _comment: "pg-meta: /pg/* -> http://supabase-basket-supabase-meta:8080/*" url: http://supabase-basket-supabase-meta:8080/ routes: - name: meta-all strip_path: true paths: - /pg/ plugins: - name: key-auth config: hide_credentials: false - name: acl config: hide_groups_header: true allow: - admin - name: dashboard _comment: 'Studio: /* -> http://supabase-basket-supabase-studio:3000/*' url: http://supabase-basket-supabase-studio:3000/ routes: - name: dashboard-all strip_path: true paths: - / plugins: - name: cors - name: basic-auth config: hide_credentials: true --- # Source: supabase/templates/vector/config.yaml apiVersion: v1 kind: ConfigMap metadata: name: supabase-basket-supabase-vector-config labels: helm.sh/chart: supabase-0.5.6 app.kubernetes.io/name: supabase app.kubernetes.io/instance: supabase-basket app.kubernetes.io/managed-by: Helm data: vector.yml: | api: enabled: true address: 0.0.0.0:9001 sources: kubernetes_host: type: kubernetes_logs extra_label_selector: app.kubernetes.io/instance=supabase-basket,app.kubernetes.io/name!=supabase-vector transforms: project_logs: type: remap inputs: - kubernetes_host source: |- .project = "default" .event_message = del(.message) .appname = del(.kubernetes.container_name) del(.file) del(.kubernetes) del(.source_type) del(.stream) router: type: route inputs: - project_logs route: kong: '.appname == "supabase-kong"' auth: '.appname == "supabase-auth"' rest: '.appname == "supabase-rest"' realtime: '.appname == "supabase-realtime"' storage: '.appname == "supabase-storage"' functions: '.appname == "supabase-functions"' db: '.appname == "supabase-db"' # Ignores non nginx errors since they are related with kong booting up kong_logs: type: remap inputs: - router.kong source: |- req, err = parse_nginx_log(.event_message, "combined") if err == null { .timestamp = req.timestamp .metadata.request.headers.referer = req.referer .metadata.request.headers.user_agent = req.agent .metadata.request.headers.cf_connecting_ip = req.client .metadata.response.status_code = req.status url, split_err = split(req.request, " ") if split_err == null { .metadata.request.method = url[0] .metadata.request.path = url[1] .metadata.request.protocol = url[2] } } if err != null { abort } # Ignores non nginx errors since they are related with kong booting up kong_err: type: remap inputs: - router.kong source: |- .metadata.request.method = "GET" .metadata.response.status_code = 200 parsed, err = parse_nginx_log(.event_message, "error") if err == null { .timestamp = parsed.timestamp .severity = parsed.severity .metadata.request.host = parsed.host .metadata.request.headers.cf_connecting_ip = parsed.client url, err = split(parsed.request, " ") if err == null { .metadata.request.method = url[0] .metadata.request.path = url[1] .metadata.request.protocol = url[2] } } if err != null { abort } # Gotrue logs are structured json strings which frontend parses directly. But we keep metadata for consistency. auth_logs: type: remap inputs: - router.auth source: |- parsed, err = parse_json(.event_message) if err == null { .metadata.timestamp = parsed.time .metadata = merge!(.metadata, parsed) } # PostgREST logs are structured so we separate timestamp from message using regex rest_logs: type: remap inputs: - router.rest source: |- parsed, err = parse_regex(.event_message, r'^(?P