SQL Server ベースの CI/CD に活用できるツールとして SqlPackage があります。
SqlPackage は、データ層アプリケーション (DAC) を操作するためのツールとなり、DACPAC / BACPAC の操作を行うことができます。
このツールのアクションとして「Script」があり、SqlPackage スクリプト パラメーターとプロパティ の機能により、DACPAC や SQL Server ベースの環境とスキーマ比較をし、増分更新で状態を反映するスクリプトの作成ができます。(Publish パラメーターを使用することで直接発行することができます。基本は増分更新ですが、オプション (/p:DropObjectsNotInSource=true) で削除スクリプトを生成するかを調整することができます。)
この機能を、SQL Database に対して SQL 認証のログインで実行しようとした場合には注意点があったため本投稿でまとめておきたいと思います。
必要となるログインとユーザー / ユーザーの権限
SQL 認証で SqlPackage を実行する場合、次のログインとユーザーが必要となります。
- master データベースに作成された SQL 認証用のログイン
- 上記のログインを使用した master / SqlPackage の接続先データベースのユーザー
権限としては、ユーザーデータベースに対しての「VIEW DEFINITION」が必要となります。
「sqlpackageuser」という SQL 認証用のユーザーを使用して、SqlPackage を実行する場合は次のようなクエリでユーザーを作成しておく必要がありました。
--master デー実行 CREATE LOGIN sqlpackageuser WITH PASSWORD = '<パスワード>' GO CREATE USER sqlpackageuser FOR LOGIN sqlpackageuser WITH DEFAULT_SCHEMA = dbo GO -- ユーザーデータベースで実行 CREATE USER sqlpackageuserFOR LOGIN sqlpackageuser WITH DEFAULT_SCHEMA = dbo GO GRANT VIEW DEFINITION TO sqlpackageuser GO
SqlPackage では、「/TargetDatabase」のようなオプションを使用することで、接続するデータベースを指定することができます。
しかし、SqlPackage 内の一部の処理では、指定したデータベースだけでなく明示的に master に接続をして実行しているものがあり、master に対して接続ができないと次のようなエラーが発生します。
Cannot open database "master" requested by the login. The login failed.
SQL Database では SQL Server の 包含ユーザー のようなユーザーとして、「パスワードを持つユーザー」(ログインを持たずCREATE USER WITH PASSWORD により作成されたユーザー) を作成することができます。
この方法で作成した場合、SQL Database の論理サーバーにログインは持たず、master にはアクセスできないユーザーとして作成が行われます。このようなユーザーで SqlPackage を実行した場合、上述のような master にログインできないというエラーが発生します。
SqlPackage は、CI/CD のパイプラインの次のようなタスクで使用することができます。
このようなタスクで SQL Database に接続する場合に、ログインで問題が出た場合には、上述のクエリで作成したユーザーで試してみると解決するかもしれません。