그냥 사는 이야기

Supabase의 Row Level Security (Feat. Postgres) 본문

Development/기타

Supabase의 Row Level Security (Feat. Postgres)

없다캐라 2023. 7. 10. 19:54
반응형

이글은 https://supabase.com/docs/learn/auth-deep-dive/auth-row-level-security 를 번역한 글입니다.

About

Supabase 대시보드에서 Row Level Security(이후 행 수준 보안)을 활성화하고 Postgres 정책을 작성하여 데이터베이스 테이블에 대한 액세스를 제한하는 방법을 알아보세요.

Watch

Securing Your Tables

Supabase에서는 클라이언트(주로 웹 브라우저)에서 직접 데이터에 액세스할 수 있으며, 다음과 같이 Supabase URL과 Anon 키를 supabase-js에 전달하면 됩니다:

const supabase = createClient(
  'https://qwertyuiop.supabase.co',
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
)

"나의 Anon 보안키가 클라이언트에 있으면 누군가 내 자바스크립트를 읽고 키를 훔칠 수 없나요?"라는 흥미로운 질문이 제기될 수 있지만, 대답은 '예'입니다. 이것이 바로 Postgres 정책이 필요한 이유입니다.

Postgres의 "행 수준 보안" 정책을 사용하면 기본적으로 익명 키가 액세스할 수 있는 데이터와 액세스할 수 없는 데이터에 대한 규칙을 설정할 수 있습니다.

예를 들어, 익명 키는 특정 테이블에서 읽기만 가능하고 쓰기, 업데이트, 삭제는 할 수 없도록 설정할 수 있습니다.

그리고 이러한 규칙은 원하는 만큼 복잡할 수 있습니다. 예를 들어 목요일 오후 4시에서 6시 사이에 삽입된 행 중 id 열이 짝수인 행만 익명 키가 삭제할 수 있다고 말할 수 있습니다. 꽤 이상하지만 정책의 힘을 보여줍니다.

리더보드 테이블을 만든다고 가정해 보겠습니다. 웹사이트 사용자가 순위표를 읽을 수는 있지만 작성, 업데이트, 삭제는 할 수 없도록 하려고 합니다. 먼저 SQL로 테이블을 정의하고 몇 가지 더미 데이터를 추가합니다:

create table leaderboard (
  name text,
  score int
);

insert into leaderboard
  (name, score)
values
  ('Paul', 100),
  ('Leto', 50),
  ('Chani', 200);

이제 데이터를 읽을 수 있는 클라이언트를 설정해 보겠습니다. 라이브로 보여주기 위해 Repl로 작성하였습니다. https://replit.com/@awalias/supabase-leaderboard-demo#index.js.

 

supabase-leaderboard-demo

Run Node.js code live in your browser. Write and run code in 50+ languages online with Replit, a powerful IDE, compiler, & interpreter.

replit.com

스니펫을 복사하면 자신만의 Supabase URL과 익명 키를 연결할 수 있습니다.

이를 통해 테이블을 자유롭게 읽고 쓸 수 있다는 것을 알 수 있습니다:

// Writing
let { data, error } = await supabase.from('leaderboard').insert({ name: 'Bob', score: 99999 })

// Reading
let { data, error } = await supabase
  .from('leaderboard')
  .select('name, score')
  .order('score', { ascending: false })

이제 액세스를 제한해 보겠습니다. 테이블을 완전히 제한하는 것으로 시작하겠습니다. SQL 편집기에서 쿼리를 작성하여 이 작업을 수행할 수 있습니다:

ALTER TABLE leaderboard ENABLE ROW LEVEL SECURITY;

를 클릭하거나 Supabase 대시보드에서 Auth > Policies 으로 이동하여 순위표 표의 빨간색 자물쇠를 클릭하여 흰색으로 바꿉니다.

이제 다음과 같은 오류와 함께 읽기 및 쓰기가 모두 실패하는 것을 알 수 있습니다:

{
  hint: null,
  details: null,
  code: '42501',
  message: 'new row violates row-level security policy for table "leaderboard"'
}

이제 인증에서 익명 키(JWT)를 보내는 모든 사용자에 대해 테이블을 읽을 수 있도록 정책을 추가해야 합니다. Authorization: Bearer 헤더에 추가해야 합니다.

SQL에서는 다음과 같이 할 수 있습니다:

CREATE POLICY anon_read_leaderboard ON leaderboard
    FOR SELECT
    TO 'anon'
    USING (true);

여기서 anon_read_leaderboard는 정책에 대해 선택하는 이름일 뿐입니다. leaderboard는 테이블 이름입니다. FOR SELECT는 이 정책이 읽기(또는 SQL에서 "선택")에 대해서만 적용되기를 원한다는 의미입니다. TO는 이 정책이 anon Postgres 역할에만 적용됨을 의미합니다. 마지막으로 규칙 자체는 'true'로, anon 사용자에 대한 모든 select을 허용한다는 의미입니다.

대시보드를 사용하여 정책을 추가하려면 정책 탭에서 "Add Policy"를 클릭하고 다음과 같은 정책을 만들면 됩니다:

이제 리더보드에서 읽을 수는 있지만 쓰기, 업데이트, 삭제는 여전히 불가능하며, 이는 저희가 원했던 바로 그 결과입니다!

service_role API 키를 사용하여 이러한 행 수준 보안 정책을 우회할 수 있다는 점을 다시 한 번 알려드립니다. 하지만 이 키를 클라이언트에 포함시켜서 유출되지 않도록 각별히 주의하세요. 이 키는 내부 관리 도구를 구축하거나 API를 통해 데이터를 대량으로 삽입하거나 삭제해야 하는 경우에 유용할 수 있습니다.

다음 가이드에서는 정책을 사용자 계정과 함께 사용하여 사용자별로 데이터에 대한 액세스를 제한할 수 있는 방법에 대해 살펴보겠습니다: Part Three: Policies를 시청하세요.

 

Comments