What permissions are needed to read /write external collaboration policies? - azure

I've written a powershell script that allows me to query azure for my azure ad policies like this:
Connect-AzureAD
$currentpolicy = Get-AzureADPolicy -All $true | ?{$_.Type -eq 'B2BManagementPolicy'} | select -First 1
$currentpolicy
$newPolicyValue = #("{`"B2BManagementPolicy`":{`"InvitationsAllowedAndBlockedDomainsPolicy`":{`"AllowedDomains`": [`"a.com`",`"b.org`",`"c.org`",`"d.com`"],`"BlockedDomains`": []}}}")
}
#update existing. This works. tested.
Set-AzureADPolicy -Definition $newPolicyValue -Id $currentpolicy.Id
This works because I'm signing in with an account that's got "owner" / global admin permissions. Now we wnat to try to figure out the specific permissions that are needed and just assign those to a new AD app registration.
I've created a service principal with a cert, and I changed my code like this:
Connect-AzureAD -TenantId $tid -ApplicationId $appid -CertificateThumbprint $thumb
$currentpolicy = Get-AzureADPolicy -All $true | ?{$_.Type -eq 'B2BManagementPolicy'} | select -First 1
$currentpolicy
I didn't add any specific permissions yet, and so when I run my script, I see the following error:
Get-AzureADPolicy : Error occurred while executing GetPolicies
Code: Authorization_RequestDenied
Message: Insufficient privileges to complete the operation.
InnerError:
RequestId: d88cd5d5-f8c9-4a4d-928b-986e0d5c25eb
DateTimeStamp: Thu, 16 Jun 2022 19:06:45 GMT
HttpStatusCode: Forbidden
HttpStatusDescription: Forbidden
HttpResponseStatus: Completed
At C:\Users\me\Documents\src\test\setPolicy.ps1:4 char:18
+ $currentpolicy = Get-AzureADPolicy -All $true | ?{$_.Type -eq 'B2BMan ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-AzureADPolicy], ApiException
+ FullyQualifiedErrorId : Microsoft.Open.MSGraphBeta.Client.ApiException,Microsoft.Open.MSGraphBeta.PowerShell.GetPolicy
Ideally, we want to use MS Graph permissions to do this. So i've been poking around in Azure, under the "API Permissions" for this application registration, but so far I haven't figured out which permission I need to add.
PS I know that the AzureADPreview and AzureAD is going away. But so far, it's the only way that I can automate these tasks. I have another stack question open about how to get this entire thing working via Graph
EDIT 1
I've tried the following permissions and none of them work so far...
EDIT 2
I've granted Policy.Read.All and now I can read the policies. Now it fails trying to update the existing policy.
It'd be nice to know specificially which read permission is needed so I don't have to grant all.
As far as write permissions, I've granted everything that comes up when I search for "policy" but none of them allow me to write!
EDIT 3
I've added the policy.readwrite.applicationconfiguration but that doesn't allow me to write. I'm still get the insufficient privleges error when I try to call Set-AzureADPolicy.

I don't know if you have found an answer, but as this is one of the first results that came up, I will add my findings.
I could get nowhere from giving specific permissions to the Service Principal but adding the Security Administrator role to the app did the trick. I didn't want to give the service principal so much access, but I tried a lot of roles and permission combinations, and none were sufficient.
Apparently, the documentation states that the least privileged role that is able to configure B2B external collaboration settings is the Global Administrator. Although for this case specifically, of changing the B2BManagementPolicy via PowerShell with a service principal, the Security Administration role was enough in my testing.
Looking at the actions that this role can perform I suspect it's because it has access to microsoft.directory/policies/basic/update, but I can't be sure.
Note: When adding a role to an App registration in Azure AD you need to search for its name when selecting the members, as they don't show by default.

Thanks for reaching out , with the help you read access , you will only able to get the data ,if you want to add or update you should have write permission as well , please add permission Policy.ReadWrite.ApplicationConfiguration and try again .
ref doc - https://learn.microsoft.com/en-us/graph/api/tenantappmanagementpolicy-update?view=graph-rest-beta&tabs=http
Edit 2
Update policy is available for PowerShell 2.0 preview
To update you need to use
Set-AzureADPolicy -ObjectId -DisplayName
To learn more about Set-AzureADPolicy, please checkout - https://learn.microsoft.com/en-us/powershell/module/azuread/set-azureadpolicy?view=azureadps-2.0-preview&viewFallbackFrom=azureadps-2.0
Thanks

Related

Automate connecting to Azure for checking and creating resources without prompt

I am required to write a PowerShell script, which can connect to my company's Azure account, check and create Azure resources (eg. Service Bus namespace, Service Bus topic, and Service Bus subscriptions). Everything worked well until I tried to deploy my script as a step in my project's on-premise TeamCity. I keep getting this error message
Exception calling "ShouldContinue" with "2" argument(s): "Windows
PowerShell is in NonInteractive mode. Read and Prompt functionality is
not available."
I investigated and found out that the problem is in this line
Connect-AzAccount
If I run the script manually, it will pop up a prompt asking me to login to Azure. I believe that's what went wrong. Because my project's on-premise TeamCity does not seem have an option to open a prompt for PowerShell command. I have read some workarounds, even on this website, but none of them is applicable to my case. Even a solution like https://stackoverflow.com/a/61099568/8213536 gave me these errors
WARNING: Unable to acquire token for tenant 'organizations' with error
'UsernamePasswordCredential authentication failed: There was an error
parsing WS-Trust response from the endpoint. This may occur if there
is an issue with your ADFS configuration. See
https://aka.ms/msal-net-iwa-troubleshooting for more details. Error
Message: Object reference not set to an instance of an object. See the
troubleshooting guide for more information.
https://aka.ms/azsdk/net/identity/usernamepasswordcredential/troubleshoot'
Connect-AzAccount : UsernamePasswordCredential authentication failed:
There was an error parsing WS-Trust response from the endpoint. This
may occur if there is an issue with your ADFS configuration. See
https://aka.ms/msal-net-iwa-troubleshooting for more details. Error
Message: Object reference not set to an instance of an object. See the
troubleshooting guide for more information.
https://aka.ms/azsdk/net/identity/usernamepasswordcredential/troubleshoot
At line:1 char:1
Connect-AzAccount -Credential $creds
+ CategoryInfo : CloseError: (:) [Connect-AzAccount], AuthenticationFailedException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand
One of the other solutions https://stackoverflow.com/a/52014189/8213536 requires an application's principal id, which is not applicable for my scenario either, as I am not creating a new application. I just need to be able to automatically connect to Azure (without prompt), check and create SB Namespace, SB Topic and SB Subscription.
Could someone please help me on this? Thanks.
As promised, I would like to post my solution. First I created a service principal with a client secret key. Then I asked my company's cloud engineer to assign it to the Azure subscription of my company and to the resource group that I intended to group all my necessary resources into. Finally in my code, I implemented something similar to https://stackoverflow.com/a/61099568/8213536
$applicationId = $azServicePrincipalId
Write-Host "Connecting to Azure using principal $applicationId"
$securePassword = $azServicePrincipalPw | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $applicationId, $securePassword
Connect-AzAccount -ServicePrincipal -TenantId $azureTenantId -Credential $credential
$azServicePrincipalId and $azServicePrincipalPw came from the Service Principal itself, while $azureTenantId came from my company's Azure subscription.
It is now working as expected.

How to reset credentials of an Azure service principal using an automation account PowerShell runbook?

I'm trying to reset the password credentials of a service principal (let's call it SP1) through the following PowerShell commands:
Remove-AzADSpCredential -ObjectId <SP1_objectId> -Force
$Password = New-AzADSpCredential -ObjectId <SP1_objectId>
This works well when I run it through the PowerShell by my own user account, which has an Owner role assigned to SP1.
I also have this code in a runbook in an automation account with a "run as account" service principal (let's call it SP2).
I assigned the ownership of SP1 to SP2 as well through the command Add-AzureADServicePrincipalOwner and confirmed it through Get-AzureADServicePrincipalOwner.
I expected the runbook to be able to run the Remove-AzADSpCredential command on the SP1 after making its service principal the owner of SP1. But I get the following error:
Remove-AzADSpCredential : Insufficient privileges to complete the operation. At line:43 char:9 + Remove-AzADSpCredential -ObjectId $key.Name -Force + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [Remove-AzADSpCredential], Exception + FullyQualifiedErrorId : Microsoft.Azure.Commands.ActiveDirectory.RemoveAzureADSpCredentialCommand
And the same error for New-AzADSpCredential command as well.
I thought maybe the ownership of SP1 should be assigned to the App for the run as account, instead of its service principal.
So I also ran the following:
Add-AzureADServicePrincipalOwner -ObjectId <SP1_ObjectId> -RefObjectId <runasaccount_app_ObjectId>
But this wasn't possible, as I got the error:
Code: Request_BadRequest
Message: The reference target 'Application_xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx' of type 'Application' is invalid for the 'owners' reference.
So I assume the ownership should have been assigned only to SP2, and not to the app.
I looked at here but the accepted answer says
If your user accounts are the Owner of the service principal(Enterprise application), the command New-AzADSpCredential will work.
which is true in my case, and yet, it's not working when running the runbook.
I also looked at here and it seems I need to do the #1 which the OP describes as easy to do.
Any input on how to do this will be greatly appreciated.
If you want to use a service principal to add/remove credentials for another service principal, it is different from using a user account to do that.
I assigned the ownership of SP1 to SP2 as well through the command Add-AzureADServicePrincipalOwner and confirmed it through Get-AzureADServicePrincipalOwner.
This way is correct, but not only the Owner, also you need to give an Application.ReadWrite.OwnedBy Application permission in Azure Active Directory Graph (Not Microsoft Graph)API after that.
Navigate to the API permissions of your automation account corresponded AD App in the portal -> add the permission like below, don't forget to click the Grant admin consent for xxx button at last.
Then test it in the runbook, it works fine.
New-AzADSpCredential -ObjectId xxxxxxxxxxxxx
The combination of Owner and Application.ReadWrite.OwnedBy is the minimum privilege in this case, there are also other ways, you can also give the Application Administrator directory role as you saw here or Application.ReadWrite.All Application permission in Azure Active Directory Graph, both will work.

Permissions error upon running Add-DistributionGroupMember PS cmdlet on Exchange Online

I'm currently trying to automate the user creation in Azure AD, and addition to a distribution group in Exchange Online using a PowerShell script. I've followed this guide for that - I've set up an app registration with a certificate and that's how I'm authenticating to both Azure AD and Exchange Online - without human intervention.
The specific Exchange cmdlet I'm running in the script (for the EXO part) is Add-DistributionGroupMember -member "user#domain.com" -identity "dlist" -BypassSecurityGroupManagerCheck, and once I run it I receive the following error output:
Active Directory operation failed on XXXXXXXXXXXXXXX.XXXXXXXXXXX.PROD.OUTLOOK.COM. This error is not retriable. Additional information: Insufficient access rights to perform the operation.
Active directory response: 00002098: SecErr: DSID-XXXXXXXX, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0
+ CategoryInfo : NotSpecified: (:) [Add-DistributionGroupMember], ADOperationException
+ FullyQualifiedErrorId : [Server=XXXXXXXXXXXXX,RequestId=8ac3130a-4bbe-41a0-b062-4768b6f51234,TimeStamp=1/3/2021 2:18:13 PM] [FailureCategory=Cmdlet-ADOperationException] XXXXXXX,Microsoft.Exchange.Management.RecipientTasks.AddDistribu
tionGroupMember
+ PSComputerName : outlook.office365.com
Other cmdlets such as
Get-Mailbox work correctly, but this specific one is giving me problems constantly. I've tried giving all API permissions I can think of in Azure to the application, both Delegated and Application permissions, and yet I'm still facing the error. Here's the current full list and I've had no success whatsoever:
I also tried replacing some of the Delegated permissions with Application permissions to no avail either. I tried assigning a variety of roles to the application as mentioned in the article too and every single time I get that Insufficient access rights to perform the operation error.
Could someone tell me why? Where and how am I supposed to grant the necessary permissions for the app to add a user to a distribution (mailing) list?
I've been searching around and found no answer to it for that last few days. Any help would be greatly appreciated.
Based on my test, adding Exchange.ManageAsApp Application permission and assigning Exchange Service administrator role is enough.
Create the AAD app with adding Exchange.ManageAsApp Application permission.
$appName = 'Exo_V2_App'
$api = (Get-AzureADServicePrincipal -Filter "AppID eq '00000002-0000-0ff1-ce00-000000000000'")
$permission = $api.AppRoles | Where-Object { $_.Value -eq 'Exchange.ManageAsApp' }
$apiPermission = [Microsoft.Open.AzureAD.Model.RequiredResourceAccess]#{
ResourceAppId = $api.AppId ;
ResourceAccess = [Microsoft.Open.AzureAD.Model.ResourceAccess]#{
Id = $permission.Id ;
Type = "Role"
}
}
$myApp = New-AzureADApplication -DisplayName $appName -ReplyUrls 'http://localhost' -RequiredResourceAccess $apiPermission
$mySP = New-AzureADServicePrincipal -AppID $myApp.AppID
$myApp | Format-List DisplayName,ObjectID,AppID
Assign the service principal to Exchange Service administrator role.
$directoryRole = 'Exchange Service Administrator'
$RoleId = (Get-AzureADDirectoryRole | Where-Object {$_.displayname -eq $directoryRole}).ObjectID
Add-AzureADDirectoryRoleMember -ObjectId $RoleId -RefObjectId $mySP.ObjectID -Verbose
You can try to create a new clean Azure AD app without adding additional configuration to have a test.
If I am not wrong, you should be part of the ManagedBy of the group before adding the members.
Step 1 :
First execute one of the below commands :
Set-DistributionGroup <NameOfGroup> -ManagedBy "<Your Alias>" -BypassSecurityGroupManagerCheck
Or :
Set-DistributionGroup Accounting -ManagedBy #{Add="< Your Alias>"} -BypassSecurityGroupManagerCheck
Step 2 :
Then execute the command to add the user to the group.
Add-DistributionGroupMember -Identity <NameOfGroup> -Member user#contoso.com
We had a very similar issue that was resolved by updating the Exchange Online PowerShell module version from 2.0.5 to 3.1.0.
Command to check version:
Get-InstalledModule ExchangeOnlineManagement | Format-List Name,Version,InstalledLocation
Command to update to latest version:
Update-Module -Name ExchangeOnlineManagement

