The default setting for all organizations using Teams is the phone numbers are masked from the participants outside of the organization. The phone numbers are fully displayed to internal participants.
Based on certain uses cases and added privacy, Teams administrators have the ability to choose how the participants’ phone numbers appear in meetings. Options available,
Phone numbers are not masked, which makes it visible to everyone in the meeting
Phone numbers are masked for everyone except the organizer
Phone numbers are masked only from external participants
Using PowerShell to define phone-number masking
Use the MaskPstnNumbersType parameter of the Set-CsOnlineDialInConferencingTenantSettings cmdlet to change PSTN masking setting,
Please checkout Part I if you landed directly on this page.
This post is a continuation how to Forms and Power Automate can be used to create an approval workflow to automatically provision a Team. We will see the user’s experience here.
When user submits the Microsoft Form, the approver gets an email.
In my scenario, I’m using a service account called ‘Teams admin’ and I can see the email as below,
In the Outlook.office.com, the approver can directly click on ‘Approve’ or ‘Reject’ and also add comments if they wish to.
Once approved, the rest of the flow runs and at the end the user gets an email confirming the Team creation.
User can also launch Teams and check that he is part of the new Team that was created.
As you can see the ‘Teams admin’ service account is also a owner in the Team it created. This might become an issue during compliance audits and this can be fixed by adding a step in Power Automate with a HTTP request.
The HTTP request option is a premium feature and hence no screenshot here.
Teams has become more popular in the recent work from home era and the list of features it offers are great and no doubt about it. Microsoft keeps adding more appealing features for remote and users working from office locations. As more companies adopt Teams for its collaboration features which help increase productivity, no one wants to lose control of the M365 environment because of what is bein allowed to be created or provisioned by the users.
In this post, I’ll go over a on a high-level of what is a Team and what happens when Team is created. Also I’ll go over steps which I recently used to implement a Teams provisioning with an approval workflow process using Microsoft Forms and Power Automate.
What is a Team?
In Microsoft Teams, Teams are groups of people brought together for work, projects, or common interests. Teams are made up of two types of channels,
Standard
Is open for all members and anything posted is searchable by others
Private
Focused, private conversations with a specific audience. Example: Specific audience for a particular subject
Files shared are only viewable by the members of the channel and are stored in a separate SharePoint site from the rest of the team’s files
Shared channels
For collaborating with people inside and outside your team or organization
Only team owners can create shared channels
Only shared channel owners can add members or share the channel with a team
Can’t be changed to standard or private channel and vice versa
What happens when a Team is created?
When a Team is created, the following also gets provisioned,
A corresponding O365 group
Owner of the O365 Group is the Owner of the team
The members of the Group are the Members of the team, as added by the person who created the Team
An Exchange mailbox with a Group email address
Will appear in everyone’s Outlook client
A new SharePoint site is created
Sharing files via Teams leads to data being stored either in SharePoint or OneDrive
Files uploaded to a Teams channel are automatically saved to the Teamβs SharePoint folder
Files uploaded in a 1:1 or group chat are stored in the OneDrive folder and shared only with colleagues in that conversation
A connection to OneNote
Team Creation Options
As I put together above, it is easy to see that adding a Team might seem like a simple task and it is but from a data security and governance point of view, it can easily get out of hands if controls are not put it place. When you role out Microsoft Teams, you get a few options on how to handle Team creation.
Allow all users to create Teams
This will allow users to create their own Teams without any restrictions. This is the easiest option but easy to lose control and will eventually add more burden on the IT admins
Block all users from creating Teams
This is the most restrictive option and users have to reach out to IT to create Teams. There is also a risk of users moving onto more accessible solutions that don’t take compliance and security policies seriously and ending up shadow IT in the process
Limit to a certain security group
With this option, we can limit a certain group of users to be able to create groups/Teams. I like this idea and to add to it, I’ll have someone from the compliance team in charge of this if that was an option. I’ve covered how to limit a certain group in an earlier post
That being said, IMO it is best to have an approval workflow and a controlled provisioning process for Teams creation. This will help any organization to prevent sprawl, uncontrollable growth, help IT admins reduce some unnecessary work and more importantly allow a controlled adoption of Microsoft Teams while helpdesk and IT admins catchup.
Teams Provisioning and Approval Workflow with Power Automate
I’ll detail the steps needed to create a provisioning workflow with the native capabilities in Forms and Power Automate.
Components involved in creating this workflow,
Microsoft Forms
Power Automate
SharePoint (optional)
I’ve put together a flowchart of the thought process,
Some considerations to keep in mind,
It is better to create the Microsoft Forms and Power Automate Flow using a service account which has a mailbox enabled and permissions within Teams to create Team. This is usually a good idea because, if this was created under a specific Teams administrator account and if he or she wins a lottery and figures not to show up for work anymore, this process can go on without disruption and is one less thing for you to worry while disabling the administrator’s account.π
In my scenario, I’m using a service account to setup the components needed.
Microsoft Forms
Microsoft Forms is a great product and I love the simplicity. With enough time and effort, I think organizations can leverage Forms to get rid of most of what their users are doing on paper forms.
I’ve created a simple form titled ‘New Team Creation Request Form’ to collect the information needed to create a Team. You can also use SharePoint instead of Forms but this approach is much easier.
I’ve added branching to the 6th question.
Logic behind 6th question: If private Team, provide justification. If not, go to question 8
If you’d like to get fancy, there is PowerApps which will require more effort and depends on your knowledge into it.
Power Automate
Open Power Automate
Click My Flows
Click on New Flow and Select Automated cloud flow
Click Skip on the Build an automated cloud flow pop-up window
Search for ‘forms’ and select Microsoft Forms and then When a new response is submitted
Note: It is good practice to rename every step while you create it with the purpose of what that step does.
As I created the Form with the same account, it shows up in the drop-down
Click New Step, Microsoft Forms –> Get response details
This action retrieves a form response
Select the Form in Form Id and in Response Id, click Add dynamic content and select Response Id
Add step, search for Azure AD and in actions select Get user
The next two steps are to get information about the requestor and the owner from Azure AD
This is useful while sending email to the approver, these values can be used
User Id or Principal Name –> Add dynamic content and select Responder’s Email from the form
Similarly in the second step, User Id or Principal Name –> Add dynamic content and select ‘Please enter email address of who will be this Team’s owner’ in under ‘Get response details’
In the next step, I’m initializing a variable called varCoOwners. And in the step after, I’m using the compose action to do a split based on comma
The reason why we need these two steps is, in the Form we have an entry to input co-owners and if more than one co-owner email address is entered by the user comma-separated, the entire value is considered a string
Power Automate is looking for an array
The split function breaks down a string into an array of strings using a delimiter we define
We are going to use comma
split(variables('varCoOwners'),',')
Next step, add Start and wait for an approval
This starts an automated approval process and then waits for it to complete. The approval is cancelable
I’m choosing the Approval type as Approve/Reject – First to respond
Optional Step. Updating a SharePoint list for tracking.
We add a condition to see if the request was approved
We add condition control which performs one or more tasks only if a condition is true or false
Outcome = Approve
Continuing from the previous condition step,
If yes –> We create a Team, add Team owner, add Team co-owner(s) and send an email to the requestor
Create a Team based on submitted Form
Add Team Owner
Team = New Team ID
A user AAD ID for the user to add to a team = UPN from ‘Get Team owner’s info’ Azure AD step
Should the newly added user be an owner of the team = Yes
Add Team Co-owners
Search Control -> Apply to each -> In Select an output from previous steps, select Output of compose step
Azure AD -> Get User ->In User Id or Principal Name, select Current item
Teams -> Add a member to a team
Team = New Team ID
A user AAD ID for the user to add to a team = UPN from ‘Get Co-Owners’ Azure AD step
Should the newly added user be an owner of the team = Yes
If no –> We send an email to the requestor with comments from the approver
See below on how the steps are done,
Continuation on ‘If yes’ after ‘Add co-owners to team’ step,
Final Automated Flow
This is how the final automated flow looks,
I added a step to remove a member from group. This is for removing the service account which created the Team from being a member. As Teams are in turn Azure AD security groups, I used a remove member from group action to remove the service account. I noticed that this step failing often and the reason was the Azure AD group was not found and hence I added a delay of a 3 minutes and then run the action.
This might seem a little too overwhelming at first glance but once you understand the power of Microsoft Forms, Power Automate, SharePoint and the potential it brings to organizations, you’ll be complaining about what more features you’d like to have in this in no time.
I’ll cover the user experience of this process in a following post.
It is important to know about the current state of your Teams rollout and this is one of those which can easily get out of control in a blink of an eye. I wanted to understand and determine the current Teams state in a tenant I manage and I had to create reports to present.
The portal does give a few options to export the data but I decided to take a look at the option the Teams PowerShell module offers. I spent some time on creating a script that will output these five reports,
All Teams data with Channel type, Channel count, Channel count with types, Teams member count and owners count
Teams users data with role information
Channel information for each Teams with Channel types
Channel user information with user information and role
Permissions on each Teams
This report can also be scheduled to run if you already use a mechanism to store your credentials securely and pass it on to your PS scripts.
I use the ImportExcel PowerShell module for this script,
Install-Module -Name ImportExcel
Before proceeding further, make sure you have the Teams PowerShell module installed. You’ll need to run this script with Teams Administrator role.
This one took me a while to understand what is happening and how to resolve it. The Teams audio and calling functions are not something I deal with on a daily basis but it was good learning experience.
One of the Teams tenant I manage kept running out of pooled minutes really quickly. I wasn’t actively monitoring the usage but I did notice the emails from Microsoft that were warning us that the minutes are almost used up and users won’t be able to use the PSTN conferencing services for the rest of the calendar month unless more communication credits were added.
What is the deal here exactly?
Each user assigned an ‘Audio Conferencing’ license which provides a dial-in phone number when they schedule a meeting, is given 60 minutes per month of pooled minutes that can be used for inbound or outbound PSTN dialing for meetings. This ‘Audio Conferencing’ license is only needed for users scheduling the meetings. Meeting attendees who dial in don’t need this license. Depending on how you have deployed Teams in your organization, whether as a full blown phone system or used specifically for meetings, this pooling minutes is only for meetings and is separate from other dial plans(domestic or international) that you may have.
Users with ‘Audio Conferencing’ license are given a default invite number in the same country as what their O365 account’s usage location is set to.
In a example scenario where an organization has 100 users that have ‘Audio Conferencing’ license, 100 X 60 minutes and you get 6000 pooled minutes for your tenant to PSTN dial-in and dial-out of meetings. One the 6000 minutes are consumed users will no longer be able to dial-in or dial-out of the meetings using the number provided in the meetings.
Note: Users can still participate using the Teams meeting clients(Desktop or phone app).
Why users use the PSTN dial-in numbers for Teams online meetings
Personally I love the Teams app, both on the desktop and the phone. And I can tell Microsoft is adding new functionalities over time. I also like it how I can use the phone app for voice and also launch Teams on my desktop and I get an option to ‘add the device’ to the ongoing call on the phone. This way, I can present using the desktop.
Using this VOIP features via the Teams app(phone or desktop) doesn’t incur additional cost to the organization but there are some scenarios where including a dial-in number to meetings makes sense,
Poor or limited internet connectivity
Users moving in and out of limited data coverage where voice quality may be better
Users having issues with VOIP on their PC and phone app
Users are used to the old ways
Users lack training in Teams clients(Desktop or phone app)
Determine pooled minutes and usage
To check your PSTN pooled minutes, you can run usage reports in the Teams admin center,
Teams Admin Center –> Analytics & reports –> Usage reports
PSTN minute and SMS(preview) pools
PSTN and SMS(preview) usage
What is burning precious PSTN minutes
Based on the reports and further reading I realized the ‘Call me‘ feature in Teams is apparently a well known and heavily used user loved feature which seems to be a behavior that followed users from using other conferencing tools.
Users can join a meeting and have the meeting call and join them or dial in manually to the meeting.
As I mentioned earlier, the users using this feature didn’t realize they can use their computer audio or the Teams app on their phone. There were others who thought this was a handy feature and more convenient. Well, what they didn’t know or didn’t care is, the outbound calls were eating those pooled PSTN minutes and affecting the entire organization for users who would really need it.
What is the fix?
This can be fixed by educating the users about the VOIP options, using the computer or phone Teams app. And yes, obviously by putting policies in the tenant.
In the Teams admin center, the dial-out from meeting can be controlled on a per-user basis
In the left navigation, select Users, and then select the display name of the user from the list of available users
Under Audio Conferencing, select Edit
Under Dial-out from meetings, select the dial-out restriction option you desire
Select Save
This may resolve the issue by assigning ‘Don’t allow’ policy for the users who are the heavy hitters of the ‘Call me’ feature but more users might start using this feature and you’ll have to constantly monitor the usage.
To prevent this, you can set a tenant level policy based on your requirements and organizational needs. Once the global policy is in place, you can assign a policy on a per-user level.
The following table provides an overview of each policy.
PowerShell cmdlet
Description
DialoutCPCandPSTNInternational
User in the conference can dial out to international and domestic numbers, and this user can also make outbound calls to international and domestic numbers.
DialoutCPCDomesticPSTNInternational
User in the conference can only dial out to domestic numbers, and this user can make outbound calls to international and domestic numbers.
DialoutCPCDisabledPSTNInternational
User in the conference can’t dial out. This user can make outbound calls to international and domestic numbers.
DialoutCPCInternationalPSTNDomestic
User in the conference can dial out to international and domestic numbers, and this user can only make outbound calls to domestic PSTN number.
DialoutCPCInternationalPSTNDisabled
User in the conference can dial out to international and domestic numbers, and this user cannot make any outbound calls to PSTN number besides emergency numbers.
DialoutCPCandPSTNDomestic
User in the conference can only dial out to domestic numbers, and this user can only make outbound call to domestic PSTN numbers.
DialoutCPCDomesticPSTNDisabled
User in the conference can only dial out to domestic numbers, and this user cannot make any outbound calls to PSTN number besides emergency numbers.
DialoutCPCDisabledPSTNDomestic
User in the conference can’t dial out, and this user can only make outbound call to domestic PSTN numbers.
DialoutCPCandPSTNDisabled
User in the conference can’t dial out, and this user can’t make any outbound calls to PSTN number besides emergency numbers.
DialoutCPCZoneAPSTNInternational
User in the conference can only dial out to Zone A countries and regions, and this user can make outbound calls to international and domestic numbers.
DialoutCPCZoneAPSTNDomestic
User in the conference can only dial out to Zone A countries and regions, and this user can only make outbound calls to domestic PSTN number.
DialoutCPCZoneAPSTNDisabled
User in the conference can only dial out to Zone A countries and regions, and this user can’t make any outbound calls to PSTN number besides emergency numbers.
To set the policy on the tenant level, use following cmdlet. Use the pre-defined policy from the table above for the ‘policy name’
In my scenario, my plan is to set the global dial-out from meetings policy to DialoutCPCandPSTNDisabled. And assign per-user policy based on their needs.
Note: All users of the tenant who don’t have any dial-out policy assigned will get the global policy.
You can set what is allowed per-user using the Teams admin center as covered earlier or you can use PowerShell to assign a policy to a list of users using this below script.
#Connect-MicrosoftTeams
$list=import-csv "c:\tmp\user.csv"
Foreach($user in $list){
Grant-CsDialoutPolicy -identity $user.UserId -PolicyName "DialoutCPCandPSTNDomestic" #Setting 'DialoutCPCandPSTNDomestic' policy to the users
}
You can also export a report of users and their Dial-Out policy assigned to them,
Teams and its audio services are a much more detailed topic and I covered what applied to the issue I faced. Hope you’d be able to as well if you encounter this.