Featured image of post Automating with PowerShell: Deploying Microsoft Teams Templates

Automating with PowerShell: Deploying Microsoft Teams Templates

One of the biggest challenges we’ve faced when moving over our client base towards a cloud-only infrastructure has been the development of Teams. Teams is amazing tool on it’s own but there is a risk regarding governance and training, but also explosive growth of teams and the way these are implemented. Especially because Teams makes self-services super easy.

So, to assist our clients we’ve created a Teams Template that we deploy to everyone to help them out in how to set-up their Teams environment. This template is pushed towards all our clients using the Secure Application Model. The script I’m sharing can easily be adapted to fit your own needs. As an example we’re creating an IT-support team, but you can also edit the template as a general Team deployment that you use everywhere.

The script

Our template team will have two channels. An announcement channel, and a training channel. The training channel will have a tab to our ticketing system, a tab to our FAQ, and a tab our online training website. You could even attach an email address to a channel directly so you have an easy way to distribute announcements.

Before you continue, make sure your secure application model app has the following permissions added:

  • Go to the Azure Portal.
  • Click on Azure Active Directory, now click on “App Registrations”.
  • Find your Secure App Model application. You can search based on the ApplicationID.
  • Go to “API Permissions” and click Add a permission.
  • Choose “Microsoft Graph” and “Application permission”.
  • Add the following permissions: Team.Create, Group.ReadWrite.All, Directory.ReadWrite.All
  • perform the same for “Delegate Permissions”.
  • Finally, click on “Grant Admin Consent for Company Name.

After you’ve done this, change the parameters in the script to whatever you want them to be. If you want to remove the “General” team or apply other settings such as classroom rules, voting systems, etc. then check out the Teams Templates at the documentation here.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
######### Secrets #########
$ApplicationId = 'AppID'
$ApplicationSecret = 'AppSecret' | ConvertTo-SecureString -Force -AsPlainText
$TenantID = 'YourTenantID'
$RefreshToken = 'TheannoyinglyLongRefreshToken'
######### Secrets #########

$credential = New-Object System.Management.Automation.PSCredential($ApplicationId, $ApplicationSecret)

$aadGraphToken = New-PartnerAccessToken -ApplicationId $ApplicationId -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.windows.net/.default' -ServicePrincipal -Tenant $tenantID
$graphToken = New-PartnerAccessToken -ApplicationId $ApplicationId -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.microsoft.com/.default' -ServicePrincipal -Tenant $tenantID
Connect-MsolService -AdGraphAccessToken $aadGraphToken.AccessToken -MsGraphAccessToken $graphToken.AccessToken
$customers = Get-MsolPartnerContract -All

foreach ($customer in $customers) {
$OwnerID = (get-msoluser -TenantId $customer.TenantId "YourAdminUser@$($customer.DefaultDomainName)" ).ObjectId

$TeamsSettings = [PSCustomObject]@{
    "template@odata.bind" = "https://graph.microsoft.com/v1.0/teamsTemplates('standard')"
    "visibility"          = "Public"
    "displayName"         = "IT-Support Team"
    "description"         = "The Team for all your IT support needs"
    "memberSettings"      = @{
        "allowCreateUpdateChannels"         = $false
        "allowDeleteChannels"               = $false
        "allowAddRemoveApps"                = $false
        "allowCreateUpdateRemoveTabs"       = $false
        "allowCreateUpdateRemoveConnectors" = $false
    }
    "guestSettings"       = @{
        "allowCreateUpdateChannels" = $false
        "allowDeleteChannels"       = $false
    }
    "funSettings"         = @{
        "allowGiphy"            = $false
        "giphyContentRating"    = "Moderate"
        "allowStickersAndMemes" = $false
        "allowCustomMemes"      = $false
    }
    "messagingSettings"   = @{
        "allowUserEditMessages"    = $false
        "allowUserDeleteMessages"  = $false
        "allowOwnerDeleteMessages" = $false
        "allowTeamMentions"        = $false
        "allowChannelMentions"     = $false
    }
    "discoverySettings"   = @{
        "showInTeamsSearchAndSuggestions" = $true
    }
    "members" = @(@{
           "@odata.type" = "#microsoft.graph.aadUserConversationMember"
           "roles" = @("owner")
           "user@odata.bind" = "https://graph.microsoft.com/v1.0/users('$($OwnerID)')"
        })
    "channels"            = @(@{
            "displayName"         = "Announcements ?"
            "isFavoriteByDefault" = $true
            "description"         = "This is a channel for announcement from your IT-Provider"
        }
        @{
            "displayName"         = "Training ?️"
            "isFavoriteByDefault" = $true
            "description"         = "This channel contains all IT-training stuff."
            "tabs"                = @(@{
                    "teamsApp@odata.bind" = "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps('com.microsoft.teamspace.tab.web')"
                    "displayName"         = "YourWebsite.com"
                    "configuration"       = @{
                        "contentUrl" = "https://docs.microsoft.com/microsoftteams/microsoft-teams"
                    }
                }, @{
                    "teamsApp@odata.bind" = "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps('com.microsoft.teamspace.tab.web')"
                    "displayName"         = "An FAQ"
                    "configuration"       = @{
                        "contentUrl" = "https://google.com"
                    }
                }
            )
        }
    )
} | convertto-json -Depth 10
    write-host "Logging into tenant $($customer.DefaultDomainName)"
$body = @{
        'resource'      = 'https://graph.microsoft.com'
        'client_id'     = $ApplicationId
        'client_secret' = ((New-Object PSCredential "user", $ApplicationSecret).GetNetworkCredential().Password)
        'grant_type'    = "client_credentials"
        'scope'         = "openid"
    }
    $ClientToken = Invoke-RestMethod -Method post -Uri "https://login.microsoftonline.com/$($customer.TenantId)/oauth2/token" -Body $body -ErrorAction Stop
    $headers = @{ "Authorization" = "Bearer $($ClientToken.access_token)" }

    write-host "Creating Team for tenant $($customer.DefaultDomainName)"
    $Teams = (Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/teams" -Headers $Headers -Method POST -body $TeamsSettings -ContentType "application/json" -verbose)

}

As always, Happy Powershelling!

P.S. Have you registered for the CyberDrain CTF yet? The CyberDrainCTF is an event just for SysAdmins, IT-Pros, and MSPs. more info at ctf.cyberdrain.com

All blogs are posted under AGPL3.0 unless stated otherwise
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy