Freigabe von durch Kennwort verschlüsselten Zertifikaten zwischen DBs und Instanzen


7

Frage:

Ich versuche, ein einzelnes (selbstsigniertes) Zertifikat zu erstellen und in vielen Datenbanken und Instanzen bereitzustellen.

Ich erstelle und sichere das Zertifikat mit:

USE MASTER
CREATE CERTIFICATE DavesCert ENCRYPTION BY PASSWORD ='S3creT!' WITH SUBJECT = 'The master cert'

BACKUP CERTIFICATE DavesCert TO FILE = 'd:\DavesCert.cer' 
WITH PRIVATE KEY ( DECRYPTION BY PASSWORD = 'S3creT!' ,
FILE = 'd:\DavesCert.pvk' , 
ENCRYPTION BY PASSWORD = 'S3creT!' );

Ich restauriere mit

USE FOO
GO

CREATE CERTIFICATE ERecruitStatsGatheringCert       
FROM FILE = 'd:\DavesCert.cer'      
WITH PRIVATE KEY (FILE = 'd:\DavesCert.pvk', 
DECRYPTION BY PASSWORD = 'S3creT!')

und erhalten Sie die folgende Fehlermeldung: "Bitte erstellen Sie einen Hauptschlüssel in der Datenbank oder öffnen Sie den Hauptschlüssel in der Sitzung, bevor Sie diesen Vorgang ausführen."

Ich möchte keinen Datenbankhauptschlüssel erstellen. Gerne entschlüssele ich das Zertifikat bei Bedarf per Passwort.

Hintergrund: SaaS-Anwendung. Viele-zu-Viele-Beziehung zwischen DBs und Instanzen.

Ich benötige jede Datenbank, um ihre eigenen Statistiken abfragen zu können, indem eine gespeicherte Prozedur ausgeführt wird, die einige Aufrufe an DMVs abschließt, um die Statistiken zurückzugeben.

Die App wird unter einem Konto mit geringen Berechtigungen ausgeführt. DMVs erfordern die Berechtigung VIEW SERVER STATE. Daher implementiere ich das Signieren der gespeicherten Prozeduren mithilfe von Zertifikaten.

Die grundlegende Methode zum Einrichten ist:

  1. Erstellen Sie ein Zertifikat in der Benutzer-DB.
  2. Sichern / Wiederherstellen dieses Zertifikats auf dem Master.
  3. Erstellen Sie einen Login im Master, weisen Sie diese Berechtigungen zu usw.
  4. Zertifikat zur gespeicherten Prozedur hinzufügen.

Ich habe Testcode für die oben genannten und es funktioniert gut, aber das Modell skaliert nicht sehr gut für die Bereitstellung über mehrere Instanzen / Datenbank.

Daher denke ich , dass ich für alle DBs / Instanzen dasselbe Zertifikat verwenden möchte.

Gerne für andere Vorschläge / Ansätze.

- Ursprünglich in Stack Exchange veröffentlicht und dann auf Vorschlag einer anderen Verwendung verschoben

Antworten:


5

Sie geben nur das Kennwort an, mit dem die private Schlüsseldatei entschlüsselt werden soll. Sie müssen ein Kennwort hinzufügen, um das Zertifikat zu speichern mit:

CREATE CERTIFICATE ERecruitStatsGatheringCert        
ENCRYPTION BY PASSWORD = 'S3creT!
FROM FILE = 'd:\DavesCert.cer'       
WITH PRIVATE KEY (
    FILE = 'd:\DavesCert.pvk',  
    DECRYPTION BY PASSWORD = 'S3creT!');

Aber Ihre Hintergrundinformationen machen die ganze Übung sinnlos. Du machst es falsch. Die richtige Reihenfolge der Aktionen lautet:

  1. Erstellen Sie ein Zertifikat in der Benutzer-DB
  2. Fügen Sie die Signatur zu den Speicherprozeduren hinzu.
  3. Löschen Sie den privaten Schlüssel des Zertifikats
  4. Sichern / Wiederherstellen dieses Zertifikats auf master(nur öffentlicher Schlüssel!)
  5. Erstellen Sie ein Login master, weisen Sie diese Berechtigung zu usw.

