web-dev-qa-db-ja.com

SQL Serverユーザーがすべてのログインを表示できない

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へのクエリにリストできるようにするにはどうすればよいですか?

4
Alex

ユーザーを表示するには、ユーザープリンシパルの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
2
D Kramer

ユーザーにすべてのユーザーを「表示」させるためのデータベース内の最小の権限はVIEW DEFINITIONです。

この権限は、ユーザーにalterを許可しませんが、データベースオブジェクトのすべての定義をユーザーに公開します:tablesproceduresなど。

4
sepupic

sys.database_principalsの-​​ documentation によると:

どのユーザーも、自分のユーザー名、システムユーザー、および固定データベースロールを表示できます。他のユーザーを表示するには、ALTER ANY USER、またはユーザーの権限が必要です。ユーザー定義の役割を表示するには、ALTER ANY ROLE、または役割のメンバーシップが必要です。

このような強力な権限を直接付与したくない場合があるので、 モジュール署名 のような他のオプションを調べてください。

1
user195591