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 を使用して、リソース ガバナによる分類実行時にスキーマに対するアクセスを 1 人のユーザーに許可することもできます。次のコード例とコメントは、リソース ガバナにおける所有権継承の動作を示しています。

注意

次の例は、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

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

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

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

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

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

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

テストのため、別のクライアント接続から NormalUser1 としてログインしてみます。Windows イベント ビューアを開きます。アプリケーション ログに分類子エラーのエントリが表示されます。NormalUser1 は、Schema1.groupTable に対するアクセス権を、Schema1.classifier からの所有権継承によって継承します。しかし Schema1 には、Schema2.groupTable にアクセスする権限がありません。

次のテストでは、Schema2.groupTable に対する SELECT 権限を、SchemaUser1 に与えます。

GRANT SELECT ON Schema2.groupTable TO SchemaUser1
go

GRANT SELECT ON Schema2.groupTable TO SchemaUser1
go

NormalUser1 としてログインします。今回も、イベント ログに分類子エラーのエントリが表示されます。このエラーが発生するのは、NormalUser1 に SELECT 権限があるかどうかをサーバーがチェックするためです。この権限は SchemaUser1 から継承されません。

次のコード例では、別の分類関数を作成します。今回は、ログインに 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

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 権限があるため、NormalUser1 でのログインで Schema1.classifier2() 関数を問題なく実行できます。

NormalUser1 として再度ログインし、イベント ログに分類子エラーがないかどうかを確認します。

注意

NormalUser1 には Schema1.classifier2 関数に対する EXECUTE 権限がないため、NormalUser1 はこの関数をアドホック クエリとして実行できません。

詳細については、「所有権の継承」を参照してください。

分類関数のテスト

作成した分類関数は、受信要求の分類に使用する前に、テストと最適化を行う必要があります。関数の記述に問題があると、タイムアウトによってシステムが使用不可能になり、構成情報が公開される場合があります。リソース ガバナが有効になっている際に分類関数のトラブルシューティングを行うには、専用管理者接続 (DAC) を使用できます。この接続は分類の対象とならないためです。サーバーで DAC を有効にすることをお勧めします。詳細については、「専用管理者接続の使用」を参照してください。

注意

トラブルシューティングに DAC を使用できない場合は、システムをシングル ユーザー モードで再起動します。シングル ユーザー モードは分類の対象となりませんが、実行中のリソース ガバナ分類子をこのモードで診断することはできません。