AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 318375
Accepted
Muflix
Muflix
Asked: 2022-10-19 13:33:41 +0800 CST2022-10-19 13:33:41 +0800 CST 2022-10-19 13:33:41 +0800 CST

O acesso cruzado ao banco de dados com confiável não funciona para conta de serviço nem com certificado

  • 772

eu tenho essa configuração

insira a descrição da imagem aqui

  • Criei dois bancos de dados (origem e destino).
  • O banco de dados de origem possui um procedimento armazenado que está acessando a tabela no banco de dados de destino.
  • O procedimento armazenado é executado como conta de serviço
  • O login da conta de serviço tem conta de usuário em ambos os bancos de dados
  • A conta de serviço tem permissão de conexão e autenticação ao banco de dados de destino
  • A conta de serviço tem permissão de leitura no esquema de banco de dados de destino
  • Ambos os bancos de dados têm confiança em

mesmo assim deu erro

O principal do servidor "ServiceAccount" não pode acessar o banco de dados "TargetDatabase" no contexto de segurança atual.

script SQL

-- Create logins
CREATE LOGIN SourceDatabaseOwner    WITH PASSWORD = 'Pa$$w0rd'  
CREATE LOGIN TargetDatabaseOwner    WITH PASSWORD = 'Pa$$w0rd'  
CREATE LOGIN ServiceAccount         WITH PASSWORD = 'Pa$$w0rd'  

-- Create databases
CREATE DATABASE SourceDatabase
CREATE DATABASE TargetDatabase

-- Setup trustworthy
ALTER DATABASE SourceDatabase SET TRUSTWORTHY ON;
ALTER DATABASE TargetDatabase SET TRUSTWORTHY ON;

-- Setup database owners
USE SourceDatabase
GO
EXEC dbo.sp_changedbowner @loginame = N'SourceDatabaseOwner'

USE TargetDatabase
GO
EXEC dbo.sp_changedbowner @loginame = N'TargetDatabaseOwner'

-- Add ServiceAccount to source database
USE SourceDatabase
GO
CREATE USER ServiceAccount FOR LOGIN ServiceAccount;  

-- Add ServiceAccount to target database
USE TargetDatabase
GO
CREATE USER ServiceAccount FOR LOGIN ServiceAccount;  

-- Enable ServiceAccount to authenticate to target database
USE TargetDatabase
GO
GRANT AUTHENTICATE TO ServiceAccount;

-- Grant permissions
USE TargetDatabase
GO
GRANT SELECT ON SCHEMA::dbo TO ServiceAccount

-- Create table with data
USE TargetDatabase
GO
create table dbo.InterestingData (Id int identity primary key, Content nvarchar(255))
insert into dbo.InterestingData (Content) values ('Foo'), ('Bar')

-- Create stored procedure executing under service account and accessing target database
USE SourceDatabase
GO
create or alter procedure dbo.GetData
with execute as 'ServiceAccount' as
begin
    select id, content from TargetDatabase.dbo.InterestingData
end

-- Execution does not work under service account
-- The server principal "ServiceAccount" is not able to access the database "TargetDatabase" under the current security context.
exec dbo.GetData

Então continuei e tentei assinar o procedimento com o certificado e configurar permissões na tabela de destino para o login desse certificado

-- create certificate in master
use master 
go

CREATE CERTIFICATE SignProcedureCert
ENCRYPTION BY PASSWORD = 'Pa$$w0rd'
WITH SUBJECT = 'Certificate for signing stored procedures'
GO

-- backup certificate
BACKUP CERTIFICATE SignProcedureCert TO FILE ='C:\Certs\SignProcedureCert.cer'
WITH PRIVATE KEY
(       
    FILE = 'C:\Certs\SignProcedureCert.pvk',
    DECRYPTION BY PASSWORD = 'Pa$$w0rd',
    ENCRYPTION BY PASSWORD = 'Pa$$w0rd'
)
GO

-- create login from the certificate
create login SignProcedureLogin from certificate SignProcedureCert

-- Import certificate to the source database
CREATE CERTIFICATE SignProcedureCert
FROM FILE = 'C:\Certs\SignProcedureCert.cer'
WITH PRIVATE KEY (FILE = 'C:\Certs\SignProcedureCert.pvk', 
ENCRYPTION BY PASSWORD = 'Pa$$w0rd', 
DECRYPTION BY PASSWORD = 'Pa$$w0rd')

-- Sign the procedure
ADD SIGNATURE TO dbo.GetData   
   BY CERTIFICATE SignProcedureCert  
    WITH PASSWORD = 'Pa$$w0rd';  
GO  

-- Setup permission for SignProcedureLogin to target database
USE TargetDatabase
GO
CREATE USER SignProcedureLogin FOR LOGIN SignProcedureLogin;  
GRANT SELECT ON SCHEMA::dbo TO SignProcedureLogin

então agora eu deveria ter essa configuração

insira a descrição da imagem aqui

mas quando eu executo

USE SourceDatabase
GO
exec dbo.GetData

eu tenho o mesmo erro

