I have to update a Script which should create an application in Azure and subsequently use it to traverse resources.
Among the commands to update is to create a credential for the application created.
$AppSPN = New-AzADServicePrincipal -DisplayName "Move_Validation_SPN"
subsequently I need to use a credential to traverse the resources, according to the same Microsoft documentation, it can be created like this:
$creds = New-Object `
-TypeName "Microsoft.Azure.PowerShell.Cmdlets.Resources.MSGraph.Models.ApiV10.MicrosoftGraphPasswordCredential" `
-Property #{ 'DisplayName' = $name; 'StartDateTime' = $startDate; 'EndDateTime' = $endDate }
New-AzADAppCredential -ApplicationId $AppSPN.appId -PasswordCredentials #creds
Here comes the question, when I create a Token, how do I retrieve the password from the MicrosoftGraphPasswordCredential object? which is: $creds
$Token = Get-Token -TenantId $TenantId -SubscriptionID $SourceSub.Id -ApplicationID $AppSPN.appID -ApplicationKey $creds
From version 6.6.0, there are breaking changes in this cmdlet New-AzADAppCredential.
As mentioned in this MS Doc, Az PowerShell cmdlets module moved from Azure AD Graph to Microsoft Graph. So, it is better to use the cmdlet of New-AzureADApplicationPasswordCredential.
Workaround:
As mentioned here, there should be a mistake in the official doc, in the example, it uses the New, not Get.If you try New, it appears like the doc.
Source: New-AzureADApplicationPasswordCredential
Related
I am preparing the report which contains all the users access level tenant wise from the azure.
is there any one command or script to get all the users access level from Azure tenant ?
That is a little be trick: The PS library for Azure is different from the PS library for the AD. You must cross informations.
You must get all users from you AD using the command above and save as variable
$allUsers = Get-ADUsers -Filter *
Now you can navigate to all subscriptions into your tenant, all resource groups and resources and for each and every one get the IAM (who came with the objectId of the user) and cross with the variable $allUsers to identify everyone.
The sample is not the best but maybe can help you:
Connect-AzAccount
$listIAM = New-Object System.Collections.ArrayList
$listSubscriptions = Get-AzSubscription
foreach($subscription in $listSubscriptions){
Set-AzContext -SubscriptionId $subscription.SubscriptionId
# Now you have all roleAssignements for this subscription
$subscriptionIAM = Get-AzRoleAssignment -Scope /subscriptions/$subscription.SubscriptionId
$listIAM.Add($subscriptionIAM) | Out-Null
# Navigate into resource groups
$listResourceGroups = Get-AzResourceGroup
foreach($resourceGroup in $listResourceGroups){
$rgIAM = Get-AzRoleAssignment -ResourceGroupName $resourceGroup.ResourceGroupName
$listIAM.Add($rgIAM) | Out-Null
# Navigate into resources
$listResources = Get-AzResource -ResourceGroupName $resourceGroup
foreach($resource in $listResources){
$rIAM = Get-AzRoleAssignment -Scope $resouce.ResourceId
$listIAM.Add($rIAM) | Out-Null
}
}
}
You can do this in either PowerShell or the Graph API. Both methods are in preview (the graph API calls are under the beta branch).
#Get the user
$userId = (Get-AzureADUser -Filter "userPrincipalName eq 'alice#contoso.com'").ObjectId
#Get direct role assignments to the user
$directRoles = (Get-AzureADMSRoleAssignment -Filter "principalId eq '$userId'").RoleDefinitionId
Prerequisites
AzureADPreview module when using PowerShell
Microsoft.Graph module when using PowerShell
Admin consent when using Graph Explorer for Microsoft Graph API
https://learn.microsoft.com/en-us/azure/active-directory/roles/list-role-assignments-users
I recently started using PowerShell 7.x and I've came around some problems. I am not able to retrieve the secret of my service principal when I create it through PowerShell 7. The return body does not give the "Secret" property. I used to work with PowerShell 5.x and I used to get a "Secret" property in the return object after creating a service principal. I've added the screenshots of creating service principal through both PowerShell 7.x and PowerShell 5.x.
As you can see while working with Powershell 5 I could just use an object and save the returned object in it and access the secret like:
$sp = New-AzADServicePrincipal -DisplayName "xyz"
$secret = $sp.Secret
$plainSecret = convertFromSecureString $secret
convertFromSecrureString is just a basic function which converts the secret to plain text.
But I cannot use the same approach with PowerShell 7. How can I retrieve the secret?
$sp = New-AzADServicePrincipal -DisplayName "xyz" $secret = $sp.Secret
$plainSecret = convertFromSecureString $secret
We have tested the above shared cmdlets in our local environment which has PowerShell running with different versions 5.1 & 7.2.
Using those cmdlets we are able to create the service principal & able to see the same properties in the output in either of both versions.
Here is the sample output screenshot for reference :
New-AzADServicePrincipal returns the IMicrosoftGraphServicePrincipal structure, which didn't match the example code.
IMicrosoftGraphServicePrincipal Interface (latest PS version)
Here is the code that works for me:
Connect-AzAccount -Tenant 'TENANT_ID' -Subscription 'SUBSCRIPTION_ID'
$sp = New-AzADServicePrincipal -DisplayName $Name
$clientsec = [System.Net.NetworkCredential]::new("", $sp.passwordCredentials.secretText).Password
$jsonresp =
#{clientId=$sp.appId
clientSecret=$clientsec
}
$jsonresp | ConvertTo-Json
I have a PowerShell script that logs into Azure subscription with the command Connect-AzAccount using user's credentials.
The code is the following:
$userPassword='password'
$userName="username"
$tenantId="########-####-####-####-############"
$subscriptionId="########-####-####-####-############"
$azureSecpassword = $userPassword | ConvertTo-SecureString -asPlainText -Force
$azureCredential = New-Object System.Management.Automation.PSCredential($userName, $azureSecpassword)
Connect-AzAccount -Credential $azureCredential -Tenant $tenantId -SubscriptionId $subscriptionId
The code above works without any user interaction.
Few days ago the customer enabled the multi-factor authentication for the users.
How can I keep a fully automated login process (without user interactions) with the multi-factor authentication?
Best Regards.
This is a common question. Unfortunately, the answer is No. If the account is MFA-enabled, you could just login with an interactive way.
In such a case, we choose to use the service principal to login with non-interactive in general.
$azureAplicationId ="Azure AD Application Id"
$azureTenantId= "Your Tenant Id"
$azurePassword = ConvertTo-SecureString "client secret" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
Reference - Sign in with a service principal.
If you must log in as a user, there might be 2 optional approaches.
1. If you will run the script locally or in a specific PC
You can Persist Azure user credentials. You can enable auto save, or manually save the context to a file, and then use it in another PS session.
If you enabled auto save, then you can directly get the context as following:
Get-AzContext
# If you have more than one contexts, you can choose one by specifing the name
Get-AzContext -Name 'CSP Azure (e5b0****-****-****-****-5e5f****4c68) - jack#h****a.onmicrosoft.com'
If you want to manually do it, here is the sample:
# Interactively log for one time
Connect-AzAccount
# Save the context
Save-AzContext -Path D:\ctx.dat
And in another PS session, you can:
Import-AzContext -Path D:\ctx.dat
2. Use refresh token to acquire token, and connect to Azure
You can get the refresh token from the auto saved Azure context (usually at C:\Users\<UserName>\.Azure\TokenCache.dat).
Open the dat file with notepad, and you will get the refresh token:
Then you can get a new token in PowerShell with that refresh token, and connect to Azure:
Clear-AzContext
$tenantId = "e4c9ab4e-****-****-****-230b****57fb"
$subscriptionId = "e5b0fcfa-****-****-****-5e5f****4c68"
$refreshToken = 'AQABAAAAAAAP0****a lot of characters here*****0A9FWoB8mvDtoWRJHBVO7GJzodLKYmNIAA'
$url = "https://login.microsoftonline.com/" + $tenantId + "/oauth2/token"
$body = "grant_type=refresh_token&refresh_token=" + $refreshToken
$response = Invoke-RestMethod $url -Method POST -Body $body
$AccessToken = $response.access_token
Connect-AzAccount -AccountId "the user id, jack#h****a.onmicrosoft.com" -AccessToken $AccessToken -Tenant $tenantId -SubscriptionId $subscriptionId
How can I keep a fully automated login process (without user interactions) with the multi-factor authentication?
You can't do this with a user account--that's the whole point of multi-factor authentication.
Instead, Azure AD supports authenticating with a service principal (instead of a user principal, like you're doing currently), and Azure supports granting access to Azure resources to service principals.
MFA requirements (and other conditional access policies) do not apply to service principals (often referred to as an Azure AD "app"), and service principals support more secure methods of authentication for automation scenarios (e.g. public/private key pairs).
So, what you should do:
Ensure the machine running this script is secure. Anyone with access to the machine has the same amount of access as the script.
Create an application identity and associate credentials with it.
Note: It is strongly recommend you use certificate-based authentication for your service principal, instead of password-based. It is a very insecure practice to have any kind of secret stored in a PowerShell script!
Grant the service principal the minimum level of access to Azure resources, to allow it to complete the required task.
Update your script to use the app's identity (service principal) instead of the user's identity. It's even simpler than using a user account:
$tenantId = "########-####-####-####-############"
$subscriptionId = "########-####-####-####-############"
$appId = "########-####-####-####-############"
$thumbprint= "##############"
Connect-AzAccount -ServicePrincipal -TenantId $tenantId -ApplicationId $appId -CertificateThumbprint $thumbprint
Note: If this script is running on a VM in Azure, you should forget step 2, and simply enable a managed identity and use that.
I am trying to write some powershell script that has to combine both Az cmdlets and AzureRM to accomplish some of the stuff I want to do.
What truly happens though when I call all in the same script:
Connect-AzAccount
Connect-AzureAD
Connect-AzureRMAccount
Initially, I make a call to Get-Credential and save that in a variable.
Then I use those credentials to populate -Credential in the Connect-AzAccount
Then because of Multi-Factor Authentication, I have to then make a call to Connect-AzureAD, which prompts a popup that allows the user to enter Email, Password and Code from MFA text to phone.
Later in the script, there are some cmdlets that are in the RM version, and so I call Connect-AzureRMAccount with the previous Credentials from above.
$credentials = Get-Credential
$azureCredentials = New-Object System.Management.Automation.PSCredential ($credentials.UserName, $credentials.Password)
Connect-AzAccount -Credential $azureCredentials -Tenant $tenantID -SubscriptionId $subscriptionID
Connect-AzureAD -Tenant $tenantID
Connect-AzureRMAccount -Credential $azureCredentials -Tenant $tenantID -SubscriptionId $subscriptionID
What is actually happening in terms of Authentication during this entire script where several different Connect cmdlets are called.
Due to some reason, there is a specific cmdlet
$AppRegistration = New-AzureADApplication -DisplayName $appName -HomePage $AppURI -IdentifierUris $AppURI -ReplyUrls $AppURI -PasswordCredentials $psadCredential
where I get an error in Powershell telling me that I need to call Connect-AzureAD again, even though it was already called once during the script. Does it time out with the MFA?
How can I avoid having to get the user to sign in several times after running the script?
I don't think this is a correct option, if you want to avoid MFA, the workaround is to create a service principal(AD App), grant the permissions for it, then you can login with the service principal without MFA.
You could follow the steps below.
1.Create an Azure Active Directory application, then Upload a certificate and Get values for signing in.
2.Navigate to the Azure Active Directory in the portal -> Roles and administrators -> click Application administrator -> Add assignment -> search by your AD App name(service principal name) -> select it -> Select.
Note: In your case, you want to use the command New-AzureADApplication, so you need to give the Application administrator directory role to your AD App(service principal), if you want to do other things need more permissions, you may need to give a role like Global administrator, it depends on you.
3.Then you could use the command below to login with Az module and AzureAD module.
Connect-AzAccount -CertificateThumbprint "F1D9FE13A8FBxxxx1C8B07D1666" -ApplicationId "aa60b5df-xxxxxx8ae8e0cc2e4" -Tenant "bb58915cxxxxxxb97ed6c65" -ServicePrincipal
Connect-AzureAD -CertificateThumbprint "F1D9FE13A8FBxxxx1C8B07D1666" -ApplicationId "aa60b5df-xxxxxx8ae8e0cc2e4" -Tenant "bb58915cxxxxxxb97ed6c65"
New-AzureADApplication -DisplayName "newapp" -IdentifierUris "http://mynewapp11.contoso.com"
Connect-AzureRMAccount doesn't work. I don't care. I don't want to run through the process of needing a PhD to understand why PowerShell never wants to work. So I'm going to use Login-AzureRMAccount
I've followed the docs. Of course it's inadequate so here I am.
https://learn.microsoft.com/en-us/powershell/azure/authenticate-azureps?view=azurermps-6.6.0
"In order to get the service principal's credentials as the appropriate object, use the Get-Credential cmdlet. This cmdlet will display a dialog box to enter the service principal user ID and password into."
Where do I even find my userID? I followed another docs instructions on creating an SP and all I did was create an app. I got the SP object in PowerShell, all it did was give me a NAME of the SP .
Now that I understand what User ID is. HOW do I log in? I use Login-AzureRmAccount AND Add-AzureRMAccount and they BOTH say
$p = Get-Credential
Add-AzureRmAccount -ServicePrincipal -ApplicationId "XXXXXXXXXX" -Credential $p -TenantId "XXXXXXXXXXX"
Add(/Login)-AzureRmAccount : Parameter set cannot be resolved using the specified named parameters.
Try the command below to log in as a service principal,it works fine on my side.
$azureAplicationId ="Azure AD Application Id"
$azureTenantId= "Your Tenant Id"
$azurePassword = ConvertTo-SecureString "strong password" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Add-AzureRmAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
For more details, refer to this similar issue.
The what you call userId is the Application Id (Also known as ClientID) of your service principal.
The following really should work for you
$pscredential = Get-Credential
Connect-AzureRmAccount -ServicePrincipal -ApplicationId "http://my-app" -Credential $pscredential -TenantId $tenantid
Source: Microsoft Docs