Showing posts with label Automation. Show all posts
Showing posts with label Automation. Show all posts

Monday, August 15, 2022

Automating Teams voice reporting of users (2:2)

This is a follow up on my last blog post covering automated teams voice assignment for users. This time I will cover how the mentioned routine has been expanded to do reporting in PowerBI to show evolution and distribution throughout the lifetime of the service.

After running my routine of automated voice assignment in Teams for a while, I felt the need to have an overview of the solution and how it evolved.



Monday, August 8, 2022

Automating Teams voice assignment for users (1:2)

In order to manage voice and phone number assignments in Microsoft Teams, you need at least Teams Communications Administrator role. This role does however have more privileges than most organizations want to assign to their first line staff. This blog post will cover a way for first line to automate voice activation of users with the granularity necessary to cover several technologies such as Direct Routing and Operator Connect.

The main idea is to let first line operators use the tools they have access to when managing users without the demand of acquiring extra privileges.


By adding the Teams phone number in E.164 format to the users telephoneNumber field in AD/AAD and assigning the user as member of a defined security group, I have enough information to automate the Teams voice assignment for the user. This could also include license assignment through the group membership.

Tuesday, July 12, 2022

Posten inn i Homey

Inspirert av lærdommen fra prosjektet med å få Min renovasjon inn i Homey har jeg kastet meg over Posten sin løsning for å se om jeg kan få lest inn postbudets rute som variabler i min Homey.

Posten.no

Posten leverer nå ut post annenhver dag. Dette betyr postombæring mandag, onsdag og fredag den ene uken og tirsdag og torsdag den andre uken. Det kan jo være mulig å enkelt reprodusere denne takten ved hjelp av oddetall og partalls uker. Men - posten har jo laget en egen webside hvor man kan slå opp når man kan forvente post utlevert: https://www.posten.no/levering-av-post. Dette betyr kanskje at det kan oppstå uregelmessigheter her - og det må jo fanges opp av et smart hus.

Monday, July 11, 2022

Automatic file upload from legacy server to Microsoft 365

Companies that have gone through several generations of IT systems will have to make their cloud journey in small steps - system by system. Devices and document storage are quickly moved to Microsoft 365. Special Line of Business systems may take longer to cloudify. This can present challenges in making data from dinosaur systems available to users of the modern Microsoft 365 platform.

The challenge from a real world scenario

I was challenged by a customer with a production environment running in an old on premises environment while all users and endpoints had converted to Microsoft 365. They had challenges in reaching reports that were produced on premises and needed a solution to have this data automatically uploaded to Sharepoint for easy and modern access. Challenge accepted!

Wednesday, July 6, 2022

HP Connect for Intune, Part1: BIOS Update

To be certain we have a secure system from chip to cloud, it is fundamental to boot device from a trusted BIOS - often referred as secure boot. HP Connect for Microsoft Endpoint Manager is a cloud application designed to ease the management of UEFI BIOS on supported HP systems. This blog post will cover updating the BIOS on HP devices using MEM.

We need to have control of the boot environment of our managed devices

Please note: This is not a sponsored post!

Tuesday, July 5, 2022

Fortinet VPN Profile distribution with MDM

Fortinet Document Library has a documented routine for distributing the FortiClient application with Intune to Microsoft Windows. This routine is working Ok, but it is missing information on how to distribute the VPN profiles to the client. This will be the topic for this post.

Installation of the FortiClient application

Please read and follow the document in Fortinet Document Library covering the topic of configuring the FortiClient application in Intune. During this routing you need to download the current FortiClient VPN client and start the downloaded EXE file to download the actual MSI installation. This could be wise to do in a Windows Sandbox environment. You will find the MSI file in the newest folder with {randomguid} name under %localappdata%\Temp\.

After this routine has been setup and you have the app distributed to a group and installed, you will find the application available in the system tray on the devices.
FortiClient without VPN profile

The problem here, is the missing VPN profile for connecting your client to the service.

Tuesday, June 21, 2022

Rename computers with countrycode in Intune

During an engagement at a customer there was a demand of having all computers in Endpoint Manager/Intune renamed to a naming standard including the two character ISO country code from the device owner followed by the serial number of the device. This was solved by using Graph API in a Powershell script running in an Azure Runbook.

The mission

The mission is to have all Windows devices in Microsoft Endpoint Manager follow a specified naming standard giving the device a unique name consisting of a country code and the device serial - ie: NO-132435465768. The solution must address existing and new devices.

The challenge with this design is related to compiling a device name consisting of the country code found at the user owning the device and the serial found on the device it self. I have found examples online for renaming endpoints, but these did not get hold of the country codes from the user to use as part of the new device name. Some of these examples include:

