Estou usando o SSDT 14.0.50730.0 no Visual Studio Professional 2015. Estou comparando bancos de dados entre duas instâncias e descobri que existem procedimentos armazenados que não correspondem em relação às suas assinaturas.
Em ambas as instâncias, o Certificado foi criado em cada instância a partir do mesmo script e as assinaturas também foram adicionadas pelo CERTIFICADO com uma SENHA usando o mesmo script em cada instância.
No entanto, a Comparação de Esquema está mostrando o procedimento na origem e no destino como tendo um CERTIFICATE com uma ASSINATURA com valores de assinatura que não correspondem. COM ASSINATURA. O valor da assinatura corresponde ao que foi mostrado na instância de origem. No entanto, o script falha com a mensagem "A assinatura da chave pública é inválida".
O que devo fazer para sincronizar esses procedimentos?
Antes de entrar em detalhes sobre a criação do certificado e a assinatura do módulo, podemos pelo menos verificar se as duas instâncias têm ou não o mesmo certificado. Execute o seguinte em ambas as instâncias:
Se os certificados forem iguais, todos esses campos terão valores idênticos em ambas as instâncias (ou em ambos os bancos de dados na mesma instância). Mas você só precisa verificar o
thumbprint
campo, pois é um hash SHA-1 do certificado. Se esse valor for diferente entre os dois locais, você não está lidando com o mesmo certificado.Você diz que
mas não mencione exatamente como os Certificados estão sendo criados. Eles podem ser gerados no SQL Server (isso é conhecido como "autoassinado") usando a seguinte sintaxe:
Este método irá gerar uma nova chave privada (cada vez que for executado) e criptografá-la com a senha especificada na
ENCRYPTION BY PASSWORD
cláusula mais criptografada pela chave mestra do banco de dados (é por isso que é melhor especificar a senha).Ou você pode criá-los fornecendo um literal Assembly, File ou Binary existente:
Os métodos
FILE
eBINARY
permitem especificar opcionalmente um arquivo de chave privada ou literal binário. Portanto, se estiver usando um desses métodos juntamente com a especificação da chave privada, ou se estiver usando o assinadoASSEMBLY
, a criação de um certificado dessa maneira deve fornecer a você a mesma chave privada todas as vezes.Então, como você obtém os valores
FILE
ouBINARY
?ARQUIVO:
Depois de criar o Certificado inicial, exporte-o (incluindo a chave privada!) usando o seguinte:
E no novo local:
BINARY: (disponível apenas no SQL Server 2012 e mais recente)
Depois de criar o certificado inicial, obtenha os valores do certificado e da chave privada usando o seguinte:
E no novo local:
Se você estiver usando o SQL Server 2012 ou mais recente, o
BINARY
método seria o mais fácil, pois é totalmente independente (ou seja, não depende de nenhum arquivo externo).OBSERVE:
WITH SIGNATURE
cláusulaADD SIGNATURE
, pois ela só é usada quando a chave privada foi removida ou não foi usada na criação do Certificado.Neste caso (ou seja, todos esses campos
sys.certificates
correspondentes e usando a chave privada noCREATE CERTIFICATE
), os módulos de assinatura em dois locais diferentes que têm exatamente a mesma definição (como em: byte a byte o mesmo) produzirão a mesma assinaturaWITH SIGNATURE
cláusula e passar o literal binário da assinatura que foi gerada pela mesma chave privada e a mesma definição de módulo de um local que pelo menos em um ponto tenha a chave privada. Esta é uma configuração mais segura porque permite apenas a assinatura de módulos para os quais você fornece as assinaturas. Se um Certificado não tiver uma chave privada, ele ainda pode ser usado para verificar a validade dos módulos assinados, mas não pode ser usado para assinar módulos novos ou alterados (o que é bem legal).MAS , se:
ADD SIGNATURE
está sendo usado no banco de dados de destino usando aWITH SIGNATURE
cláusula,o literal binário que está sendo usado é o mesmo encontrado no banco de dados de origem por meio de:
então você precisa verificar o
OBJECT_DEFINITION
módulo em ambos os locais. Eles precisam ser idênticos , incluindo caixa, etc. Você pode fazer umSELECT CONVERT(VARBINARY(MAX), OBJECT_DEFINITION(OBJECT_ID(N'{module_name}')))
só para ter certeza. É possível que a comparação do esquema esteja ignorando diferenças nos comentários e/ou maiúsculas e minúsculas daCREATE
palavra-chave no início da definição e/ou algum espaço em branco, etc.Consulte as seguintes páginas do MSDN para obter detalhes: