Connect-O365.ps1
<#PSScriptInfo
.TITLE Connect-O365 .VERSION 1.5.6 .GUID a3515355-c4b6-4ab8-8fa4-2150bbb88c96 .AUTHOR Jos Verlinde [MSFT] .COMPANYNAME Microsoft .COPYRIGHT .TAGS O365 RMS 'Exchange Online' 'SharePoint Online' 'Skype for Business' 'PnP-Powershell' 'Office 365' .LICENSEURI .PROJECTURI mailto:jos.verlinde@microsoft.com .ICONURI https://onedrive.live.com/download?resid=5DF749BB977BF4D6!393423&authkey=!ADcrsZkNg64G36w&v=3&ithint=photo%2cpng .EXTERNALMODULEDEPENDENCIES MSOnline, Microsoft.Online.SharePoint.PowerShell, AADRM, OfficeDevPnP.PowerShell.V16.Commands .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES v1.5.5 added -close and fixed parameter sets, added inline help to parameters v1.5.5 Fixed Language for MSOnline / AAD module v1.5 Add installation of dependent modules v1.4 Corrected bug wrt compliance search, remove prior created remote powershell sessions V1.3 Add dependend module information V1.2 add try-catch for SPO PNP Powershell, as that is less common V1.1 initial publication to scriptcenter #> <# .Synopsis Connect to Office 365 and get ready to administer all services. Includes installation of PowerShell modules 1/4/2016 .DESCRIPTION Connect to Office 365 and most related services and get ready to administer all services. The commandlet supports saving your administrative credentials in a safe manner so that it can be used in unattended files Allows Powershell administration of : O365, Azure AD , Azure RMS, Exchange Online, SharePoint Online including PNP Powershell .EXAMPLE connect-O365 -Account 'admin@contoso.com' -SharePoint .EXAMPLE connect-O365 -Account 'admin@contoso.com' -SPO -EXO -Skype -Compliance -AADRM .EXAMPLE #close any previously opened PS remote sessions (Exchange , Skype , Compliance Center) connect-O365 -close .EXAMPLE #Connect to MSOnline, and store securly store the credentials connect-O365 -Account 'admin@contoso.com' -Persist:$false .EXAMPLE connect-O365 -Account 'admin@contoso.com' #retrieve credentials for use in other cmdlets $Creds = Get-myCreds 'admin@contoso.com' .EXAMPLE connect-O365 -install #> [CmdletBinding()] [Alias("COL")] [Alias("Connect-Office365")] [OutputType([int])] Param ( [CmdletBinding(DefaultParametersetName=”Admin")] # Specify the (Admin) Account to authenticate with [Parameter(ParameterSetName="Admin",Mandatory=$false,Position=0)] [string]$Account, # Save the account credentials for later use [Parameter(ParameterSetName="Admin",Mandatory=$false)] [switch]$Persist = $false, #Connect to Azure AD aka MSOnline [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Alias("AzureAD")] [switch]$AAD = $true, #Connect to Exchange Online [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Alias("EXO")] [switch]$Exchange = $false, #Connect to Skype Online [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Alias("CSO")] [switch]$Skype = $false, #Connecto to SharePoint Online [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Alias("SPO")] [switch]$SharePoint = $false, #Load and connecto to the O365 Compliance center [Parameter(ParameterSetName="Admin",Mandatory=$false)] [switch]$Compliance = $false, #Connect to Azure Rights Management [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Alias("AZRMS")] [Alias("RMS")] [switch]$AADRM = $false, <# Add seperate parameterset #> #Close all open Connections [Parameter(ParameterSetName="Close",Mandatory=$false)] [switch]$Close = $false, <# Add seperate parameterset #> #Download and Install the supporting Modules [Parameter(ParameterSetName="Install",Mandatory=$true)] [switch]$Install, #Specify the Language code of the modules to download ( not applicable to all modules) #Sample : -Language NL [Parameter(ParameterSetName="Install",Mandatory=$false)] [Alias("Lang")] $Language = 'EN', #Specify the Language-Locale code of the modules to download ( not applicable to all modules) #Sample : -Language NL-NL #Sample : -Language EN-US [Parameter(ParameterSetName="Install",Mandatory=$false)] $LangCountry = 'EN-US', #Specify where to download the installable MSI and EXE modules to [Parameter(ParameterSetName="Install",Mandatory=$false)] $Folder = $null, #'C:\Users\Jos\Downloads', # [Parameter(ParameterSetName="Install",Mandatory=$false)] # $InstallPreview = $true, #Not in a specific parameterset #Force asking for, and optionally force the Perstistance of the credentials. [Parameter(Mandatory=$false)] [switch]$Force = $false ) function global:Store-myCreds ($username){ $Credential = Get-Credential -Credential $username $Store = "$env:USERPROFILE\creds\$USERNAME.txt" MkDir "$env:USERPROFILE\Creds" -ea 0 | Out-Null $Credential.Password | ConvertFrom-SecureString | Set-Content $store Write-Verbose "Saved credentials to $store" return $Credential } function global:Get-myCreds ($UserName , [switch]$Persist, [switch]$Force=$false){ $Store = "$env:USERPROFILE\creds\$USERNAME.txt" if ( (Test-Path $store) -AND $Force -eq $false ) { #use a stored password if found , unless -force is used to ask for and store a new password Write-Verbose "Retrieved credentials from $store" $Password = Get-Content $store | ConvertTo-SecureString $Credential = New-Object System.Management.Automation.PsCredential($UserName,$Password) return $Credential } else { if ($persist -and -not [string]::IsNullOrEmpty($UserName)) { $admincredentials = Store-myCreds $UserName return $admincredentials } else { return Get-Credential -Credential $username } } } if($Close) { write-verbose "Closing open sessions for Exchange Online, Skype and Compliance Center" #Close Existing (remote Powershell Sessions) Get-PSSession -Name "Exchange Online" -ea SilentlyContinue | Remove-PSSession Get-PSSession -Name "Compliance Center" -ea SilentlyContinue | Remove-PSSession Get-PSSession -Name "Skype Online" -ea SilentlyContinue| Remove-PSSession return } if (-NOT $install) { $admincredentials = Get-myCreds $account -Persist:$Persist -Force:$Force if ($admincredentials -eq $null){ throw "A valid Tenant Admin Account is required." } if ( $AAD) { write-verbose "Connecting to Azure AD" #Imports the installed Azure Active Directory module. Import-Module MSOnline -Verbose:$false if (-not (Get-Module MSOnline ) ) { Throw "Module not installed"} #Establishes Online Services connection to Office 365 Management Layer. Connect-MsolService -Credential $admincredentials } if ($Skype ){ write-verbose "Connecting to Skype Online" #Imports the installed Skype for Business Online services module. Import-Module SkypeOnlineConnector -Verbose:$false -Force #Remove prior Session Get-PSSession -Name "Skype Online" -ea SilentlyContinue| Remove-PSSession #Create a Skype for Business Powershell session using defined credential. $SkypeSession = New-CsOnlineSession -Credential $admincredentials -Verbose:$false $SkypeSession.Name="Skype Online" #Imports Skype for Business session commands into your local Windows PowerShell session. Import-PSSession -Session $SkypeSession -AllowClobber -Verbose:$false } If ($SharePoint) { write-verbose "Connecting to SharePoint Online" if (!$AAD) { Throw "AAD Connection required" } else { #get tenant name for AAD Connection $tname= (Get-MsolDomain | ?{ $_.IsInitial -eq $true}).Name.Split(".")[0] } #Imports SharePoint Online session commands into your local Windows PowerShell session. Import-Module Microsoft.Online.Sharepoint.PowerShell -DisableNameChecking -Verbose:$false #lookup the tenant name based on the intial domain for the tenant Connect-SPOService -url https://$tname-admin.sharepoint.com -Credential $admincredentials try { write-verbose "Connecting to SharePoint Online PNP" import-Module OfficeDevPnP.PowerShell.V16.Commands -DisableNameChecking -Verbose:$false Connect-SPOnline -Credential $admincredentials -url "https://$tname.sharepoint.com" } catch { Write-Warning "Unable to connecto to SharePoint Online using the PNP PowerShell module" } } if ($Exchange ) { write-verbose "Connecting to Exchange Online" #Remove prior Session Get-PSSession -Name "Exchange Online" -ea SilentlyContinue| Remove-PSSession #Creates an Exchange Online session using defined credential. $ExchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $admincredentials -Authentication "Basic" -AllowRedirection $ExchangeSession.Name = "Exchange Online" #This imports the Office 365 session into your active Shell. Import-PSSession $ExchangeSession -AllowClobber -Verbose:$false } if ($Compliance) { write-verbose "Connecting to the Unified Compliance Center" #Remove prior Session Get-PSSession -Name "Compliance Center" -ea SilentlyContinue| Remove-PSSession $PSCompliance = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid/ -Credential $AdminCredentials -Authentication Basic -AllowRedirection $PSCompliance.Name = "Compliance Center" Import-PSSession $PSCompliance -AllowClobber -Verbose:$false } If ($AADRM) { write-verbose "Connecting to Azure Rights Management" #Azure RMS import-module AADRM -Verbose:$false Connect-AadrmService -Credential $admincredentials } } if ($install) { # Get the location of the downloads folder # Ref : http://stackoverflow.com/questions/25049875/getting-any-special-folder-path-in-powershell-using-folder-guid Add-Type @" using System; using System.Runtime.InteropServices; public static class KnownFolder { public static readonly Guid Documents = new Guid( "FDD39AD0-238F-46AF-ADB4-6C85480369C7" ); public static readonly Guid Downloads = new Guid( "374DE290-123F-4565-9164-39C4925E467B" ); } public class shell32 { [DllImport("shell32.dll")] private static extern int SHGetKnownFolderPath( [MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath ); public static string GetKnownFolderPath(Guid rfid) { IntPtr pszPath; if (SHGetKnownFolderPath(rfid, 0, IntPtr.Zero, out pszPath) != 0) return ""; // add whatever error handling you fancy string path = Marshal.PtrToStringUni(pszPath); Marshal.FreeCoTaskMem(pszPath); return path; } } "@ #Lookup downloads location if ($Folder -eq $null ) {$folder = [shell32]::GetKnownFolderPath([KnownFolder]::Downloads) } write-verbose "Download folder : $folder" $Components = ConvertFrom-Json @" { "AdminComponents": [ { "Tag": "SIA", "Name": "Microsoft Online Services Sign-In Assistant for IT Professionals", "Source": "http://download.microsoft.com/download/5/0/1/5017D39B-8E29-48C8-91A8-8D0E4968E6D4/$Language/msoidcli_64.msi", "Type": "MSI", "ID": "{D8AB93B0-6FBF-44A0-971F-C0669B5AE6DD}" } , { "Tag" : "AAD", "Module" : "MSOnline", "Name": "Windows Azure Active Directory Module for Windows PowerShell", "Source": "https://bposast.vo.msecnd.net/MSOPMW/Current/amd64/AdministrationConfig-$Language.msi", "Type": "MSI", "ID": "{43CC9C53-A217-4850-B5B2-8C347920E500}" }, { "Tag": "SKYPE", "Module": "SkypeOnlineConnector", "Name": "Skype for Business Online, Windows PowerShell Module", "Source": "https://download.microsoft.com/download/2/0/5/2050B39B-4DA5-48E0-B768-583533B42C3B/SkypeOnlinePowershell.exe", "Type": "EXE", "SetupOptions" : "/Install /Passive", "ID": "{D7334D5D-0FA2-4DA9-8D8A-883F8C0BD41B}" }, { "Tag": "SPO", "Module" : "Microsoft.Online.SharePoint.PowerShell", "Name": "SharePoint Online Management Shell", "Source" : "https://download.microsoft.com/download/0/2/E/02E7E5BA-2190-44A8-B407-BC73CA0D6B87/sharepointonlinemanagementshell_4915-1200_x64_$LangCountry.msi", "Type": "MSI", "Version" : "16.0.4915.1200", "Web": "https://www.microsoft.com/en-us/download/confirmation.aspx?id=35588&6B49FDFB-8E5B-4B07-BC31-15695C5A2143=1", "ID": "{95160000-115B-0409-1000-0000000FF1CE}" }, { "Tag": "RMS", "Module" : "aadrm", "Name": "Windows Azure AD Rights Management Administration", "Source" : "https://download.microsoft.com/download/1/6/6/166A2668-2FA6-4C8C-BBC5-93409D47B339/WindowsAzureADRightsManagementAdministration_x64.exe", "Type": "EXE", "Version" : " 1.0.1443.901", "Web": "https://www.microsoft.com/en-us/download/confirmation.aspx?id=30339", "ID": "{6EACEC8B-7174-4180-B8D6-528D7B2C09F0}" }, { "Tag": "PNPPS", "Preview" : "Yes", "Module": "OfficeDevPnP.PowerShell.V16.Commands", "Name": "OfficeDevPnP.PowerShell", "Source" : "PSGallery", "Type": "Module", "Web": "https://github.com/OfficeDev/PnP-PowerShell" } ], "Exclude" : [ { "Tag": "WMF5-Preview", "Preview" : "Yes", "Module" : "WMF5", "Type": "MSI", "Name": "Windows Management Framework 5.0 Production Preview", "Source" : "https://download.microsoft.com/download/3/F/D/3FD04B49-26F9-4D9A-8C34-4533B9D5B020/Win8.1AndW2K12R2-KB3066437-x64.msu", "SetupOptions" : "/quiet", "OS": "6,8", "XVersion" : "", "Web": "https://www.microsoft.com/en-us/download/confirmation.aspx?id=30339", "ID": "{BE4B4004-DE97-4185-A2B4-C147DAC9AD2C}", "Source2" : "https://download.microsoft.com/download/3/F/D/3FD04B49-26F9-4D9A-8C34-4533B9D5B020/W2K12-KB3066438-x64.msu" } ] } "@ # (Get-Module aadrm -ListAvailable).Version <# use the below in order to update relevant information Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | sort -Property DisplayName | select PSChildName, DisplayName, Publisher, DisplayVersion #> foreach ($c in $Components.AdminComponents) { if ($c.Preview -ieq "Yes" -and $InstallPreview -eq $false) { write-host -f Gray "Skip Preview component : $($c.Name)" continue; } #IF OS Major Specified , and if the current OS Matches the specified OS if ($c.OS) { if ( ($c.OS).Split(",") -notcontains $PSVersionTable.BuildVersion.Major) { write-host -f Gray "OS mismatch, Skip component : $($c.Name)" continue; } } switch ($c.Type.ToUpper() ) { {$_ -in "EXE","MSI"} { Write-Verbose "EXE or MSI package" $AppInfo = Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\$($c.ID)" -ErrorAction SilentlyContinue $Installed = $false; if ($AppInfo ) { $Installed = $appInfo.Displayname -ne $null } if (-not $Installed -or $force) { # Filename $file = Split-Path $c.Source -Leaf #path in downloads $msi = join-path $folder $file #remove existing item prior to Downloading Remove-Item $msi -Force -ea SilentlyContinue try { #download it Write-Verbose "Download package" Invoke-WebRequest $c.Source -OutFile $msi if ( Test-Path $msi ) { $Sign = Get-AuthenticodeSignature $msi if ( $Sign.Status -eq 'Valid' -and $sign.SignerCertificate.DnsNameList[0].Unicode -eq 'Microsoft Corporation' ) { if ($force) { #de-install before re-install write-host -ForegroundColor Yellow "Removing current $($c.Type) package" Start-Process -FilePath "msiexec" -ArgumentList "/uninstall $($c.ID) " -Wait } try { if ($c.Type -ieq "MSI" ) { Write-Verbose "Install MSI package : $msi" Start-Process -FilePath "msiexec" -ArgumentList "/package $msi /passive" -Wait } else { $Options = "/Passive" if ($c.Setup ) { $Options = $c.SetupOptions } Write-Verbose "Install EXE package : $msi $options" Start-Process -FilePath $MSI -ArgumentList $options -Wait } $AppInfo = Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\$($c.ID)" -ErrorAction SilentlyContinue Write-Host $c.Name "Version :" $AppInfo.DisplayVersion " was installed" -f Green } catch { Write-warning "$($c.Name) could not be installed" #Open in browser if (-not [string]::IsNullOrEmpty($c.Web)){ Start-Process $c.Web } } } } } catch { Write-Warning "could not install: $($c.Name)" } } else { Write-Host $c.Name "Version :" $AppInfo.DisplayVersion " is already installed" } } "MODULE" { # Add check for PS5 / WMF 5 if (Get-Command install-module) { #check for installed version of this module $Current = Get-Module $c.Module -ListAvailable $Source = Find-Module -Name $c.Module -Repository $c.Source -Verbose:$false if ( $Current -eq $null ) { write-verbose "Preparing to install module $($c.Module)" #Not yet installed , find source #if not installed or newer version avaialble if( $Source -and $Current -eq $null -or ($Source.Version -GT $Current.Version) ) { #install it $IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") #Check Admin Perms if (-not $IsAdmin) { Write-Verbose "Start PS elevated to admin to run the install" Start-Process "$psHome\powershell.exe" -Verb Runas -ArgumentList "-Command Install-Module -Name $($c.Module) -Repository $($c.Source)" } else { Install-Module -InputObject $source } $Now = Get-Module $c.Module -ListAvailable -Verbose:$false if ($now){ Write-Host "Installed $($now.Name) version : $($Now.Version)" } } else { #Could not be found Write-warning "The Module $($c.Name) Could not be located" #Open in browser if (-not [string]::IsNullOrEmpty($c.Web)){ Start-Process $c.Web } } } else { #version already installed if ($Source.Version -gt $Current.Version -or $force ) { write-verbose "Updating Module $($c.Module)" if (-not $IsAdmin) { Write-Verbose "Start PS elevated to admin to run the install" Start-Process "$psHome\powershell.exe" -Verb Runas -ArgumentList "-Command update-Module -Name $($c.Module) -Force:$force" } else { update-Module -InputObject $source -Force:$force } } else { Write-verbose "$($c.Name) Version : $($Current.Version) is already installed" } $NOW = Get-Module $c.Module -ListAvailable Write-Host $c.Name "Version :" $NOW.Version" is now installed" } } else { #No PS5 / WMF 5 Write-warning "The Module $($c.Name) cannot be installed automatically. Please install manually or install WMF 5 (preview)" #Open in browser if (-not [string]::IsNullOrEmpty($c.Web)){ Start-Process $c.Web } } } default { Write-Warning "Unknown component type"} } } } |