New devices - autopilot profiles


During the initial phase of this project, I did design a configuration for Autopilot allowing the devices to start out with the correct device name upon the initial onboarding. This was based on several group tags matched with corresponding AutoPilot profiles. A specialized menu was built in order to ease the hash collection and at the same time have the group tag specified.

image
Menu used for selecting country code when getting the hardware hash code

This did work as expected for new computers. The CSV hash file got a Grouptag specified pr. device based on the operators choice when collecting the hash. When uploaded to Intune, the Grouptag did match with an Azure dynamic device group which in turn was targeted towards the corresponding autopilot profile setting the correct name on the device.

Although this was a full-blown technical solution, it didn't live up to the expectations of easy implementation from the first line helpdesk. The setup was therefore reversed leaving one common autopilot profile for each and every windows device in the tenant.

Existing devices - renaming with script

Initially this was thought as a one shot run to rename existing devices. As the first phase of naming new machines during Autopilot was neglected, the challenge is somewhat extended to do renaming of devices on a regular basis. This has led to a Powershell script running in an Azure Runbook on a schedule once pr. day.

Pseudo code

The script has a hash table with current countries. The script will recure the country list selecting all users belonging to each country and further on list each device belonging to those users. Attributes from the user gives access to information about the country, while attributes from the device gives information about the serial number. The script takes into account the maximum length of 15 characters for computer names. This gives the fundaments for renaming the computer to the given naming standard. A rename will be initiated if the existing computer name differs from the standard.

Azure App Registration

The script authenticates through an Azure App Registration which has the following Microsoft Graph API application permissions:

  • DeviceManagementManagedDevices.PrivilegedOperations.All
  • DeviceManagementManagedDevices.ReadWrite.All
  • Directory.Read.All
  • User.Read
The app secret for the app registration is created with powershell in order to have extra life time:
    $startDate = Get-Date
    $endDate = $startDate.AddYears(9)
    $ObjectID = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
    $aadAppsecret01 = New-AzureADApplicationPasswordCredential -ObjectId $ObjectID -StartDate $startDate -EndDate $endDate
    ($aadAppSecret01).Value

Azure Runbook

The TenantID, ClientID and ClientSecret from the app registration are stored as encrypted variables in the Azure Runbook.
Encrypted variables stored in the runbook

The runbook does have most of the modules loaded already, except for the Microsoft.Graph.Authentication module which has to be added from the Gallery.

The script can now be added, published and linked to a schedule in the runbook. The script is available on my Github, and it has some comments throughout the code describing the process.

<#

  .NOTES
  ===========================================================================
   Created on:      09.05.2022
   Created by:      Simon Skotheimsvik
   Filename:        MEM-ChangeOfComputerNames-Runbook.ps1
  ===========================================================================
 
  .DESCRIPTION
    This script uses the Graph API to bulk rename Windows devices. It can for
    example be used in a scenario where autopilot default naming has been used
    and a new standardised naming convention has been agreed upon. This Script
    will use the Country Code from the owning users Azure Account. It can be
    modified to use other user variables as well.

    The script is designed to run unattended in an Azure Runbook.
     
  .EXAMPLE
    MEM-ChangeOfComputerNames-Runbook.ps1

#>

$GLOBAL:DebugPreference="Continue"

$Countries = @{
    Norway = "NO"
    Vietnam = "VN"
    Brazil = "BR"
    Chile = "CL"
    Croatia = "HR"
    India = "IN"
    Italy = "IT"
    Poland = "PL"
    Romania = "RO"
    Singapore = "SG"
    Canada = "CA"
}

# CONNECT TO GRAPH WITH AZURE APP-REGISTRATION STORED AS ENCRYPTED VARIABLES
$TenantId = Get-AutomationVariable -Name 'Computer_Rename_TenantID'
$ClientId = Get-AutomationVariable -Name 'Computer_Rename_ClientID'
$ClientSecret = Get-AutomationVariable -Name 'Computer_Rename_ClientSecret'

# Create a hashtable for the body, the data needed for the token request
# The variables used are explained above
$Body = @{
    'tenant' = $TenantId
    'client_id' = $ClientId
    'scope' = 'https://graph.microsoft.com/.default'
    'client_secret' = $ClientSecret
    'grant_type' = 'client_credentials'
}

# Assemble a hashtable for splatting parameters, for readability
# The tenant id is used in the uri of the request as well as the body
$Params = @{
    'Uri' = "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token"
    'Method' = 'Post'
    'Body' = $Body
    'ContentType' = 'application/x-www-form-urlencoded'
}