Azure Automation - Unable to Remove-AzResourceLock

I have an issue deleting an Azure Lock, at the resource group level. I am doing it from an Azure Runbook.
I authenticate fine (I am able to Get details of whatever I want). Here's the code for that:
# Ensures you do not inherit an AzureRMContext in your runbook
Disable-AzContextAutosave –Scope Process
"Logging in to Azure..."
$connection = Get-AutomationConnection -Name AzureRunAsConnection
Connect-AzAccount -ServicePrincipal -Tenant $connection.TenantID -ApplicationId $connection.ApplicationID -CertificateThumbprint $connection.CertificateThumbprint
And if I do, say, Get-AzResource -ResourceGroupName $RG, I get the info I need. But the problem is that I actually need to delete some resources of that resource group, and it has a lock.
When I Remove-AzResourceLock -LockId $getAzureLock.LockId -Force, I am thrown this:
Remove-AzResourceLock : AuthorizationFailed : The client XX with object id XX does not have authorization to perform action 'Microsoft.Authorization/locks/delete' over scope '/subscriptions/<redacted>/resourceGroups/<redacted>/providers/Microsoft.Authorization/locks/resourceDellock' or the scope is invalid. If access was recently granted, please refresh your credentials.
FYI, I've redacted the subscription/object id information.
For the life of me, I am not able to get around it. The application is added as a Contributor at the subscription level, from Access Control (IAM).
I have tried so many things, that I am just to tired to write down! I am sorry. The last 4 hours I've been reading and trying stuffs. So pardon me!
Please, help me get around this..
As per the documentation, only Owner and User Access Administrator built-in roles have the permission to delete a lock and not the Contributor role.
Deletes the management lock of a resource or any level below the
resource. To delete management locks, you must have access to
Microsoft.Authorization/* or Microsoft.Authorization/locks/* actions.
Of the built-in roles, only Owner and User Access Administrator are
granted those actions.
So your solution would be to either grant Owner/User Access Administrator role to your service principal or create a custom role and grant appropriate permissions on Microsoft.Authorization/* actions.

How to Connect-AzAccount in Powershell Core (without prompt)?

I did see this q/a: Connect-AzAccount without prompt
But when I tried the accepted answer, I get the following error:
[6/12/2020 12:36:20 AM] ERROR: Connect-AzAccount : Username + Password authentication is not supported in PowerShell Core. Please use device code authentication for interactive log in, or Service Principal authentication for script log in.
So I went to example 3 of the Connect-AzAccount documentation which specifies the "Service Principal" authentication method, so I mix the two because the suggested vanilla Get-Credential triggers another interactive session. So here's the script now:
$User = "myemail#gmail.com"
$PWord = ConvertTo-SecureString -String "**********" -AsPlainText -Force
$tenant = "f*********************************"
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User,$PWord
# $Credential = Get-Credential
Connect-AzAccount -Credential $Credential -Tenant $tenant -ServicePrincipal
which brings my next error: [6/12/2020 12:45:45 AM] ERROR: Connect-AzAccount : AADSTS700016: Application with identifier 'myemail' was not found in the directory 'f*********************************'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant.
I'm really confused at this point because all I have done at this point in Azure is:
Create a new Azure account
Provision an Azure API Management instance through the UI (which btw, takes like 20 minutes)
Try the above code to connect to Azure inside of a Powershell Azure Function locally.
I think something is wrong with the information I've provided or how I've configured something.
$User is the email I signed up to Azure with.
$PWord is my Azure password
$tenant is the first thing I saw when I opened Azure AD:
What's wrong with how I'm trying to connect to Azure through Powershell Core?
Based on Example 3, it asks for entering your application ID for the username and service principal secret as the password.
So you need to create a service principal at first. And then use its application ID and client secret as the credential.
$User = "{application id}"
$PWord = ConvertTo-SecureString -String "{client secret}" -AsPlainText -Force
I don't like Azure documentation. It gives off a very different vibe from GCP and feels much less beginner friendly.
With that said, they did have some kind of write-up that addresses my issue of creating a service principal and using it to authenticate.
I actually ended up just finding a video (and I never do this) because I wanted to skip past all the technical jargon and just create the darn service principal.
It's not even intuitive - it's like Microsoft could have added a button in AZ AD or IAM that said "Create Service Principal" but no, you have to go to a bunch of other pages that say nothing about service principals. You'll see:
In Azure Portal, navigate to the App Registrations page in Azure Active Directory. What an "app registration" has to do with a service principal, I couldn't tell you. I also couldn't tell you what a service principal is, but I'd imagine it has something to do with service accounts.
Make a New Registration and give it some sort of name to describe what the scope of this service principal will entail. Like normal service account naming conventions. I don't think the account type matters but I chose Multitenant. Redirect URL has nothing to do with service principals, and honestly makes it all the more confusing. I would never associate service accounts with any kind of redirect url, but here we are.
You're going to arrive at a page with Display Name (the name of the service principal you gave it in step 2), Application (client) ID (this is actually your service account username, which is imo non-intuitive), and Object ID (I have no idea what this is but I never needed to use it.
Guess what, you have only created 1/3 of your service account. It doesn't even have a password yet. Within your created app registration, there's a Certificates & Secrets page. On that page, you want to add a new client secret. For my description I just put my service principal "display name". I don't think that was necessary because this client secret is within the scope of the app registration, so even if I named it "poop" I could reasonably assume what it was for. Azure will generate a nuanced client secret and display it, but not warn you that this is the only time you will be able to see the key. Copy it. This is, in normal people talk, your service principal password.
For the last step, you need to get out of dodge, I mean Azure AD. Navigate to your Subscriptions page and click on your active subcription. For some reason IAM is here, so click on that. At this point, your service principal has a username and password, but no actual permissions - you have to configure that manually too. Click Add -> Add Role Assignment. For role, you should do your research but if it's not serious Contributor is probably a safe bet. It has read/write but it doesn't supersede Owner. Make sure you're assigning access to a service principal, and search for its display name. Save.
With all of that done, Connect-AzAccount finally worked.

Resources