List / discover all Azure SQL Database backup retention policies - azure-sql-database

I have a large number of Azure SQL Databases and I would like to create a list or report of some kind that shows what backup retention policies are in place for each one.
All I can find is how to check on per-database or per-server basis. This would take me a long time and is error-prone and not something I can check on a regular basis or easily provide to an auditor/manager who wants confirmation that everything is being backed up and retained properly.
Is there a way to obtain all this information in one place? A PowerShell solution would be acceptable.

You can use Powershell commands to get the Long-term retention policies for your SQL Server or even for each database using below commands:
# get all LTR policies within a server
$ltrPolicies = Get-AzSqlDatabase -ResourceGroupName $resourceGroup -ServerName $serverName | `
Get-AzSqlDatabaseLongTermRetentionPolicy
# get the LTR policy of a specific database
$ltrPolicies = Get-AzSqlDatabaseBackupLongTermRetentionPolicy -ServerName $serverName -DatabaseName $dbName `
-ResourceGroupName $resourceGroup
You can also use CLI command to get LTR policies for each database.
az sql db ltr-policy show \
--resource-group mygroup \
--server myserver \
--name mydb
In the above code only you can write the code for each database to get the LTR policies.
Refer: Manage Azure SQL Database long-term backup retention

Related

Get-AzRoleAssignment command returning users and service principles who are removed from RBAC Permissions

I am using Get-AzRoleAssignment to get RBAC details for Data Lake Storage Gen1 resource.
Command :
Get-AzRoleAssignment -ResourceGroupName "test" -ResourceName "testResource" -ResourceType "Microsoft.DataLakeAnalytics/accounts"
Above command gives us list of resources who have access to resource mentioned. Since first use of this command we have removed access for many resources but command still return names for those. I logged out and logged in multiple times to check if its caching issue but no use.

Adding all databases in an elastic pool to an availability group

Executing the Powershell get-help Add-AzureRmSqlDatabaseToFailoverGroup -examples gives three examples with #3
PS C:\> $failoverGroup = Get-AzureRmSqlDatabaseFailoverGroup -ResourceGroupName rg -ServerName primaryserver -FailoverGroupName fg
PS C:\> $databases = Get-AzureRmSqlElasticPoolDatabase -ResourceGroupName rg -ServerName primaryserver -ElasticPoolName pool1
PS C:\> $failoverGroup = $failoverGroup | Add-AzureRmSqlDatabaseToFailoverGroup -Database $databases
"This command adds all databases in an Elastic Pool to a Failover Group."
Has anyone gotten this to work as presented?
I can successfully execute the Get-AzureRmSqlDatabaseFailoverGroup & Get-AzureRmSqlElasticPoolDatabase steps but the third step returns a
Add-AzureRmSqlDatabaseToFailoverGroup : FailoverGroupUnableToPerformGroupOperationOnDatabases: The operation cannot be
performed due to multiple errors.
"Now just have to figure out why it expects my secondary server to be associated with the primary elastic pool." Azure expects DR server elastic pool name would be the same as your Primary elastic pool name. If name is different you will not be able add db's to failover group.
I believe this is due to azure allow have multiple elastic pools on the same server and it have to know somehow in which one it should place database after you add it to failover group.
Hope it helps.

Backup Azure SQL DB during VSTS Release

