Connect-ADAccount with service principal: Insufficient privileges to perform requested operation - azure

I need to be able to run Connect-ADAccount in a non-interactive mode, invite a user to my AD, assign some resource permissions to this new user.
So I have:
Created a service principal.
Created a certificate using the following code:
Connect-AzureAD
$Certname = Read-Host "Enter Certificate Name"
$Cert = New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname $Certname -Provider “Microsoft Enhanced RSA and AES Cryptographic Provider”
$pw = ConvertTo-SecureString -String "Pazzword" -Force -AsPlainText
$thumbprint = $Cert.Thumbprint
Export-PfxCertificate -cert cert:\localMachine\my\$thumbprint -FilePath $env:USERPROFILE\Desktop\$Certname.pfx -Password $pw
Get-PfxCertificate -FilePath $env:USERPROFILE\Desktop\$Certname.pfx | Export-Certificate -FilePath
$env:USERPROFILE\Desktop\OutputCert.crt -Type Cert
Uploaded it manually.
Gave owner permissions to my service principal.
Now I am able to run the following code but it would fail on the New-AzureADMSInvitation step.
Connect-AzureAD -TenantId $ObjectId -ApplicationId $AppId -CertificateThumbprint $thumb
New-AzureADMSInvitation -InvitedUserDisplayName $userName -InvitedUserEmailAddress $userEmail -InviteRedirectUrl 'https://portal.azure.com/' -SendInvitationMessage $true
I am not sure what would be the required permissions in this case.
New-AzureADMSInvitation : Error occurred while executing NewAzureADMSInvitation
Code: Unauthorized
Message: Insufficient privileges to perform requested operation by the application '00000003-0000-0000-c000-000000000000'. ControllerName=MSGraphInviteAPI, ActionName=CreateInvite [...]

New-AzureADMSInvitation invoke Create invitation MS Graph API in the backend.
POST https://graph.microsoft.com/v1.0/invitations
You need to add one of the following application permission when using service principal:
User.Invite.All,
User.ReadWrite.All,
Directory.ReadWrite.All
Please navigate to App registration > your app > add API Permissions > Microsoft Graph API > Select the previous in Application Permission. And also remember to grant admin consent for your tenant.

Related

Azure Automation Variables

I am trying to make a code using PowerShell so that secrets are not hardcoded on my runbook so that it will not be exposed in the script. I created encrypted variables in my automation account. These variables are AppID, AppSecret and TenantID.
This is the part of the script to login automatically to Azure. I didn't use managed identity for some compatibility reasons with the script.
My script is running fine when secrets and IDs are hardcoded but when I created variables it is not working. Error message is "Run Connect-AzAccount". Below is my code. Need help on how to correct this. Thank you in advance.
$AzVariableApplicationID = 'AppID'
$AzVariableAppSecret = 'AppSecret'
$AzVariableTenantID = 'TenantID'
$AppID = Get-AzAutomationVariable -Name $AzVariableApplicationID
$AppSecret = Get-AzAutomationVariable -Name $AzVariableAppSecret
$TenantID = Get-AzAutomationVariable -Name $AzVariableTenantID
$SecureSecret = $AppSecret | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential `
-ArgumentList $AppID, $SecureSecret
Connect-AzAccount -ServicePrincipal -Credential $Credential -Tenant $TenantID
As described in PsCustom Object - Hitchikers GUID(e) to Automation
, It is not possible to retrieve values for encrypted variables as they’re available within the runbook at runtime via the Get-AutomationVariable cmdlet
I found an alternative approach to "Connect Azure" by using "Certificate-based authentication" inside PowerShell runbook without hardcoding the values:
Created a new Service principal and provided the "Owner" role access to avoid any restrictions.
To authenticate via service principal, I create a new self-signed certificate with the command:
$cert=New-SelfSignedCertificate -Subject "CN=xxxxxCert" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature
Upload a certificate under Certifications & Secrets:
Click windows + R to open the run box and give certmgr.msc as shown here.
Export a certificate without private key.
Upload a certificate in the below path:
AzureAD -> App registrations -> Serviceprincipal
Now, I have exported the same certificate with key and uploaded inside my automation account to authenticate Service principal connection:
Added an "Azure Service Principal" connection inside automation accounts by providing "ApplicationID, TenantID, Certificate Thumbprint" of my Service principal as shown:
Inside PowerShell runbook, I ran the below script that works for me:
$connectionName = "serviceprincipalname"
try
{
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
"Logging in to Azure..."
Add-AzureRMAccount
-ServicePrincipal `
-TenantID $servicePrincipalConnection.TenantID `
-ApplicationID $servicePrincipalConnection.applicationID `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found. "
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
Logged in to Azure:
Register an App in App registrations and create a service principal in AzureAD

Connect-Exchange CertificatePath in Azure Function

