Connect an Azure App Registration to Azure SQL Database via Powershell - powershell

Need a Powershell script to run on-prem that will login into an Azure SQL database as an Azure AD App Registration. I am able to acquire an access token for the App Registration, but I get an error when I attempt to login to the database with it:
Exception calling "Open" with "0" argument(s): "Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'."
I have created the user and applied grants inside the target database.
CREATE USER [App Reg Dave Test] FROM EXTERNAL PROVIDER;
ALTER ROLE [db_datareader] ADD MEMBER [App Reg Dave Test];
ALTER ROLE [db_datawriter] ADD MEMBER [App Reg Dave Test];
I'm not sure it's necessary, but I have also granted api permissions to the App registration for SQL Database User_Impersonation and App_Impersonation. Here is a sample of my PS code. It's failing on the $connection.open() command.
#-- Intall ADAL.ps
# Import-Module ADAL.PS
#-----------------------------------
#-- Get Token for App Registration
#-----------------------------------
$tenantId = "448b9f7b-9e69-xxxx-xxxx-xxxxxxxxxxxx"
$authority = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/authorize"
$resourceUrl = "api://123a7216-7b20-yyyy-yyyy-yyyyyyyyyyyy"
$clientId = "123a7216-7b20-yyyy-yyyy-yyyyyyyyyyyy"
$secret = ConvertTo-SecureString -String "X87ZK#NPw=zzzzzzzzzzzzzzzzzzzx/-" -AsPlainText -Force
$response = Get-ADALToken -Authority $authority -Resource $resourceUrl -ClientId $clientId -ClientSecret $secret
$token = $response.AccessToken
#-----------------------------------
#-- Connect to DB
#-----------------------------------
$sqlServerUrl = "dave-sqls2.database.windows.net"
$database = "advworks"
$connectionString = "Server=tcp:$sqlServerUrl,1433;Initial Catalog=$database;Persist Security Info=False;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;"
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
# Add AAD generated token to SQL connection token
$connection.AccessToken = $response.AccessToken
$connection #-- Output connection object for debugging.
$query = "SELECT ##Servername, ##Version"
$command = New-Object -Type System.Data.SqlClient.SqlCommand($query, $connection)
$connection.Open()
$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataSet) | Out-Null
$connection.Close()
$dataSet.Tables

According to the PowerShell script you provide, you use the wrong resourceUrl. Please update the resource url as https://database.windows.net/. For more details, please refer to the blog.
The detailed steps are as below.
1. Create service principal
$SecureStringPassword = ConvertTo-SecureString -String "[Enter SPN Password]" -AsPlainText -Force
New-AzureRmADApplication -DisplayName "[Enter name for Application]" -HomePage "https://www.contoso.com/sqldb-spn" -IdentifierUris "https://www.contoso.com/sqldb-spn" -Password $SecureStringPassword -OutVariable app
New-AzureRmADServicePrincipal -ApplicationId $app.ApplicationId
Use Azure AD admin to login Azure SQL via SSMS. Then run the following command
CREATE USER [your app name] FROM EXTERNAL PROVIDER;
ALTER ROLE [db_datareader] ADD MEMBER [App Reg Dave Test];
ALTER ROLE [db_datawriter] ADD MEMBER [App Reg Dave Test];
Get Access token
$tenantId = "your tenant id"
$authority = "https://login.microsoftonline.com/$tenantId/oauth2/authorize"
$resourceUrl = "https://database.windows.net/"
$clientId = "your application id"
$secret=ConvertTo-SecureString "" -AsPlainText -Force
$response = Get-ADALToken -Authority $authority -Resource $resourceUrl -ClientId $clientId -ClientSecret $secret
$token = $response.AccessToken
4 Connect SQL
$sqlServerUrl = "<your server name>.database.windows.net"
$database = "master"
$connectionString = "Server=tcp:$sqlServerUrl,1433;Initial Catalog=$database;Connect Timeout=30"
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
$connection.AccessToken = $response.AccessToken
$connection.Open()
$query="SELECT name, database_id, create_date FROM sys.databases ; "
$command = New-Object -TypeName System.Data.SqlClient.SqlCommand($query, $connection)
$Result = $command.ExecuteScalar()
$Result
$connection.Close()

Related

while execute a powershell using service account getting unknown_user_type error

