파이프라인 작업의 보안 규칙

파이프라인 작업 규칙을 사용하면 기존 규칙 엔진의 필터링 기능과 일치시킬 수 있습니다. 파이프라인 작업은 다양한 기능을 제공하지만 규칙 엔진은 쿼리 만족도와 보안을 보장하기 위해 간단한 필드만 인식하도록 제한됩니다.

버전 및 모드 요구사항

이 문서는 기본 모드의 Firestore Enterprise 버전에 적용됩니다.

지원되는 필터 표현식

쿼리가 규칙에 의해 제한되려면 상수에 대해 표준 비교 연산자를 사용해야 합니다. 규칙 엔진에서 인식하는 필터 유형은 다음과 같습니다.

  • 등호 및 부등: eq, neq.
  • 비교: gt, gte, lt, lte.
  • 멤버십: in, arrayContains.

예를 들면 다음과 같습니다.

  • where(eq("foo", 2))
  • where(lt("foo", 2))
  • documents("/user/1", "/user/2").where(...)

요청 속성

표준 쿼리에서 사용할 수 있는 일부 속성은 파이프라인에서 지원되지 않지만 request 객체를 사용하여 인증을 확인하고 컨텍스트를 쿼리할 수 있습니다.

지원되는 속성

새 엔진은 다음 속성을 계속 지원합니다.

  • request.auth: 사용자 UID 및 토큰 데이터에 액세스합니다.
  • request.method: 작업을 식별합니다(예: get, list).
  • request.path: 액세스되는 리소스의 경로입니다.
  • request.time: 요청의 서버 측 타임스탬프입니다.

지원되지 않는 속성

limit, offset, orderBy와 같은 request.query 속성은 다단계 쿼리에서 이러한 값을 결정하는 복잡성으로 인해 파이프라인 규칙 검사에서 지원되지 않습니다.

파이프라인 단계 처리 및 권한

보안 규칙의 세부 작업에 매핑되는 다양한 파이프라인 단계가 있습니다.

  • allow list 권한: collection(), collectionGroup(), database() 단계에서 트리거됩니다.
  • allow get 권한: 일괄 get 작업과 유사하게 처리되는 documents() 단계에 의해 트리거됩니다.
  • allow create 권한: 새 문서를 만들 때 insert() 단계 및 upsert() 단계에서 트리거됩니다.
  • allow update 권한: 기존 문서를 업데이트할 때 update() 단계 및 upsert() 단계에서 트리거됩니다.
  • allow delete 권한: delete() 단계에서 트리거됩니다.
  • allow write 권한: 모든 DML 작업 (insert(), update(), upsert(), delete())에 적용됩니다.
  • 필드 수정 단계: 규칙은 파생 값이 아닌 저장된 데이터에만 적용됩니다. 파이프라인에 필드를 수정하는 단계 (예: AddFields, ReplaceWith, Select)가 포함된 경우 규칙 엔진은 해당 단계가 발생한 후 필터 제약 조건 적용을 중지합니다.
  • 리터럴 단계: literals() 단계는 데이터베이스에서 읽지 않지만 비용이 발생할 수 있습니다. 악용을 방지하려면 규칙으로 확인할 수 있는 다른 단계 (예: collection())와 페어링해야 합니다.

데이터 조작 언어 (DML) 단계 및 보안 규칙

데이터 조작 언어 (DML) 단계 (insert(), update(), upsert(), delete())를 실행할 때 보안 규칙은 읽기 쿼리와 다르게 권한을 평가합니다.

  • 문서별 규칙 평가: 계획 시 쿼리를 제한하기 위해 필터 표현식이 미리 필요한 읽기 파이프라인과 달리 DML 작업은 각 개별 문서 변형에 대해 보안 규칙을 평가합니다.
  • 규칙 변수:
    • request.resource: insert(), update(), upsert() 작업에 대해 제안된 문서 데이터가 포함됩니다.
    • resource: 수정 전에 데이터베이스에 저장된 현재 문서 데이터가 포함됩니다 (기존 문서의 update(), delete(), upsert()에 사용 가능).

DML을 사용한 시스템 한도 및 실행 동작

보안 규칙으로 DML 작업을 실행할 때는 다음 시스템 한도 및 실행 동작에 유의하세요.

get() 및 exists()의 조회 한도 20개

Firebase 보안 규칙은 전체 요청에서 최대 20개의 문서 조회 (get() 또는 exists())를 허용합니다.

DML 파이프라인이 명시적 트랜잭션 외부에서 실행되면 문서가 일괄 처리됩니다. 각 배치는 자체 트랜잭션에서 실행되고 배치가 실행되는 사이에 문서가 동시에 수정될 수 있으므로 각 쓰기 배치에 대해 보안 규칙과 문서 조회가 다시 평가됩니다.

보안 규칙이 단일 정적 문서를 기준으로 평가하는 경우에도 마찬가지입니다. 예를 들어 사용자가 관리자인지 확인하는 경우를 들 수 있습니다.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /posts/{postId} {
      allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.isAdmin == true;
    }
  }
}

각 문서 쓰기 배치는 조회를 수행합니다. 따라서 가능한 모든 문서를 작성한 후 요청의 조회 한도 20개에 도달하고 파이프라인이 PERMISSION_DENIED 오류와 함께 실패합니다. 또한 쓰기 배치당 수행되는 각 조회에는 자체 읽기 청구가 발생합니다.

일부 성공 및 PERMISSION_DENIED

트랜잭션 외부에서 실행할 때 DML 작업은 순차적 배치로 쓰기를 커밋합니다. 문서가 규칙 조건을 충족하지 못하거나 20회 조회 한도를 초과하여 배치가 실패하면 파이프라인이 중지되고 PERMISSION_DENIED 오류가 반환됩니다.

하지만 이미 커밋된 배치는 롤백되지 않습니다. 데이터베이스는 부분적으로 업데이트된 상태로 유지됩니다. 클라이언트는 수정된 문서 목록 없이 오류를 수신하므로 데이터를 쿼리하여 어떤 쓰기가 성공했는지 검사해야 합니다.

Cloud 감사 로그를 사용한 규칙 오류 진단

보안상의 이유로 클라이언트 측 PERMISSION_DENIED 오류는 실패한 보안 규칙 조건이나 20회 조회 한도 도달 여부를 공개하지 않습니다.

규칙 평가 실패를 진단하기 위해 프로젝트 관리자는 Google Cloud 콘솔 (Firestore > 모니터링 또는 로그 탐색기)에서 Cloud 감사 로그를 검사하여 자세한 EvaluationError 항목을 확인할 수 있습니다.