適用対象:SQL Server on Linux
SQL評価APIは、SQL Serverの設定をベストプラクティスとして評価する仕組みを提供します。 この API は、SQL Server チームが推奨するベスト プラクティス ルールを含むルール セットと共に配布されます。 このルール セットは、新しいバージョンのリリースとともに強化されます。 お使いの SQL Server の構成がベスト プラクティスに沿っていることを確認すると役立ちます。
Microsoftが提供したルールセットはGitHubで入手可能です。 サンプルのリポジトリでルールセット全体を確認することができます。
この記事では、PowerShellを使ってLinuxおよびコンテナ上のSQL Server on Linux用のSQL評価APIを実行します。
前提条件
Linux に PowerShell がインストールされていることを確認します。
SqlServerユーザーとして実行している PowerShell ギャラリーからmssqlPowerShell モジュールをインストールします。su mssql -c "/usr/bin/pwsh -Command Install-Module SqlServer"
評価を設定する
SQL評価APIはJSON形式の出力を提供します。 SQL評価APIを設定するには、以下の手順を完了してください:
評価したいインスタンスでSQL認証を使ってSQL Server評価用のログインを作成します。 以下の Transact-SQL スクリプトを使ってログインと強力なパスワードを作成します。 パスワードは SQL Server の既定のパスワード ポリシーに従う必要があります。 既定では、パスワードの長さは少なくとも 8 文字で、大文字、小文字、10 進数の数字、記号の 4 種類のうち 3 種類を含んでいる必要があります。 パスワードには最大 128 文字まで使用できます。 パスワードはできるだけ長く、複雑にします。
USE [master]; GO CREATE LOGIN [assessmentLogin] WITH PASSWORD = N'<password>'; GRANT CONTROL SERVER TO [assessmentLogin]; GOCONTROL SERVER許可はほとんどの評価で有効です。 ただし、一部の評価では システム管理者 権限が必要な場合もあります。 もしそれらの評価を実行していない場合は、CONTROL SERVER権限を使ってください。インスタンスに接続するための認証情報を保存します。 前のステップで使ったパスワードに
<password>を置き換えてください。echo "assessmentLogin" > /var/opt/mssql/secrets/assessment echo "<password>" >> /var/opt/mssql/secrets/assessmentmssqlユーザーのみが資格情報にアクセスできるようにして、新しい評価の資格情報をセキュリティで保護します。chmod 600 /var/opt/mssql/secrets/assessment chown mssql:mssql /var/opt/mssql/secrets/assessment
評価スクリプトをダウンロードする
以下のサンプルスクリプトは、先に作成した認証情報を用いてSQL評価APIを呼び出します。 スクリプトは /var/opt/mssql/log/assessments ディレクトリにJSON出力を生成します。
注
SQL Assessment API は、CSV と XML 形式で出力を生成することもできます。
このスクリプトは GitHub からダウンロードできます。
このファイルは /opt/mssql/bin/runassessment.ps1 として保存できます。
[CmdletBinding()] param ()
$Error.Clear()
# Create output directory if not exists
$outDir = '/var/opt/mssql/log/assessments'
if (-not ( Test-Path $outDir )) { mkdir $outDir }
$outPath = Join-Path $outDir 'assessment-latest'
$errorPath = Join-Path $outDir 'assessment-latest-errors'
if ( Test-Path $errorPath ) { remove-item $errorPath }
function ConvertTo-LogOutput {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true)]
$input
)
process {
switch ($input) {
{ $_ -is [System.Management.Automation.WarningRecord] } {
$result = @{
'TimeStamp' = $(Get-Date).ToString("O");
'Warning' = $_.Message
}
}
default {
$result = @{
'TimeStamp' = $input.TimeStamp;
'Severity' = $input.Severity;
'TargetType' = $input.TargetType;
'ServerName' = $serverName;
'HostName' = $hostName;
'TargetName' = $input.TargetObject.Name;
'TargetPath' = $input.TargetPath;
'CheckId' = $input.Check.Id;
'CheckName' = $input.Check.DisplayName;
'Message' = $input.Message;
'RulesetName' = $input.Check.OriginName;
'RulesetVersion' = $input.Check.OriginVersion.ToString();
'HelpLink' = $input.HelpLink
}
if ( $input.TargetType -eq 'Database') {
$result['AvailabilityGroup'] = $input.TargetObject.AvailabilityGroupName
}
}
}
$result
}
}
function Get-TargetsRecursive {
[CmdletBinding()]
Param (
[Parameter(ValueFromPipeline = $true)]
[Microsoft.SqlServer.Management.Smo.Server] $server
)
$server
$server.Databases
}
function Get-ConfSetting {
[CmdletBinding()]
param (
$confFile,
$section,
$name,
$defaultValue = $null
)
$inSection = $false
switch -regex -file $confFile {
"^\s*\[\s*(.+?)\s*\]" {
$inSection = $matches[1] -eq $section
}
"^\s*$($name)\s*=\s*(.+?)\s*$" {
if ($inSection) {
return $matches[1]
}
}
}
return $defaultValue
}
try {
Write-Verbose "Acquiring credentials"
$login, $pwd = Get-Content '/var/opt/mssql/secrets/assessment' -Encoding UTF8NoBOM -TotalCount 2
$securePassword = ConvertTo-SecureString $pwd -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($login, $securePassword)
$securePassword.MakeReadOnly()
Write-Verbose "Acquired credentials"
$serverInstance = '.'
if (Test-Path /var/opt/mssql/mssql.conf) {
$port = Get-ConfSetting /var/opt/mssql/mssql.conf network tcpport
if (-not [string]::IsNullOrWhiteSpace($port)) {
Write-Verbose "Using port $($port)"
$serverInstance = "$($serverInstance),$($port)"
}
}
# IMPORTANT: If the script is run in trusted environments and there is a prelogin handshake error,
# add -TrustServerCertificate flag in the commands for $serverName, $hostName and Get-SqlInstance lines below.
$serverName = (Invoke-SqlCmd -ServerInstance $serverInstance -Credential $credential -Query "SELECT @@SERVERNAME")[0]
$hostName = (Invoke-SqlCmd -ServerInstance $serverInstance -Credential $credential -Query "SELECT HOST_NAME()")[0]
# Invoke assessment and store results.
# Replace 'ConvertTo-Json' with 'ConvertTo-Csv' to change output format.
# Available output formats: JSON, CSV, XML.
# Encoding parameter is optional.
Get-SqlInstance -ServerInstance $serverInstance -Credential $credential -ErrorAction Stop
| Get-TargetsRecursive
| ForEach-Object { Write-Verbose "Invoke assessment on $($_.Urn)"; $_ }
| Invoke-SqlAssessment 3>&1
| ConvertTo-LogOutput
| ConvertTo-Json -AsArray
| Set-Content $outPath -Encoding UTF8NoBOM
}
finally {
Write-Verbose "Error count: $($Error.Count)"
if ($Error) {
$Error
| ForEach-Object { @{ 'TimeStamp' = $(Get-Date).ToString("O"); 'Message' = $_.ToString() } }
| ConvertTo-Json -AsArray
| Set-Content $errorPath -Encoding UTF8NoBOM
}
}
注
このスクリプトを信頼できる環境で実行していてプレログイン ハンドシェイク エラーが発生した場合は、コード内の $hostName、Get-SqlInstance、-TrustServerCertificate 行のコマンドに $serverName フラグを追加してください。
評価を実行する
mssqlユーザーがスクリプトを所有し、実行できることを確認してください。chown mssql:mssql /opt/mssql/bin/runassessment.ps1 chmod 700 /opt/mssql/bin/runassessment.ps1ログフォルダを作成し、
mssqlユーザーにそのフォルダの権限を与えてください。mkdir /var/opt/mssql/log/assessments/ chown mssql:mssql /var/opt/mssql/log/assessments/ chmod 0700 /var/opt/mssql/log/assessments/mssqlユーザーとして最初の評価を作成できます。 このユーザーとしてアセスメントを実行する方が安全で、特に後のアセスメントをcronやsystemdで自動的に実行する場合に効果的です。su mssql -c "pwsh -File /opt/mssql/bin/runassessment.ps1"コマンドが終了すると、出力はJSON形式で生成されます。 この出力は、Visual Studio Codeを含むJSONファイルの解析をサポートするあらゆるツールで使用できます。