$AuthResponse = Invoke-RestMethod @Params

$Headers = @{
    'Authorization' = "Bearer $($AuthResponse.access_token)"
}

# Connect-MgGraph with Token in order to be able to post a computer renaming
$connection = Invoke-RestMethod `
    -Uri https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token `
    -Method POST `
    -Body $body
 
$token = $connection.access_token
Connect-MgGraph -AccessToken $token

write-output "Authentication finished"

############################################################
# ROUTINE FOR RENAMING USERS AUTOPILOT DEVICES
############################################################

foreach ($CountryCode in $Countries.keys) {
    write-output "Working on country $CountryCode"
    $Country = $CountryCode
    $CountryCode = $($Countries[$Country])
    $MaxSerialLength = (15 - $CountryCode.get_Length())-1 #Max 15 characters allowed in devicename. Calculate length of serial# part.
    $userList = $Null

    # Get all users with the current country code. Use paging in order to get more than 999 which is max pr query
    $UsersURL = 'https://graph.microsoft.com/v1.0/users?$filter=startswith(country,'''+ $Country +''')&$top=999'
    While ($UsersURL -ne $Null) {
        $data = (Invoke-WebRequest -Headers $Headers -Uri $UsersURL -UseBasicParsing) | ConvertFrom-Json
        $userList += $data.Value
        $UsersURL = $data.'@Odata.NextLink'    
    }

    # Get all managed devices for each user
    foreach ($User in $UserList) {
        $upn = $User.userPrincipalName
        write-output "- Focus on user $upn"
        $DeviceList = $Null
        $deviceURL = 'https://graph.microsoft.com/v1.0/users/'+ $User.userPrincipalName +'/managedDevices?$filter=startswith(operatingSystem,''Windows'')'
        $DeviceList = (Invoke-RestMethod -Uri $deviceURL -Headers $Headers).value
        $NoOfDevices = $DeviceList.Count
        write-output "- $NoOfDevices device(s) found"

        foreach ($Device in $DeviceList) {
            $CurrentDeviceName = $Device.deviceName
            write-output "--- Focus on device $CurrentDeviceName"
            $OS = $Device.operatingSystem
            $DeviceID = $Device.id
            $FullSerial = $Device.serialNumber

            # Max 15 characters allowed in devicename - Some devices have to long serialnumber
            if ($FullSerial.get_Length() -gt $MaxSerialLength) {
                $DeviceSerial = $FullSerial.substring($FullSerial.get_Length()-$MaxSerialLength)
                write-output "---- Serial too long - shortened!"
            }
            else {
                $DeviceSerial = $FullSerial
            }
            # Calculates new devicename in format NO-12345678
            $CalculatedDeviceName = $CountryCode.ToUpper() + '-' + $DeviceSerial
           
            # Virtual computers have the text "SerialNumber" as serialnumber...
            if (($CurrentDeviceName -ne $CalculatedDeviceName) -and ($DeviceSerial -ne "SerialNumber")) {
                write-warning "---- Device $CurrentDeviceName needs to be renamed to $CalculatedDeviceName"
                # Calculate graph api url's
                $Resource = "deviceManagement/managedDevices/$DeviceID/setDeviceName"
                $GraphApiVersion = "beta"
                $URI = "https://graph.microsoft.com/$GraphApiVersion/$($Resource)"

                $JSONPayload = @{
                "deviceName" = $CalculatedDeviceName
                }

                $convertedJSONPayLoad = $JSONPayload | ConvertTo-Json
               
                #Send change to Graph.
                Invoke-MgGraphRequest -Uri $URI -Method POST -Body $convertedJSONPayLoad -Verbose -ErrorAction Continue
            }
            else {
                write-output "---- $CurrentDeviceName will not be renamed"
            }
        }
    }
}



Verify the results

When running the script, all outputs can be found in the logs, and all renamed computers are logged as warnings:

Feedback from the script with renamed computers found as warnings

This is reflected on the device in the Microsoft Endpoint Manager:

Device waiting to be renamed

As with other renaming requests in Microsoft Endpoint Manager, it requires the device to reboot before all registers (AzureAD, Intune, AutoPilot, Device) are up to date.

Device rename confirmed in the portal

Summary

This routine will effectively and automatically rename devices on a given schedule as long as the app secret is valid. The script can be altered to mix and match variables from user and device in order to create the corresponding device name for your naming convention. You can for example use information from the user like department, company, region, postalcode as a part of the computername.

No extra charge for the mistakes - solution shared as it is - use it at your own risk.

Thanks for reading - please share and comment.



Tuesday, April 19, 2022

Veeam Backup for M365 Automatic Reporting in PowerBI

Those of you which has read through the Microsoft services agreement might have noticed paragraph 6b where Microsoft recommends that you regularly backup your content and data that you store on the services using third-party apps and services. One example of such third party tool popular by managed service providers is the Veeam Backup for Microsoft 365. This blog post will explain how you can get automatic reporting on licenses and sizes used by this application.

Please note: This is not a sponsored post!

Data Deletion

Data deletion can occur when an attacker deletes your data, usually in a way that makes recovery difficult, if not impossible. A variant of this type of attack includes ransomware. With ransomware, an attacker compromises the network, encrypts data, and then demands a payment to get the key to decrypt the data. This may equate to data deletion since a successful extraction of payment often leads to more targeting by the attacker. Attacker motivations for data deletion covering the tracks of an attack, attempting to do irreparable harm to your business, or simply trying to spite you or your employees

Preventing data deletion

Other than the protection mechanisms you should employ to prevent account breach an elevation of privileges, your core prevention strategy should be to ensure you have sufficient redundancies built into your data management processes to minimize the impact of data deletion. Data in Microsoft 365 is made redundant for maximum availability by the service. However, it's still possible for an attacker to delete data from SharePoint sites and recycle bins, making it almost impossible to recover. There is also examples of bugs where data has been deleted from Teams and Sharepoint. Therefore, it's critical that you have a process for backing up mission critical data to offline stores - just like the Microsoft Services Agreement states.

Veeam Backup for Microsoft Office 365

Veeam Backup for Microsoft 365 is one application which can help eliminate the risk of losing access and control over your Office 365 data, including Exchange Online, SharePoint Online, OneDrive for Business and Microsoft Teams. This product is often used by managed service providers offering their services to customers. One challenge will be to automate a reporting solution showing the usage of the service related to license and storage on repositories.

Report automation

Niels Engelen has described a way to automatically send reports from Veeam by email. This is a simple approach to the standard functionality where PDF report will be sent by e-mail. It just didn't fit my expectations for reporting. 

PowerShell data harvesting

I have studied the Veeam Backup for Microsoft 365 PowerShell Reference and made a script counting all licenses, data usage and repository usage on a daily basis. This data is prepared in a JSON format and uploaded to an Azure Cosmos Database. The Azure Cosmos Database is quite inexpensive for this kind of usage. 

The following query will list all licensed users in a JSON format before uploading each record to the Cosmos database.
# Get VBO Licensed users, convert to JSON and upload to CosmosDB
$CosmosDBCollectionID = 'VeeamBackupLicenses'
$LicensedUser = Get-VBOLicensedUser

$output = foreach ($user in $LicensedUser) {
    $LastBackupDate = (($user.LastBackupDate).toString()).Split(" ")[0]
    $id = $([Guid]::NewGuid().ToString())
    $doc = [pscustomobject]@{
        id               = $id
        Username         = $user.UserName
        LastBackupDate   = $LastBackupDate
        Year             = (($LastBackupDate).toString()).Split(".")[2]
        Month            = (($LastBackupDate).toString()).Split(".")[1]
        LicenseState     = $user.LicenseState
        OrganizationName = $user.OrganizationName
    }
    $document = $doc | ConvertTo-json | Out-String
    # Writing data to CosmosDB
    New-CosmosDbDocument -Context $cosmosDbContext -CollectionId $CosmosDBCollectionID -DocumentBody $document -PartitionKey $id -Encoding UTF-8
}


The next query will get the usage pr. organization and upload this to a CosmosDB in JSON format:
# Get VBO Usage pr Organization, convert to JSON and upload to CosmosDB
$CosmosDBCollectionID = 'VeeamBackupUsage'
$Organizations = Get-VBOOrganization
$Date = get-date -Format "dd.MM.yyyy"

$UsageOutput = foreach ($Org in $Organizations) {
    $UsageData = Get-VBOUsageData -Organization $Org
    # Need to handle the fact that a customer can have data in several repositories
    foreach ($Usage in $UsageData) {
        $id = $([Guid]::NewGuid().ToString())
        $UsedSpaceGb = [MATH]::Round((($Usage.UsedSpace) / 1024 / 1024 / 1024), 1)
        $Udoc = [pscustomobject]@{
            id               = $id
            Date             = $Date
            RepositoryId     = $Usage.RepositoryId
            UsedSpaceB       = $Usage.UsedSpace
            UsedSpaceGB      = $UsedSpaceGb
            OrganizationName = $Usage.Organization.DisplayName
            OrganizationMSID = ($Usage.Organization.Id.Value).Split(":")[0]
        }
        $Udocument = $Udoc | ConvertTo-json | Out-String
        # Writing data to CosmosDB
        New-CosmosDbDocument -Context $cosmosDbContext -CollectionId $CosmosDBCollectionID -DocumentBody $Udocument -PartitionKey $id -Encoding UTF-8
    }
}

The third query will get information about the repositories defined in Veeam Backup for Microsoft 365 and upload this in JSON format to the Cosmos Database. The original data values from the queries are in bytes format.
# Get VBO Repositories, convert to JSON and upload to CosmosDB
$CosmosDBCollectionID = 'VeeamBackupRepositories'
$Repositories = Get-VBORepository
$Date = get-date -Format "dd.MM.yyyy"

$RepositoryOutput = foreach ($Repo in $Repositories) {
    $id = $([Guid]::NewGuid().ToString())
    $RepoCapacityTb = [MATH]::Round((($Repo.Capacity) / 1024 / 1024 / 1024 / 1024), 1)
    $RepoFreeSpaceTb = [MATH]::Round((($Repo.FreeSpace) / 1024 / 1024 / 1024 / 1024), 1)
    $Rdoc = [pscustomobject]@{
        id                    = $id
        Date                  = $Date
        RepositoryId          = $Repo.Id.Guid
        RepoName              = $Repo.Name
        RepoPath              = $Repo.Path
        RepoCapacityB         = $Repo.Capacity
        RepoCapacityTB        = $RepoCapacityTb
        RepoFreeSpaceB        = $Repo.FreeSpace
        RepoFreeSpaceTB       = $RepoFreeSpaceTb
        RepoRetentionType     = $Repo.RetentionType
        RepoRetentionPeriod   = $Repo.RetentionPeriod
        RepoRetentionFreqType = $Repo.RetentionFrequencyType
    }
    $Rdocument = $Rdoc | ConvertTo-json | Out-String
    # Writing data to CosmosDB
    New-CosmosDbDocument -Context $cosmosDbContext -CollectionId $CosmosDBCollectionID -DocumentBody $Rdocument -PartitionKey $id -Encoding UTF-8
}

These different Powershell parts are coordinated and scheduled to run as powershell scripts on a regular basis on the Veeam backup servers.
  <Actions Context="Author">
    <Exec>
      <Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
      <Arguments>-ExecutionPolicy bypass -file "C:\Simon\CountVeeam365LicensesDailyToPowerBI.ps1"</Arguments>
    </Exec>
  </Actions>

PowerBI data analyzis

Using PowerBI Desktop, it is easy to connect to the Cosmos Database. With the data loaded into Microsoft PowerBI you can do further manipulations of the data using DAX queries. One example could be to calculate the difference between capacity and free space for the repositories in order to get the used space pr. repository. This could be done like this which will return a separate column with the result ready to use in the report:
RepoUsedSpaceB = CALCULATE(SUM(VeeamRepositories[RepoCapacityB]))-CALCULATE(SUM(VeeamRepositories[RepoFreeSpaceB]))

I have also made a calculation of consumed GB pr user in each company. This is done in two steps. First I calculate number of users pr. company:
AntallBrukere = DISTINCTCOUNT(VeeamLisenser[Bruker])

Then I calculate consumed GB pr user in the company:
GBprBruker = SUM(VeeamUsage[UsedSpaceGB])/Kalkulasjonstabell[AntallBrukere]

Using Power BI we can easily create several reports to visualize the status of the service.

Example of monthly report of all companies and users protected by Veeam 365 Backup which can be the basis for invoicing where this is based on the number of users in the system pr. company.


Example of historical development of backup up users pr. company by Veeam 365 backup.

Example of gigabyte compared to number of users pr. company protected by Veeam 365 backup.

Example of usage of the calculated column for GB pr User. Infinity comes from stored data for customers which have terminated their contract where data still exists. This has been removed from the graph with a visuals filter displaying only companies with more than 0 users.


Example of report for repositories with forecast in the Veeam 365 backup service.

This gives a fully automated always up to date reporting solution showing current usage and historical development related to the provided service, license usage and storage consumptions. The reports can easily be filtered by clicking on the values and graphs giving the consumer of the reports the ability to select the desired view. 


The animation is blured to protect the data exposed in the report

If you upload your PowerBI report to the online PowerBI service, you can set the dataset to automatically update directly from the Cosmos Database. This will allow for online consumption of the report from all your devices. One idea could be to add it as a tab in a suitable team channel in Microsoft Teams giving easy access for everyone interested in the topic.

I do believe someone could have interest in the PowerBI Report file, but unfortunately this can't be shared because my reports contains PII data. 

Conclusion

I hope this could inspire someone to dive into data capturing and report building. If you have thoughts, ideas, comments or ideas after reading this far, please add a comment.




Sunday, April 3, 2022

Good insights in Microsoft license usage

Cloud based IT solutions does have a pretty predictive cost when each and every license is based on a price pr user pr month. This should make it easy to budget the cost of each user role. The challenge might be to have an up to date overview of the license portfolio, both current and over time.

In order to give automated insights to the license situation, I have made a solution which has been installed at several tenants. Based on Microsoft Graph API powershell queries for running in Azure function apps, I am populating license information data from user accounts to a cheap Azure Cosmos DB. These data are then connected to PowerBI where I have created a report giving a detailed insight to the license portfolio pr. company, department, user. The report which can be granulated on year. quarter, month, week or day gives an accurate insight to the consumption of Microsoft licenses in the tenant, which helps address any misconfigurations.

The report has several pages, where the first page gives an overview over license consumption based on company/department with both a graphical and detailed table overview as well as personal details. The report can easily be filtered by clicking on the values in each part of the report.

Click for a larger version

Page two of the report has got a timeline showing the development of Microsoft licenses over time. The report can be filtered by company/department, license or user. This gives an insight to license usage which can't be found elsewhere. The picture below is an example where you clearly can spot a change in SKUs on a large amount of users over time. 

Click for a larger version

In some cases there has been developed even further report pages in order to address the need of insights to the usage of Microsoft licenses, and these reports have several times been used to detect misallocated licenses which in turn have resulted in significant cost savings over time. An example of such report could be the one including groups used to assign licenses to the user accounts.

Click for a larger version

Regarding costs for running the function and cosmosdb in Azure, they seems to be reasonably low. A typically SMB company with arround 200 users shows cost arround 5 NOKs for one month. 

Please let me know if you find this kind of technological usage interesting.

Friday, February 14, 2020

Advanced Microsoft Teams setup at home office

The Modern Workplace supports the demand to work from anywhere. There are companies today operating mainly from home offices. How much technology is acceptable to use for hiding in the home office?

I have been experimenting with knowledge from the photography business and technology from youtuber's in the gaming industry to enrich my Microsoft Teams meetings from my home office. The goal has been to have high quality video conferencing with a simplified and quick operation. This attempt is presented in the following low cost one shot video.


Technical rundown

There has been some questions related to this setup on Twitter, so I decided to make a technical rundown of the setup.

Lights

In order to have a good picture with studio portrait quality, I need good lights. After exploring different options I ended up ordering an Elgato Key Light Air as my main light. This choice was a combination of price and lamp design and features. This lamp has a great stand, it connects wirelessly to my computer, it is cool and brightness and color can easily be controlled.

In addition I am using some Phillips Hue light sources. I have one color light source behind my monitors for ambience light, and in the ceiling I have a ledbar from IKEA which has been equipped with Hue GU10 white ambience light bulbs. I have created some scenes in the Hue system for my video conferencing setup. Two of the GU10 lights in the ceiling are pointed at the green screen trying to make an even light all over the screen. These lights has a cold temperature set in order to make the color of the green screen stand out. I have also pointed one of the GU10 hue lights towards my head to make a hair light for background separation. This light as a warmer tone set. I don't think I need any more fill lights for my current setup.
Workplace with hue ambient light

Workplace with hue ambient light and key light

Hue fill lights for green screen and hair light for background separation

Hue ambient light behind monitor
The Hue scene used for videoconferencing.


Green screen

I have considered several types of green screens. Based on my experiences in studio photography I wanted a solid type to avoid folds which in turn can be troublesome related to lighting and chroma key processing. I had my eyes on the roll-up versions from Elgato and Nebula. These are around 148 cm wide, and they seem easy to fold up an down. These can easily be found cheap on second hand webshops since there are a lot of fading youtube stars out there. I read some reviews and found them to require some floor space. They could in some circumstances also be wider. Some where experimenting with two of these to get enough width on the background - this is kind of tricky in order to get a perfect faded overlapping background.

I finally found the 190 cm wide Elgato Green Screen MT which can be easily mounted in the ceiling. This one will cover my entire bookshelf without taking up any space on the floor. I had some concerns related to the weight when mounted in the ceiling, but in practice this was not a problem. Unfortunately no Elgato Green Screen MT was found on second hand marketplaces, but it wasn't the most expensive one. When bought as new, I also got first class packaging and shipping. I certainly do not regret this choice.
Bookshelf and guitars with Green Screen MT rolled up in the ceiling

Bookshelf and guitars hidden behind Green Screen MT rolled down from the ceiling

Detail from the mounting of the Green Screen MT in the ceiling


Green Screen processing

In order to do a chroma key processing of the green screen, I am using the OBS Studio freeware. This is a software primarily made for streaming to Twitch, YouTube and other services. In this project I am using the VirtualCam function found in the Tools menu. This sends the output mix from OBS to Windows as a virtual camera driver and can therefore be selected as source in Microsoft Teams. The VirtualCam has been set to AutoStart.
Configuration of the VirtualCam in OBS
OBS-Camera selected as Camera in Teams - Settings - Devices - Camera

In OBS I have configured different scenes and scene transitions. Each scene can consist of a mix of several sources, including physical cameras attached to the computer, images, media sources and more. As a webcam I am currently using a Logi HD Pro WebCam C920. Inside OBS I have added a Chroma Key effect filter to this camera source in order to make a transparent background from the green screen. This combined with some environmental photos can make some exciting scenes. The OBS software has a lot of advanced opportunities, and you can easily find information and inspiration on this on YouTube.
1: Scenes, 2: Sources used in scenes, 3: Scene transitions, 4: Filters used on sources in scene
1: Add the Chroma Key filter, 2: Adjust the different variables, 3: Pay attention to the edge transitions

Filters

OBS has a rich pallette of options and third party plugins. One great valueadd to OBS studio is the StreamFX pluging which has a couple of great filters to enrich your setup. Alpha Gaming is giving a nice overview of this in his YouTube channel. I use the Blur filter from this package to add a small amount of blur on my background image. This technique can be used to imitate a picture with a shallow depth of view often seen by using DSLR's with pricy optics connected through Elgato Cam Link.
StreamFX Blur plugin applied to my background image

Props

When working on the different backgrounds, it is allways funny and effective to have props to put on your self in order to enhance the effect. A couple of examples in the following images.
Having a good time at my cottage

Having a good time at my home office, aka "jammekontor"

Having a rough time out in the field


Control Panel

In order to operate these technologies quick and easy, I am using a Stream Deck from Elgato. This system with all of its plugins has innumerable opportunities regarding automation and control. I have created many functions that support me throughout the day in the office. 
Elgato Stream Deck located under my monitors

In order to easily do a Microsoft Teams meeting, I have set up a Multi Action button with 10 actionpoints [1: Launch OBS Studio, 2: Pause Spotify, 3: Set Hue scene for videoconferencing, 4: Turn on KeyLight, 5: Set Key Light temperature, 6: Set Key Light brightness, 7: Select OBS Scene, 8: Move Microsoft Teams to full screen, 9: Delay for 3s 10: Go to Calendar in Teams].
Configuration of the Multi Action button for starting a Teams meeting

Actions included in the Multi Action button for starting a Microsoft Teams meeting

In the same way I have created a Multi Action button with 4 actions to use when ending a Micreosoft Teams meeting [1: Play Spotify, 2: Set Hue scene for normal office work, 3: Turn off Key Light, 4: Minimize Microsoft Teams 4: End OBS Studio]
Actions included in the Multi Action button for ending a Microsoft Teams meeting

During a Teams meeting I have found it handy to have some special actions available. These are located in a separate folder containing a new set of buttons. Today I am using these to switch between the different scenes in OBS. These scenes includes different backgrounds, screensharing with talking head etc. I have also made a button for muting the microphone.
Stream Deck with OBS Scene controls and Mic mute
OBS Scenes with corresponding buttons for toggling sources on and off

Teams meeting with OBS VirtualCam

Teams meeting with OBS VirtualCam and Background Blur in Microsoft Teams

Teams meeting with OBS Scene in with screen sharing and talking head

The talking head challenge

I do experience some blured image quality on screensharing through OBS Virtual Camera plugin to Microsoft Teams meeting. I have tried to figure this out without any success yet. In a regular Teams meeting with VirtualCam, I don't think screensharing through OBS and VirtualCam is a good idea.

I have found a working setup for sharing your screen with a talking head directly to a Teams meeting. This requires multiple monitors. In my example I have a 3 monitor setup. This setup will give sufficient quality on the content shared into the meeting.

  • Monitor#1 is used as a stage, running OBS in fullscreen projection. I have a scene with content from Monitor#2 and a talking head overlay. I will share Monitor#1 into the Teams meeting. 
  • Monitor#2 will be the workspace for content shared to the meeting. All content on this monitor will be shared to the meeting (powerpoints etc). A pro tip would be to place the cam and the workspace monitor in such a way that your head is looking inbound to the monitor in the shared window when working.
  • Monitor#3 is my Teams management monitor used to control the Teams meeting, OBS settings etc. This should be the main monitor for popups etc.


Three monitor setup for sharing screen with talking head into Teams
Right click in the preview and select Fullscreen Projector

Stream Timer 

In some cases, a counter is desirable. This is often done with the help of a third party software updating a txt file which is added as a text layer in OBS. There are many free providers, some simple while others are more advanced. One example is http://www.mystreamtimer.com/ which can do both count down and count up in addition to have a leading text and a separate ending text. This can even be triggered directly from Stream Deck! Another simple one is the free Countdown Timer v2.0.
My Stream Timer implemented in OBS

Teams Live Events

Luca Vitali has described a routine for using OBS as a source to Microsoft Teams and Stream Live Events. This routine is not using the VirtualCam, but OBS is streaming directly to the Teams Live Event. In such cases I guess the scene with screensharing and talking head is Ok.

The Pomodoro challenge

I got challenged by Ståle Hansen to include his Pomodoro powershell script into the Stream Deck. This has been testet and found Ok. I had some initial problems when using the "advanced launcher" plugin loading "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -file Start-SimplePomodoro.ps1". This powershell session didn't find the "presentationsettings" command. I had to use the "Super Macro" plugin instead. Now I have a separate button on my Stream Deck for launching 20 minutes of focus with no distractions.
Pomodoro powershell added as a button in my Stream Deck.

Alternative Pomodoro routine created with actions in Stream Deck

Embrava Busy Light

After the korona virus breakout, I have had my house full of three kids since the norwegian schools and kindergardens where closed. In order to let the kids know my working status at the home office, I have extended my home office setup with an Embrava Blynclight. This light indicates when I am "on air". This gives a better experience to my calls and meetings run from the home office during this pandemy.
Busy light on my monitor before it was moved next to the door leading to the home office.
PS! After a quick computer reset (windows autopilot), I had a problem connecting the blynclight to Microsoft Teams. This got solved after installing the Skype for Business client (the Office installation came without SFB client which I needed for customer support). Embrava support has investigated this issue and found that the Office 365 installation suite some times corrupting the registry keys required for Office Chat API interface. If such registry keys are corrupted then the Office Chat API interface won't work. A re-install or repair of the Office installation are often fixing this issue. In my case, the installation of the Skype for Business Client did. Embrava is working on a new driver version connecting directly to the Microsoft Teams server in order to get arround this problem. My guess is that they will use the Microsoft Graph API.

Snap Camera

Snapchat has lauched the Snap Camera application for Windows and MAC, bringing the magic of lenses to the video chats on PC & Mac. This can be used directly into Teams, and it can also be included in the OBS Studio. Could be kind of funny in some situations, but mostly annoying. It is also annoying that Snap Camera requires exclusive access to the webcams on your computer.

Webcamera as source

In the new Windows 10 2004 update (build 18995), it is possible for users to associate network cameras to their PC, enabling photo capture and streaming of video in camera applications. Currently Windows only supports ONVIF Profile S compliant cameras*, which are standards-compliant network cameras optimized for real-time streaming video capture. Windows provides support for discovery, pairing, configuration and streaming via WinRT APIs. These settings are described in this website. I can't wait to use a live webcamera as a source in my OBS setup!

Logitech Capture

Logitech Capture is an alternative software for managing multiple content, talking head etc. I have done some small tests, but it will not replace my usage of OBS studio. It does not integrate into the Elgato Setup, and the chroma key functions are poor compared to OBS.
Testing Logitech Capture.

Teams Customized Backgrounds

Microsoft is rolling out customized backgrounds as part of the native Teams experience. This means you now can replace the background directly in Microsoft Teams. You will find this option as part of the background blur in your Teams client. This is a nice lowcost feature, but it does not compare to a full green screen setup, and all the features you have in OBS studio - for instance add a background video.

Microsoft will sooon release the option to upload your personal images. You can however do this manually by copying your photos to the following folder: %APPDATA%\Microsoft\Teams\Backgrounds\Uploads\
Select background blur and pick your preferred background.
I have added a screenshot of my normal background with me present. Now I can walk away from the meeting but still be present :)

Use with other video systems

I have used this OBS Studio setup with the virtual camera plugin with other video systems as well - even Skype for Business. This proves that this setup is universal to all systems utilizing a webcamera on the computer.

End notes

Is this acceptable use of technology or is it overkill? Is this something you could imagine in your office or home office? Microsoft has announced a customized background feature in Microsoft Teams comming later this year. Could it be a good idea to paint a wall in your office green and install a key light for better quality during Microsoft Teams Meetings?