I'm trying to understand how to add the parameter -CertificateFilePath in a Powershell Azure Function. Locally you just add the location of the path *c:\locationpath*.
But when used in a Azure Function, I'm not sure how to add the file path from a Function App that has the cert already in TLS/SSL settings where I've uploaded the certificate.
A common way I've seen to do is:
Connect-ExchangeOnline -AppID $AppId -CertificateThumbprint $Thumbprint -Organization company.com
But that usually has a pop up that ask for an account to select which is why it might be failing in the Function. Also I'm trying to use a certificate.
Another way I've seen is using the AZ Vault, which I didn't want to use if my certificates are already in an app registration and in the Function itself in TLS/SSL Settings.
I just want to be able to query Exchange without user credentials with a service I've created. Thank you.
As venkateshdodda-mt Suggested try the below steps
1 Generate Certificate and Service Principal
By credential
By CertificateThumbprint & ApplicationId
By AadAccessToken & AccountId
# Login to Azure AD PowerShell With Admin Account
Connect-AzureAD
# Create the self signed cert
$currentDate = Get-Date
$endDate = $currentDate.AddYears(1)
$notAfter = $endDate.AddYears(1)
$pwd = "YOUR_PASSWORD"
$thumb = (New-SelfSignedCertificate -CertStoreLocation cert:\localmachine\my -DnsName YOUR_DNS -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $notAfter).Thumbprint
$pwd = ConvertTo-SecureString -String $pwd -Force -AsPlainText
Export-PfxCertificate -cert "cert:\localmachine\my\$thumb" -FilePath YOUR_PFX_PATH.pfx -Password $pwd
# Load the certificate
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate("YOUR_PFX_PATH.pfx", $pwd)
$keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())
# Create the Azure Active Directory Application
$application = New-AzureADApplication -DisplayName "YOUR_APP_NAME" -IdentifierUris "https://YOUR_APP_NAME"
New-AzureADApplicationKeyCredential -ObjectId $application.ObjectId -CustomKeyIdentifier "YOUR_PASSWORD" -StartDate $currentDate -EndDate $endDate -Type AsymmetricX509Cert -Usage Verify -Value $keyValue
# Create the Service Principal and connect it to the Application
$sp = New-AzureADServicePrincipal -AppId $application.AppId
# Give the Service Principal Reader access to the current tenant (Get-AzureADDirectoryRole)
Add-AzureADDirectoryRoleMember -ObjectId 72f988bf-86f1-41af-91ab-2d7cd011db47 -RefObjectId $sp.ObjectId
# Get Tenant Detail
$tenant = Get-AzureADTenantDetail
# Now you can login to Azure PowerShell with your Service Principal and Certificate
Connect-AzureAD -TenantId $tenant.ObjectId -ApplicationId $sp.AppId -CertificateThumbprint $thumb
# Output TenantId, AppId and Thumbprint to use in azure function's script
Write-Host "TenantId: "$tenant.ObjectId
Write-Host "AppId: "$sp.AppId
Write-Host "Thumbprint: "$thumb
2 Configure Azure Function to Use Certificate
3 Copy AzureAD PowerShell Module to Azure Function
4 Write PowerShell Script from Azure Function to Connect to Azure AD
for further information check Azure functions check with powershell

Access denied for setting up Azure B2B allow list domain using Graph API

I've created an registered app in Azure and I'be given the following API permissions for Graph API as follows:
**
Directory.ReadWrite.All
Policy.Read.All
Policy.ReadWrite.TrustFramework
User.Invite.All
User.Read
**
My plan is to add an allow list to the Azure B2B directory and then invite the guest user to my directory using the service principle i created above.
With the above permissions , I can read the current policy and send the invite to the guest user. But, I cannot append the exiting allowed domain list in my B2B directory.
Each time i try to update the existing policy I'm getting access denied as shown below:
**
Set-AzureADPolicy -Definition $policyValue -Id $currentpolicy.Id | Out-Null**
Error
Set-AzureADPolicy : Error occurred while executing SetPolicy
Code: Authorization_RequestDenied
Message: Insufficient privileges to complete the operation.
InnerError:
RequestId: 4f161b70-f71c-4507-8b91-788457429fcc
DateTimeStamp: Wed, 08 Apr 2020 16:57:39 GMT
HttpStatusCode: Forbidden
HttpStatusDescription: Forbidden
HttpResponseStatus: Completed
At line:1 char:1
+ Set-AzureADPolicy -Definition $policyValue -Id $currentpolicy.Id | Ou ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Set-AzureADPolicy], ApiException
+ FullyQualifiedErrorId : Microsoft.Open.MSGraphBeta.Client.ApiException,Microsoft.Open.MSGraphBeta.PowerShell.SetPolicy
Does anyone had any ideas what is missing here?
Also can i confirm this operation is supported with Graph API at the moment?
Thanks
Balaip
According to some test, I just add the other three permissions under "Policy" to the app you registered. And then I can use Set-AzureADPolicy command success(with connecting to Azure AD with a service principle).
Update:
I provide all of the steps for your reference:
1. Run the command below in powershell
# Login to Azure AD PowerShell With Admin Account
Connect-AzureAD
# Create the self signed cert
$currentDate = Get-Date
$endDate = $currentDate.AddYears(1)
$notAfter = $endDate.AddYears(1)
$pwd = "xxxxxxx"
$thumb = (New-SelfSignedCertificate -CertStoreLocation cert:\localmachine\my -DnsName com.foo.bar -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $notAfter).Thumbprint
$pwd = ConvertTo-SecureString -String $pwd -Force -AsPlainText
Export-PfxCertificate -cert "cert:\localmachine\my\$thumb" -FilePath c:\temp\examplecert.pfx -Password $pwd
# Load the certificate
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate("C:\temp\examplecert.pfx", $pwd)
$keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())
# Create the Azure Active Directory Application
$application = New-AzureADApplication -DisplayName "huryttt1234" -IdentifierUris "https://huryttt1234"
New-AzureADApplicationKeyCredential -ObjectId $application.ObjectId -CustomKeyIdentifier "Huryttt1234" -StartDate $currentDate -EndDate $endDate -Type AsymmetricX509Cert -Usage Verify -Value $keyValue
# Create the Service Principal and connect it to the Application
$sp = New-AzureADServicePrincipal -AppId $application.AppId
2. Now I go to the new application(Huryttt1234) in AD on Azure portal and add the five permissions to it, and grant admin consent to it.
3. Then run command below:
# Get Tenant Detail
$tenant = Get-AzureADTenantDetail
# Now you can login to Azure PowerShell with your Service Principal and Certificate
Connect-AzureAD -TenantId $tenant.ObjectId -ApplicationId $sp.AppId -CertificateThumbprint $thumb
Get-AzureADPolicy -Id xxxxxxxxxxxxxxxxxxxx
Set-AzureADPolicy -Definition #('{"TokenLifetimePolicy":{"Version":1,"MaxInactiveTime":"20:00:00"}}') -Id xxxxxxxxxxxxxxxxxxxx | Out-Null
I can run the bottom two lines(the get operation and set operation) successfully.

