Share via


리소스 관리자 보안

리소스 관리자는 인증, 사용 권한 수준 및 소유권 체인과 같은 기존 SQL Server 보안 메커니즘을 사용합니다. 이 항목에서는 잠재적인 보안 문제를 처리하기 위해 고려해야 하는 리소스 관리자 구성 및 사용의 여러 측면에 대해 살펴봅니다.

고려 사항

리소스 관리자 기능을 사용할 때 최대한 보안을 확보하려면 다음과 같은 리소스 관리자 디자인 및 구현 요소를 고려해야 합니다.

  • 사용 권한

  • 리소스 풀 및 작업 그룹 이름

  • 분류자 사용자 정의 함수

사용 권한

리소스 관리자 설정을 변경하거나 보려면 다음 사용 권한이 필요합니다.

  • 리소스 관리자 구성을 변경하려면 사용자에게 CONTROL SERVER 권한이 필요합니다. 사용 권한은 리소스 관리자 DDL 문이 실행될 때 확인됩니다.

  • 동적 관리 뷰에서 제공하는 활성 구성을 보려면 사용자에게 VIEW SERVER STATE 권한이 필요합니다.

리소스 관리자 구성을 작성 또는 변경할 수 있는 사용 권한은 숙련된 데이터베이스 관리자에게 부여하는 것이 좋습니다.

리소스 풀 및 작업 그룹 이름

모든 리소스 풀 및 작업 그룹 이름은 공개됩니다. 풀 및 그룹을 만들 때는 서버에서 실행 중인 응용 프로그램의 특성에 대한 정보를 노출시키지 않는 이름을 선택해야 합니다. 예를 들어 이름이 CompanyPayroll인 작업 그룹은 이 작업 그룹을 사용하는 응용 프로그램의 특성과 중요도를 뚜렷이 드러냅니다.

분류자 사용자 정의 함수

UDF(분류자 사용자 정의 함수)는 master 데이터베이스에 저장됩니다.

이 함수는 디자인 및 구현 측면에서 LOGON 트리거와 유사하며, 로그인 프로세스의 일부로 LOGON 트리거 이후에 실행됩니다. 요청 및 분류를 수행하는 세션의 로그인 컨텍스트에서 실행되는 함수는 세션이 실제로 설정되기 전에 마쳐야 합니다. 따라서 오류 메시지 및 PRINT 문의 메시지와 같이 일반적으로 사용자에게 전달되는 모든 분류자 함수 내 발생 메시지는 SQL Server 오류 로그로 전달됩니다.

주의 사항주의

이번 리소스 관리자 릴리스에서는 스키마 바인딩을 구현하여 분류자 UDF 내에서 만들어질 수 있는 호출을 제한하지만 이 함수에서 반환하는 데이터는 안전하지 않을 수도 있습니다. 자세한 내용은 분류자 함수 작성 시 고려 사항을 참조하십시오.

분류자 사용자 정의 함수 동작의 다음과 같은 측면을 유의하십시오.

  • 리소스 관리자는 기본적으로 로그인 사용자의 컨텍스트에서 분류의 일부로, 또는 함수에 EXECUTE AS가 지정된 경우 지정된 사용자로 이 함수를 실행합니다.

  • 이 함수를 분류의 일부로 실행하는 경우 리소스 관리자는 분류자 UDF에 대한 EXECUTE 권한을 확인하지 않습니다. 그러나 함수가 참조하는 모든 개체는 표준 권한 확인의 대상이 되며, 소유권 체인을 기반으로 액세스가 허용될 수 있습니다.

  • 함수를 리소스 관리자 분류자로 등록해도 이 함수가 리소스 관리자 분류의 범위를 벗어나 사용되는 경우 함수의 사용 권한 수준은 영향을 받지 않습니다.

리소스 관리자의 소유권 체인

기본 스키마 기반 소유권 체인을 사용하거나 EXECUTE AS를 사용하여 리소스 관리자 분류가 실행 중일 때 단일 사용자에게 스키마에 대한 액세스 권한을 부여할 수 있습니다. 다음 코드 예 및 주석은 리소스 관리자에서 소유권 체인의 동작 방식을 설명합니다.

[!참고]

다음 예에서는 SQL 로그인이 사용된다고 가정합니다.

다음 코드에서는 master에 대한 액세스 권한을 가진 스키마 사용자(SchemaUser1, SchemaUser2)를 만듭니다.

use master
go

CREATE LOGIN SchemaUser1 WITH PASSWORD='your password here';
CREATE USER SchemaUser1 FOR LOGIN [SchemaUser1];
CREATE LOGIN SchemaUser2 WITH PASSWORD='your password here';
CREATE USER SchemaUser2 FOR LOGIN [SchemaUser2];
go

다음 코드에서는 기본 로그인 권한으로 사용자(NormalUser1)를 만듭니다.

CREATE LOGIN NormalUser1 WITH PASSWORD='your password here';
CREATE USER NormalUser1 FOR LOGIN [NormalUser1];
go

