web-dev-qa-db-fra.com

Sélectionnez les données d'une autre instance de base de données sur le même serveur dans le serveur SQL

J'ai une requête ci-dessous:

select count(*) as Count, datepart(yyyy, [LogDate]) as [Year]
from ViewAssociate..Auth_Log 
where ActionCode = 12
group by datepart(yyyy, [LogDate])
order by [Year]

Cette requête fait partie d'une procédure stockée basée sur la base de données ReadAssociate. Il essaie d'obtenir des données de ViewAssociate db. L'utilisateur essayant d'exécuter le proc stocké n'a pas accès à la base de données ViewAssociate, la requête génère donc une erreur.

Ma question est de savoir si je peux modifier la requête d'une manière ou d'une autre et lui fournir un mot de passe de nom d'utilisateur à exécuter afin que je puisse obtenir des données à partir du ViewAssociate Db. Quelqu'un a suggéré Execute As mais cela ne semble pas fonctionner.

execute as login = 'viewassociate' J'obtiens cette erreur:

Impossible d'exécuter en tant que principal du serveur car le principal "viewassociate" n'existe pas, ce type de principal ne peut pas être emprunté ou vous n'avez pas l'autorisation.

Cette vue associée est une connexion SQL qui est db_owner de la base de données ViewAssociate.

3
SP1

Si la base de données à laquelle vous essayez de vous connecter se trouve sur une autre instance, je vous recommande de configurer un serveur lié que vous pouvez ensuite utiliser pour obtenir les données. Cela vous permettra d'utiliser explicitement les informations d'identification qui existent sur l'instance à laquelle vous souhaitez vous connecter - cela vous permet également de poser des questions relativement simples en n'ayant besoin de s'adapter qu'à l'utilisation d'un nom en quatre parties pour référencer la table.

-- create a linked server
USE [master]  
GO  
EXEC master.dbo.sp_addlinkedserver   
     @server = '.\INSTANCE_NAME',   
     @srvproduct=N'SQL Server' ;  
GO  
-- add a login to the linked server
EXEC master.dbo.sp_addlinkedsrvlogin   
     @rmtsrvname = '.\INSTANCE_NAME',   
     @locallogin = NULL,   
     @useself = N'False',
     @rmtuser = 'user_name_from_other_instance',
     @rmtpassword = 'password_for_remote_user';  
GO 
-- now you can query the server
SELECT *
  FROM [.\INSTANCE_NAME].master.sys.databases;
GO

D'autres options sont disponibles pour ces procédures stockées et vous pouvez également effectuer la même action à l'aide de SQL Server Management Studio. J'ai inclus quelques liens vers la documentation ci-dessous pour vous:

serveurs liés

Créer des serveurs liés

sp_addlinkedserver

sp_addlinkedserverlogin

2
Mr.Brownstone

Il s'agit simplement d'une base de données, par défaut, isolée des autres bases de données à des fins de sécurité. Avant SQL Server 2005, ce problème pouvait être résolu en activant la fonctionnalité de chaînage de propriété entre bases de données. Cependant, cette option est plutôt ouverte car elle ne permet pas de personnaliser qui peut l'utiliser. À partir de SQL Server 2005, Signature du module a été introduit et fournit un mécanisme de sécurité à granularité fine pour résoudre ce problème et bien d'autres.

J'ai quelques exemples ici (DBA.SE) montrant déjà comment faire cela, tels que:

Autorisations dans les déclencheurs lors de l'utilisation de certificats croisés

Celui-ci implique des déclencheurs, donc je l'ai simplifié pour cette question, comme indiqué ci-dessous:

