SQL Server 2016インスタンスがあり、一部のユーザーのログインが一部のユーザーに表示されないことに気づきました。たとえば、次のクエリを実行すると、
select count(*) FROM sys.database_principals a where type = 'U'
1348
。しかし、このクエリを実行すると:
execute as user = 'some_user';
select count(*) FROM sys.database_principals a where type = 'U';
revert;
92
、つまり1256
上記のユーザーに表示されないユーザー。ユーザーに付与する場合db_accessadmin
データベースロールメンバーシップを使用すると、すべてを表示できます1348
上記のクエリからユーザーが返されました。ただし、付与したくないdb_accessadmin
すべてのユーザーに付与します。これにより、許可したいアクセスよりもはるかに多くのアクセスが可能になります。
表示される92人のユーザーの1つのプロパティを、表示されないユーザーのプロパティと比較しましたが、ユーザーを一覧表示できるように見えるプロパティはありませんでした。
すべてのユーザーをdatabase_principalsへのクエリにリストできるようにするにはどうすればよいですか?
ユーザーを表示するには、ユーザープリンシパルのVIEW DEFINITION権限が必要です。これは、ALTER USER権限によって暗示されます。
ALTER USERを使用すると、db_accessadminが取得する適切なALTER ANY USERを実行できます。しかし、VIEW DEFINITIONだけにそのようなことはありません。
GRANT ALTER ANY USER TO Foo --Works
GRANT VIEW DEFINITION ANY USER TO Foo --Syntax Error
したがって、目的を達成するための最も簡単な方法は、新しいデータベースロールを作成し、データベースのすべてのユーザーにスクリプトのVIEW DEFINITION権限を付与することです。次に、これらの権限を付与するユーザーをこの新しい役割に割り当てます。
IF DATABASE_PRINCIPAL_ID('OnlySeeAllUsers') IS NULL
BEGIN
RAISERROR('OnlySeeAllUsers role is not defined yet, creating it', 1, 1) WITH NOWAIT
CREATE ROLE OnlySeeAllUsers
END
DECLARE @QUERY NVARCHAR(MAX);
DECLARE @UserName NVARCHAR(256);
DECLARE @ErrorMessage NVARCHAR(4000), @ErrorSeverity INT, @ErrorState INT;
DECLARE userIterator CURSOR LOCAL FAST_FORWARD
FOR
SELECT [DAT].[name] FROM sys.database_principals AS DAT
WHERE ([DAT].[TYPE] = 'U' --Windows logins
OR [DAT].[TYPE] = 'S') --SQL Logins
AND [DAT].[SID] IS NOT NULL --Filters out sys/information schema,
--which will cause errors otherwise
OPEN userIterator;
FETCH NEXT FROM userIterator INTO @UserName;
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
SET @QUERY = N'GRANT VIEW DEFINITION ON USER::' + @UserName + ' TO OnlySeeAllUsers';
EXEC (@QUERY);
FETCH NEXT FROM userIterator INTO @UserName;
END TRY
BEGIN CATCH
SELECT @ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(); --Get ErrorInfo
RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState) WITH NOWAIT;
BREAK; --Abort while
END CATCH
END
CLOSE userIterator;
DEALLOCATE userIterator;
上記のスクリプトは、プロシージャに保存/作成して必要に応じて再実行できます。または、新しいユーザーの作成時にトリガーを作成して、ビューの定義をデータベースロールに付与することもできます。
次に、このデータベースロールにユーザーを追加するには(SQL Server 2012以降)
ALTER ROLE OnlySeeAllUsers
ADD MEMBER Foo
EXEC sp_addrolemember 'OnlySeeAllUsers', 'Foo' --Method before SQL Server 2012
ユーザーにすべてのユーザーを「表示」させるためのデータベース内の最小の権限はVIEW DEFINITION
です。
この権限は、ユーザーにalter
を許可しませんが、データベースオブジェクトのすべての定義をユーザーに公開します:tables
、procedures
など。
sys.database_principals
の- documentation によると:
どのユーザーも、自分のユーザー名、システムユーザー、および固定データベースロールを表示できます。他のユーザーを表示するには、
ALTER ANY USER
、またはユーザーの権限が必要です。ユーザー定義の役割を表示するには、ALTER ANY ROLE
、または役割のメンバーシップが必要です。
このような強力な権限を直接付与したくない場合があるので、 モジュール署名 のような他のオプションを調べてください。