다음 코드에서는 스키마(Schema1, Schema2)를 만들고 기존 스키마 사용자에 이를 매핑합니다. 또한 스키마에 대한 테이블(groupTable)도 만듭니다.

CREATE SCHEMA Schema1 AUTHORIZATION SchemaUser1
CREATE TABLE groupTable (uname sysname, gname sysname);
CREATE SCHEMA Schema2 AUTHORIZATION SchemaUser2
CREATE TABLE groupTable (uname sysname, gname sysname);
go

다음 코드에서는 groupTable에 값을 추가합니다.

INSERT Schema1.groupTable VALUES(N'NormalUser1',N'Group1');
INSERT Schema2.groupTable VALUES(N'NormalUser1',N'Group2');
go

이 시점에서 Schema1 및 Schema2는 각각 SchemaUser1과 SchemaUser2가 소유합니다. 다음 코드 예에서는 Schema1 및 Schema2에 액세스하는 데 사용되는 함수를 만듭니다.

CREATE FUNCTION Schema1.classifier() RETURNS sysname WITH SCHEMABINDING AS
BEGIN
      DECLARE @n sysname
      SELECT @n = gname FROM Schema1.groupTable WHERE uname = SUSER_NAME()
      SELECT @n = gname FROM Schema2.groupTable WHERE uname = SUSER_NAME()
      RETURN @n
END
go

다음 코드에서는 앞의 함수를 분류자 UDF로 등록합니다. SchemaUser1에는 Schema2에 대한 액세스 권한이 없습니다.

ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION=Schema1.classifier);
ALTER RESOURCE GOVERNOR RECONFIGURE
go

테스트를 위해 다른 클라이언트 연결에서 NormalUser1로 로그인을 시도합니다. Windows 이벤트 뷰어를 엽니다. 응용 프로그램 로그에서 분류자 실패 항목을 볼 수 있습니다. NormalUser1은 소유권 체인에 의해 Schema1.classifier로부터 Schema1.groupTable에 대한 액세스 권한을 상속합니다. 그러나 Schema1에는 Schema2.groupTable에 대한 액세스 권한은 없습니다.

다른 테스트로 SchemaUser1에 Schema2.groupTable에 대한 SELECT 권한을 부여합니다. 

GRANT SELECT ON Schema2.groupTable TO SchemaUser1
go

NormalUser1로 로그인합니다. 이번에도 이벤트 로그에서 분류자 실패 항목을 볼 수 있습니다. 이 실패는 SchemaUser1로부터 상속되지 않는 SELECT 권한이 NormalUser1에 있는지 여부를 서버에서 확인하기 때문에 발생합니다.

다음 코드 예에서는 또 다른 분류자 함수를 만듭니다. 이번에는 EXECUTE AS SchemaUser1에 대한 사용 권한이 로그인에 부여됩니다.

CREATE FUNCTION Schema1.classifier2() RETURNS sysname WITH SCHEMABINDING, EXECUTE AS 'SchemaUser1' AS
BEGIN
      DECLARE @n sysname
      SELECT @n = gname FROM Schema1.groupTable WHERE uname = SUSER_NAME()
      SELECT @n = gname FROM Schema2.groupTable WHERE uname = SUSER_NAME()
      RETURN @n
END
go

ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION=Schema1.classifier2);
ALTER RESOURCE GOVERNOR RECONFIGURE;
go

새 함수는 SchemaUser1의 컨텍스트에서 실행되고 SchemaUser1에는 Schema2.groupTable에 대한 SELECT 권한이 있으므로 Schema1.classifier2() 함수는 NormalUser1 로그인에 대해 성공적으로 실행됩니다.

NormalUser1로 다시 로그인하여 이벤트 로그에 분류자 실패가 있는지 확인합니다.

[!참고]

NormalUser1에는 Schema1.classifier2 함수에 대한 EXECUTE 권한이 부여되지 않으므로 NormalUser1은 함수를 임시 쿼리로 실행할 수 없습니다.

자세한 내용은 소유권 체인을 참조하십시오.

분류자 함수 테스트

분류자 함수는 먼저 테스트하고 최적화한 다음 들어오는 요청을 분류하는 데 사용해야 합니다. 함수를 잘못 작성할 경우 제한 시간이 초과되고 구성 정보가 노출되어 시스템을 사용할 수 없게 됩니다. DAC(관리자 전용 연결)는 분류의 영향을 받지 않으므로 리소스 관리자가 사용될 때 DAC를 사용하여 분류자 함수의 문제를 해결할 수 있습니다. 서버에서 DAC를 사용하도록 설정하는 것이 좋습니다. 자세한 내용은 전용 관리자 연결 사용을 참조하십시오.

[!참고]

DAC를 사용하여 문제를 해결할 수 없는 경우 단일 사용자 모드로 시스템을 다시 시작하는 방법을 사용할 수 있습니다. 단일 사용자 모드에서는 분류의 영향을 받지 않지만 리소스 관리자 분류자가 실행 중일 때 이를 진단할 수 있는 기능이 제공되지 않습니다.