01007 privilege not granted 는?
PostgreSQL 에러 코드 01007은 SQLSTATE 경고 수준의 에러로, 특정 권한이 부여되지 않았음을 나타내는 경고(Warning)입니다. 이 에러는 GRANT 명령을 실행할 때 부여하려는 권한이 실제로는 적용되지 않았거나, 이미 존재하지 않는 권한을 다른 사용자에게 위임(GRANT OPTION)하려 할 때 주로 발생합니다. 일반적인 ERROR 수준이 아닌 WARNING 수준이기 때문에 쿼리 자체가 실패하지 않고 경고만 출력되는 경우가 많아 실무에서 놓치기 쉬운 위험한 에러입니다.
주요 발생 원인
1. GRANT OPTION 없이 다른 사용자에게 권한 위임 시도
자신이 보유한 권한에 WITH GRANT OPTION이 없는 상태에서 해당 권한을 제3의 사용자에게 부여하려 할 때 이 경고가 발생합니다. PostgreSQL에서는 권한을 위임하려면 반드시 부여자 자신도 WITH GRANT OPTION을 보유하고 있어야 하며, 그렇지 않으면 권한 부여 자체가 무시되거나 경고가 발생합니다.
2. 존재하지 않거나 이미 해제된 권한을 GRANT하려는 경우
대상 객체(테이블, 스키마, 함수 등)에 대해 부여하려는 권한이 시스템적으로 유효하지 않거나, 이미 취소(REVOKE)된 권한을 다시 위임하려 할 때 발생합니다. 예를 들어, REVOKE로 권한을 제거한 뒤 해당 권한에 대한 GRANT OPTION까지 사라진 상황에서 위임을 시도하면 이 경고가 트리거됩니다.
3. 역할(Role) 계층 구조에서의 권한 상속 문제
PostgreSQL의 역할 상속(Role Inheritance) 구조에서, 상위 역할이 NOINHERIT 옵션으로 설정되어 있거나 WITH GRANT OPTION 없이 권한을 보유한 경우, 하위 역할이 해당 권한을 제3자에게 위임하려 할 때 이 경고가 발생합니다. 역할 계층이 복잡할수록 어느 단계에서 권한 위임이 막혔는지 추적하기 어렵기 때문에 주의가 필요합니다.
해결 방법
원인 1: GRANT OPTION 없이 권한 위임 시도
먼저 현재 사용자가 해당 권한에 대해 GRANT OPTION을 보유하고 있는지 확인합니다.
-- 현재 테이블 권한 및 GRANT OPTION 보유 여부 확인
SELECT grantor, grantee, privilege_type, is_grantable
FROM information_schema.role_table_grants
WHERE table_name = 'your_table_name'
AND grantee = current_user;
is_grantable이 NO라면 WITH GRANT OPTION이 없는 상태입니다. 이 경우 슈퍼유저 또는 객체 소유자가 직접 권한을 부여하거나, 위임 권한 자체를 다시 부여해야 합니다.
-- 슈퍼유저 또는 객체 소유자가 WITH GRANT OPTION을 포함하여 권한 부여
GRANT SELECT, INSERT ON TABLE public.orders TO analyst_role WITH GRANT OPTION;
-- 이후 analyst_role 사용자가 다른 사용자에게 위임 가능
SET ROLE analyst_role;
GRANT SELECT ON TABLE public.orders TO readonly_user;
RESET ROLE;
원인 2: 이미 해제된 권한을 GRANT하려는 경우
기존 권한 상태를 먼저 점검하고, 필요한 경우 권한을 초기화하여 재설정합니다.
-- 특정 역할의 테이블별 권한 전체 조회
SELECT table_schema, table_name, privilege_type, is_grantable
FROM information_schema.role_table_grants
WHERE grantee = 'target_role'
ORDER BY table_schema, table_name;
-- 권한이 없는 경우 슈퍼유저로 재부여
GRANT SELECT, UPDATE ON TABLE public.products TO target_role;
-- GRANT OPTION까지 포함하여 위임 체계를 다시 구성
GRANT ALL PRIVILEGES ON TABLE public.products TO manager_role WITH GRANT OPTION;
GRANT SELECT ON TABLE public.products TO readonly_role; -- manager_role로 SET ROLE 후 실행
원인 3: 역할 계층 구조 문제
역할 계층과 INHERIT 설정을 점검하여 권한 위임 가능 여부를 확인합니다.
-- 역할의 INHERIT 설정 확인
SELECT rolname, rolinherit, rolcanlogin
FROM pg_roles
WHERE rolname IN ('parent_role', 'child_role', 'target_user');
-- NOINHERIT로 인해 권한이 전달되지 않는 경우, 역할을 수정하거나 직접 권한 부여
ALTER ROLE child_role INHERIT;
-- 역할 멤버십 확인
SELECT r.rolname AS role, m.rolname AS member
FROM pg_auth_members am
JOIN pg_roles r ON r.oid = am.roleid
JOIN pg_roles m ON m.oid = am.member;
-- 권한 위임을 위한 올바른 계층 재설정 예시
-- 1단계: 슈퍼유저가 상위 역할에 GRANT OPTION 부여
GRANT SELECT ON ALL TABLES IN SCHEMA public TO parent_role WITH GRANT OPTION;
-- 2단계: 하위 역할에 parent_role 멤버십 부여
GRANT parent_role TO child_role;
-- 3단계: child_role이 실제로 위임 가능한지 테스트
SET ROLE child_role;
GRANT SELECT ON TABLE public.orders TO end_user;
RESET ROLE;
경고 메시지 확인 방법
애플리케이션 레이어에서 이 경고를 명시적으로 잡고 싶다면 아래처럼 client_min_messages를 조정하여 경고를 로그에서 확인할 수 있습니다.
-- 세션 수준에서 경고 이상 메시지 출력
SET client_min_messages = 'WARNING';
-- 이후 GRANT 실행 시 01007 경고 메시지가 클라이언트에 표시됨
GRANT SELECT ON TABLE public.sensitive_data TO some_role;
-- psql에서 직접 SQLSTATE 확인
\set VERBOSITY verbose
GRANT SELECT ON TABLE public.sensitive_data TO some_role;
예방 방법
1. 권한 부여 전 항상 현재 권한 상태를 스크립트로 점검하는 습관 만들기
운영 환경에서 GRANT 명령을 실행하기 전에, 반드시 현재 권한 상태와 GRANT OPTION 보유 여부를 사전에 조회하는 쿼리를 표준 절차로 만들어야 합니다. 특히 역할 계층이 3단계 이상인 경우 권한 위임 체계를 문서화하고, 아래와 같은 점검 쿼리를 배포 스크립트에 포함시키는 것이 좋습니다.
-- 권한 점검용 표준 쿼리 (배포 전 항상 실행)
SELECT
grantee,
table_schema,
table_name,
string_agg(privilege_type, ', ') AS privileges,
bool_or(is_grantable = 'YES') AS has_grant_option
FROM information_schema.role_table_grants
WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
GROUP BY grantee, table_schema, table_name
ORDER BY grantee, table_schema, table_name;
2. 권한 관리 전용 역할(Role)을 분리하여 중앙화된 권한 위임 체계 구축하기
모든 개발자나 애플리케이션 계정이 직접 권한을 위임하도록 허용하면 01007 경고뿐 아니라 권한 누락, 과다 권한 등의 보안 문제가 발생합니다. 권한 부여 권한(WITH GRANT OPTION)은 반드시 전용 DBA 역할 또는 권한 관리 역할에만 부여하고, 그 역할을 통해서만 권한이 위임되도록 구조화해야 합니다.
-- 권한 관리 전용 역할 생성 및 중앙화 예시
CREATE ROLE permission_manager NOLOGIN;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO permission_manager WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO permission_manager WITH GRANT OPTION;
-- 실제 권한 위임은 permission_manager 역할로만 수행
GRANT permission_manager TO dba_user; -- DBA만 이 역할을 사용 가능
SET ROLE permission_manager;
GRANT SELECT ON TABLE public.orders TO app_readonly;
GRANT INSERT, UPDATE ON TABLE public.orders TO app_writer;
RESET ROLE;
관련 에러
-
42501(insufficient_privilege):01007과 달리 실제 쿼리 실행 시 권한이 없어 에러로 실패하는 경우입니다.01007이 GRANT 단계의 경고라면,42501은 실제 DML/DDL 실행 단계에서 발생하는 하드 에러입니다. -
01006(privilege_not_revoked): REVOKE 명령 실행 시 해당 권한이 애초에 부여되지 않아 취소할 권한이 없을 때 발생하는 경고로,01007과 쌍을 이루는 관련 에러입니다. -
0LP01(invalid_grant_operation): 유효하지 않은 GRANT 작업 자체를 시도할 때 발생하며, 객체 타입과 권한 타입이 맞지 않는 경우(예: 테이블에 EXECUTE 권한 부여 시도)에 나타납니다.
Top comments (0)