Beachten Sie, dass nicht nur der private Schlüssel die Datenbank niemals verlässt , sondern direkt nach dem Signieren der Prozedur explizit gelöscht wird. Dies ist erforderlich , um die weitere Verwendung dieses Zertifikats zum Signieren anderer Verfahren und zum Missbrauch der in Schritt 5 erstellten Anmeldeberechtigungen zu verhindern. Sie wiederholen diese Schritte für jede Datenbank und verwenden für jede Datenbank ein anderes Zertifikat. Sie wiederholen diese Schritte jedes Mal, wenn Sie eine der signierten Prozeduren ändern und jedes Mal ein neues Zertifikat erstellen.

In der Regel ist jedes RSA-Schema (Signature / Encryption Public / Private Key), für das eine Kopie des privaten Schlüssels erforderlich ist, fehlerhaft. Aus diesem Grund wird es als privat bezeichnet, und dies ist es, was der Signatur einen Wert verleiht: Das Wissen, dass es nur eine Instanz dieses privaten Schlüssels auf der Welt gibt, daher ist alles, was von ihm signiert wird, ein Beweis dafür, dass es vom einzigen Eigentümer / Inhaber stammt des eindeutigen privaten Schlüssels.


Ich weiß, dass es einige gibt, die meine Empfehlung, den privaten Schlüssel sofort nach dem Signieren des Verfahrens zu löschen, meiden. Ich stehe zu meiner Empfehlung, aber das Wichtigste für Ihr Problem ist, dass es nicht erforderlich ist, den privaten Schlüssel zu kopieren, um die gewünschte Codesignaturberechtigung[master] zu nutzen. Sie können (und sollten) das vom Zertifikat abgeleitete Login nur mit dem öffentlichen Schlüssel erstellen.

In Bezug auf die Automatisierung: Aus meiner Sicht handelt es sich im Grunde genommen um ein Tool (Skript, App), das zwei Eingaben benötigt: eine sichere (Prozedur, Funktion, Modul) und eine Berechtigung ( VIEW SERVER STATE). Alles andere ist ein automatisierter Prozess (einmaliges Wegwerfzertifikat erstellen, signieren, exportieren, Zertifikat importieren [master], Login erstellen, Berechtigung erteilen). Die implizierten Namen (Zertifikatsname, Anmeldename) können alle generiert werden.

Die Verbreitung von Namen ist ein berechtigtes Anliegen. Eine Alternative wäre, nur ein Zertifikat und den zugehörigen privaten Schlüssel zu verwenden, und das Signatur-Tool könnte den privaten Schlüssel bei Bedarf hinzufügen (beim Signieren des Verfahrens) und ihn dann nach dem Signieren entfernen. Es geht wirklich darum, wie Sie Ihren Shop betreiben und wie wichtig das zu schützende Gut ist. Wichtig ist jedoch, dass Sie den privaten Schlüssel nicht importieren müssen[master] .


1

Ich habe in der Produktion nicht viel Zertifikate und Schlüssel verwendet, aber ich verstehe das Konzept so, dass das Erstellen eines Zertifikats mit einem privaten Schlüssel die Verwendung des Datenbankhauptschlüssels zum Verschlüsseln des privaten Schlüssels des Zertifikats bedeutet.

Ich habe diesen Artikel auf technet gefunden: http://technet.microsoft.com/en-us/library/bb964742.aspx

Der Datenbankhauptschlüssel ist ein symmetrischer Schlüssel, der zum Schutz der privaten Schlüssel von Zertifikaten und asymmetrischen Schlüsseln verwendet wird, die in der Datenbank vorhanden sind.

Um zu sehen, ob ich Ihr Zertifikat auf einem anderen Server verwenden kann, habe ich Ihr Zertifikat ohne privaten Schlüssel erstellt.

CREATE CERTIFICATE DavesCert WITH SUBJECT = 'The master cert'

Dann habe ich es gesichert

BACKUP CERTIFICATE DavesCert TO FILE = 'D:\MSSQL\davescert.cer'

Ich habe das Zertifikat auf einen anderen Server verschoben und wiederhergestellt.

CREATE CERTIFICATE davescert FROM FILE = 'd:\mssql\davescert.cer'