I am exploring VSTS Release Management and I wanted to backup my production database hosted on Azure SQL DB before I apply any migration scripts to it. I fail to find any particular task or preferred way of waiting till the Azure SQL DB is fully backed up so that I can proceed with deployment only after the database is correctly backed up. 
I have looked at either using a PowerShell task or Azure SQL CMD task, but I am not sure how to make rest of the tasks wait for the backup to complete. 
Would appreciate if anyone could point me in the right direction. Thanks. 
You can backup Azure SQL database and check the status in a loop.
$exportRequest = New-AzureRmSqlDatabaseExport -ResourceGroupName $ResourceGroupName -ServerName $ServerName `
-DatabaseName $DatabaseName -StorageKeytype $StorageKeytype -StorageKey $StorageKey -StorageUri $BacpacUri `
-AdministratorLogin $creds.UserName -AdministratorLoginPassword $creds.Password
$importStatus = Get-AzureRmSqlDatabaseImportExportStatus -OperationStatusLink $importRequest.OperationStatusLink
[Console]::Write("Exporting")
while ($importStatus.Status -eq "InProgress")
{
$importStatus = Get-AzureRmSqlDatabaseImportExportStatus -OperationStatusLink $importRequest.OperationStatusLink
[Console]::Write(".")
Start-Sleep -s 10
}
[Console]::WriteLine("")
$importStatus
More information, you can refer to Export an Azure SQL database to a BACPAC file.
Another way is that you can backup Azure SQL database by call Microsoft.SqlServer.Dac.DacServices.ExportBacpac method with PowerShell.
param([string]$ConnectionString, [string]$DatabaseName,[string]$OutputFile,[string]$s)
Add-Type -Path "$s\AzureDatabaseSolution\SQLDatabase\lib\Microsoft.SqlServer.Dac.dll"
$now = $(Get-Date).ToString("HH:mm:ss")
$Services = new-object Microsoft.SqlServer.Dac.DacServices $ConnectionString
Write-Host "Starting at $now"
$Watch = New-Object System.Diagnostics.StopWatch
$Watch.Start()
$Services.ExportBacpac($OutputFile, $DatabaseName)
$Watch.Stop()
Write-Host "Backup completed in" $Watch.Elapsed.ToString()
Note: Using the assembly in this package: Microsoft.SqlServer.Dac 1.0.3 (I add it to the source control and map to build agent)
On the other hand, to add firewall rule, you can refer to this thread: Deploy Dacpac packages via power shell script to Azure SQL Server.
BTW, you can build the custom build/release step/task with these PowerShell scripts. Add a build task
Azure SQL Databases are continually backed up automatically. If you are trying to create a copy of the database or archive the database to a BACPAC file, you can do either.
https://learn.microsoft.com/en-us/azure/sql-database/sql-database-automated-backups
https://learn.microsoft.com/en-us/azure/sql-database/sql-database-copy
https://learn.microsoft.com/en-us/azure/sql-database/sql-database-export

How to run a Powershell Script block with elevated privileges

I am writing a PowerShell script to archive compressed C2 Audit files to a file share. What is possibly the last problem I am having is giving the .Net compression routine the privilege to manipulate the files. During development, I could flaunt my account's admin role to propagate Full Access privileges to the files in the DATA directory. However, the script is to run from a PowerShell step in an Agent job, and I want to automate the ACL change as well.
For an added level of difficulty, I am doing this under SQL Server 2012, so I am stuck with PowerShell 2.0. I am using .Net 4.5 compression routines via a process of loading $RunActivationConfigPath with a temporary config file. I was not able to find a way to change that config file to promote the admin role, though.
This is a segment of a script by Benjamin Armstrong that checks if the connection is using Administrator privileges.
# Get the ID and security principal of the current user account
$runtimeWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent();
$runtimeWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($runtimeWindowsID);
# Get the security principal for the administrator role
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator;
Write-Output ("Running under "+$runtimeWindowsID.Name)
Write-Output ("PS Version "+$PSVersionTable.PSVersion.Major)
# Check to see if we are currently running as an administrator
if ($runtimeWindowsPrincipal.IsInRole($adminRole) -eq $true) {
Write-Output "We are strong."
} else {
Write-Output "We are not strong."
}
Running the script as an Agent Job step produces:
Running under NT Service\SQLSERVERAGENT
PS Version 2
We are not strong.
Running the script from sqlps in Admin mode produces:
Running under DOMAIN\myusername
PS Version 2
We are strong.
All the ways I've seen to elevate a script involve using a script file. For example, creating a new process and executing it with RunAs as the Verb. I want to avoid script files and have everything in the step. I like the added security (however small) of needing SSMS privileges to view the code.
So, here are my questions:
1) Is there a way to elevate commands in a script block?
2) Is there a way to have the PowerShell step in an Agent Job run in Admin mode?
Extra credit question:
3) If I do need to add the Agent service account to a Windows User Group, which of the two dozen groups would give that account the minimum privileges needed to alter an ACL for a file, then eventually delete it?

