Set-CalendarProcessing -ResourceDelegates (and Friends) Without Tears

(Get-CalendarProcessing -Identity “MyAwesomeRoom”).ResourceDelegates is equal to (Get-Mailbox -Identity “MyAwesomeRoom”).GrantSendOnBehalfTo. This is good to know, because while you can do Set-Mailbox -GrantSendOnBehalfTo @{add=”user3@awesome.com”} and not kick out user1 and user2, Set-CalendarProcessing does not do this. If you try it, you get back this mess:

Cannot process argument transformation on parameter ‘ResourceDelegates’. Cannot convert the “System.Collections.Hashtable”
value of type “System.Collections.Hashtable” to type “Microsoft.Exchange.Configuration.Tasks.RecipientIdParameter[]”.

Unfortunately, I have yet to find a similar, more friendly route for adding BookInPolicy, RequestInPolicy or RequestOutOfPolicy.

All of these parameters will take an array, so you need to read in what’s there, append your new delegate(s), then write the new list to Set-CalendarProcessing:

function Add-CalendarResourceDelegate {
Param(
$roomName
, $newDelegate
)
$resourceDelegates = (Get-CalendarProcessing -Identity $roomName).ResourceDelegates
$resourceDelegates += $newDelegate
Set-CalendarProcessing -Identity $roomName -ResourceDelegates $resourceDelegates
}
function Add-CalendarBookInPolicy {
Param(
$roomName
, $newDelegate
)
$bookInPolicy = (Get-CalendarProcessing -Identity $roomName).BookInPolicy
$bookInPolicy += $newDelegate
Set-CalendarProcessing -Identity $roomName -BookInPolicy $bookInPolicy
}

Add-CalendarResourceDelegate -roomName “MyAwesomeRoom” -newDelegate user3

Removing delegates is a bit trickier; they are stored in the array as canonical names (awesome.com/Site1/Users/user1), not email or UserPrincipalName (User.One@awesome.com or user1@awesome.com). However, you just need to do (Get-Mailbox user1).Identity to get this.

function Remove-CalendarResourceDelegate {
Param(
$roomName
, $delegateToRemove
)
$resourceDelegates = (Get-CalendarProcessing -Identity $roomName).ResourceDelegates
$delegateToRemoveIdentity = (Get-Mailbox $delegateToRemove).Identity
$resourceDelegates.Remove($delegateToRemoveIdentity)
Set-CalendarProcessing -Identity $roomName -ResourceDelegates $resourceDelegates
}

And so on for BookInPolicy, RequestInPolicy and RequestOutOfPolicy.

A step closer to extending ActiveRoles Server to handle all the Set-CalendarProcessing attributes…

The publicDelegates AD Attribute: Change GrantSendOnBehalfTo the ARS Way

While the Active Directory object’s publicDelegates attribute matched the contents of (Get-Mailbox “aliasGoesHere”).GrantSendOnBehalfTo for all the resource mailboxes and distribution groups I checked, I hesitated to give the way of modifying publicDelegates directly with ARS instead of using Set-Mailbox -GrantSendOnBehalfTo with Exchange Management Shell in my previous post on this topic. A little more research (and trial and error) shows that indeed, publicDelegates really is what Exchange uses to decide who gets to send stuff on behalf of another mailbox.

Here is a thread from the [ActiveDir] listserv archive in which Joe Richards, an author of the classic O’Reilly Active Directory reference, states that “[t]he stuff in AD is strictly how Send On Behalf is controlled” and goes on to explain how an update bug in Exchange 2003 might prevent a recent change from being propogated to a user in a different domain from the delegated object. Since the conversation took place before Exchange 2007 was on the scene, I was a bit skeptical about its applicability to Exchange 2010.

To see which one of several dozen edsva-MsExch-blahblahblah attributes does this for the ARS connector to Exchange 2010, I used the ARS web interface to add and remove delegates from the “Send on Behalf” list of one of the test room mailboxes (Exchange Properties -> Delivery Options -> (Send on behalf) “Add”), then looked at the Change History for that room mailbox. The publicDelegates attribute was the only item changed. Still, I was concerned: the publicDelegatesBL for the delegates outside the domain of the room mailbox weren’t getting updated.

