행 수준 보안 정책
적용 대상: ✅Microsoft Fabric✅Azure Data Explorer
그룹 멤버 자격 또는 실행 컨텍스트를 사용하여 데이터베이스 테이블의 행에 대한 액세스를 제어합니다.
행 수준 보안(RLS)은 보안 설계 및 코딩을 간소화합니다. 애플리케이션에서 데이터 행 액세스에 대한 제한을 적용할 수 있습니다. 예를 들어 부서와 관련된 행에 대한 사용자 액세스를 제한하거나 고객과 관련된 데이터로만 고객 액세스를 제한합니다.
액세스 제한 논리는 다른 애플리케이션 계층의 데이터와 다소 떨어진 데이터베이스 계층에 위치합니다. 데이터베이스 시스템은 모든 계층에서 데이터 액세스를 시도할 때마다 액세스 제한을 적용합니다. 이 논리는 보안 시스템의 노출 영역을 줄여 보안 시스템을 보다 안정적이고 강력하게 만듭니다.
RLS를 사용하면 테이블의 특정 부분에만 다른 애플리케이션 및 사용자에 대한 액세스를 제공할 수 있습니다. 예를 들어, 다음을 수행합니다.
- 일부 조건을 충족하는 행에만 액세스 권한 부여
- 일부 열에서 데이터 익명화
- 위 항목 모두 해당
참고 항목
테이블에서 RLS 정책을 사용하도록 설정하면 액세스가 테이블에 정의된 RLS 쿼리로 완전히 바뀝니다. 액세스 제한은 데이터베이스 관리자 및 RLS 작성자를 포함한 모든 사용자에게 적용됩니다. RLS 쿼리는 액세스 권한을 부여하려는 모든 유형의 사용자에 대한 정의를 명시적으로 포함해야 합니다.
자세한 내용은 행 수준 보안 정책을 관리하기 위한 관리 명령을 참조하세요.
팁
이러한 함수는 쿼리를 row_level_security 데 유용한 경우가 많습니다.
제한 사항
- 행 수준 보안 정책을 구성할 수 있는 테이블 수에는 제한이 없습니다.
- 외부 테이블에는 행 수준 보안 정책을 구성할 수 없습니다.
- 다음 상황에서는 테이블에서 RLS 정책을 사용하도록 설정할 수 없습니다.
- 업데이트 정책이 관리 ID로 구성되지 않은 동안 업데이트 정책 쿼리에서 참조되는 경우
- 가장 이외의 인증 방법을 사용하는 연속 내보내기에서 참조되는 경우
- 제한된 뷰 액세스 정책이 테이블에 대해 구성된 경우
- RLS 쿼리는 다른 데이터베이스에 있는 테이블을 참조할 수 없습니다.
예제
Sales 테이블에 대한 액세스 제한
테이블의 Sales
각 행에는 판매에 대한 세부 정보가 포함됩니다. 열 중 하나에는 영업 사원의 이름이 포함됩니다. 영업 사원에게 모든 레코드 Sales
에 대한 액세스 권한을 부여하는 대신 이 테이블에서 행 수준 보안 정책을 사용하여 영업 사원이 현재 사용자인 레코드만 반환할 수 있습니다.
Sales | where SalesPersonAadUser == current_principal()
전자 메일 주소를 마스킹할 수도 있습니다.
Sales | where SalesPersonAadUser == current_principal() | extend EmailAddress = "****"
모든 영업 사원이 특정 국가/지역의 모든 판매를 보도록 하려면 다음과 유사한 쿼리를 정의할 수 있습니다.
let UserToCountryMapping = datatable(User:string, Country:string)
[
"john@domain.com", "USA",
"anna@domain.com", "France"
];
Sales
| where Country in ((UserToCountryMapping | where User == current_principal_details()["UserPrincipalName"] | project Country))
관리자가 포함된 그룹이 있는 경우 모든 행에 대한 액세스 권한을 부여할 수 있습니다. 행 수준 보안 정책에 대한 쿼리는 다음과 같습니다.
let IsManager = current_principal_is_member_of('aadgroup=sales_managers@domain.com');
let AllData = Sales | where IsManager;
let PartialData = Sales | where not(IsManager) and (SalesPersonAadUser == current_principal()) | extend EmailAddress = "****";
union AllData, PartialData
다른 Microsoft Entra 그룹의 구성원에게 다른 데이터 노출
Microsoft Entra 그룹이 여러 개 있고 각 그룹의 멤버가 다른 데이터 하위 집합을 표시하도록 하려면 RLS 쿼리에 이 구조를 사용합니다.
Customers
| where (current_principal_is_member_of('aadgroup=group1@domain.com') and <filtering specific for group1>) or
(current_principal_is_member_of('aadgroup=group2@domain.com') and <filtering specific for group2>) or
(current_principal_is_member_of('aadgroup=group3@domain.com') and <filtering specific for group3>)
여러 테이블에 동일한 RLS 함수 적용
먼저 테이블 이름을 문자열 매개 변수로 수신하고 연산자를 사용하여 테이블을 참조하는 함수를 table()
정의합니다.
예시:
.create-or-alter function RLSForCustomersTables(TableName: string) {
table(TableName)
| ...
}
그런 다음, 다음과 같이 여러 테이블에서 RLS를 구성합니다.
.alter table Customers1 policy row_level_security enable "RLSForCustomersTables('Customers1')"
.alter table Customers2 policy row_level_security enable "RLSForCustomersTables('Customers2')"
.alter table Customers3 policy row_level_security enable "RLSForCustomersTables('Customers3')"
무단 액세스 시 오류 생성
인증되지 않은 테이블 사용자가 빈 테이블을 반환하는 대신 오류를 수신하도록 하려면 이 함수를 assert()
사용합니다. 다음 예제에서는 RLS 함수에서 이 오류를 생성하는 방법을 보여 줍니다.
.create-or-alter function RLSForCustomersTables() {
MyTable
| where assert(current_principal_is_member_of('aadgroup=mygroup@mycompany.com') == true, "You don't have access")
}
이 방법을 다른 예제와 결합할 수 있습니다. 예를 들어 다른 Microsoft Entra 그룹의 사용자에게 다른 결과를 표시하고 다른 사용자에게 오류를 생성할 수 있습니다.
팔로워 데이터베이스에 대한 권한 제어
프로덕션 데이터베이스에서 구성하는 RLS 정책은 팔로워 데이터베이스에도 적용됩니다. 프로덕션 및 팔로워 데이터베이스에는 다른 RLS 정책을 구성할 수 없습니다. 그러나 RLS 쿼리의 current_cluster_endpoint()
함수를 사용하여 팔로워 테이블에 다른 RLS 쿼리가 있는 것과 동일한 효과를 얻을 수 있습니다.
예시:
.create-or-alter function RLSForCustomersTables() {
let IsProductionCluster = current_cluster_endpoint() == "mycluster.eastus.kusto.windows.net";
let DataForProductionCluster = TempTable | where IsProductionCluster;
let DataForFollowerClusters = TempTable | where not(IsProductionCluster) | extend EmailAddress = "****";
union DataForProductionCluster, DataForFollowerClusters
}
참고 항목
위의 RLS 함수는 리더 클러스터의 쿼리에 성능에 전혀 영향을 주지 않습니다. 팔로워 클러스터의 쿼리에 대한 성능 영향은 복잡성에 DataForFollowerClusters
의해서만 영향을 받습니다.
바로 가기 데이터베이스에 대한 권한 제어
프로덕션 데이터베이스에서 구성하는 RLS 정책도 바로 가기 데이터베이스에 적용됩니다. 프로덕션 및 바로 가기 데이터베이스에는 다른 RLS 정책을 구성할 수 없습니다. 그러나 RLS 쿼리의 current_cluster_endpoint()
함수를 사용하여 바로 가기 테이블에 다른 RLS 쿼리가 있는 것과 동일한 효과를 얻을 수 있습니다.
예시:
.create-or-alter function RLSForCustomersTables() {
let IsProductionCluster = current_cluster_endpoint() == "mycluster.eastus.kusto.windows.net";
let DataForProductionCluster = TempTable | where IsProductionCluster;
let DataForFollowerClusters = TempTable | where not(IsProductionCluster) | extend EmailAddress = "****";
union DataForProductionCluster, DataForFollowerClusters
}
참고 항목
위의 RLS 함수는 원본 데이터베이스의 쿼리에 성능에 아무런 영향을 주지 않습니다. 바로 가기 데이터베이스의 쿼리에 대한 성능 영향은 복잡성에 DataForFollowerClusters
의해서만 영향을 받습니다.
더 많은 사용 사례
- 콜 센터 지원 담당자는 사회 보장 번호의 여러 자리로 발신자를 식별할 수 있습니다. 이 번호는 지원 담당자에게 완전히 노출되어서는 안 됩니다. 테이블에 RLS 정책을 적용하여 쿼리 결과 집합에서 사회 보장 번호의 마지막 4자리를 제외한 모든 숫자를 마스킹할 수 있습니다.
- PII(개인 식별 정보)를 마스킹하고 개발자가 규정 준수 규정을 위반하지 않고 문제 해결을 위해 프로덕션 환경을 쿼리할 수 있도록 하는 RLS 정책을 설정합니다.
- 병원은 간호사가 환자의 데이터 행만 볼 수 있도록 하는 RLS 정책을 설정할 수 있습니다.
- 은행은 직원의 비즈니스 부서 또는 역할에 따라 금융 데이터 행에 대한 액세스를 제한하는 RLS 정책을 설정할 수 있습니다.
- 다중 테넌트 애플리케이션은 여러 테넌트에서 데이터를 단일 테이블 세트에 저장할 수 있습니다(효율적임). RLS 정책을 사용하여 각 테넌트의 데이터 행을 다른 모든 테넌트의 행에서 논리적으로 분리하도록 적용하므로 각 테넌트는 해당 데이터 행만 볼 수 있습니다.
쿼리에 대한 성능 영향
테이블에서 RLS 정책을 사용하도록 설정하면 해당 테이블에 액세스하는 쿼리에 몇 가지 성능 영향이 있습니다. 테이블에 대한 액세스는 해당 테이블에 정의된 RLS 쿼리로 대체됩니다. RLS 쿼리의 성능 영향은 일반적으로 다음 두 부분으로 구성됩니다.
- Microsoft Entra ID의 멤버 자격 확인: 검사는 효율적입니다. 쿼리 성능에 큰 영향을 주지 않고 수십 또는 수백 개의 그룹에서 멤버 자격을 확인할 수 있습니다.
- 데이터에 적용되는 필터, 조인 및 기타 작업: 영향은 쿼리의 복잡성에 따라 달라집니다.
예시:
let IsRestrictedUser = current_principal_is_member_of('aadgroup=some_group@domain.com');
let AllData = MyTable | where not(IsRestrictedUser);
let PartialData = MyTable | where IsRestrictedUser and (...);
union AllData, PartialData
사용자가 속해 있지 some_group@domain.comIsRestrictedUser
않으면 .로 평가됩니다false
. 평가되는 쿼리는 다음과 유사합니다.
let AllData = MyTable; // the condition evaluates to `true`, so the filter is dropped
let PartialData = <empty table>; // the condition evaluates to `false`, so the whole expression is replaced with an empty table
union AllData, PartialData // this will just return AllData, as PartialData is empty
마찬가지로, 계산되는 true
경우 IsRestrictedUser
쿼리 PartialData
만 평가됩니다.
RLS를 사용할 때 쿼리 성능 향상
- 높은 카디널리티 열(예: DeviceID)에 필터를 적용하는 경우 분할 정책 또는 행 순서 정책을 사용하는 것이 좋습니다.
- 중간 카디널리티가 낮은 열에 필터를 적용하는 경우 행 순서 정책을 사용하는 것이 좋습니다.
수집에 대한 성능 영향
수집에는 성능에 영향을 주지 않습니다.