Connect-AzAccount - how to avoid azure device authentication?

I have installed the PowerShell 6.1.3 version and
I want to get a connection to the Azure account using the following Azure PowerShell command:
Connect-AzAccount -Tenant <tenantId> -Subscription <subId>
After entering this command I get the warning with the url and some code.
Then I have to go to the URL and enter the code there. After that, I get a connection to the Azure account.
Are there any ways to avoid this confirmation?
I've also tried to do it using the following command:
az login -u <username> -p <password>
This command only returns some account information(subscriptionId, tenantId etc) but it doesn't install a connection to this account.
1.To login with the user account, try the command as below, make sure your account doesn't enable the MFA(Multi-Factor Authentication).
$User = "xxx#xxxx.onmicrosoft.com"
$PWord = ConvertTo-SecureString -String "<Password>" -AsPlainText -Force
$tenant = "<tenant id>"
$subscription = "<subscription id>"
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User,$PWord
Connect-AzAccount -Credential $Credential -Tenant $tenant -Subscription $subscription
2.You can also use a service principal to login, use the command as below.
$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)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
See a similar issue I answered here, it use the old AzureRM module, for Az, just change the last line.
If you are not familiar with service principal, Also see : How to: Use the portal to create an Azure AD application and service principal that can access resources, the application id and authentication key are the Azure AD Application Id and strong password you need.
You have 2 options.
Sign in with credentials (Requires Az.Accounts v 1.2.0 or higher)
You can also sign in with a PSCredential object authorized to connect to Azure. The easiest way to get a credential object is with the Get-Credential cmdlet. When run, this cmdlet will prompt you for a username/password credential pair.
$creds = Get-Credential
Connect-AzAccount -Credential $creds
Sign in with a service principal
Service principals are non-interactive Azure accounts. Like other user accounts, their permissions are managed with Azure Active Directory. By granting a service principal only the permissions it needs, your automation scripts stay secure.
To learn how to create a service principal for use with Azure PowerShell, see Create an Azure service principal with Azure PowerShell.
Source: https://learn.microsoft.com/en-us/powershell/azure/authenticate-azureps?view=azps-1.3.0
If Multi Factor Enabled then also below logic should work
$clientId = "***********************"
$clientSecret = "********************"
$tenantId = "***********************"
$tempPassword = ConvertTo-SecureString "$clientSecret" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($clientId ,
$tempPassword)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal

Login-AzureRmAccount from VS Code terminal

When I try to login to Azure RM from VS Code terminal it just hangs. No prompt with login / password is shown.
Is there any way to get logged in from that terminal? Otherwise running / debugging Azure PS scripts becomes more complicated than it should be :)
The login window pops-up in the background... if you minimize all your windows you'll eventually find it.
You need to wait for a moment, then you could see the login page.
According to your description, I suggest you could select Non-interactive login. You could create a service principal that can access resource. Please refer to this link:Use portal to create an Azure Active Directory application and service principal that can access resources. You will get clientid and client secret. You could use the following code to login your Azure account.
$subscriptionId=""
$tenantid=""
$clientid=""
$password=""
$userPassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$userCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $clientid, $userPassword
Login-AzureRmAccount -TenantId $tenantid -ServicePrincipal -SubscriptionId $subscriptionId -Credential $userCredential

Resources