For comparison, I added some delegates the Exchange way:

Set-Mailbox “Room Name” -GrandSendOnBehalfTo @{add=”username”}

Then the Quest AD Management Shell way:

Set-QADUser -ObjectAttributes @{publicDelegates=@{append=(Get-QADUser username).DN}}

(trying to append the username directly didn’t work; it wants the distinguishedName)

After some more experimentation, I discovered that when a user in an different domain is added to the publicDelegates attribute, the delegated object will not show up in the user’s publicDelegatesBL, whether you use Exchange, Quest AD Management Shell or the ARS web interface, while the change to publicDelegatesBL occurs immediately for delegates within the domain of the delegated object. Cross-domain delegated objects will only show up in a user’s publicDelegatesBL once that user has connected to the object for the first time.

If anyone knows why this is, what trouble it might cause, or better yet, how to fix it, please post a comment. More importantly, if anyone knows of a reason NOT to use publicDelegates instead of GrandSendOnBehalfTo, please let me know. And let the ActiveRoles Server dev team know ­čÖé

Fun fact about the CalendarProcessing ResourceDelegates attribute: it is equal to a resource mailbox’s GrantSendOnBehalfTo, which is controlled by the AD attribute publicDelegates.

Next step: figuring out how to control the other CalendarProcessing attributes via ARS.

Goal: Complete management of resource mailboxes via ARS.

Modifying GrantSendOnBehalfTo Without Tears

If you run the cmdlet

Set-DistributionGroup "Sales Team" -GrantSendOnBehalfTo jonestom

you will overwrite the current contents of that distribution group’s GrantSendOnBehalfTo list. Oops.

One of my colleagues, a very old Exchange hand and a new PowerSheller, asked me if there was a simpler way to add one mailbox owner ($trustee) to the GrantSendOnBehalfTo attribute of another Exchange mailbox or distribution group ($target) than having to get both items, extract $trustee.distinguishedname and the current value of $target.GrantSendOnBehalfTo (and save it to another variable, $currentTrustees), append the trustee’s distinguished name to the current list of trustees ($currentTrustees += $trustee.DistinguishedName), then finally replace the old value of $target.GrantSendOnBehalfTo with $currentTrustees (Set-DistributionGroup $target -GrantSendOnBehalfTo $currentTrustees)

Yes, there is, at least as of Exchange 2010 SP1.

Set-DistributionGroup "Sales Team" -GrantSendOnBehalfTo @{add='domainA\jonestom','domainB\smithjane'}

Removing an unwanted trustee works the same way:

Set-DistributionGroup "Sales Team" -GrantSendOnBehalfTo @{remove='domainA\jonestom'}

Because combining these operations often does not end well, here is a cmdlet I made for the help desk to replace a departing colleague with his successor:

function Replace-DLGrantSendOnBehalfTo {
Param($oldTrustee,
	$newTrustee,
	$targetDistributionGroup
	)
Set-DistributionGroup $targetDistributionGroup -GrantSendOnBehalfTo @{add=$newTrustee}
Set-DistributionGroup $targetDistributionGroup -GrantSendOnBehalfTo @{remove=$oldTrustee}
}

For greater efficiency, it can be part of a pipeline, preceded by the names of the target distibution groups and surrounded by a foreach statement. A similar cmdlet can be made for mailboxes. There is probably a way to make it more generic; I might add that later.

The only article I’Ve seen that showed the @{add=$foo}, @{remove=$bar} way to modify this: http://blogs.technet.com/b/manjubn/archive/2012/10/02/grantsendonbehalfto-permissions-for-mailbox-overwrites-existing-permission.aspx

An article that shows the longer way around I described at the beginning, but gives a good explanation of the difference between GrantSendOnBehalfTo and SendAs permissions in Exchange: http://exchangeserverpro.com/exchange-2010-grant-send-behalf-permissions-distribution-group