적용 대상:SQL Server on Linux
SQL 평가 API는 SQL Server 구성을 평가하여 모범 사례를 평가할 수 있는 메커니즘을 제공합니다. API는 SQL Server 팀에서 권장하는 모범 사례가 포함된 규칙 집합과 함께 제공됩니다. 이 규칙 집합은 새 버전의 출시로 향상되었습니다. SQL Server 구성이 권장 모범 사례와 일치하는지 확인하는 것이 유용합니다.
Microsoft에서 제공하는 규칙 세트는 GitHub에서 확인할 수 있습니다. 샘플 리포지토리에서 전체 규칙 세트를 볼 수 있습니다.
이 글에서는 PowerShell을 사용해 Linux와 컨테이너에서 SQL Server on Linux용 SQL Assessment API를 실행해 보세요.
필수 조건
Linux에 Azure 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자 이상이어야 하며 대문자, 소문자, 0~9까지의 숫자 및 기호 네 가지 집합 중 세 집합의 문자를 포함해야 합니다. 암호 길이는 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 평가 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
}
}
참고
이 스크립트를 신뢰할 수 있는 환경에서 실행할 때 사전 로그인 핸드셰이크 오류가 발생하면, 코드에서 Get-SqlInstance, $serverName, -TrustServerCertificate 줄의 명령에 $hostName 플래그를 추가하세요.
평가 실행
사용자가 스크립트를 소유하고 실행할 수 있는지 확인하세요
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 파일 파싱을 지원하는 모든 도구와 함께 사용할 수 있습니다.