How do I connect to Azure through PowerShell Modules, using the Service principal of a Registered App? - azure

I need to create a powershell script that queries Azure Resources.
What I have is an App Registration.
App Registrations give us the following information:
# --- APP REGISTRATION OUTPUT
# appId = "***** APP ID *******"
# displayName = "**** APP Name **** "
# password = "***** SECRET *******"
# tenant = "**** TENANT ID *****"
I need to use these credentials to now access Azure via PowerShell script.
I have tried the following:
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ApplicationId, $SecuredPassword
Connect-AzAccount -ServicePrincipal -TenantId $TenantId -Credential $Credential
But I get an error:
… Account -ServicePrincipal -TenantId $TenantId -Credential $Credential
| ~~~~~~~~~~~
| Cannot bind argument to parameter 'Credential' because it is null.
I don't think what Im doing is abnormal. App Registrations give us the ability to allow Apps (PowerShell Apps!) to interact with a given tenant. Or am I mistaken?
I don't want the app to login every time using an account (i.e. To have a browser window open whenever the script runs).
What am I doing wrong?

You have missed converting your password into secure string. You could verify that in your $credential variable.
$ApplicationId = "0000-0000-0000-0000"
$Password = "000000000000000"
$TenantId = "0000-0000-000-000"
$subscriptionId = "0000-0000-0000-0000"
$SecuredPassword = ConvertTo-SecureString -AsPlainText $Password -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ApplicationId, $SecuredPassword
Connect-AzAccount -ServicePrincipal -TenantId $TenantId -Credential $Credential
$sub = Get-AzSubscription -SubscriptionId $subscriptionId
Set-AzContext -Subscription $sub

I have reproduced in my environment and below script worked for me :
$appId ="53f3ed85-70c1c2d4aeac"
$pswd="55z8Q~_N9SRajza8R"
$t = "72f988bf-cd011db47"
[ValidateNotNullOrEmpty()]$pswd="55z8BU4oik.kVrZWyaK8R" $sp = ConvertTo-SecureString -String $pswd -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $appId, $sp
Connect-AzAccount -ServicePrincipal -TenantId $t -Credential $Credential
Output:
You need to convert the secret value(password) into secured password like above, then it will work as mine worked.

Related

PowerShell - How do I bulk upload Certificates to an Azure App Registration Certificate store?

As you can see from the code below I can upload on certificate at a time, but the problem is it wipes out all of the existing certificates when doing so.
$Tenant_ID = '00000000-0000-0000-0000-000000000000'
$Subscription_ID = '00000000-0000-0000-0000-000000000000'
$Azure_PassWord = (Get-StoredCredential -Target 'Domain' -Type Generic -AsCredentialObject).Password
$UserName = "$($env:USERNAME)#Google.com"
$EncryptedPassword = ConvertTo-SecureString $Azure_PassWord -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PsCredential($UserName,$EncryptedPassword)
$AzureConnection = (Connect-AzAccount -Credential $Credential -Tenant $Tenant_ID -Subscription $Subscription_ID -WarningAction 'Ignore').context
$AzureContext = (Set-AzContext -SubscriptionName $Subscription_ID -DefaultProfile $AzureConnection)
$Application_ID = '00000000-0000-0000-0000-000000000000'
$PFX_FileName = "Azure_Dev_V2"
$Cert_Password = "123456"
$Cert_Password = ConvertTo-SecureString -String $Cert_Password -Force -AsPlainText
$CurrentDate = Get-Date
$EndDate = $CurrentDate.AddYears(10)
$certificatePath = "C:\FilePath\Certificates\Certs\$($PFX_FileName).pfx" # OR Get-ChildItem -Path cert:\localmachine\my\$($Certificate_Thumbprint)
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2($certificatePath, $Cert_Password)
$keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())
$Azure_App_Registration = Get-AzADApplication -ApplicationId $Application_ID -DefaultProfile $AzureContext
New-AzADAppCredential -ApplicationObject $Azure_App_Registration -CertValue $keyValue -EndDate $EndDate -StartDate $CurrentDate
Connect-AzAccount -Subscription $Subscription_ID -ApplicationId $Azure_App_Registration.AppId -Tenant $Tenant_ID -CertificateThumbprint $cert.Thumbprint | Out-Null
Get-AzADAppCredential -ApplicationId $Azure_App_Registration.AppId | Where-Object {$_.DisplayName -match "CN=Azure_Dev_V2"}
In the Azure portal multiple certificates can be uploaded manually, and they will not delete the existing certificates.
EDIT: If bulk upload is not possible then how would I go about making sure the existing certificates that are in the Azure AD App Registration cert store do not get deleted ?
Thanks in Advance.

