Azure Function calling a Powershell script and unattended login - powershell

I'm creating an Azure Function that will call a PowerShell script. In order to do this I need to have the PS script do an unattended login. So I created an application and Service Principal as follows:
# Create an Azure Active Directory Application that will be used for authentication in Powershell Automation scripts.
$Password = ConvertTo-SecureString '<MyPassword>' -AsPlainText -Force
$AzureAdApplication = New-AzureRmADApplication -DisplayName "PowerShellAdminApp" -Password $Password -HomePage "https://www.phoenix.com" -IdentifierUris "https://www.phoenix.com"
# Create the Service Principal
New-AzureRmADServicePrincipal -ApplicationId $AzureAdApplication.ApplicationId
# Add permissions to the Server Principal
New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $AzureAdApplication.ApplicationId.Guid
This all works correctly.
Then, in my PS script(s), I will log in, unattended, as follows:
$Username = "https://www.phoenix.com"
$Password = ConvertTo-SecureString "<MyPassword>" -AsPlainText -Force
$Credential = new-object -typename System.Management.Automation.PSCredential -argumentlist $Username, $Password
Login-AzureRmAccount -ServicePrincipal -Credential $Credential -TenantId '<MyTenantId'
This works as well. However, I feel like I'm not understanding something or I'm missing something. This is not at all secure. If I have to have this login code in all my PS scripts, I'm basically letting anyone who has access to these scripts see the tenant Id and the password to the app. They then could perform any activity the app can perform.
Am I doing this correctly or not understanding something?

You can use App Settings to define environment variables and store passwords there and in your code just read them:
$username = $env:username
$password = ConvertTo-SecureString $env:password -AsPlainText -Force
Here's how to configure that. https://learn.microsoft.com/en-us/azure/azure-functions/functions-how-to-use-azure-function-app-settings

Related

Receive "must call the Connect-AzureAD" even I run it before

My problem
I try to run Get-AzureADGroup connected with an App Registration, but get this error message:
Get-AzureADGroup : You must call the Connect-AzureAD cmdlet before
calling any other cmdlets.
But what I am running is:
$secPasswd = ConvertTo-SecureString $secret -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential($appId , $secpasswd)
Connect-AzAccount -Credential $cred -ServicePrincipal -Tenant $tenantId
$gpe = Get-AzureADGroup -SearchString "group1"
Connect-AzAccount is run, so I don't understand this error message.
My execution context
I just created an App Registration and a secret to connect with.
What I need
Why do I get this message since I run Connect-AzureD?
What should I do?
Thanks
Comments are helpful.
Get-AzureADGroup is under Azure AD module while Connect-AzAccount is under Az.Accounts module. They are different.
To run Get-AzureADGroup, you need to sign in with Connect-AzureAD which is the login command in Azure AD module.
If you don't want to install Azure AD module, you can choose to use Get-AzADGroup instead of Get-AzureADGroup.

Pick an account after Connect-MicrosoftTeams