I have one simple powershell script where i'm authorizing salesforce logic app connector.
When i execute script using service account credentials I'm getting below error -
Connect-AzureRmAccount : unknown_user_type: Unknown User Type
At C:\Users\test.ps1:34 char:5
+ Connect-AzureRmAccount -Credential $pscredential -Tenant $Tenant ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Connect-AzureRmAccount], AadAuthenticationFailedException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand
what is going wrong here any clue?
i'm executing below script to authorize salesforce connector api connection into azure logic app
Param(
[string] $ResourceGroupName = 'ResourceGroupName',
[string] $Subscription = 'Subscription',
[string] $ConnectionName = 'ConnectionName',
#Defines which Authorization type to authenticate the connector with.
#AuthorizationTypes: 'ServiceAccount', 'ServicePrincipal'
[string] $AuthorizationType = 'ServiceAccount'
)
#region mini window, made by Scripting Guy Blog
Function Show-OAuthWindow {
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object -TypeName System.Windows.Forms.Form -Property #{Width=600;Height=800}
$web = New-Object -TypeName System.Windows.Forms.WebBrowser -Property #{Width=580;Height=780;Url=($url -f ($Scope -join "%20")) }
$DocComp = {
$Global:uri = $web.Url.AbsoluteUri
if ($Global:Uri -match "error=[^&]*|code=[^&]*") {$form.Close() }
}
$web.ScriptErrorsSuppressed = $true
$web.Add_DocumentCompleted($DocComp)
$form.Controls.Add($web)
$form.Add_Shown({$form.Activate()})
$form.ShowDialog() | Out-Null
}
#endregion
$pscredential = Get-Credential
#You should not need to change this Id
$Tenant = Get-AzureRmTenant -TenantId "TenantId"
if ($AuthorizationType -eq 'ServiceAccount') {
Connect-AzureRmAccount -Credential $pscredential -Tenant $Tenant -Subscription $Subscription
}
elseif ($AuthorizationType -eq 'ServicePrincipal') {
Connect-AzureRmAccount -ServicePrincipal -Credential $pscredential -Tenant $Tenant -Subscription $Subscription
}
As mentioned in the comment, I suppose you want to login with a service principal, I can also reproduce your issue.
If you want to login with a service principal, you need to pass the -ServicePrincipal parameter.
You could refer to the complete script below.
$azureAplicationId ="<applicationId>"
$azureTenantId= "<TenantId>"
$azurePassword = ConvertTo-SecureString "<client-secret>" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
Besides, I notice you use the old AzureRm module command Connect-AzureRmAccount. You should note the AzureRm module was deprecated and will not be updated anymore, so I recommend you to uninstall it and install the new Az module. If you still want to use the old module, just change Connect-AzAccount to Connect-AzureRmAccount in my script.

add permissions to Azure RM AD application via powershell

I can create a new Azure RM AD application like so:
New-AzureRmADApplication -DisplayName "xxx" -HomePage "xxx" -IdentifierUris "xxx" -ReplyUrl "xxx"
I am trying to add application permission to this, so that the app will be created with my specified permissions. The permission I want looks like this in the manifest:
"requiredResourceAccess": [
{
"resourceAppId": "00000002-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "311a71cc-e848-46a1-bdf8-97ff7156d8e6",
"type": "Scope"
}
]
}
]
This is a permission for Windows Azure Active Directory - Delegated - Sign in and read user profile.
Is there some way I can add this during of after creating my AD app via powershell?
Try the command below, change the ObjectId , it works fine on my side.
$req = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$req.ResourceAccess = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "311a71cc-e848-46a1-bdf8-97ff7156d8e6","Scope"
$req.ResourceAppId = "00000002-0000-0000-c000-000000000000"
Set-AzureADApplication -ObjectId <ObjectId> -RequiredResourceAccess $req
The screenshot of Manifest :
You can also create an AAD app with given permission. Then you need New-AzureADApplication from AzureAD module. The code snippet is like:
$SiteUri = "https://example.com/"
$displayName = $SiteUri.Host
[string[]]$replyUrl = $SiteUri.AbsoluteUri + ".auth/login/aad/callback"
$reqAAD = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
# This is "Windows Azure Active Directory".
$reqAAD.ResourceAppId = "00000002-0000-0000-c000-000000000000"
# This is to "Sign you in and read your profile"
$permission = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "311a71cc-e848-46a1-bdf8-97ff7156d8e6","Scope"
$reqAAD.ResourceAccess = $permission
New-AzureADApplication -DisplayName $displayName -IdentifierUris $SiteUri -Homepage $SiteUri -ReplyUrls $replyUrl -RequiredResourceAccess $reqAAD
For more details, you can read https://blogs.msdn.microsoft.com/azuregov/2017/12/06/web-app-easy-auth-configuration-using-powershell/