Zertifikat anzeigen

SELECT name, certificate_id, pvt_key_encryption_type_desc from sys.certificates


name    certificate_id  pvt_key_encryption_type_desc
davescert   257 NO_PRIVATE_KEY

Wenn Sie zum Verschlüsseln Ihres Zertifikats keinen privaten Schlüssel verwenden, benötigen Sie den Datenbankhauptschlüssel nicht. Wenn Sie einen privaten Schlüssel verwenden, müssen Sie für jede Datenbank, in der Sie Ihr Zertifikat verwenden, einen Hauptschlüssel erstellen.


In Bezug auf " Erstellen eines Zertifikats mit einem privaten Schlüssel bedeutet das Verwenden des Datenbank-Hauptschlüssels zum Verschlüsseln des privaten Schlüssels des Zertifikats. ": Sie benötigen nur den DB-Hauptschlüssel, wenn Sie kein Kennwort angeben (dh ENCRYPTION BY PASSWORD). Ein Zertifikat ohne privaten Schlüssel kann nicht verschlüsseln oder signieren, aber es kann entschlüsseln und überprüfen. Sie können also ohne den privaten Schlüssel erstellt werden. Ob dies jedoch sinnvoll ist oder nicht, hängt davon ab, was benötigt wird. Außerdem gilt der Schutz, der Hauptschlüssel oder das Kennwort nur für den privaten Schlüssel. Der öffentliche Schlüssel wird nicht geschützt. Also kein privater Schlüssel = kein Schutzbedarf :-)
Solomon Rutzky

1

Sie sollten einen Hauptschlüssel pro Server erstellen, um den Fehler zu vermeiden. Folgendes habe ich getan, um denselben Fehler auf meinen sekundären Servern zu beheben .

drop certificate [MyCertwithPK]
drop master key 

create master key encryption by password = '4_Str0ng!MasterKey'

--verify.
open master key decryption by password = '4_Str0ng!MasterKey';
close master key;

--next.
create certifate [MyCertwithPK] from file = '\\SQL1\Backups\MyCertwithPK.cer' 
with private key (file = '\\SQL1\Backups\MyCertwithPK.key' , decryption by 
password = '4_Str0ng!CertKey') ;

--Note: My cert doesn't encrypt by password. Uses encryption hierarchy & private key instead.     

--To clarify, these were my initial create/backup cmds on my **primary** svr.
create master key encryption by password = '4_Str0ng!MasterKey';
create certificate [MyCertwithPK] with subject = 'Certificate for SQL backups with Private Key' ;
backup certificate [MyCertwithPK] to file = '\\SQL1\Backups\MyCertwithPK.cer' with private key (file= '\\SQL1\Backups\MyCertwithPK.key', encryption by password = '4_Str0ng!CertKey') ;

Überprüfen Sie dies auf allen Servern, auf denen Sie Datenbanken mit einem Hauptschlüssel abgleichen möchten, der mit dem Diensthauptschlüssel des Servers verschlüsselt ist.

select name from sys.databases where is_master_key_encrypted_by_server=1

Referenz: https://docs.microsoft.com/en-us/sql/relational-databases/security/encryption/sql-server-and-database-encryption-keys-database-engine

Dieser Absatz hat mir geholfen:

Die Kopie des DMK in der gespeicherten Master - System - Datenbank wird stillschweigend aktualisiert , wenn das DMK geändert wird. Diese Standardeinstellung kann jedoch mithilfe der Option DROP ENCRYPTION BY SERVICE MASTER KEY der Anweisung ALTER MASTER KEY geändert werden . Ein DMK, das nicht mit dem Diensthauptschlüssel verschlüsselt ist, muss mit der Anweisung OPEN MASTER KEY und einem Kennwort geöffnet werden.


Beachten Sie, dass im Originalposter die Replikation / Always On-Beteiligung nicht erwähnt wurde, sondern nur mehrere Datenbanken und Instanzen. Er erwähnte auch nicht das Erstellen oder Verwenden eines MASTER KEY(was vielleicht sein Problem war, aber das wird in Ihrer Antwort in keiner Weise erwähnt).
RDFozz
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.