ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Supabase][보안] backend별 secret key를 따로 만들고 유출 시 어느 서비스부터 rotation하나
    기타개발지식/풀스택개발 2026. 8. 1. 20:13

    IT 리서치 노트

    [Supabase][보안] backend별 secret key를 따로 만들고 유출 시 어느 서비스부터 rotation하나

    Supabase에서 secret key를 새 체계로 옮긴 뒤에도 많은 팀이 backend 전체에 같은 key를 계속 쓴다. 하지만 2026년 8월 1일 기준 Supabase 공식 문서를 다시 보면, backend component마다 secret key를 따로 두고 유출 시 해당 컴포넌트만 교체하는 편이 좋다고 권장한다. 이 글은 backend별 secret key를 어떻게 나누고, 문제가 생겼을 때 어느 서비스부터 rotation할지 정리한 것이다.

    1. 개요

    결론부터 말하면 Supabase secret key는 관리자 API, 배치 worker, pg_net·Database Webhooks, Edge Functions 관리자 경로처럼 backend component별로 따로 두는 편이 안전하다. 유출이 생겼을 때는 새 key 생성, 컴포넌트별 순차 교체, old key 삭제 순서로 가야 하고, pg_net·webhook은 Authorization이 아니라 apikey 헤더 전환까지 확인해야 한다.

    한 key를 backend 전체에 공유하면 rotation 하나가 모든 서비스의 동시 배포가 된다. 반대로 경계를 나눠 두면 incident를 가장 작은 서비스 단위에서 닫을 수 있다.

    2. 어디서 실제로 막히는가

    실무에서 먼저 막히는 지점은 세 가지다. 첫째, 관리자 API와 cron worker와 webhook이 같은 secret key를 공유해 한 지점 유출이 전 서비스 incident가 된다. 둘째, 새 key를 만들었지만 어떤 backend가 아직 old key를 쓰는지 목록이 없어 삭제 시점을 못 잡는다. 셋째, pg_net와 Database Webhooks는 여전히 Authorization: Bearer로 key를 보내고 있어 새 secret key cutover가 실패한다.

    Supabase API key 문서는 backend component마다 separate secret key를 권장하고, secret key rotation은 새 key 생성 후 모든 component 교체를 확인한 다음 기존 key를 삭제하라고 안내한다. migration guide는 새 secret key가 JWT가 아니므로 pg_net와 Database Webhooks에서 Authorization 헤더 대신 apikey 헤더를 써야 한다고 적는다. 즉 key rotation은 환경변수 문자열 교체와 HTTP 헤더 교체가 같이 끝나야 닫힌다.

    • 증상: secret key를 바꿨는데 일부 webhook과 SQL 호출만 계속 실패한다.
    • 실패: backend 전체가 같은 key를 공유해 영향 범위를 줄이지 못한다.
    • 막힘: old key를 쓰는 component inventory가 없다.
    • 누락: pg_net와 Database Webhooks 헤더를 Authorization에서 apikey로 안 바꾼다.
    질문 먼저 볼 곳 판단 기준
    어디까지 같은 key를 쓰나 backend component inventory admin API, worker, webhook, function을 분리한다
    왜 새 key가 호출에서 실패하나 헤더 종류와 verify_jwt 경로 JWT가 아닌 key는 apikey header로 보낸다
    언제 old key를 삭제하나 component별 cutover 완료 기록 구 key 사용량이 0이 된 뒤 삭제한다

    3. 실무에서 적용하는 순서

    운영 순서는 다섯 단계가 가장 실용적이다. 먼저 backend component inventory를 만든다. 다음으로 새 secret key를 만들고 대상 컴포넌트 하나에만 연결한다. 세 번째로 관리자 API, 배치 worker, webhook, Edge Function을 순차 교체한다. 네 번째로 pg_net와 Dashboard webhook은 Authorization 헤더를 제거하고 apikey 헤더로 바꾼다. 마지막으로 old key 사용 로그가 남아 있지 않은 것을 확인한 뒤 기존 key를 삭제한다.

    실제 작업에서는 Dashboard의 Settings > API Keys 메뉴를 클릭해 새 key를 만들고, 각 서비스의 환경변수 필드에 입력한 뒤 배포를 실행하고 응답 상태와 서버 로그를 확인한다. Database Webhooks 화면에서는 HTTP headers 메뉴를 열어 Authorization 항목을 제거하고 apikey 필드를 추가한 뒤 저장 버튼을 누른다. Edge Functions > Secrets 탭에서도 키 존재 여부와 함수 실행 결과를 다시 조회한다.

    1. backend component inventory를 만든다.
    2. 새 secret key를 만들고 대상 서비스 하나에 먼저 붙인다.
    3. 관리자 API와 worker를 순차 교체한다.
    4. pg_net·Database Webhooks는 apikey 헤더로 바꾼다.
    5. 구 key 사용량이 0이 되면 기존 key를 삭제한다.

    이 순서를 따르면 rotation이 '프로젝트 전체 갈아엎기'가 아니라 '특정 backend service incident 대응'이 된다. 특히 pg_net와 Database Webhooks는 key를 SQL이나 Dashboard 설정에 평문으로 남기기 쉬우므로 Vault 참조와 header 교체를 같이 끝내는 편이 좋다.

    component=queue-worker
    new_secret_key_name=queue-worker-v2
    env_updated=true
    deploy_completed=true
    webhook_header_mode=apikey
    old_key_requests=0
    delete_old_key_ready=true

    이 메모가 있으면 새 key를 넣은 뒤에도 왜 특정 webhook만 깨졌는지, old key 삭제를 왜 아직 못 하는지, 어느 서비스가 남아 있는지를 즉시 설명할 수 있다.

    4. 공식 문서와 예시 화면으로 확인하기

    첫 공식 화면은 secret key 운영 원칙을 직접 적은 구간이다. Supabase는 backend component마다 secret key를 따로 두라고 권장한다.

    Supabase API key 문서는 backend component마다 별도 secret key를 써야 한 서비스 유출 시 전체가 아니라 해당 서비스만 교체하면 된다고 설명한다.
    Supabase API key 문서는 backend component마다 별도 secret key를 써야 한 서비스 유출 시 전체가 아니라 해당 서비스만 교체하면 된다고 설명한다.

    즉 rotation 기준은 프로젝트 전체가 아니라 컴포넌트 경계다. 이미 publishable·secret·service_role 분리 글이 환경별 key 배치를 다뤘다면, 이번 글은 backend 내부를 더 잘게 나누는 단계다.

    두 번째 자료는 실제 secret key rotation 안내다. 문서는 새 secret key를 만든 뒤 모든 component가 새 key를 쓰는 것을 확인하고, 마지막에 기존 key를 삭제하라고 적고 있다.

    Supabase 문서는 secret key rotation을 새 key 생성, component 교체, 기존 key 삭제 순서로 설명한다.
    Supabase 문서는 secret key rotation을 새 key 생성, component 교체, 기존 key 삭제 순서로 설명한다.

    여기서 중요한 점은 '모든 component'의 범위를 작게 만드는 것이다. backend별로 key를 안 나눠 두면 rotation 하나가 전체 서비스 배포가 된다.

    세 번째 화면은 migration guide의 pg_net와 Database Webhooks 구간이다. 여기서는 새 secret key가 JWT가 아니므로 Authorization: Bearer 헤더에 실을 수 없고 apikey 헤더로 보내야 한다고 설명한다. 이 화면에서는 header 이름, before 예시, after 예시, SQL 호출 결과를 같이 확인해야 한다.

    Supabase migration guide는 pg_net와 Database Webhooks가 새 secret key를 쓸 때 Authorization 대신 apikey 헤더로 바뀌어야 한다고 설명한다.
    Supabase migration guide는 pg_net와 Database Webhooks가 새 secret key를 쓸 때 Authorization 대신 apikey 헤더로 바뀌어야 한다고 설명한다.

    즉 backend별 key rotation은 환경변수만 바꾸는 작업이 아니다. SQL webhook과 Edge Functions처럼 key를 넘기는 헤더 방식도 같이 바뀌는지 확인해야 cutover가 닫힌다. header 필드, webhook 메뉴, 저장 버튼, 호출 결과 로그까지 같이 봐야 한다.

    backend를 표로 쪼개면 어떤 서비스가 독립 rotation 대상인지 바로 보인다. admin API, cron, pg_net webhook, Edge Function을 한 key로 묶어 두면 한 지점 누출이 전체 incident가 된다.

    Supabase secret key를 backend component별로 쪼개는 기준표다.
    Supabase secret key를 backend component별로 쪼개는 기준표다.

    특히 legacy key migration 순서 글 다음에는 이 표를 만들어 두는 편이 좋다. migration 완료 뒤 실제 운영 리스크는 backend별 경계에서 갈린다.

    rotation playbook은 코드와 운영 메모를 한 번에 보여 주는 편이 좋다. 교체 순서를 컴포넌트 단위로 적어 두면 incident 때 의사결정이 짧아진다.

    새 secret key 생성 뒤 backend별로 순차 교체하는 예시다.
    새 secret key 생성 뒤 backend별로 순차 교체하는 예시다.

    이 예시처럼 key id, 대상 서비스, 적용 완료 확인을 한 줄로 남기면 전체 backend를 동시에 뒤엎지 않고도 rotation을 닫을 수 있다.

    마지막 자료는 유출 대응 체크리스트다. key 생성만 하고 실제 트래픽이 어느 서비스에서 아직 옛 key를 쓰는지 안 보면 삭제 시점에 장애가 난다.

    Supabase secret key 유출 시 backend별 rotation 순서를 정리한 체크리스트다.
    Supabase secret key 유출 시 backend별 rotation 순서를 정리한 체크리스트다.

    핵심은 새 key를 먼저 만들고, 영향을 받는 backend 경계를 가장 좁게 정의한 뒤, apikey 헤더 전환까지 확인하고 오래된 key를 지우는 순서다.

    5. 주의사항과 리스크

    첫 번째 리스크는 secret key가 브라우저에서 401을 주니 유출돼도 피해가 작다고 오해하는 것이다. 공식 문서는 다른 도구로 악용될 수 있으니 즉시 삭제를 검토하라고 적는다. 두 번째는 pg_net와 Database Webhooks가 새 key에서도 계속 Authorization: Bearer를 쓰고 있어 cutover가 미완료인데도 끝났다고 생각하는 것이다. 세 번째는 backend inventory 없이 전체 서비스에 같은 key를 공유해 incident 범위를 불필요하게 키우는 것이다.

    운영 전에 확인할 때는 component 이름, key 이름, 교체 완료 시각, header 방식, old key 사용량 다섯 항목을 표로 남겨 두는 편이 좋다. 이 다섯 칸이 없으면 rotation 후속 작업이 계속 뒤로 밀린다.

    • secret key는 backend component별로 나눈다.
    • pg_net와 webhook은 apikey 헤더 전환을 따로 확인한다.
    • old key 삭제는 사용량 0 확인 뒤에 한다.

    6. 결론

    Supabase secret key rotation의 핵심은 새 key를 만드는 일보다 backend 경계를 작게 나누는 일이다. 관리자 API, worker, webhook, Edge Function을 분리하고, pg_net·Database Webhooks의 apikey 헤더 전환까지 확인한 뒤 old key를 지우면 incident 범위와 배포 범위를 동시에 줄일 수 있다.

    여기서 한 단계 더 들어가면 backend-only 함수에서 verify_jwt=false와 apikey 헤더를 어디까지 허용할지 경계를 따로 문서화해야 한다. 이어지는 후속 글 verify_jwt=false 엔드포인트와 backend secret key를 같이 쓸 때 apikey와 Authorization을 어디서 먼저 나누나에서 webhook·pg_net·worker route 분리와 header cutover 순서를 정리했다.

    • backend마다 별도 secret key를 둔다.
    • rotation은 컴포넌트 단위로 순차 적용한다.
    • pg_net와 webhook은 Authorization이 아니라 apikey를 쓴다.

    7. 참고 링크

    1. https://supabase.com/docs/guides/getting-started/api-keys
    2. https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys
Designed by Tistory.