Connect-O365.ps1
<#PSScriptInfo
.VERSION 1.5.4 .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 .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 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 PSremote sessions ( Exchnage , Skype connect-O365 -close .EXAMPLE 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")] [OutputType([int])] Param ( [CmdletBinding(DefaultParametersetName=”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, #Azure AD [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Alias("AzureAD")] [switch]$AAD = $true, #Exchange Online [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Alias("EXO")] [switch]$Exchange = $false, #Skype Online [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Alias("CSO")] [switch]$Skype = $false, # [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Alias("SPO")] [switch]$SharePoint = $false, #Compliance center [Parameter(ParameterSetName="Admin",Mandatory=$false)] [switch]$Compliance = $false, #Azure Rights Management [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Alias("AZRMS")] [Alias("RMS")] [switch]$AADRM = $false, <# Add seperate parameterset #> #Install Modules [Parameter(ParameterSetName="Install",Mandatory=$true)] [switch]$Install, [Parameter(ParameterSetName="Install",Mandatory=$false)] [Alias("Lang")] $Language = 'EN', [Parameter(ParameterSetName="Install",Mandatory=$false)] $LangCountry = 'EN-US', [Parameter(ParameterSetName="Install",Mandatory=$false)] $Folder = $null, #'C:\Users\Jos\Downloads', [Parameter(ParameterSetName="Install",Mandatory=$false)] $InstallPreview = $true, [Parameter(ParameterSetName="Install",Mandatory=$false)] [switch]$Force = $false ) function global:Store-myCreds ($username){ $Credential = Get-Credential -Credential $username MkDir "$env:USERPROFILE\Creds" -ea 0 | Out-Null $Credential.Password | ConvertFrom-SecureString | Set-Content $env:USERPROFILE\Creds\$USERNAME.txt return $Credential } function global:Get-myCreds ($UserName , [switch]$Persist){ $Store = "$env:USERPROFILE\creds\$USERNAME.txt" if (Test-Path $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 (-NOT $install) { $admincredentials = Get-myCreds $account -Persist:$Persist if ($admincredentials -eq $null){ throw "A valid Tenant Admin Account is required." } if($Close) { write-verbose "Closing open sessions for Exchange Online 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 } 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/en/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-$LANG.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"} } } } |