Connect-AzureAD : parsing_wstrust_response_failed: Parsing WS-Trust response failed

I am getting the following below error when every time i run my script to connect to Azure Ad via Powershell
Connect-AzureAD : One or more errors occurred.: parsing_wstrust_response_failed: Parsing WS-Trust response failed
At C:\Azure-AD\Azure-Connect.ps1:10 char:1
+ Connect-AzureAD -TenantId $TenantId -credential $MyCredential
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : AuthenticationError: (:) [Connect-AzureAD], AadAuthenticationFailedException
+ FullyQualifiedErrorId : Connect-AzureAD,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD
Below is the script i have created
$TenantId = ""
$SecFile = "C:\Azure-AD\Password.txt"
$SecUser = "C:\Azure-AD\UserName.txt"
$MyCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SecUser,
(Get-Content $SecFile | ConvertTo-SecureString)
Connect-AzureAD -TenantId $TenantId-credential $MyCredential
I am using the following line to generate to encrypt my password
(Get-Credential).Password | ConvertFrom-SecureString | Out-File "C:\AzureAD\Password.txt"
Any solutions on how I can fix the errors and connect to Azure Ad via Powershell
I have tested in my environment.
Please use the below script :
$tenantID = ""
$secfile = "C:\Azure-AD\Password.txt";
$secuser = "C:\Azure-AD\UserName.txt";
$username = Get-Content $secuser;
$password = Get-Content $secfile | ConvertTo-SecureString -AsPlainText -Force;
$MyCredential = New-Object Management.Automation.PSCredential ($username, $password);
Connect-AzureAD -TenantId $tenantID -credential $MyCredential

Download parquet file from ADL Gen2 using Get-AzureStorageBlobContent