Failed to connect to database server. How do I connect to a database that is not on my localhost using powershell and integrated security?

Background to my question
At any moment I am expecting the security people in black suits and black sun glasses to come and take me away because of all my sql server login attempts...
I used and adapted iris classon's example to connect to a database via Powershell. The adapted code uses Integrated Security=True"
$dataSource = my_enterprise_db_server
$database = my_db
$connectionString = "Server=$dataSource;Database=$database;Integrated Security=True;"
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$table = new-object “System.Data.DataTable”
$query = "..."
$connection.Open()
$command = $connection.CreateCommand()
$command.CommandText = $query
...
Hot diggity dog that worked. Thank's Iris.
I read the snapin verses the Import-Module sqlps way of executing a sql command. I also read all the links that Michael Sorens provided in his answer. I can mount a sqlserver connect with mount mydb SQLSERVER SQLSERVER:\SQL, use ls or dir, walk the path down the objects, etc. I also revised the main part of what Iris provided to
$table = Invoke-Sqlcmd –Server $dataSource –Database $database -Query $query
This version of Invoke-Sqlcmd allows me to connect to an "enterprise" database. The problem with all the references provided are that they expect you to work with a localhost sqlexpress database. The moment I try to use
Set-Location SQLSERVER:\SQL\my_enterprise_db_server\my_db
or similar constructs, I receive a message that ends with
...WARNING: Could not obtain SQL Server Service information. An attempt to connect to WMI on 'my_enterprise_db_server' failed with the following error: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
I also saw mention of the SQLCMDSERVER and SQLCMDDBNAME environment variables. I set these to
$env:SQLCMDDBNAME = "my_db"
$env:SQLCMDSERVER = "my_enterprise_db_server"
set-location sqlserver:\sql
ls
produces
MachineName
-----------
localhost
Question
How do I correctly use set-location or New-PSDrive-Name for a database that does not reside on my local computer?
I found the answer by a serendipitous route. I right clicked on a database object in sql server management studio. There was an option to start powershell. Even though this looks like the order sqlps option, SSMS gave me the right way to set the location.
Option 1. If the server does not have instances, then add DEFAULT after the server_name in the slashy path.
Set-Location SQLSERVER:\SQL\server_name\DEFAULT\Databases\database_name\Tables\dbo.table_name
Option 2. If you have a server with an instance, then set the instance name after the server_name in the slashy path.
Set-Location SQLSERVER:\SQL\server_name\instance_name\Databases\database_name\Tables\dbo.table_name
I am a mere mortal as far as database security goes. Many of the features of SSMS are turned off to me because of my security settings verses how the dba security settings are configured. I receive errors in in SSMS all the time. Well that is no different with Powershell using the Set-Location. I did not realize that the two error messages where related because of the security policy configuration verses pilot error. If I set a location to a table, then I only have two warnings of access denied. If I set the location to the database level, then Powershell blows chunks for a bit but I have my slashy path setting. I do not see the errors if I used the Invoke-SqlCmd. I see now that the way the security errors were presented in Powershell are why I thought there was a problem with how I was attempting to connect to the database. Now I can do this:
mount rb SELSERVER SQLSERVER:\SQL\server_name\DEFAULT\Databases\database_name\Tables
# Look at a list of tables.
ls
# Go to a traditional file system
cd F:\
# Go to the Linux Style mounted file system
cd rb:\
# Go to a table like a directory
cd dbo.my_table_name
# Look at the column names
ls
# Use relative navigation
cd ..\dbo.my_other_table_name
ls
# Compare column names with another table using relative navigation after I have just
# listed the current directory/table that I am in.
ls ..\dbo.my_table_name
That just rocks! Now all I need to do is come up with an array of server names and databases to create mount points for all the databases that I can connect to. An array like that is just begging for an iteration to create all the mount points.