O principal do servidor "ServiceAccount" não pode acessar o banco de dados "TargetDatabase" no contexto de segurança atual.

o que estou perdendo?

Atualizar

Quando eu removo a with execute ascláusula, ela funciona

-- Setup trustworthy
ALTER DATABASE SourceDatabase SET TRUSTWORTHY OFF;
ALTER DATABASE TargetDatabase SET TRUSTWORTHY OFF;

USE SourceDatabase
GO

create or alter procedure dbo.GetData
--with execute as 'ServiceAccount' 
as
begin
    select id, content from TargetDatabase.dbo.InterestingData
end

GRANT EXECUTE ON SCHEMA::dbo TO ServiceAccount

execute as login = 'ServiceAccount'
exec dbo.GetData
revert

mas ainda é possível executar de alguma forma o procedimento com a with execute ascláusula?

sql-server
  • 1 1 respostas
  • 73 Views

1 respostas

  • Voted
  1. Best Answer
    Solomon Rutzky
    2022-11-05T08:21:00+08:002022-11-05T08:21:00+08:00

    Você estava realmente muito perto de sua configuração inicial. Você estava apenas faltando 1 passo (e tem 2 passos estranhos). Porém, antes de explicar como fazer o cenário original funcionar, preciso mencionar/avisar que o cenário original não é o ideal e não deve ser utilizado, mesmo que corrigido, pois existe um método melhor e mais seguro: Module Signing. Expliquei a solução preferida para o problema geral abordado pela configuração original na minha resposta à sua pergunta relacionada: A opção Confiável deve ser desativada, mas qual é uma alternativa? .

    Como você descobriu (com base em sua atualização na pergunta), o problema é devido ao uso da WITH EXECUTE AS ...cláusula (ou seja, representação) na definição do proc. Isso coloca o processo em quarentena no banco de dados atual. Sim, habilitar TRUSTWORTHY(como você tentou inicialmente) pode ajudar a superar isso, mas as regras nem sempre são diretas. Primeiro, TRUSTWORTHYafeta apenas onde um processo está sendo iniciado, portanto, não há motivo para habilitar TRUSTWORTHYno banco de dados de destino (que é uma das duas etapas estranhas). Segundo, ao habilitar TRUSTWORTHY, o foco da segurança passa a ser o proprietário do banco de dados atual (ou seja, onde o processo está sendo iniciado). Portanto, a questão é se SourceDatabaseOwnertem ou não permissão para atuar como autenticador em [TargetDatabase], nãoServiceAccount(ou seja, a etapa ausente é conceder AUTHENTICATEa SourceDatabaseOwner- o que exigirá a adição SourceDatabaseOwnercomo usuário [TargetDatabase]- e a segunda etapa estranha é conceder AUTHENTICATEa ServiceAccount).

    Aqui está uma demonstração de trabalho, com base no seu código de exemplo da pergunta:

    Configuração inicial

    /* -- Clean Up
    USE [master];
    DROP DATABASE SourceDatabase;
    DROP DATABASE TargetDatabase;
    
    DROP LOGIN SourceDatabaseOwner;
    DROP LOGIN TargetDatabaseOwner;
    DROP LOGIN ServiceAccount;
    */
    
    -- Create logins
    CREATE LOGIN SourceDatabaseOwner WITH PASSWORD = 'Pa$$w0rd';
    CREATE LOGIN TargetDatabaseOwner WITH PASSWORD = 'Pa$$w0rd';
    CREATE LOGIN ServiceAccount WITH PASSWORD = 'Pa$$w0rd';
    
    -- Create databases
    CREATE DATABASE SourceDatabase;
    CREATE DATABASE TargetDatabase;
    
    -- Setup trustworthy
    ALTER DATABASE SourceDatabase SET TRUSTWORTHY ON;
    --------ALTER DATABASE TargetDatabase SET TRUSTWORTHY ON; -- ???????????!!
    
    -- Setup database owners
    -- ( sp_changedbowner is deprecated )
    ALTER AUTHORIZATION ON DATABASE::[SourceDatabase] TO [SourceDatabaseOwner];
    ALTER AUTHORIZATION ON DATABASE::[TargetDatabase] TO [TargetDatabaseOwner];
    
    -- Add ServiceAccount to source database
    USE SourceDatabase
    CREATE USER ServiceAccount FOR LOGIN ServiceAccount;  
    GO
    
    -- Add ServiceAccount to target database
    USE TargetDatabase
    CREATE USER ServiceAccount FOR LOGIN ServiceAccount;  
    GO
    
    ---------- Enable ServiceAccount to authenticate to target database
    --------USE TargetDatabase
    --------GO
    --------GRANT AUTHENTICATE TO ServiceAccount; -- ???????????!!
    
    -- Grant permissions
    USE TargetDatabase
    GRANT SELECT ON SCHEMA::dbo TO ServiceAccount;
    GO
    
    -- Create table with data
    USE TargetDatabase;
    GO
    CREATE TABLE dbo.InterestingData (
        Id INT IDENTITY PRIMARY KEY,
        Content NVARCHAR(255)
    );
    INSERT INTO dbo.InterestingData (Content) VALUES ('Foo'), ('Bar');
    GO
    
    -- Create stored procedure executing under service account and
    -- accessing target database
    USE SourceDatabase;
    GO
    CREATE OR ALTER PROCEDURE dbo.GetData
    WITH EXECUTE AS 'ServiceAccount'
    AS
    BEGIN
        SELECT SESSION_USER AS [CurrentUser];
        SELECT Id, Content FROM TargetDatabase.dbo.InterestingData;
    END;
    GO
    

    Teste

    -- Execution does not work under service account
    -- The server principal "ServiceAccount" is not able to access the database
    --     "TargetDatabase" under the current security context.
    USE [SourceDatabase];
    EXEC dbo.GetData;
    GO
    

    FIXAR ...

    • para permitir o acesso a bancos de dados individuais

      USE [TargetDatabase];
      CREATE USER [SourceDatabaseOwner];
      GRANT AUTHENTICATE TO [SourceDatabaseOwner];
      

      — ??? —

    • para permitir o acesso a todos os bancos de dados

      USE [master];
      GRANT AUTHENTICATE SERVER TO [SourceDatabaseOwner];
      

    Teste novamente

    USE [SourceDatabase];
    EXEC dbo.GetData;
    -- Success!!
    GO
    

    Se, por algum motivo, você realmente precisava/querer usar WITH EXECUTE AS(embora normalmente não haja motivo para isso, já que a assinatura de módulo permite que o proc/função/gatilho funcione de forma consistente, independentemente de quem o executa), você ainda pode fazer isso sem habilitar TRUSTWORTHYvia assinatura de módulo. Assim como na configuração original, você estava novamente perto das etapas adicionais de assinatura de módulo, mas havia novamente uma etapa ausente e uma etapa irrelevante. A assinatura de módulo muda o foco da segurança para o certificado (e, portanto, para o logon e/ou usuário baseado em certificado). Portanto, a etapa que faltava não era conceder AUTHENTICATEao usuário baseado em certificado em[TargetDatabase]. E a etapa estranha foi criar um Login para o Certificado, pois não há permissões de nível de servidor concedidas neste cenário.

    Aqui está uma demonstração de trabalho, continuando a demonstração de cima (ou seja, não independente):

    Desfaça a etapa extra da demonstração acima que fez as coisas funcionarem (para mostrar que a assinatura de módulo também corrige esse cenário)

    USE [TargetDatabase];
    DROP USER [SourceDatabaseOwner];
    
    USE [master];
    REVOKE AUTHENTICATE SERVER TO [SourceDatabaseOwner];
    

    Teste novamente (verifique se o proc não funciona mais)

    USE [SourceDatabase];
    EXEC dbo.GetData;
    -- error
    GO
    

    Configurar a assinatura do módulo

    USE [SourceDatabase];
    
    -- Create certificate
    CREATE CERTIFICATE [SignProcedureCert]
        ENCRYPTION BY PASSWORD = 'Pa$$w0rd'
        WITH SUBJECT = 'Certificate for signing stored procedures';
    
    -- Sign the procedure
    ADD SIGNATURE TO dbo.GetData   
        BY CERTIFICATE SignProcedureCert  
        WITH PASSWORD = 'Pa$$w0rd';  
    GO  
    -----------------
    
    -- Copy certificate to target DB ( CERTENCODED in SQL Server 2012+ )
    DECLARE @Cert NVARCHAR(4000);
    SET @Cert = CONVERT(NVARCHAR(4000),
                        CERTENCODED(CERT_ID(N'SignProcedureCert')), 1);
    SELECT CERT_ID(N'SignProcedureCert'), @Cert;
    
    EXEC (N'USE [TargetDatabase];
    CREATE CERTIFICATE [SignProcedureCert] FROM BINARY = ' + @Cert);
    
    -- Create certificate-based User to allow access to DB
    USE [TargetDatabase];
    CREATE USER [SignProcedureCert] FROM CERTIFICATE [SignProcedureCert];
    
    -- Allow access to target object in target DB
    USE [TargetDatabase];
    GRANT SELECT ON SCHEMA::dbo TO [SignProcedureCert];
    GO
    

    Teste novamente (verifique se o proc ainda não funciona)

    A configuração de assinatura de módulo que funcionou na pergunta relacionada (vinculada ao topo) não funciona aqui.

    USE [SourceDatabase];
    EXEC dbo.GetData;
    -- error
    GO
    

    O problema é a WITH EXECUTE AScláusula na definição do proc.

    FIXAR

    USE [TargetDatabase];
    GRANT AUTHENTICATE TO [SignProcedureCert];
    

    Teste novamente

    USE [SourceDatabase];
    SELECT SESSION_USER AS [CurrentUser];
    EXEC dbo.GetData;
    -- Success!!
    GO
    

    Para obter mais informações sobre a assinatura de módulo em geral, visite meu site:
    https://ModuleSigning.Info/

    • 1

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve