Visual Studio Professional2015でSSDT14.0.50730.0を使用しています。2つのインスタンス間でデータベースを比較していますが、署名に関して一致しないストアドプロシージャがあることがわかりました。
どちらの場合も、証明書は同じスクリプトから各インスタンスで作成され、署名も各インスタンスで同じスクリプトを使用してパスワードを使用してCERTIFICATEによって追加されました。
ただし、スキーマ比較では、ソースとターゲットの両方で、署名値が一致しないSIGNATUREを持つCERTIFICATEがあるものとしてプロシージャが表示されます。生成された公開スクリプトは、SIGNATURE BY CERTIFICATEを削除し、プロシージャを変更してから、SIGNATURE BYCERTIFICATEを追加します。署名付き。シグニチャ値は、ソースインスタンスに表示された値と一致します。ただし、スクリプトは「公開鍵の署名が無効です」というメッセージで失敗します。
これらの手順を同期させるにはどうすればよいですか?
証明書の作成とモジュールの署名に関する詳細に入る前に、少なくとも2つのインスタンスが同じ証明書を持っているかどうかを確認できます。両方のインスタンスで以下を実行します。
_SELECT [thumbprint], [cert_serial_number], [sid],
[issuer_name], [subject],
[expiry_date], [start_date]
FROM sys.certificates
WHERE [name] = N'cert_name';
_
証明書が同じである場合、それらのフィールドはすべて、両方のインスタンス(または同じインスタンス上の両方のデータベース)で同じ値になります。ただし、これは証明書のSHA-1ハッシュであるため、主にthumbprint
フィールドを確認する必要があります。その値が2つの場所で異なる場合は、同じ証明書を扱っていません。
あなたはそれを言う
証明書は、同じスクリプトから各インスタンスで作成されました
ただし、証明書が作成されている方法方法については正確に言及しないでください。これらは、次の構文を使用してSQL Serverで生成できます(これは「自己署名」と呼ばれます)。
_CREATE CERTIFICATE [cert_name]
ENCRYPTION BY PASSWORD = 'certpassword' -- this is optional but best to use
WITH SUBJECT = 'cert_subject';
_
このメソッドは、(実行されるたびに)新しい秘密鍵を生成し、_ENCRYPTION BY PASSWORD
_句で指定されたパスワードで暗号化します。それ以外の場合は、データベースマスター鍵で暗号化します(そのため、パスワードを指定することをお勧めします)。
または、既存のアセンブリ、ファイル、またはバイナリリテラルを提供して作成できます。
_CREATE CERTIFICATE [cert_name]
FROM
Assembly assembly_name
| EXECUTABLE FILE = 'path_to_DLL'
| FILE = 'path_to_file'
WITH PRIVATE KEY ( FILE = 'path_to_private_key' )
| BINARY = 0x......
WITH PRIVATE KEY ( BINARY = 0x..... )
_
FILE
およびBINARY
メソッドでは、オプションで秘密鍵ファイルまたはバイナリリテラルを指定できます。したがって、秘密鍵を指定するとともにこれらの方法の1つを使用する場合、または署名されたAssembly
を使用する場合、この方法で証明書を作成すると、毎回同じ秘密鍵が提供されます。
では、どのようにしてFILE
またはBINARY
の値を取得しますか?
ファイル:
最初の証明書を作成したら、以下を使用してそれをエクスポートします(秘密鍵を含む!)。
_BACKUP CERTIFICATE [cert_name]
TO FILE = 'path\to\cert_file.cer'
WITH PRIVATE KEY
(
DECRYPTION BY PASSWORD = 'cert_password',
FILE = 'path\to\key_file.pvk',
ENCRYPTION BY PASSWORD = 'file_password'
);
_
そして新しい場所で:
_CREATE CERTIFICATE [cert_name]
FROM FILE = 'path\to\cert_file.cer'
WITH PRIVATE KEY
(
FILE = 'path\to\key_file.pvk',
DECRYPTION BY PASSWORD = 'file_password',
ENCRYPTION BY PASSWORD = 'cert_password'
);
_
BINARY:(SQL Server 2012以降でのみ使用可能)
最初の証明書を作成したら、以下を使用して証明書と秘密鍵の値を取得します。
_SELECT CERTENCODED(CERT_ID('cert_name')) AS [CertificateBinary],
CERTPRIVATEKEY(
CERT_ID('cert_name'),
'temp_password',
'cert_password'
) AS [PrivateKeyBinary];
_
そして新しい場所で:
_CREATE CERTIFICATE [cert_name]
FROM BINARY = 0x{CertificateBinary}
WITH PRIVATE KEY
(
BINARY = 0x{PrivateKeyBinary},
DECRYPTION BY PASSWORD = 'temp_password',
ENCRYPTION BY PASSWORD = 'cert_password'
);
_
SQL Server 2012以降を使用している場合は、BINARY
メソッドが完全に自己完結型であるため(つまり、外部ファイルに依存しないため)、最も簡単です。
注意:
WITH SIGNATURE
_の_ADD SIGNATURE
_句は必要ありません。証明書の作成。sys.certificates
_のすべてのフィールドが一致しおよび_CREATE CERTIFICATE
_の秘密鍵を使用)、モジュールに署名しますまったく同じ定義を持つ2つの異なる場所(バイトごとに同じ)は、同じ署名を生成しますWITH SIGNATURE
_句を指定する必要がありますそして、少なくともある時点で秘密鍵を持っていた場所から、同じ秘密鍵と同じモジュール定義によって生成された署名のバイナリリテラルを渡します。これは、署名を提供するモジュールにのみ署名できるため、より安全な設定です。証明書に秘密鍵がない場合でも、署名されたモジュールの有効性を確認するために使用できますが、新しいモジュールまたは変更されたモジュールに署名するために使用することはできません(これはちょっとクールです)。[〜#〜] but [〜#〜]、次の場合:
ADD SIGNATURE
_は、_WITH SIGNATURE
_句を使用して宛先データベースで使用されています。使用されているバイナリリテラルは、次の方法でソースデータベースにあるものと同じです。
_SELECT OBJECT_NAME(major_id), crypt_property
FROM sys.crypt_properties;
_
次に、両方の場所でそのモジュールの_OBJECT_DEFINITION
_を確認する必要があります。それらは、ケーシングなどを含めて同一である必要があります。念のためにSELECT CONVERT(VARBINARY(MAX), OBJECT_DEFINITION(OBJECT_ID(N'{module_name}')))
を実行できます。スキーマの比較で、コメントの違いや、定義の先頭にあるCREATE
キーワードの大文字と小文字の違いや空白などが無視されている可能性があります。
詳細については、次のMSDNページを参照してください。