Convert Azure AD B2B Users from Guest to Member: How and Why

The primary difference between a Guest and a Member user lies in their lookup rights in the Azure AD domain. There are some important differences between UserType of Guest vs Member, specifically:

  • Member. A user expects to have access to internal-only sites. This user is not considered an external collaborator. This will be important when trying to exercise rights that come with privileged roles like Global Administrator.
  • Guest. indicates a user who isn’t considered internal to the company. This type of user will have restricted access and lookup rights in the directory.

Read more about this in “Understand the B2B user”.

To convert a user from UserType Guest to Member

Install the Azure AD PowerShell module

Install-Module AzureAD

Authenticate to your Azure AD tenant

Connect-AzureAD

Search for your user by upn (just to be sure).

Get-AzureADUser -SearchString pete.zerger@lumagatena.com

Now, pass the output to Set-AzureADUser, setting UserType to member

Get-AzureADUser -SearchString pete.zerger@lumagatena.com | Set-AzureADUser -UserType member

Repeat the Get-AzureADUser search to confirm the output shows Usertype = Member

Get-AzureADUser -SearchString pete.zerger@lumagatena.com

This would be a handy feature in the UI for sure. There is an actually a request on User Voice for this feature. Vote it up if you agree: Update UserType from portal.

Enable modern authentication for Exchange Online via PowerShell

Modern authentication is disabled in Exchange Online in Office 365  by default. However, you are quite likely to want modern authentication, because modern authentication in Office 365 enables authentication features like multi-factor authentication (MFA) using smart cards, certificate-based authentication, and third-party SAML identity providers.

You can enable modern authentication in Exchange Online via PowerShell. However, I found the article explaining how to enable modern authentication for Exchange Online is missing some detail regarding how to connect to Exchange Online.

For reference, below is a sample script for connecting to Exchange Online

# Capture your credentials to a credential object 
$UserCredential = Get-Credential

# Establish a remote connection to EO in your O365 tenant
$Session = New-PSSession -ConfigurationName Microsoft.Exchange `
-ConnectionUri https://outlook.office365.com/powershell-liveid/ `
-Credential $UserCredential -Authentication Basic -AllowRedirection

Import-PSSession $Session

# Check if modern auth is in place already 
Get-OrganizationConfig | Format-Table -Auto Name,OAuth*
 
# If modern auth setting is false, then enable it
Set-OrganizationConfig -OAuth2ClientProfileEnabled $true

# Check again to ensure it comes back as "True"
Get-OrganizationConfig | Format-Table -Auto Name,OAuth*

Questions or comments? Use the comments section below.

Enable modern authentication for Skype for Business Online via PowerShell

