Sync Sharedchannel Owners Scheduled
Ensure a security group's members are owners of mapped Teams and their shared channels.
Description
Teams shared channels do not inherit ownership from their parent team. This scheduled runbook closes that gap: for each team named in a mapping, it ensures the members of a mapped security group are owners of the team and of every shared channel the team hosts. The team-name-to-owner-group mapping is maintained centrally as a RealmJoin org setting. The runbook is add-only - existing owners and members are never removed - so newly created shared channels are simply picked up on the next run. It can optionally email a report and/or upload the CSV results as a download link. See the accompanying documentation for the mapping rules and configuration.
How it works
On each run the runbook:
Reads the team-name-to-owner-group mapping from the org setting
SharedChannelOwners.Mapping.For each entry, looks up the team by its exact display name.
Expands that entry's owner group to its transitive user members (guests are skipped - they cannot belong to a shared channel).
Ensures those users are owners of the team and of every hosted shared channel of the team.
The runbook is add-only: it never demotes or removes existing owners or members. Newly created shared channels are therefore picked up automatically on the next scheduled run, without disturbing anything already in place.
Mapping configuration
The mapping lives centrally in the RealmJoin org settings (Runbook Customization → Settings → SharedChannelOwners.Mapping) so it is maintained once and shared by every schedule. It is a list of { TeamName, OwnerGroupId } objects, where TeamName is the exact team display name (see the Notes section for a ready-to-use example). The hidden TeamOwnerGroupMapping parameter is injected from this setting; the runbook accepts it either as a structured array (recommended sub-setting form) or as a JSON string and normalizes both.
Team matching
Each mapping entry targets one explicitly named team:
A team is matched by its exact display name (case-insensitive, consistent with Microsoft Graph; surrounding whitespace in the configured name is ignored). Only that team is processed - there is no prefix or wildcard behaviour, so naming an entry
EXT Service Anever affectsEXT Service A Backupor similar.Display names are not guaranteed unique in Entra ID. If several teams share the configured name, the owner group is applied to all of them. If no team matches, the entry is reported as not found and skipped.
Team selection
For every configured TeamName the runbook runs a Graph displayName eq '...' lookup and keeps only Microsoft 365 groups that are provisioned as a Team.
What gets changed
Team (optional,
IncludeTeamOwners, default on): the owner-group users are added as owners and members of the parent M365 group. Team membership is also the technical prerequisite for becoming a shared-channel owner, so this step enables the channel step.Shared channels: for every hosted shared channel (
membershipType eq 'shared'), each owner-group user is ensured as a channel owner - added directly if absent, or promoted if already a member. If a direct owner-add is rejected (e.g. membership replication lag), the runbook falls back to adding the user as a member first and then promoting.
Dry run
Set WhatIfMode to log what would change without writing anything. In this mode the runbook prints, up front, the teams it would process (with their owner group) and any configured team names that were not found.
Reporting (optional, both default off)
SendEmailReportsends a RealmJoin-branded email (viaSend-RjReportEmail) with run statistics and two CSV attachments: a per-team summary and a per-change detail list. The sender is taken from theRJReport.EmailSendersetting.CreateDownloadLinkuploads the same CSVs to a storage account and returns time-limited SAS download links (also embedded into the email when both options are enabled). The target storage account is taken from theRJReport.StorageAccount.*settings.
The storage upload authenticates with the Automation account's managed identity; that identity needs the Storage Blob Data Contributor RBAC role on the target storage account (this is an Azure RBAC assignment, not a Graph application permission).
Scheduling
Designed to run unattended on a schedule. Because configuration is centralized in the org settings and the runbook is add-only and idempotent, a single recurring schedule keeps all mapped teams and their shared channels in sync as people and channels come and go.
Location
Organization → General → Sync Sharedchannel Owners (Scheduled)
Full Runbook name
rjgit-org_general_sync-sharedchannel-owners_scheduled
Permissions
Application permissions
Type: Microsoft Graph
Group.ReadWrite.All
GroupMember.ReadWrite.All
Channel.ReadBasic.All
ChannelMember.ReadWrite.All
Mail.Send
Parameters
TeamOwnerGroupMapping
Mapping of an exact team display name to an owner security group object id, e.g. [{ "TeamName": "EXT Service A", "OwnerGroupId": "00000000-0000-0000-0000-000000000000" }]. Hidden parameter, bound to the org Setting "SharedChannelOwners.Mapping". The RealmJoin portal injects that value; the runbook accepts it either as the deserialized object/array (structured sub-settings) or as a JSON string and normalizes both.
Required
false
Default Value
[]
Type
Object
IncludeTeamOwners
When enabled (default), the owner-group members are also ensured as owners and members of the parent team itself (M365 group owners/members). Team membership is also the prerequisite for channel ownership.
Required
false
Default Value
True
Type
Boolean
WhatIfMode
When enabled, the runbook only logs the changes it would make without writing anything.
Required
false
Default Value
False
Type
Boolean
SendEmailReport
When enabled, a RealmJoin-branded email report is sent via Send-RjReportEmail after the run. The body contains run statistics and two CSV attachments (per-team summary and per-change detail).
Required
false
Default Value
False
Type
Boolean
EmailTo
Recipient email address(es) for the report (comma-separated). Only used when SendEmailReport is enabled.
Required
false
Default Value
Type
String
EmailFrom
Sender mailbox for the report. Bound to the org Setting "RJReport.EmailSender".
Required
false
Default Value
Type
String
CreateDownloadLink
When enabled, the CSV report(s) are uploaded to a storage account and a time-limited download link is returned (and included in the email report if that is also enabled). Default off.
Required
false
Default Value
False
Type
Boolean
ContainerName
Storage container used for the upload. Configured per runbook (not a global RJReport setting).
Required
false
Default Value
shared-channel-owners
Type
String
ResourceGroupName
Resource group that contains the storage account. Bound to "RJReport.StorageAccount.ResourceGroup".
Required
false
Default Value
Type
String
StorageAccountName
Storage account used for the upload. Bound to "RJReport.StorageAccount.StorageAccountName".
Required
false
Default Value
Type
String
LinkExpiryDays
Days until the generated download link expires. Bound to "RJReport.StorageAccount.LinkExpiryDays".
Required
false
Default Value
6
Type
Int32
Last updated
Was this helpful?