[~ # ~] nettoyage [~ # ~]

USE [master];
GO
IF EXISTS (SELECT 1 FROM [sys].[databases] WHERE [name] = N'DatabaseA')
BEGIN
    PRINT 'Dropping [DatabaseA] DB...';
    ALTER DATABASE [DatabaseA] SET OFFLINE WITH ROLLBACK IMMEDIATE;
    ALTER DATABASE [DatabaseA] SET ONLINE;
    DROP DATABASE [DatabaseA];
END;

IF EXISTS (SELECT 1 FROM [sys].[databases] WHERE [name] = N'DatabaseB')
BEGIN
    PRINT 'Dropping [DatabaseB] DB...';
    ALTER DATABASE [DatabaseB] SET OFFLINE WITH ROLLBACK IMMEDIATE;
    ALTER DATABASE [DatabaseB] SET ONLINE;
    DROP DATABASE [DatabaseB];
END;

IF (SUSER_ID(N'JohnnyLunchbucket') IS NOT NULL)
BEGIN
  PRINT 'Dropping [JohnnyLunchbucket] Login...';
  DROP LOGIN [JohnnyLunchbucket];
END;

[~ # ~] configuration [~ # ~]

USE [master];

EXECUTE AS LOGIN = N'sa';
PRINT 'Creating databases...';
CREATE DATABASE [DatabaseA] COLLATE Latin1_General_100_CI_AS_SC;
CREATE DATABASE [DatabaseB] COLLATE Latin1_General_100_CI_AS_SC;
REVERT;
GO

-- Default for both options should be OFF, but just to be sure:
ALTER DATABASE [DatabaseA] SET DB_CHAINING OFF, TRUSTWORTHY OFF, RECOVERY SIMPLE;

ALTER DATABASE [DatabaseB] SET DB_CHAINING OFF, TRUSTWORTHY OFF, RECOVERY SIMPLE;
GO

CREATE LOGIN [JohnnyLunchbucket] WITH PASSWORD = 'OhSoSecure;)';


USE [DatabaseA];

CREATE USER [JohnnyLunchbucket] FOR LOGIN [JohnnyLunchbucket];
GO

CREATE PROCEDURE dbo.SelectFromDatabaseB
AS
SET NOCOUNT ON;

SELECT *
FROM   [DatabaseB].dbo.SomeTable;
GO

GRANT EXECUTE ON dbo.SelectFromDatabaseB TO [JohnnyLunchbucket];
GO

USE [DatabaseB];

CREATE TABLE dbo.SomeTable (Col1 INT);
INSERT INTO dbo.SomeTable ([Col1]) VALUES (111);
GO

TEST 1 (pas d'accès)

USE [DatabaseA];

EXECUTE AS LOGIN = N'JohnnyLunchbucket';

SELECT * FROM [DatabaseB].dbo.SomeTable;
/*
Msg 916, Level 14, State 1, Line XXXXX
The server principal "JohnnyLunchbucket" is not able to access the database "DatabaseB" under the current security context.
*/

EXECUTE dbo.[SelectFromDatabaseB];
/*
Msg 916, Level 14, State 1, Procedure dbo.SelectFromDatabaseB, Line XXXXX [Batch Start Line YYYYY]
The server principal "JohnnyLunchbucket" is not able to access the database "DatabaseB" under the current security context.
*/

REVERT;

AJOUTER LA SIGNATURE DU MODULE

CREATE CERTIFICATE [PermissionsCert]
  AUTHORIZATION [dbo]
  ENCRYPTION BY PASSWORD = 'WeakPassword'
  WITH SUBJECT = 'Used to test granting permissions to code',
  EXPIRY_DATE = '2099-12-31';

ADD SIGNATURE TO [dbo].[SelectFromDatabaseB]
    BY CERTIFICATE [PermissionsCert]
    WITH PASSWORD = 'WeakPassword';

-- Copy Certificate (public key only) to DatabaseB
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = N'USE  [DatabaseB];
CREATE CERTIFICATE [PermissionsCert] AUTHORIZATION [dbo] FROM BINARY = '
  + CONVERT(NVARCHAR(MAX), CERTENCODED(CERT_ID(N'PermissionsCert')), 1)
  + N';'

EXEC (@SQL);

USE [DatabaseB];

CREATE USER [PermissionsUser] FROM CERTIFICATE [PermissionsCert];

GRANT SELECT ON [dbo].[SomeTable] TO [PermissionsUser];
GO

TEST 2 (accès accordé, mais uniquement via un module signé)

USE [DatabaseA];

EXECUTE AS LOGIN = N'JohnnyLunchbucket';

SELECT * FROM [DatabaseB].dbo.SomeTable;
/*
Msg 916, Level 14, State 1, Line XXXXX
The server principal "JohnnyLunchbucket" is not able to access the database "DatabaseB" under the current security context.
*/

EXECUTE dbo.[SelectFromDatabaseB];
-- 111

REVERT;

Seuls les modules signés ont l'accès accordé aux connexions et/ou aux utilisateurs créés à partir du certificat. Et les utilisateurs n'ont accès qu'aux modules auxquels vous leur accordez l'accès.

2
Solomon Rutzky