1+ # ----------------------------------------------------------------------------------
2+ #
3+ # Copyright Microsoft Corporation
4+ # Licensed under the Apache License, Version 2.0 (the "License");
5+ # you may not use this file except in compliance with the License.
6+ # You may obtain a copy of the License at
7+ # http://www.apache.org/licenses/LICENSE-2.0
8+ # Unless required by applicable law or agreed to in writing, software
9+ # distributed under the License is distributed on an "AS IS" BASIS,
10+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+ # See the License for the specific language governing permissions and
12+ # limitations under the License.
13+ # ----------------------------------------------------------------------------------
14+
15+ <#
16+ . SYNOPSIS
17+ Tests end to end scenario for SQL vulnerability assessment on SQL VM.
18+ This test is live only because it cannot be recorded.
19+ New-AzMonitorLogAnalyticsSolution cmdlet depends on Az.MonitoringSolution
20+ which is a generated module and is not currently supported by the testing framework
21+ #>
22+ function Test-AzSecuritySqlVulnerabilityAssessment
23+ {
24+ # Setup
25+ $testPrefix = " pssqlva"
26+ $testParams = Get-SecuritySqlVulnerabilityAssessmentTestEnvironmentParameters $testPrefix
27+ $vmResourceId = " /subscriptions/" + $testParams.subscriptionId + " /resourceGroups/" + $testParams.rgName + " /providers/Microsoft.Compute/VirtualMachines/" + $testParams.sqlVmNamePrefix
28+ Create- TestEnvironmentWithParams $testParams
29+
30+ $vaScanRecord = Get-AzSecuritySqlVulnerabilityAssessmentScanRecord - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - ScanId latest
31+ $resultsOnMaster = Get-AzSecuritySqlVulnerabilityAssessmentScanResult - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master
32+ $resultsWithFindingsOnMaster = $resultsOnMaster | where { $_.Status -eq " Finding" }
33+
34+ Assert-True { $resultsOnMaster.Count -eq $vaScanRecord.TotalRulesCount }
35+ Assert-True { $resultsWithFindingsOnMaster.Count -eq $vaScanRecord.TotalFailedRulesCount }
36+
37+ $finding = $resultsWithFindingsOnMaster | select - first 1
38+ $ruleResult = Get-AzSecuritySqlVulnerabilityAssessmentScanResult - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - ScanId $vaScanRecord.Name - RuleId $finding.Name
39+
40+ Assert-True { $finding.Name -eq $ruleResult.Name }
41+
42+ # check add baseline with latest.
43+ Add-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - RuleId $finding.Name
44+
45+ $baseline = Get-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - RuleId $finding.Name
46+
47+ Assert-NotNull $baseline
48+
49+ $baseline | Remove-AzSecuritySqlVulnerabilityAssessmentBaseline - Force
50+
51+ Assert-Throws { Get-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - RuleId $finding.Name }
52+
53+ # check Add baseline with result
54+ Add-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - RuleId $finding.Name - Baseline $finding.QueryResults
55+
56+ $baseline = Get-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - RuleId $finding.Name
57+ Assert-NotNull $baseline
58+
59+ $baseline | Remove-AzSecuritySqlVulnerabilityAssessmentBaseline - Force
60+
61+ # ## Check piping
62+
63+ $resultsOnMsdb = Get-AzSecuritySqlVulnerabilityAssessmentScanResult - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database msdb
64+ $resultsWithFindingsOnMsdb = $resultsOnMsdb | where { $_.Status -eq " Finding" }
65+ $rulesNamesOnMsdb = $resultsWithFindingsOnMsdb | select - ExpandProperty Name
66+ $rulesNamesOnMaster = $resultsWithFindingsOnMaster | select - ExpandProperty Name
67+
68+ # get rules intersection between master and msdb
69+ $ruleWithFindingsOnBothDbs = $rulesNamesOnMaster | ? {$rulesNamesOnMsdb -contains $_ }
70+
71+ if ($ruleWithFindingsOnBothDbs.Count -gt 0 )
72+ {
73+ # add baseline on master
74+ Add-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - RuleId $ruleWithFindingsOnBothDbs [0 ]
75+
76+ # bypass it to msdb
77+ Get-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - RuleId $ruleWithFindingsOnBothDbs [0 ] `
78+ | Add-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database msdb
79+
80+ $baseline = Get-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database msdb - RuleId $ruleWithFindingsOnBothDbs [0 ]
81+ Assert-NotNull $baseline
82+ }
83+
84+ # Set all latest results as Baseline
85+ Set-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - Force
86+ $vaScanRecord = Get-AzSecuritySqlVulnerabilityAssessmentScanRecord - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - ScanId latest
87+
88+ Assert-True { $vaScanRecord.State -eq " Passed" }
89+ Assert-True { $vaScanRecord.TotalFailedRulesCount -eq 0 }
90+
91+ Get-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master | Remove-AzSecuritySqlVulnerabilityAssessmentBaseline - Force
92+
93+ $baselineSet = @ {}
94+ $resultsWithFindingsOnMaster | select - skip 3 | ForEach-Object { $baselineSet.Add ($_.RuleId , $_.QueryResults )}
95+
96+ Set-AzSecuritySqlVulnerabilityAssessmentBaseline - ResourceId $vmResourceId - WorkspaceId $testParams.workspaceId - Server $testParams.sqlServerName - Database master - BaselineSet $baselineSet - Force
97+
98+ Delete- TestEnvironments ($testParams )
99+ }
100+
101+ <#
102+ . SYNOPSIS
103+ Gets the values of the parameters used at the tests
104+ #>
105+ function Get-SecuritySqlVulnerabilityAssessmentTestEnvironmentParameters ($testPrefix )
106+ {
107+ $location = Get-Location " Microsoft.Compute" " virtualMachines" " East Us 2 Euap" ;
108+ $sqlVmName = getAssetName ($testPrefix + ' vm' );
109+
110+ return @ { subscriptionId = (Get-AzContext ).Subscription.Id;
111+ rgName = getAssetName ($testPrefix );
112+ sqlVmNamePrefix = $sqlVmName ;
113+ sqlVmDomain_prefix = ' domainvm' ;
114+ sqlVmMaxLength = 15 ;
115+ sqlVmUserName = ' testuser' ;
116+ sqlVmPassword = Generate- RandomVmPassword;
117+ sqlServerImage = ' MicrosoftSQLServer:SQL2017-WS2016:Enterprise:latest' ;
118+ sqlServerVmSize = ' Standard_DS2_v2' ;
119+ sqlServerName = " MSSQLSERVER"
120+ operationalInsightsWorkspaceName = getAssetName ($testPrefix + " psWorkspace" );
121+ workspaceId = " " ;
122+ location = location;
123+ vmLocation = $location.Replace (' ' , ' ' );
124+ vmDomainNameLabel = (getAssetName ($sqlVmName + ' -' )).ToLower();
125+ }
126+
127+ }
128+
129+ <#
130+ . SYNOPSIS
131+ Creates the basic test environment needed to perform the sql vulnerability assessment tests - resource group, VM, workspace,... etc
132+ #>
133+ function Create-TestEnvironmentWithParams ($testParams )
134+ {
135+ # Create a new resource group.
136+ New-AzResourceGroup - Name $testParams.rgName - Location $testParams.location
137+
138+ $passWord = ConvertTo-SecureString - String $testParams.sqlVmPassword - AsPlainText - Force
139+ $cred = New-Object - TypeName System.Management.Automation.PSCredential - ArgumentList $testParams.sqlVmUserName , $passWord
140+
141+ # Create the sql virtual machine.
142+ Write-Host " ResourceGroupName " + $testParams.rgName + " -Location " + $testParams.location " -Size " + $testParams.sqlServerVmSize + " -Image " + $testParams.sqlServerImage + " -Credential " + $cred " -Name " + $testParams.sqlVmNamePrefix
143+
144+ New-AzVm - ResourceGroupName $testParams.rgName - Location $testParams.vmLocation - Image $testParams.sqlServerImage - Credential $cred - Name $testParams.sqlVmNamePrefix - DomainNameLabel $testParams.vmDomainNameLabel
145+
146+ # Create the log analytics worskspace
147+ $workspace = New-AzOperationalInsightsWorkspace - Location $testParams.location - Name $testParams.operationalInsightsWorkspaceName - ResourceGroupName $testParams.rgName
148+ New-AzMonitorLogAnalyticsSolution - Type SQLVulnerabilityAssessment - ResourceGroupName $testParams.rgName - Location $testParams.location - WorkspaceResourceId $workspace.ResourceId
149+
150+ # Install microsoft Monitoring agent on the VM
151+ $workspaceKeys = Get-AzOperationalInsightsWorkspaceSharedKey - Name $testParams.operationalInsightsWorkspaceName - ResourceGroupName $testParams.rgName
152+ $publicSettings = @ {" workspaceId" = $workspace.CustomerId }
153+ $protectedSettings = @ {" workspaceKey" = $workspaceKeys.PrimarySharedKey }
154+
155+ $testParams.workspaceId = $workspace.CustomerId ;
156+
157+ Set-AzVMExtension - ExtensionName " MicrosoftMonitoringAgent" `
158+ - ResourceGroupName $testParams.rgName `
159+ - VMName $testParams.sqlVmNamePrefix `
160+ - Publisher " Microsoft.EnterpriseCloud.Monitoring" `
161+ - ExtensionType " MicrosoftMonitoringAgent" `
162+ - TypeHandlerVersion 1.0 `
163+ - Settings $publicSettings `
164+ - ProtectedSettings $protectedSettings `
165+ - Location $testParams.vmLocation
166+
167+ # Update the registery and restart the Monitoring agent to force a scan.
168+ Invoke-AzVMRunCommand - ResourceGroupName $testParams.rgName - Name $testParams.sqlVmNamePrefix - CommandId ' RunPowerShellScript' - ScriptPath ' SqlVulnerabilityAssessmentTestResources\SetUpVm.ps1'
169+
170+ Start-Sleep - Seconds 180
171+ }
172+
173+ <#
174+ . SYNOPSIS
175+ Deletes the Test enviroment once the test passes.
176+ #>
177+ function Delete-TestEnvironments ($testParams )
178+ {
179+ New-AzResourceGroup - Name $testParams.rgName
180+ }
181+
182+ <#
183+ . SYNOPSIS
184+ Generates a random password for vm that satisfies these conditions:
185+ - At least 15 character long
186+ - Contains at at least one number
187+ - Contains at least one lower case letter
188+ - Contains at least one upper case letter
189+ #>
190+ function Generate-RandomVmPassword ()
191+ {
192+ $password = (" abcdefghijklmnopqrstuvwxyz" .tochararray() | sort {Get-Random })[0 .. 4 ] -join ' '
193+ $password += (" ABCDEFGHIJKLMNOPQRSTUVWXYZ" .tochararray() | sort {Get-Random })[0 .. 7 ] -join ' '
194+ $password += (" 0123456789" .tochararray() | sort {Get-Random })[0 .. 4 ] -join ' '
195+
196+ return ($password.tochararray () | sort {Get-Random }) -join ' '
197+ }
0 commit comments