Invoke-Sqlcmd with account that uses MFA in Azure - azure-sql-server

Anyone of you knows an option to execute a SQL command using PowerShell with Azure AD account that has MFA enabled? What is an alternative? Do I need to create a service principal for that?
I had no luck but only found this cmdlet,
Add-SqlAzureAuthenticationContext
but when I try to run Invoke-Sqlcmd I am getting the following error:
Invoke-Sqlcmd : The target principal name is incorrect. Cannot
generate SSPI context.

To connect to an azure database using AAD credential (mfa or not), you need to provide the -AccessToken parameter with a token of the authenticated user or service principal.
Take this for instance.
Connect to Azure SQL Database using an access token
# Obtain the Access Token: this will bring up the login dialog
Connect-AzAccount -TenantId 'Tenant where your server is'
#AZ Module
$AccessToken = (Get-AzAccessToken -ResourceUrl https://database.windows.net).Token
$SQLInfos = #{
ServerInstance = 'SERVERNAME.database.windows.net'
Database = 'DBNAME'
AccessToken = $AccessToken
}
Invoke-Sqlcmd #SQLInfos -Query 'select * from sys.tables'
If you don't need or want the manual credentials entry, you can make use of a service principal that is configured with proper access to the server / database and use this instead to obtain your token.
Using service principal client ID / secret to get the access token
$clientid = "enter application id that corresponds to the Service Principal" # Do not confuse with its display name
$tenantid = "enter the tenant ID of the Service Principal"
$secret = "enter the secret associated with the Service Principal"
$request = Invoke-RestMethod -Method POST `
-Uri "https://login.microsoftonline.com/$tenantid/oauth2/token"`
-Body #{ resource="https://database.windows.net/"; grant_type="client_credentials"; client_id=$clientid; client_secret=$secret }`
-ContentType "application/x-www-form-urlencoded"
$AccessToken = $request.access_token
References
MSdoc - Invoke-Sqlcmd
SecretManagement / SecretStore modules
(This second link is not directly related but if you go the Client ID / Secret route, consider storing your credentials in a secret vault rather than in your script directly.)

Not really an answer.
Tried the following
Add-SqlAzureAuthenticationContext -Interactive
$sql = 'SELECT ##SERVERNAME AS ServerName';
$ConnectionString = 'Data Source=tcp:azSERVER.database.windows.net,1433;Initial Catalog=DBNAME;Authentication="Active Directory Interactive";User ID=USERXX#DOMAINYY.COM'
Invoke-Sqlcmd -ConnectionString $ConnectionString -Query $sql -Verbose
and got
Invoke-Sqlcmd : One or more errors occurred.
At line:4 char:5
Please notice that I want to use the interactive flag,

Related

how to construct header for (REST API) azure storage SAS (shared accesss signature)