Modern authentication is disabled in Skype for Business Online in Office 365  by default. However, you can enable it via PowerShell. The article explaining how to enable modern authentication in Skype for Business in Office 365 is missing a small item or two (like where to get the PowerShell snap-in you need.

For reference, below is a sample script with the basics in one place.

First, download and install Skype for Business PowerShell snap-in:
https://www.microsoft.com/en-us/download/details.aspx?id=39366

Run these commands one at a time, as you will need to paste a value into line 10, as mentioned in the comment on line 9 below.

# Capture your credentials to a credential object 
$UserCredential = Get-Credential

# Connect to Skype for Business in your Office 365 tenant
$session = New-CsOnlineSession -Credential $UserCredential -Verbose

Import-PSSession $session

# Paste the value from Name field to replace tmp_vubyaegp.m3f below 
Get-Command -Module tmp_vubyaegp.m3f

# Enable Skype for Business tenent to support modern auth
Set-CsOAuthConfiguration -ClientAdalAuthOverride Allowed

# verify success
Get-CsOAuthConfiguration

Questions or comments? Use the comments section below.

Remoting in Azure Automation Runbooks (SQL DB Creation sample)

I find that using PowerShell remoting in my Azure automation runbooks is sometimes more convenient, as it eliminates the need to install and update additional PowerShell modules on my OMS hybrid runbook worker. For future reference, I wanted to capture an example of a simple approach to PowerShell remoting I find intuitive.

The activities in this relatively simple example of remoting in an Azure Automation runbook include the following:

  • Retrieves user and password info from Azure automation variables, then creates a PsCredential object
  • Remotes from the worker where it is run (the HRW in my case) to a SQL 2014 or 2016 server. (The name of the server and SQL instance are supplied in the $RemoteComputer and $SQLInstance parameters of the runbook)
  • Loads the SQL PowerShell module
  • Creates the SQL database with the default settings, named per the $DatabaseName runbook parameter
  • This sample also includes a trace log to demonstrate where the code executes (on the remote SQL server)
PARAM(

$RemoteComputer,
$SqlInstance,
$DatabaseName

)

# Retrieve admin user and password, create credential object
$strScriptUser = Get-AutomationVariable -Name 'ContosoAdminUser'
$strPass = Get-AutomationVariable -Name 'ContosoAdminPassword'
$PSS = ConvertTo-SecureString $strPass -AsPlainText -Force
$cred = new-object system.management.automation.PSCredential $strScriptUser,$PSS

#Invoke script block on the remote SQL server
Invoke-Command -Computername $RemoteComputer -Credential $cred -ScriptBlock {

# Import SQL Server Module called SQLPS
Import-Module SQLPS -DisableNameChecking

# Simple log to prove we are remoting
# Logs to c:\Windows\Temp\remoting.txt
$CurrDate = Get-Date
$message = "We remoted to $env:ComputerName on $CurrDate"
$file = "c:\Windows\Temp\remoting.txt"
$Message | Add-Content -Path $file

# Your SQL Server Instance Name
$SqlInst = "$using:SqlInstance"
$Srvr = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server -ArgumentList $SqlInst

# Database PSDB with default settings
# By assuming that this database does not yet exist in current instance
$DBName = "$using:DatabaseName"
$db = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Database($Srvr, $DBName)
$db.Create()

}

Searching files in a zip archive in memory with PowerShell

I found myself tonight needing to build a function to search the contents of text files in a very large zip archive to find one containing a specific value. To handle the operation quickly, I wanted to perform the operation in memory. While that may be too specific to be useful for most, I thought at least an example of how to retrieve a file within a zip archive and parse its content might be interesting to a wider audience, and more importantly, a useful archive for myself.

P.S. – I am happy to share the more complex end result if anyone tells me it’s useful to them.

What you will need

While the new extract-archive and compress-archive cmdlets are handy for basic zip archive creation and extraction, they are not much help when you need to get down to the item level within a zip archive. The system.io.compression assemblies are required, which you must load explicitly, as they are not loaded by default. For this simple example, these are key enablers:

ZipFile class, to open the archive to parse members
https://msdn.microsoft.com/en-us/library/system.io.compression.zipfile(v=vs.110).aspx

GetEntry method, to retrieve individual file (or files) in the archive
https://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive.getentry(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1

StreamReader class, to read the file into memory and search content
https://msdn.microsoft.com/en-us/library/system.io.streamreader(v=vs.110).aspx

Sample Code

In this example, we will open a zip archive named scripts.zip on the D:\ drive, retrieve a file named ConnectToAzure.txt and search for the value.

Select your zip archive.

$ZipArchive = "d:\scripts.zip"

Open archive for reading.

$ZipStream = [io.compression.zipfile]::OpenRead(“$ZipArchive”)

Select the item in the archive. Notice how you must reference the folder in the path to the file.

$ZipItem = $ZipStream.GetEntry('Scripts/ConnectToAzure.txt ')

Open the item from the archive.

$ItemReader = New-Object System.IO.StreamReader($ZipItem.Open())

Use Streamreader class and read into memory. $DocItemSet represents the contents of the file.

$DocItemSet = $ItemReader.ReadToEnd()

Search the file contents for desired value.

$DocItemSet.Contains("Connect-MsolService")

Happy PowerShelling!

Install SQL Server Mgmt Studio (SSMS) with PowerShell

Below for reference is a quick PowerShell sample for downloading and installing SQL Server 2016 Management Studio (SSMS). While this component used to be included in the SQL Server installer, it is now a separate download.

# Set file and folder path for SSMS installer .exe
$folderpath="c:\windows\temp"
$filepath="$folderpath\SSMS-Setup-ENU.exe"

#If SSMS not present, download
if (!(Test-Path $filepath)){
write-host "Downloading SQL Server 2016 SSMS..."
$URL = "https://download.microsoft.com/download/3/1/D/31D734E0-BFE8-4C33-A9DE-2392808ADEE6/SSMS-Setup-ENU.exe"
$clnt = New-Object System.Net.WebClient
$clnt.DownloadFile($url,$filepath)
Write-Host "SSMS installer download complete" -ForegroundColor Green

}
else {

write-host "Located the SQL SSMS Installer binaries, moving on to install..."
}

# start the SSMS installer
write-host "Beginning SSMS 2016 install..." -nonewline
$Parms = " /Install /Quiet /Norestart /Logs log.txt"
$Prms = $Parms.Split(" ")
& "$filepath" $Prms | Out-Null
Write-Host "SSMS installation complete" -ForegroundColor Green

Questions or comments? Use the comments section below.

Switch from dynamic IP to IP Pool in VMM 2016

Recently I migrated a VM from standalone Hyper-V server in 2016 to a Hyper-V cluster managed by Virtual Machine Manager (VMM) 2016. The VM was using DHCP for addressing and I wanted to flip it to get its address from the IP pool assigned to its logical network in VMM. However, even with the VM powered off, I found the setting to flip the VM to use a static IP was grayed out in the UI.

VM_Settings

How to fix? PowerShell, via the VMM cmdlets. Here is a sample script, intended to run on your VMM server.

$vm = Get-ScvirtualMachine -Name “<My VM Name>"

$staticIPPool = Get-SCStaticIPAddressPool -Name "< Name of my IP Pool>"

Grant-SCIPAddress -GrantToObjectType "VirtualNetworkAdapter" -GrantToObjectID$vm.VirtualNetworkAdapters[0].ID -StaticIPAddressPool $staticIPPool

Set-SCVirtualNetworkAdapter -VirtualNetworkAdapter $vm.VirtualNetworkAdapters[0]-IPv4AddressType static

<pre>

Questions or comments? Use the comments section below.

TIP: Keep your Azure Automation runbooks healthy across PowerShell module updates

Here’s a quick tip that may help you ensure you’re protect yourself from a problem that happens occasionally.

Problem: I had a runbook that was broken when the PowerShell modules in the store were updated.

Solution: What can you do to prevent this problem? One thing you can do to protect yourself against breaking changes in new versions of PowerShell moduels is to configure your runbook to run on a schedule. Once schedule is created, that runbook will always run with the modules that were in the store at the time of the schedule creation.

Get a deep dive on Azure Automation in our comprehensive book on the Microsoft Operations Management Suite (OMS), which is available free on the TechNet Gallery or if you prefer, for a small price in paperback and Kindle formats on Amazon.com.

Creating ConfigMgr User Collections with PowerShell

Below for reference a quick PowerShell sample for creating a query-based user collection in System Center Configuration Manager (ConfigMgr), along with a demonstration of some of the options you can supply to control collection population and refresh behavior.

You can download the up-to-date ConfigMgr PowerShell cmdlets at https://www.microsoft.com/en-us/download/details.aspx?id=46681.

The ConfigMgr PowerShell cmdlet reference documentation is available at https://technet.microsoft.com/en-us/library/jj821831(v=sc.20).aspx.

Sample script for user collections

# Import ConfigMgr PowerShell module 
Import-Module (Join-Path $(Split-Path $env:SMS_ADMIN_UI_PATH) ConfigurationManager.psd1) 

# Change to ConfigMgr drive, where HOU is your site code
cd ‘c:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin’
Set-Location HOU:

# Create schedules for refreshing collection membership
$MonSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Monday -RecurCount 1
$TueSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Tuesday -RecurCount 1
$WedSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Wednesday -RecurCount 1
$ThuSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Thursday -RecurCount 1
$FriSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Friday -RecurCount 1
$SatSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Saturday -RecurCount 1
$SunSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Sunday -RecurCount 1

# Define user collection we will create 
# If you want to enable incremental updating on the Collections, you can set the –RefreshType to 'Both'. 
New-CMUserCollection -Name "Accounting Users" -LimitingCollectionName "All Users" `
-RefreshSchedule $MonSched -RefreshType Periodic

# Define query rule for my collection 
Add-CMUserCollectionQueryMembershipRule -CollectionName "Accounting Users" `
-QueryExpression "select * from SMS_R_User where SMS_R_User.UserGroupName = 'CONTOSO\\Accounting'" `
-RuleName "AcctingUsersQueryRule"

Questions or comments? Use the comments section below.

Creating ConfigMgr Device Collections with PowerShell

Below for reference a quick PowerShell sample for creating a query-based device collection in System Center Configuration Manager (ConfigMgr), along with a demonstration of some of the options you can supply to control collection population and refresh behavior.

You can download the up-to-date ConfigMgr PowerShell cmdlets at https://www.microsoft.com/en-us/download/details.aspx?id=46681.

The ConfigMgr PowerShell cmdlet reference documentation is available at https://technet.microsoft.com/en-us/library/jj821831(v=sc.20).aspx.

Sample script for device collections

# Import ConfigMgr PowerShell module 
Import-Module (Join-Path $(Split-Path $env:SMS_ADMIN_UI_PATH) ConfigurationManager.psd1) 

# Change to ConfigMgr drive, where HOU is your site code
cd ‘c:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin’
Set-Location HOU:

# Create schedules for refreshing collection membership
$MonSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Monday -RecurCount 1
$TueSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Tuesday -RecurCount 1
$WedSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Wednesday -RecurCount 1
$ThuSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Thursday -RecurCount 1
$FriSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Friday -RecurCount 1
$SatSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Saturday -RecurCount 1
$SunSched = New-CMSchedule -Start "01/01/2017 10:00 PM" -DayOfWeek Sunday -RecurCount 1

# Define device collection we will create 
# If you want to enable incremental updating on the Collections, you can set the –RefreshType to 'Both'. 
New-CMDeviceCollection -Name "Pete Servers" -LimitingCollectionName "All Systems" `
-RefreshSchedule $MonSched -RefreshType Periodic

# Define query rule for my collection 
Add-CMDeviceCollectionQueryMembershipRule -CollectionName "Pete Servers" `
-QueryExpression "select * from SMS_R_System where SMS_R_System.SystemGroupName = 'CONTOSOCORP\\Pete Servers'" `
-RuleName "PeteServerQueryRule"

Questions or comments? Use the comments section below.