web-dev-qa-db-ja.com

DBとインスタンス間でパスワードによって暗号化された証明書を共有する

質問:

単一の(自己署名)証明書を作成し、多くのデータベースとインスタンスに展開しようとしています。

私は証明書を作成してバックアップします:

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!' );

で復元する

USE FOO
GO

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

次のエラーが表示されます:「データベースにマスターキーを作成するか、この操作を実行する前にセッションでマスターキーを開いてください。」

データベースマスターキーを作成したくありません。必要に応じて、パスワードで証明書を復号化できます。

背景: SaaSアプリケーション。DBとインスタンス間の多対多の関係。

DMVへの呼び出しをラップして統計を返すストアドプロシージャを実行することにより、各DBがそれ自体の統計を照会できるようにする必要があります。

アプリは低い特権のアカウントで実行されます。 DMVにはVIEW SERVER STATE権限が必要であるため、証明書を使用してストアドプロシージャの署名を実装しています。

これを設定する基本的な方法は次のとおりです。

  1. ユーザーDBに証明書を作成します。
  2. その証明書をマスターにバックアップ/復元します。
  3. マスターにログインを作成し、その権限などを割り当てます。
  4. ストアドプロシージャに証明書を追加します。

上記のテストコードがありますが、うまく機能しますが、モデルは複数のインスタンス/ dbにまたがる展開に適していません。

したがって、私はthinkすべてのDB /インスタンスで同じ証明書を使用したいと考えています。

他の提案/アプローチに満足しています。

-元はStack Exchangeに投稿された後、別の用途からの提案に移動しました

7
David Ames

秘密鍵ファイルを復号化するためのパスワードのみを指定します。証明書を保存するには、次のパスワードを追加する必要があります。

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

しかし、あなたのBackground情報は、エクササイズ全体を無駄にします。あなたはそれを間違っています。正しい一連のアクションは次のとおりです。

  1. ユーザーDBに証明書を作成する
  2. 署名をストアプロシージャに追加します。
  3. 証明書の秘密鍵を削除する
  4. 証明書をmasterにバックアップ/復元(公開鍵のみ!)
  5. masterにログインを作成し、その権限を割り当てます。

プライベートキーデータベースを離れないだけでなく、実際にはプロシージャに署名した直後に明示的に削除されることに注意してください。これは必須であり、この証明書を使用して他の手順に署名したり、手順5で作成したログイン権限を悪用したりしないようにするために、各データベースでこれらの手順を繰り返し、各データベースで異なる証明書を使用します。署名された手順を変更するたびにこれらの手順を繰り返し、毎回新しい証明書を生成します。

一般的なルールとして、秘密キーのcopyを必要とする署名/暗号化の公開/秘密キー(RSA)スキームはすべて無効になります。これがprivateと呼ばれる理由であり、これが署名に価値を与えるものです。この秘密鍵のインスタンスは世界に1つしか存在しないという知識があるため、署名されたものはすべてnique秘密鍵の唯一の所有者/所有者からのものであることの証明。


手順に署名するために使用された直後に秘密鍵をドロップするという私の推奨を回避する人がいることは知っています。私は私の推奨を支持しますが、あなたの問題にとって重要なことはあなたが望むコード署名許可を活用するために秘密鍵を[master]にコピーする必要はありません。公開鍵のみを使用して、証明書から派生したログインを作成できます(作成する必要があります)。

自動化に関して:私が見るように、基本的にそれは2つの入力を取るツール(スクリプト、アプリ)です。セキュリティ保護可能な(プロシージャ、関数、モジュール)とアクセス許可(VIEW SERVER STATE)です。その他はすべて自動化されたプロセスです(使い捨ての使い捨て証明書の作成、署名、証明書のエクスポート、[master]への証明書のインポート、ログインの作成、権限の付与)。暗黙の名前(証明書名、ログイン名)をすべて生成できます。

名前の急増は正当な懸念事項です。別の方法としては、証明書と関連する秘密鍵を1つだけ使用し、署名ツールは必要に応じて(手順に署名するときに)秘密鍵を追加し、署名後に削除することができます。本当にあなたがあなたの店をどのように運営しているか、そしてあなたが保護している資産がどれほど重要であるかという問題です。ただし、重要なのは、[master]に秘密鍵をインポートする必要がないことです。

5
Remus Rusanu

エラーを回避するには、サーバーごとにマスターキーを作成する必要があります。 secondaryサーバーで同じエラーを修正するために私がやったことは次のとおりです。

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') ;

データベースをサーバーのサービスマスターキーで暗号化されたマスターキーと照合するサーバー全体でこれを確認します。

select name from sys.databases where is_master_key_encrypted_by_server=1

リファレンス: https://docs.Microsoft.com/en-us/sql/relational-databases/security/encryption/sql-server-and-database-encryption-keys-database-engine

この段落は私を助けました:

masterシステムデータベースに保存されているDMKのコピーは、DMKが変更されるたびに通知なく更新されます。ただし、このデフォルトは、ALTER MASTER KEYステートメントのDROP ENCRYPTION BY SERVICE MASTER KEYオプションを使用して変更できます。サービスマスターキーで暗号化されていないDMKは、OPEN MASTER KEYステートメントとパスワードを使用して開く必要があります。

1
Hiram

私は証明書とキーを運用であまり使用していませんが、概念を理解する方法は、秘密キーで証明書を作成するということは、データベースマスターキーを使用して証明書の秘密キーを暗号化することです。

Technetでこの記事を見つけました: http://technet.Microsoft.com/en-us/library/bb964742.aspx

データベースマスターキーは、証明書の秘密キーとデータベースに存在する非対称キーを保護するために使用される対称キーです

別のサーバーで証明書を使用できるかどうかを確認するために、秘密鍵なしで証明書を作成しました。

CREATE CERTIFICATE DavesCert WITH SUBJECT = 'The master cert'

それから私はそれをバックアップしました

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

証明書を別のサーバーに移動して復元しました。

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

証明書を見る

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

秘密キーを使用して証明書を暗号化しない場合、データベースマスターキーは必要ありません。秘密キーを使用する場合は、証明書を使用する各データベースにマスターキーを作成する必要があります。

1
Craig Efrein