I am debugging a client application calling REST API embedded with AZURE storage SAS-shared access signature to access azure storage resource. However, it is not getting through. The azure threw out an error stating that the mandatory header is missing, and abort the operation.
The REST API is fairly simple, although it is embedded with the SAS token generated by the azure storage account. The client application uses the REST API to write data into an azure blob.
is there anywhere I can find a good example showing how to generate the header for the REST API (SAS)? I need to find out the exact layout of the header (such as the type of information that needs to be embedded in the header.
Also, do I need to register my client application with the Azure AD?
I didn't think my client application needs to be registered with the AZURE since that is why we have client-side SAS. But, I could be wrong. Therefore, any input will be appreciated.
Thanks in advance.
If you use sas token to call Azure blob rest api, the request URL should be like
https://myaccount.blob.core.windows.net/<cantianer>/<blob>?<sastoken>
For example
$accountName=""
$accountKey=""
$containerName="output"
$blobName="test.txt"
$context= New-AzStorageContext -StorageAccountName $accountName -StorageAccountKey $accountKey
$sas = New-AzStorageAccountSASToken -Service Blob -ResourceType Service,Container,Object -Permission "rwdlacx" -Context $context
$body = "Hello"
$headers=#{"x-ms-blob-type"="BlockBlob"; "Content-Type"="text/plain"}
$url="https://$accountName.blob.core.windows.net/$containerName/$blobName$sas"
Invoke-WebRequest -Uri $url -Method Put -Headers $headers -Body $body -UseBasicParsing

How to add an api key to the Credentials of Azure Automation Account?

I want to add an api key for my sendgrid account to Azure Automation account.
I did the search but no luck.
How should I do this? Thank you in advance!
You could add your api key in password and set a related username(it does not verify the connection between username and password) like below:
Usually we use get a credential with Get-AutomationPSCredential and get its username and password
$myCred = Get-AutomationPSCredential -Name 'MyCredential'
$userName = $myCred.UserName
$securePassword = $myCred.Password
$password = $myCred.GetNetworkCredential().Password
For now, you need only to get the password which is sendgrid api key.

Azure PowerShell Az module: generate bearer token for Databricks

I need to generate token for Databricks usage (it will be used to generate Databricks token)
In Azure CLI az account get-access-token --resource '2ff814a6-3304-4ab8-85cb-cd0e6f879c1d' --out tsv --query '[accessToken]' worked perfectly well
I know that there's no alternative in Azure PowerShell Az module so I did research and found the following:
$context = Get-AzContext
$profile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
$profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($profile)
$token = $profileClient.AcquireAccessToken($context.Subscription.TenantId)
$token.AccessToken
It does work, but generated token has https://management.core.windows.net/ claim instead of 2ff814a6-3304-4ab8-85cb-cd0e6f879c1d required for Databricks
Any ideas how to run alternative to az account get-access-token --resource '2ff814a6-3304-4ab8-85cb-cd0e6f879c1d' in Azure PowerShell with Az module?
I have service principal with certificate auth protected by password and can't use az cli / python /etc, just Azure PowerShell Az module
If you want to call Azure Databricks REST API with Azure Powershell, please refer to the following script
$teantId
$subId="the id of the subscription which contains the databrick"
Connect-AzAccount -Subscription $subId -Tenant $teantId
$context= Get-AzContext
$resource="2ff814a6-3304-4ab8-85cb-cd0e6f879c1d"
$token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account,
$context.Environment,
$context.Tenant.Id.ToString(),
$null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, $resource).AccessToken
$groupName="the databrick resource group name"
$workSpaceName="the databrick workspace name"
$headers=#{
"Authorization"= "Bearer " + $token;
"X-Databricks-Azure-Workspace-Resource-Id" = "/subscriptions/$($subId)/resourceGroups/$($groupName)/providers/Microsoft.Databricks/workspaces/$($workSpaceName)"
}
$databricksInstance="" # such as adb-976301816870846.6.azuredatabricks.net
$url="https://$($databricksInstance)/api/2.0/clusters/list"
$result=Invoke-RestMethod -Method Get -Uri $url -Headers $headers -ContentType "application/json" -UseBasicParsing
$result| ConvertTo-Json
For more details about how to call Azure Databricks REST API, please refer to the document

PowerShell send SMTP email without (default) authentication

I am attempting to deliver an email to an Exchange-server using PowerShell. My goal is to use plain old SMTP to deliver a message to a local user (mailbox) on the Exchange-server. The Exchange-server is located within the same network and AD-domain as the sending server and as the logged on sending user.
However the user I am sending from does not have access to send emails on that Exchange-server. And PowerShell seems to send authentication using the logged on user credentials by default.
$smtp = new-object Net.Mail.SmtpClient("exchangeserver.mylan")
$smtp.Send($emailFrom, $emailTo, $subject, $message)
I have tried to add $smtp.UseDefaultCredentials = $false before the $smtp.Send(... line without success.
One solution would be to allow this user to send messages on the Exchange server. However the user will change depending on what service is running this script, so I don't want to solve it that way.
Another solution would be to hardcode credentials using something like $smtp.Credentials = New-Object System.Net.NetworkCredential("DOMAIN\user", "password") (also before $smtp.Send(... line). I've had no luck in this either.
The solution I'd really like is to just send email in PowerShell anonymously using good old auth free SMTP.
1) Create new Receive Connector
2) Enable anonymous authentication on it
3) Lock it down to IP address of the computer you are running the script on
I realize this is old, but I'm surprised there isn't an answer here for this. I was confused initially because I have some similar code I wrote in C# and it works just fine. It seems PowerShell will default to using someone's credentials. I won't assume it's who runs the script, but it could be.
When I'm building up the credential object, I pass in a space for the username and password and that seems to work fine.
$credential = New-Object System.Management.Automation.PSCredential (" ", " ")
If I completely leave out the credential part then it will use someone's credentials or something. Until now I was getting the following message:
The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.1 Client was not authenticated
I hope this helps someone with such an odd problem.

LDAP Authentication using CGI+TCL

How can I authenticate a user with LDAP using CGI/TCL stack?
Please provide a sample code-snippet if possible.
I am using an Apache Web Server on RHEL 5.0; AD exists on a remote Win2003 server.
Here is an example that will connect to an ldap server and retrieve all of the info ldap has about an email address:
package require ldap
set sEmailAddress "user#example.com"
set handle [::ldap::connect example.com 3268]
ldap::bind $handle
set result [::ldap::search $handle "dc=example,dc=com" "(mail=$sEmailAddress)" {sAMAccountName}]
foreach {object attributes} $result {
foreach {name val} $attributes {
puts "$name\t$val"
}
}
Here's the ldap package. You first bind using some "bind user" who can see everyone. You then search for the user based on some attribute like e-mail address or sAMAccountName. If the user exists, bind again using the given password and the full path of the user.