I am trying below powershell command to download parquet file from ADL Gen 2 to local system.
Below is the code snippet
#this appid has access to ADL
[string] $AppID = "bbb88818-aaaa-44fb-q2345678901y"
[string] $TenantId = "ttt88888-xxxx-yyyy-q2345678901y"
[string] $SubscriptionName = "Sub Sample"
[string] $LocalTargetFilePathName = "D:\MoveToModern"
Write-Host "AppID = " $AppID
Write-Host "TenantId = " $TenantId
Write-Host "SubscriptionName = " $SubscriptionName
Write-Host "AzureDataLakeAccountName = " AzureDataLakeAccountName
Write-Host "AzureDataLakeSrcFilePath = " $AzureDataLakeSrcFilePath
Write-Host "LocalTargetFilePathName = " $LocalTargetFilePathName
#this is the access key of the appid
$AccessKeyValue = "1234567=u-r.testabcdefaORYsw5AN5"
$azurePassword = ConvertTo-SecureString $AccessKeyValue -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($AppID, $azurePassword)
Login-AzureRmAccount -Credential $psCred -ServicePrincipal -Tenant $TenantId
Get-AzureRmSubscription
Get-AzureRmSubscription -SubscriptionName $SubscriptionName | Set-AzureRmContext
Get-AzureStorageBlobContent -Container "/Test/Partner/Account/" -Blob "Account.parquet" -Destination "D:\MoveToModern"
But I am getting below error
May be we have to set the storage context. Can you please let me know how to set the storage context with the service principal. (I have app id & app key of service principal. W.r.t ADL Gen2 source, I just have the path details. Source team has provided access to service principal)
If you want to download files from Azure Data Lake Gen2, I suggest you use PowerShell module Az.Storage. Meanwhile, regarding how to implement it with a service principal, you have two choices.
1. Use Azure RABC Role
If you use Azure RABC Role, you need to assign the special role(Storage Blob Data Reader) to the sp.
For example
$AppID = ""
$AccessKeyValue = ""
$TenantId=""
$SubscriptionName = ""
#1. Assign role at the storage account level
#please use owner account to login
Connect-AzAccount -Tenant $TenantId -Subscription $SubscriptionName
New-AzRoleAssignment -ApplicationId $AppID -RoleDefinitionName "Storage Blob Data Reader" `
-Scope "/subscriptions/<subscription>/resourceGroups/<resource-group>/providers/Microsoft.Storage/storageAccounts/<storage-account>"
# download
$azurePassword = ConvertTo-SecureString $AccessKeyValue -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($AppID, $azurePassword)
Connect-AzAccount -Credential $psCred -ServicePrincipal -Tenant $TenantId -Subscription $SubscriptionName
$AzureDataLakeAccountName = "testadls05"
$ctx =New-AzStorageContext -StorageAccountName $AzureDataLakeAccountName -UseConnectedAccount
$LocalTargetFilePathName = "D:\test.parquet"
$filesystemName="test"
$path="2020/10/28/test.parquet"
Get-AzDataLakeGen2ItemContent -Context $ctx -FileSystem $filesystemName -Path $path -Destination $LocalTargetFilePathName
Use Access control lists
If you use the method, to grant a security principal read access to a file, you'll need to give the security principal Execute permissions to the container, and to each folder in the hierarchy of folders that lead to the file.
For example
$AppID = ""
$AccessKeyValue = ""
$TenantId=""
$azurePassword = ConvertTo-SecureString $AccessKeyValue -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($AppID, $azurePassword)
Connect-AzAccount -Credential $psCred -ServicePrincipal -Tenant $TenantId
$AzureDataLakeAccountName = "testadls05"
$ctx =New-AzStorageContext -StorageAccountName $AzureDataLakeAccountName -UseConnectedAccount
$filesystemName="test"
$path="2020/10/28/test.parquet"
$LocalTargetFilePathName = "D:\test1.parquet"
Get-AzDataLakeGen2ItemContent -Context $ctx -FileSystem $filesystemName -Path $path -Destination $LocalTargetFilePathName
For more details, please refer to
https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-access-control
https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-access-control-model
https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-directory-file-acl-powershell

Azure Analytics Database with automate Backup

The powershell is used to automate the backup of AAS instance.
The instance have Multi-factor authentication and I think that is the problem.
Powershell:
$TenantId = "TenentID"
$Cred = Get-AutomationPSCredential -Name 'SSASModelBackup'
$Server = "ServerName"
$RolloutEnvironment = "location.asazure.windows.net"
$ResourceGroup = "ReourceGroupName"
#Create Credentials to convertToSecureString
$applicationId = "applicationId "
$securePassword = "securePassword " | ConvertTo-SecureString -AsPlainText -Force $Credential = New-Object
-TypeName System.Management.Automation.PSCredential -ArgumentList $applicationId, $securePassword
#Define the list of AAS databases
$asDBs = #('database1','database2')
Write-Output "Logging in to Azure..."
#Add-AzureAnalysisServicesAccount -Credential $Credential -ServicePrincipal -TenantId $TenantId -RolloutEnvironment $RolloutEnvironment
ForEach($db in $asDBs)
{
Write-Output "Starting Backup..."
Backup-ASDatabase `
–backupfile ($db +"." + (Get-Date).ToString("ddMMyyyy") + ".abf") `
–name $db `
-server $Server `
-Credential $Cred
Write-Output "Backup Completed!"
}
You are correct that the issue is with multi-factor authentication. Since the point of multi-factor is the require interaction with a secondary source like your phone there is no way to automate the process.
I would suggest that you look into using service principle authentication for the purpose of taking backups. By using a service principle to your server you can allow for automated tasks to run without 2-factor while minimizing the security risk.

Authenticated with "Login-AzureRmAccount -ServicePrincipal" but no subscription is set?

I've successfully created a self-signed certificate with application & service principle using the New-AzureRmADApplication and New-AzureRmADServicePrincipal cmdlets.
I can execute the login using this command after retrieving the certificate:
Login-AzureRmAccount -ServicePrincipal -CertificateThumbprint $cert.Thumbprint -TenantId $tenantID -ApplicationId $applicationID
However, the SubscriptionId/SubscriptionName attributes of this authentication display as blank:
Environment : AzureCloud
Account : ********************
TenantId : ********************
SubscriptionId :
SubscriptionName :
CurrentStorageAccount :
Subsquently, this command works!
$secret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $keyName
What is confusing to me is that I am able to retrieve a AzureKeyVaultSecret in my DEV subscription, but I do not understand how this cmdlet knows which of my subscriptions to use??? I intend to create the same vault in my PROD subscription, but first need to understand how this ServicePrincipal/Certificate authentication knows which subscription to pull from and/or how to manipulate it?
I can say that when I created the App/ServicePrincipal, I logged in specifying the "DEV" subscription like so:
$subscriptionName = "DEV"
$user = "user#company.com"
$password = "*****"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($user, $securePassword)
Login-AzureRmAccount -Credential $credential -SubscriptionName $subscriptionName

Resources