I'd like to write a PowerShell script which will update Teams members from input list/object. However if I run Connect-MicrosoftTeams command (to authenticate/connect to cloud service) for the first time I am asked to pick an account to use for login. This is an issue since I would like this script to be run as scheduled job. Is there a way how to avoid this when running Connect-MicrosoftTeams command ? Commands I am using:
$credential = Get-Credential
Connect-MicrosoftTeams -Credential $credential
I tried to use "-AccountId "email#address.com" but that didn't help. Of course later I will change Get-Credential to username and encrypted password
EDIT
If I run Connect-MicrosoftTeams -Credential $credential on other computer, where I've never been logged in with my account, instead of "Pick an account" window, I get credential window for username and password:
As commented, this is certainly a dissapointment, but Single-Sign-On cannot be enabled in Microsoft Teams.
See the discussion here
This should achieve what you're trying to do.
Credits to: https://www.jaapbrasser.com/quickly-and-securely-storing-your-credentials-powershell/
Save Credentials
$Credential = Get-Credential
$Credential | Export-CliXml -Path "<File path/name to save credentials"
Connect using saved credentials through MS Teams PowerShell
$Credential = Import-CliXml -Path "<path of exported credential>"
Connect-MicrosoftTeams -AccountId "<email>" -Credential $Credential
For that I always use this from Jaap Brasser:
https://www.jaapbrasser.com/quickly-and-securely-storing-your-credentials-powershell/
At the end I used other module 'AzureAD' and command 'Add-AzureADGroupMember':
# 'password' | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString $Password = "01000000d08c9..." | ConvertTo-SecureString
$Credentials = (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "user#domain.com", $Password)
Connect-AzureAD -Credential $Credentials
$AZ_USER=Get-AzureADUser -Filter "UserPrincipalName eq 'user#domain.com'"
$AZ_GROUP=Get-AzureADGroup -Filter "DisplayName eq 'teams_name'"
Add-AzureADGroupMember -ObjectId $AZ_GROUP.ObjectId -RefObjectId $AZ_USER.ObjectId
then I have to wait couple hours until Active Directory and Teams got synchronized and users were added to AD groups / Teams teams. It's not ideal, but it works with saved credentials and with no user interaction.

Azure credentials have not been set up or have expired

I have scheduled a PowerShell script to execute a pipeline in Azure.
Have generated the login script(ProfileContext.ctx) using Login-AzureRMAccount
Below is the code to schedule:
$path = "D:\ProfileContext.ctx"
Import-AzureRmContext -Path $path
$dfn = "salesprod"
$rgn = "sale-dw"
$df=Get-AzureRmDataFactory -ResourceGroupName $rgn -Name $dfn
$ISTstartdate = get-date
#Set Pipeline active period
$UTCstartdate = $ISTstartdate.touniversaltime().addminutes(5)
$UTCenddt = $UTCstartdate.AddHours(5)
$pipelinename = "SalesPipeline"
Set-AzureRmDataFactoryPipelineActivePeriod -ResourceGroupName $rgn -PipelineName $pipelinename -DataFactoryName $dfn -StartDateTime $UTCstartdate -EndDateTime $UTCenddt -Force
Above code works fine for 2 or 3 days but then I start getting below issue:
Your Azure credentials have not been set up or have expired, please run Login-AzureRMAccount to set up your Azure credentials.
At D:\RunPipeline.ps1
Below are the version nos:
PSVersion - 5.0.10586.117
Azure - 4.2.1
I resolved it by using below work around: This would auto login for me and then I can schedule without a context file:
$accountName = "pqr#xyz.com"
$password = ConvertTo-SecureString "mypwd" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($accountName, $password)
Login-AzureRmAccount -Credential $credential
Get-AzureRmResource
Add Joseph's answer. Your answer only works on Azure AD account, Microsoft account does not support non-interactive login. According to your scenario, I suggest you could use Service Principal, it is more safer and not leak your account information. What is Service Principal?
When you have an app or script that needs to access resources, you can
set up an identity for the app and authenticate the app with its own
credentials. This identity is known as a service principal.
You could refer to refer to this link to create a new service principal and give Contributor role. You could use the following command to login your subscription.
$subscriptionId=""
$tenantid=""
$clientid=""
$password=""
$userPassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$userCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $clientid, $userPassword
Add-AzureRmAccount -TenantId $tenantid -ServicePrincipal -SubscriptionId $subscriptionId -Credential $userCredential
I came across with same issue today but after update Azure PowerShell Modules to the latest version, all good. You can do this while easily using Update-Module or just go ahead and use Install-Module AzureRm -Force.

Azure Credentials for build server