Create Azure AD B2C local account user with Powershell New-AzureADUser

I'm trying to create a local user in an Azure AD B2C directory which can be used for authentication immediately after creation.
Connect-AzureAD -TenantId $targetB2cTenant
$passwordProfile = New-Object -TypeName Microsoft.Open.AzureAD.Model.PasswordProfile
$passwordProfile.Password = "Test-User-Password-Here"
$userName = "TestUser#MyTestB2CTenant.onmicrosoft.com"
$signInNames = #(
(New-Object `
Microsoft.Open.AzureAD.Model.SignInName `
-Property #{Type = "userName"; Value = $userName})
)
$newUser = New-AzureADUser -AccountEnabled $True -DisplayName "testpowershellusercreation" -PasswordProfile $passwordProfile -SignInNames $signInNames -CreationType "LocalAccount"
Disconnect-AzureAD
From reading the documentation I need to specify the CreationType parameter as "LocalAccount":
https://learn.microsoft.com/en-us/powershell/module/azuread/new-azureaduser?view=azureadps-2.0
Creating a B2C user with MFA that can immediately login
However when I run the powershell code I receive the following error:
New-AzureADUser : Error occurred while executing NewUser
Code: Request_BadRequest
Message: One or more properties contains invalid values.
This error message is not present when I remove the -CreationType parameter.
What is the correct way to create a local account in a B2C directory using Powershell?
A sign-in name of type "userName" can't contain the '#' character in the value property.
i.e. You can't set it to an email address.
You might want to also set the following parameters for the new user:
$passwordProfile = New-Object -TypeName Microsoft.Open.AzureAD.Model.PasswordProfile
$passwordProfile.ForceChangePasswordNextLogin = $False
$passwordProfile.Password = "<Password>"
$newUser = New-AzureADUser ... -PasswordPolicies "DisablePasswordExpiration"
I think you could also change the type of sign-in name from "userName" to "email", to work around this issue and allow users to continue using their foreign domain email addresses as login, if required.
$signInNames = (
(New-Object `
Microsoft.Open.AzureAD.Model.SignInName `
-Property #{Type = "email"; Value = "pstesta#fsdfsd.com"})
)

How to connect Azure Paas Database using Powershell with intergrated security

How can I connect to an Azure SQLDatabase (Paas Instance) using Powershell without a username & password but rather with Active Directory. I can connect with a username and password when I use invoke-sqlcmd as below
$Servername = "XXXXXX.database.windows.net"
$params = #{
Database = $databasename
ServerInstance = $ServerName
Username = $UserName
Password = $password
'OutputSqlErrors' = $true
Query = $QueryString
}
Invoke-Sqlcmd #params
I need the ability to do it with Active Directory. I have read a few articles on how to connect with active directory as long as you specify it on the connection string (Context of C#) Using ODBC connection or other data sources. Since Powershell is based on .Net; this should be do-able..
$ConnString = "DRIVER=ODBC Driver 13 for SQL Server;SERVER=xxxxx.database.windows.net;DATABASE=DBName;Trusted_Connection=Yes"
$Conn = new-object System.Data.Odbc.OdbcConnection($ConnString)
$conn.open()
$cmd = new-object System.Data.Odbc.OdbcCommand("select getdate() as X", $Conn)
$data = new-object System.Data.Odbc.OdbcDataAdapter($cmd)
$dt = new-object System.Data.DataColumn
$data.Fill($dt)
$Conn.Close()
#`server=Server;database=Database;Authentication=ActiveDirectoryIntegrated;`
The objective of trying to use Active Directory is that, within Paas, only AD Accounts can Add other AD accounts. I want to be able to add other accounts with method rather than logging in the Azure portal and adding an AD account manually.
You could use Azure AD account to login Azure SQL database(Paas) by using Azure Active Directory Authentication. More information please refer to this link.
Note: Local domian AD user does not support this.
You could use following script to login with Azure AD authentication.
#You admin Azure AD user name
$Username = "shuitest#*****.onmicrosoft.com"
$Password = "********"
$Database = "testg"
$Server = 'test.database.windows.net'
$Port = 1433
$cxnString = "Server=tcp:$Server,$Port;Database=$Database;Authentication=Active Directory Password;UID=$UserName;PWD=$Password;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;"
$query = "select count(*) from dbo.Authors"
$cxn = New-Object System.Data.SqlClient.SqlConnection($cxnString)
$cxn.Open()
$cmd = New-Object System.Data.SqlClient.SqlCommand($query, $cxn)
$cmd.CommandTimeout = 120
$cmd.ExecuteNonQuery()
$cxn.Close()
The following sample shows how to invoke Add-AzureAccount without the popup dialog:
$username = "someorgid#orgaccount.com"
$password = "Pa$$w0rd" | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password
Add-AzureAccount -Credential $credential
AAD does not / can not parse Kerbs tokens. In order to get integrated auth to work from your desktop, you need to have ADFS (or similar) in your environment. That way your desktop will authenticate against AAD, redirect to ADFS, and your kerbs token will be recognized.
See https://learn.microsoft.com/en-us/azure/sql-database/sql-database-aad-authentication for more information.
this now works for me in the connection string instead of user and pass
Authentication=Active Directory Integrated;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;
Depending on your query you might have to use $cmd.ExecuteScalar() instead of $cmd.ExecuteNonQuery() for example
$query = 'select ##version'
$cxn = New-Object System.Data.SqlClient.SqlConnection($cxnString)
$cxn.Open()
$cmd = New-Object System.Data.SqlClient.SqlCommand($query, $cxn)
$cmd.CommandTimeout = 120
$cmd.ExecuteScalar()
$cxn.Close()

Login-AzureRmAccount wont log in using PSCredential

I am writing a PowerShell script to be able to access my Azure account. From the PowerShell command line, I can type Login-AzureRmAccount, manually enter my login information, and details of my account then display in the terminal inside PowerShell. However, if I try to make the script do the same thing, I get the following error:
And here is my code. Commented out is other ways i have tried so far.
# Credential Section
$azureAccountName ='login info here'
$azurePassword = ConvertTo-SecureString 'pass here' -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAccountName, $azurePassword)
Login-AzureRmAccount -Credential $psCred
#$tenantId = "tenant id here"
#$login = "login info here"
#$login1 = 'login info here'
#$pass1 = 'pass here'
#Create Credentials
#$pass = ConvertTo-SecureString 'pass here' -AsPlainText –Force
#$cred = New-Object -TypeName pscredential –ArgumentList $login1, $pass1
#Automate Future Logins
#Login-AzureRmAccount -Credential $psCred #-ServicePrincipal –TenantId $tenantId
$Subscription = Select-AzureSubscription -Default -SubscriptionName "sub info here"
$StorageAccountName = Get-AzureStorageAccount –StorageAccountName "account name here"
$StorageAccountKey = (Get-AzureStorageKey -StorageAccountName $StorageAccountName).Primary
$context = New-AzureStorageContext $StorageAccountName -StorageAccountKey $StorageAccountKey -SubscriptionName $Subscription
Write-Output $context
I entered the login and pass manually when i typed Login-AzureRmAccount into the terminal but the script doing the same thing would not login. Any thoughts?
If you are using a microsoft account like - outlook/hotmail account, it is bound to throw errors like the above. This is how Azure AD is designed. Please use any org account or create your own Azure AD and use the user credentials of that Azure AD to login using the "Login-AzureRMAccount".
These commands work for me
# Credential Section
$azureAccountName ="aaa#edmistorm.onmicrosoft.com"
$azurePassword = ConvertTo-SecureString "aaaaaabbb" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAccountName, $azurePassword)
Login-AzureRmAccount -Credential $psCred
$Subscription = Select-AzureSubscription -SubscriptionId 6f1ac837-2c76-4fd2-b6ce-8b991a0dec0ad
You may want to follow this thread as well
https://github.com/Azure/azure-powershell/issues/1309