Private/Sessions.ps1
<#
.SYNOPSIS Registers a session. .DESCRIPTION Registers a session by determining Resource Provider specific information. Utilizes the information gathered, validated, and stored in $Global:session. The information gathered is determined by the resource type, however some resource information is general. We do not do a lot of input validation at this point since the inputs should already have been validated in prior steps. .NOTES Initial framework author: Cale Vernon (CAVERNON) Adapted from the works of: Hayder Sabeeh (HAALZUBA); Qing Liu (QLIU); Andy Zhao (KUZHAO) #> function Register-Session { # Begin parsing the URI. # This information is used as the foundation for later finding the Resource Provider specific instance information. $tokens = ($Global:session.uri).Split('/') $sessionProperties = @{ subscriptionID = $tokens[2] resourceGroup = $tokens[4] resourceProvider = $tokens[6] resourceType = $tokens[7] # Spaces are trimmed on the resource token as URIs copied from other tools, like ASC, tend to have a trailing space. resource = ($tokens[8] -Replace '\s', '') timespanStart = (Get-Date($Global:session.start)).ToString() timespanEnd = (Get-Date($Global:session.end)).ToString() # If the follow Kusto and Jarvis time calculations are changed then you may need to update the Invoke-Operation functions in order to be reflected in Free Mode. timespanStartKusto = "$(Get-Date $Global:session.start -Format s)Z" timespanEndKusto = "$(Get-Date $Global:session.end -Format s)Z" timespanStartJarvisGlobal = ((New-TimeSpan -Start (Get-Date('2020-01-01')) -End (Get-Date($Global:session.start)).ToString("yyyy'-'MM'-'dd")).TotalSeconds * 1000 + 1577836800000).ToString() timespanEndJarvisGlobal = ((New-TimeSpan -Start (Get-Date('2020-01-01')) -End (Get-Date($Global:session.end)).ToString("yyyy'-'MM'-'dd")).TotalSeconds * 1000 + 1577836800000).ToString() } $Global:session | Add-Member -NotePropertyMembers $sessionProperties # Begin using actual resource location processes. Switch ($Global:session.resourceType) { <######################################## # Start: VM instance selection. #########################################> 'virtualMachines' { # Locate instances of the resource. Write-Console "Searching for instances of $($Global:session.resource)..." $query = " cluster('AzureCM').database('AzureCM').LogContainerSnapshot | where PreciseTimeStamp >= datetime($($Global:session.timespanStartKusto)) and PreciseTimeStamp <= datetime($($Global:session.timespanEndKusto)) | where subscriptionId in ('$($Global:session.subscriptionID)') | where roleInstanceName in ('_$($Global:session.resource)', '$($Global:session.resource)') | summarize ContainerChangeDateOrEarliestKnownDate=min(PreciseTimeStamp) by CloudName, Region, DataCenterName, Tenant, AvailabilityZone, nodeId, containerId, roleInstanceName, tenantName, virtualMachineUniqueId | join kind=leftouter(cluster('Azuredcm'). database('AzureDCMDb').ResourceSnapshotV1) on `$left.nodeId == `$right.ResourceId | extend NodeIdUpper=toupper(nodeId) | join kind=leftouter(cluster('aznwcc').database('aznwmds').Servers) on `$left.NodeIdUpper == `$right.NodeId | join kind=leftouter(cluster('aznwcc').database('aznwmds').DeviceInterfaceLinks) on `$left.DeviceName == `$right.StartDevice | project roleInstanceName, ContainerChangeDateOrEarliestKnownDate, Region, DataCenterName, Tenant, AvailabilityZone,virtualMachineUniqueId, nodeId, containerId, tenantName, IPAddress, EndDevice | order by ContainerChangeDateOrEarliestKnownDate desc " $instances = Invoke-Kusto -KustoCluster 'AzureCM' -KustoDatabase 'AzureCM' -Query $query # Instances were found; begin instance selection and session creation. If ($instances) { $instance = $instances | Out-GridView -Title "[Nanite] Please select an instance of $($Global:session.resource):" -OutputMode Single If (!$instance) { Write-Console "No instances of $($Global:session.resource) were selected." Return } Else { # Look up the region's Shoebox name to be used in certain operations such as VMDash. $query = " cluster('AzureCM').database('AzureCM').LogClusterSnapshot | where tenantName contains '$($instance.Tenant)' | where shoeboxMdmAccountName !in ('', 'NA') | distinct shoeboxMdmAccountName " $regionShoebox = Invoke-Kusto -KustoCluster 'AzureCM' -KustoDatabase 'AzureCM' -Query $query Write-Console -Message "Creating session information for the selected instance of $($Global:session.resource)..." $instanceProperties = @{ roleInstanceName = $instance.roleInstanceName region = $instance.Region regionShoebox = $regionShoebox.shoeboxMdmAccountName nodeID = $instance.NodeID bladeID = $instance.NodeID vmID = $instance.VirtualMachineUniqueId tenantName = $instance.tenantName cluster = $instance.Tenant containerID = $instance.ContainerID nodeIP = $instance.IPAddress torName = $instance.EndDevice } $Global:session | Add-Member -NotePropertyMembers $instanceProperties } } # No instances were found. Else { Invoke-NoInstancesFound Return } # Break out of the Switch statement. Break } <######################################## # End: VM instance selection. #########################################> <######################################## # Start: VMSS instance selection. #########################################> 'virtualMachineScaleSets' { # Locate instances of the resource. Write-Console "Searching for instances of $($Global:session.resource)..." $query = " cluster('AzureCM').database('AzureCM').LogContainerSnapshot | where PreciseTimeStamp >= datetime($($Global:session.timespanStartKusto)) and PreciseTimeStamp <= datetime($($Global:session.timespanEndKusto)) | where subscriptionId in ('$($Global:session.subscriptionID)') | where roleInstanceName startswith ('_$($Global:session.resource)') | summarize ContainerChangeDateOrEarliestKnownDate=min(PreciseTimeStamp) by CloudName, Region, DataCenterName, Tenant, AvailabilityZone, nodeId, containerId, roleInstanceName, tenantName, virtualMachineUniqueId | join kind=leftouter(cluster('Azuredcm'). database('AzureDCMDb').ResourceSnapshotV1) on `$left.nodeId == `$right.ResourceId | extend NodeIdUpper=toupper(nodeId) | join kind=leftouter(cluster('aznwcc').database('aznwmds').Servers) on `$left.NodeIdUpper == `$right.NodeId | join kind=leftouter(cluster('aznwcc').database('aznwmds').DeviceInterfaceLinks) on `$left.DeviceName == `$right.StartDevice | project roleInstanceName, ContainerChangeDateOrEarliestKnownDate, Region, DataCenterName, Tenant, AvailabilityZone,virtualMachineUniqueId, nodeId, containerId, tenantName, IPAddress, EndDevice | order by ContainerChangeDateOrEarliestKnownDate desc " $instances = Invoke-Kusto -KustoCluster 'AzureCM' -KustoDatabase 'AzureCM' -Query $query # Instances were found; begin instance selection and session creation. If ($instances) { $instance = $instances | Out-GridView -Title "[Nanite] Please select an instance of $($Global:session.resource):" -OutputMode Single If (!$instance) { Write-Console "No instances of $($Global:session.resource) were selected." Return } Else { # Look up the region's Shoebox name to be used in certain operations such as VMDash. $query = " cluster('AzureCM').database('AzureCM').LogClusterSnapshot | where tenantName contains '$($instance.Tenant)' | where shoeboxMdmAccountName !in ('', 'NA') | distinct shoeboxMdmAccountName " $regionShoebox = Invoke-Kusto -KustoCluster 'AzureCM' -KustoDatabase 'AzureCM' -Query $query Write-Console -Message "Creating session information for the selected instance of $($Global:session.resource)..." $instanceProperties = @{ roleInstanceName = $instance.roleInstanceName region = $instance.Region regionShoebox = $regionShoebox.shoeboxMdmAccountName nodeID = $instance.NodeID bladeID = $instance.NodeID vmID = $instance.VirtualMachineUniqueId tenantName = $instance.tenantName cluster = $instance.Tenant containerID = $instance.ContainerID nodeIP = $instance.IPAddress torName = $instance.EndDevice } $Global:session | Add-Member -NotePropertyMembers $instanceProperties } } # No instances we found. Else { Invoke-NoInstancesFound Return } } Default { # Realistically, the unsupported resource type is caught by Test-URI in Nanite.ps1, but we Default to it here to be safe. Write-Console -Message "The specified resource type of $($Global:session.resourceType) is not supported." Exit } <######################################## # End: VMSS instance selection. #########################################> } <######################################## # Start: Session saving. #########################################> If ($Global:session.case) { $Global:session | ConvertTo-Json -Depth 10 | ForEach-Object { [System.Text.RegularExpressions.Regex]::Unescape($_) } | Out-File "$($Global:configuration.Output)\Sessions\$case.json" -Force Write-Console -Message "Saved session information under case number #$($Global:session.case)." } Else { Write-Console -Message "Not saving session information for reuse as no case number was provided." } <######################################## # End: Session saving. #########################################> } |