I'm having authentication headaches with Azure. I have a continuous build server running powershell scripts, and I'm getting messages like:
Your Azure credentials have not been set up or have expired, please run Login-AzureRMAccount to set up your Azure credentials.
I don't like having to login with my account on the build server. I suppose I could create another account just for building, but that will expire as well. Is there a better way of handling this?
You should not use Login-AzureRmAccount in your build/deploy scripts because this is an interactive login, but rather Add-AzureRmAccount instead.
Add-AzureRmAccount requires you create a service principal (application) in Azure AD and use its client id and secret/key to authenticate.
Here is a code snippet that you can use:
$clientID = "<the client id of your AD Application>"
$key = "<the key of your AD Application>"
$SecurePassword = $key | ConvertTo-SecureString -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential `
-argumentlist $clientID, $SecurePassword
Add-AzureRmAccount -Credential $cred -Tenant "xxxx-xxxx-xxxx-xxxx" -ServicePrincipal
To find out you tenant id (single subscription)
$tenant = (Get-AzureRmSubscription).TenantId
Find tenant id (multiple subscriptions)
$tenant = (Get-AzureRmSubscription -SubscriptionName "My Subscription").TenantId

Azure Powershell programmatic login

I am working with Azure (HDInsight in particular) using a personal account (no work/school acocunt).
I would create a script that automatically login on azure and perform some actions.
I found a solutions saving an azure publishsetting json file after logging with our credentials but this settings file contains token that expires.
How can I deal with this issue? What is the best way to accomplish this automatico logon?
Thanks
Roberto
You need to create a service principal. Once you've created the service principal you can assign it permissions on specific resources using Role-Based Access Control. From there your script can login as the service principal without requiring you to login interactively.
The main concern with this approach is securing access to your script since it contains credentials that allow access to your Azure resources.
This article has a good walkthrough:
#First, login as yourself so you can setup the service principal
Login-AzureRmAccount
#Password doesn't have to be *your* password, but the password the script will use
$app = New-AzureRmADApplication –DisplayName "<Your script name>" –HomePage "http://localhost" –IdentifierUris "http://localhost/YourAppName" –Password "<Password>"
#Create the service principal
New-AzureRmADServicePrincipal –ApplicationId $app.ApplicationId
#Assign the Reader role to your new service principal. Other roles listed at
#https://azure.microsoft.com/en-us/documentation/articles/role-based-access-built-in-roles/
New-AzureRmRoleAssignment –RoleDefinitionName Reader –ServicePrincipalName $app.ApplicationId
$pass = ConvertTo-SecureString "<Password>" -AsPlainText –Force
#Servce principal username looks like 92c22f1f-d1d4-46a1-b025-edb47fc03809#something.onmicrosoft.com
#the GUID part is $app.ApplicationId and the domain part is found in the Azure portal
$cred = New-Object -TypeName pscredential –ArgumentList "<Service Principal UserName>", $pass
Login-AzureRmAccount -Credential $cred -ServicePrincipal –TenantId <TenantId>
If it is not a production/shared setup and more a developer setup you can also do, careful, the password is plain text here:
$SubscriptionName = 'MySubscription'
$pswd = 'MyPassword' | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Credential -UserName 'MyEmail#something.com' -Password $pswd
Add-AzureRmAccount -Credential $creds
Set-AzureRmContext -SubscriptionName $SubscriptionName
Login-AzureRmAccount -Credential $creds -SubscriptionName $SubscriptionName
Below information might help you
Create an Automation Account in Azure
Add your credentials in Automation Account as a variable ( e.g
variablename = loginazure) Below Script will automatically login into azure (use Powershell workflow runbook).
$AzureLogin = Get-AutomationPSCredential -Name 'loginazure'
$AzurePortalLogin = New-Object -TypeName System.Management.Automation.PSCredential$AzureLogin
Add-AzureRmAccount -Credential $AzurePortalLogin
Get-AzureRmSubscription -SubscriptionName "your subscription name" | Set-AzureRmContext
use the above script within Inline Script {}
Regards
Thamarai Selvan S
Here are a couple of commands that you can fire up to get started.
$credentials = Get-Credential
Login-AzureRmAcoount -Credential $credentials
$SubscriptionName
Select-AzureRmSubscription -SubscriptionName "The name of your subscription"
Select-AzureRmSubscription -SubscriptionName $SubscriptionName