Pages

Friday, May 29, 2020

Planning and setting up a Site-to-Site VPN connection between an on-premise network and Azure

One of the tasks most administrators will have to perform when adopting Microsoft’s Azure as their cloud platform is setting up a site-to-site VPN connection between their on-premise infrastructure to an Azure region where they will host their IaaS, PaaS or SaaS services. There are plenty of blog posts, YouTube videos and Microsoft documentation demonstrating the configuration but I find that most of the environments I come across tend to show that not a thought has been put into something as simple as, yet I feel is very important, naming conventions. With that in mind, this post serves to place a bit more emphasis on preparing the resources that will be required to set up the VPN connection prior to proceeding with the configuration.

The following is a diagram of what the topology would look like along with the resources we will be creating:

image 

Azure Resource Preparation

image

It is possible to create the Azure resources required for a site-to-site VPN connection during the configuration but making decision on the fly is prone to mistakes that you may make so it is always best to plan and design the resources before commencing with the configuration.

As a start, if this has not been done, spend some time to determine how resources should be named. Maintaining a standard naming convention will save you a lot of grief in the future and make it much easier to identify resources and/or sort them into lists for exercises such as billing. Microsoft has an official document that provides recommendations for naming and tagging here:

Recommended naming and tagging conventions
https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging

**Note that I don’t proclaim that my naming conventions are the best but I hope a demonstration would provide an example for such an exercise.

image 

Resource Groups
Every resource in Azure needs to be placed into a resource group so the first step is to determine where the resources that will be required for the site-to-site VPN will be created. It is possible to move a resource to another resource group or even another subscription but putting a bit of thought in how you would like to organize your resources and maintaining a standard will ensure tidiness. For the purpose of this example, all of the resources created for the site-to-site VPN will be placed into a single resource group containing networking items as the environment isn’t very large. It is possible to break up the components into dedicated groups (e.g. Public IPs, Virtual Network Gateways, Virtual Networks).

Resource group: rg-prod-network

image 

Subnets
Subnets are networks you define in Virtual Networks (VNet) and it is not something you create before the creation of the Virtual Network but it is best to pre-plan the name and subnet prior to the configuration.

Subnet

Parameter

Configuration

Name

snet-prod-svr-10.248.1.0-24

Address range (CIDR block)

10.248.1.0/24

The naming convention chosen is to use the snet- prefix followed by the environment (in this case production) and then the Azure region (East US).

Gateway Subnet
The gateway subnet contains the IP addresses that the virtual network gateway virtual machines and services use. When you create your virtual network gateway, gateway VMs are deployed to the gateway subnet and configured with the required VPN gateway settings. This subnet is reserved solely for the virtual network gateway so do not deploy anything else into it. The subnet size can be as small as /29 but it is recommended to be /27 or larger as this would accommodate most configurations and not limit additional virtual network gateway connections in the future.

Gateway Subnet

Parameter

Configuration

Name

GatewaySubnet

Address range (CIDR block)

10.248.255.0/27

The Gateway Subnet is specific to the VNet and you are not allowed to provide a custom name so the default will be used.

image 

Virtual Networks
The Azure Virtual Network (also known as VNet) is a fundamental building block for the network in Azure. These objects define the IP scheme of the resources located within it and interacts with other VNets and/or networks through a Virtual network Gateway. Note that moving a virtual machine between VNets isn’t very straight forward and trying to redesign VNets after a deployment can be a laborious task so spend some time to think out the naming convention and IP addressing before creating and using them. For the purpose of this example, we’ll have one VNet that contains all of the production servers.

Virtual network

Parameter

Configuration

Name

vnet-prod-eastus

Location

East US

Address Space

10.248.0.0/16

Subnets

Hosts Subnet: 10.248.1.0/24 (247 addresses)

GatewaySubnet: 10.248.255.0/27 (26 IP addresses)

DNS servers

Domain Controllers

The naming convention chosen is to use the vnet- prefix followed by the environment (in this case production) and then the Azure region (East US).

image 

Public IP Address
Public IP addresses are fairly self-explanatory as these objects represent the public IP addresses available that can be assigned to resources such as a virtual machine, Virtual Network Gateway or application. The public IP address we’ll need for the site-to-site VPN is a public IP for the VPN Gateway.

Public IP Address:

Parameter

Configuration

Name

pip-vgw-EastUS

SKU

Basic

IP address assignment

Dynamic

The naming convention chosen is to use the pip- prefix followed by the Virtual Network Gateway prefix vgw- and then the Azure region (East US).

image 

Virtual Network Gateway
The Virtual Network Gateway is the device that establishes the connection to the VPN device at your on-premise datacenter or office. Note that a single Virtual Network Gateway can establish multiple site-to-site VPN connections so it is not advisable to name it to include where it is connecting to.

Virtual Network Gateway

Parameter

Configuration

Name

vgw-EastUS

VPN type

Route-based

SKU

VpnGw1

Gateway type

VPN

The naming convention chosen is to use the vgw- prefix followed by the Azure region (East US).

image 

Local Network Gateway
The Local Network Gateway represents the device at your on-premise datacenter or office that establishes the connection to the Virtual Network Gateway at the Azure region. You will need to work with the network engineer to determine what static IP address this device will use to accept the site-to-site VPN connection as well as the address space (subnets) that reside in the network so the VNet will know what traffic to route through this VPN.

Local Network Gateway

Parameter

Configuration

Name

lgw-BDA-EastUS

IP Address

162.x.213.x

Address Space

10.247.0.0/16, 192.168.113.0/24

The naming convention chosen is to use the lgw- prefix followed by the location of the gateway (in this case BDA represents Bermuda) and finally which Azure region (East US) it is connecting to.

image 

Connection (Site-to-Site)
The connection represents the site-to-site connection between the Azure Virtual Network Gateway to the Local Network Gateway.

Connection between Azure Virtual Network Gateway to Local Network Gateway

Parameter

Configuration

Connection Type

Site-to-Site

Name

cn-lgw-BDA-EastUS-to-vgw-EastUS

Shared key (PSK)

<create a unique string>

Protocol

IKEv2

Location

East US

The naming convention chosen is to use the cn- prefix followed by the local network gateway object name, then the -to- to indicate that it is connected to the virtual network gateway in Azure.

On-Premise Preparation

The network engineer configuring the VPN appliance on-premise will likely ask you for the:

  • Public IP address of the virtual network gateway in Azure
  • Shared key
  • Address space in Azure (if they were not involved with the subnet planning)
  • VPN type

You wouldn’t be able to complete the configuration without asking and obtaining the following information for the on-premise appliance:

  • Public IP address of the local network gateway located on-premise

What I typically do is agree on a shared key, address space and VPN type with the network engineer, proceed to create the virtual network gateway, supply the information to the engineer, then ask for them to provide me with the public IP address of the local network gateway.

Deployment

Resource Group
Begin by creating the resource group or groups that these resources will reside in. For the purpose of this example, we will create one resource group named rg-prod-network for all of the resources.

image

Virtual Networks
Create the virtual network (VNet) that will be used to host the Virtual Network Gateway and host the resources such as virtual machines.

image

Remove the default IPv4 address space of 10.0.0.0/16 and default subnet of 10.0.0.0/24 if those are not the address space and subnet you will be using:

image

Add the subnet you’ll be using into the VNet configuration:

image

image

Leave DDoS protection on and the firewall either as disabled or enabled if one is configured and to be used:

image

Add a designed tag for the resources if ones have been planned for the resource:

image

Proceed to create the VNet:

image

Once the Virtual Network has been created, proceed to navigate into the resource, then to Subnets and then click on Gateway subnet:

image

Create the Gateway Subnet with the pre-planned subnet:

image

For the purpose of this example, we will only configure the Address range (CIDR block) and leave the rest as default/unconfigured.

You should now see the two subnets configured for the VNet:

image

Public IP Address
It may seem logical to create a public IP address before creating the virtual network gateway but what I’ve noticed in the past (not sure if this has changed) is you cannot assign a static public IP address to the gateway and creating a dynamic public IP address would not allow you to select it during the virtual network gateway configuration (probably because a dynamic public IP address doesn’t actually have an IP assigned to it until it is associated and used) so this is the one component that I create during the configuration of the virtual network gateway. Having the name of the public IP address for the virtual network gateway planned should still be done.

Virtual Network Gateway
Proceed to create the virtual network gateway by navigating to the virtual network gateways resource and click Add:

image

Create the virtual network gateway with the configuration previously planned:

image

The creation of the gateway takes a bit of time (upwards to 20 minutes or more) so do not expect it to be within a few minutes.

image

You’ll notice that the public IP address gets created quickly but there is no IP address assigned:

image

The reason is because this public IP address is configured for the virtual network gateway and the deployment hasn’t completed yet. Note how the Assignment configuration is set to Dynamic as well.

image

Once the virtual network gateway deployment has completed, obtain the public IP address that has been assigned to it, proceed to reach out to the network engineer configuring the local network gateway and provide him with the public information.

image

Also ensure that you have obtained the Public IP address of the local network gateway located on-premise.

Local Network Gateway
While waiting for the virtual network gateway deployment to complete, you can continue with creating the local network gateway by navigating to the local network gateways resource and click Add:

image

Create the local network gateway with the configuration previously planned:

image

The deployment, unlike the virtual network gateway, shouldn’t take too long to complete:

image

Connection (Site-to-Site)
Once you have confirmed with the network engineer that the on-premise VPN appliance is configured, you can proceed to connect the Azure Virtual Network Gateway to the Local Network Gateway. Proceed to navigate to the virtual network gateway object, connections and then click on the Add button:

image

Create the virtual network gateway connection to the local network gateway with the configuration previously planned:

image

The creation of the connection doesn’t take long and the initial connection Status will be labeled as Unknown:

image

Assuming there are no problems with the configuration then the Status will be change to Connected:

image

image

**Note that one of the things I’ve noticed in the past is that if you do not define an address space for the local gateway network then the connection status would remain unknown indefinitely so ensure that it has been configured.

image

You can proceed to configure additional site-to-site connections to other gateways if there are other datacenters or offices that need to connect into Azure.

image

Generating a SharePoint Online permissions audit report by site collection

I was recently asked by a client to look for a PowerShell script that would export the permissions for all of the files and folders within each of their site collection so they can perform a thorough audit and as common as such a request seemed to me, I had much difficulty when I searched through the internet for such a script. Since I did not have any luck finding one that actually worked, I reached out to one of our SharePoint resources for help and he eventually provided one that was able to execute and export the permissions to a CSV file. I am unsure as to where the script is from so I’d like to apologize for not crediting the author but I hope this will provide anyone who may be looking for such a script as I did.

The generated report will look as such:

image  image

The following PowerShell script runs against per site collection so you will need to run it multiple times against as many sites as required as well as grant yourself administrative permissions to the site collection:

image

image

The script only requires two lines to be adjusted accordingly:

image

#region ***Parameters***

$SiteURL="https://contoso.sharepoint.com/"

$ReportFile="C:\temp\SitePermissionRepor.csv"

#endregion

Other sites will require the path to be adjusted as such:

$SiteURL="https://contoso.sharepoint.com/sites/FinanceSite"

The following is the PowerShell script:

image

#Function to Get Permissions Applied on a particular Object, such as: Web, List, Folder or List Item

Function Get-PnPPermissions([Microsoft.SharePoint.Client.SecurableObject]$Object)

{

#Determine the type of the object

Switch($Object.TypedObject.ToString())

    {

"Microsoft.SharePoint.Client.Web"  { $ObjectType = "Site" ; $ObjectURL = $Object.URL; $ObjectTitle = $Object.Title }

"Microsoft.SharePoint.Client.ListItem"

        {

If($Object.FileSystemObjectType -eq "Folder")

            {

$ObjectType = "Folder"

#Get the URL of the Folder

$Folder = Get-PnPProperty -ClientObject $Object -Property Folder

$ObjectTitle = $Object.Folder.Name

$ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''),$Object.Folder.ServerRelativeUrl)

            }

Else #File or List Item

            {

#Get the URL of the Object

Get-PnPProperty -ClientObject $Object -Property File, ParentList

If($Object.File.Name -ne $Null)

                {

$ObjectType = "File"

$ObjectTitle = $Object.File.Name

$ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''),$Object.File.ServerRelativeUrl)

                }

else

                {

$ObjectType = "List Item"

$ObjectTitle = $Object["Title"]

#Get the URL of the List Item

$DefaultDisplayFormUrl = Get-PnPProperty -ClientObject $Object.ParentList -Property DefaultDisplayFormUrl

$ObjectURL = $("{0}{1}?ID={2}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''), $DefaultDisplayFormUrl,$Object.ID)

                }

            }

        }

Default

        {

$ObjectType = "List or Library"

$ObjectTitle = $Object.Title

#Get the URL of the List or Library

$RootFolder = Get-PnPProperty -ClientObject $Object -Property RootFolder

$ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''), $RootFolder.ServerRelativeUrl)

        }

    }

#Get permissions assigned to the object

Get-PnPProperty -ClientObject $Object -Property HasUniqueRoleAssignments, RoleAssignments

#Check if Object has unique permissions

$HasUniquePermissions = $Object.HasUniqueRoleAssignments

#Loop through each permission assigned and extract details

$PermissionCollection = @()

Foreach($RoleAssignment in $Object.RoleAssignments)

    {

#Get the Permission Levels assigned and Member

Get-PnPProperty -ClientObject $RoleAssignment -Property RoleDefinitionBindings, Member

#Get the Principal Type: User, SP Group, AD Group

$PermissionType = $RoleAssignment.Member.PrincipalType

#Get the Permission Levels assigned

$PermissionLevels = $RoleAssignment.RoleDefinitionBindings | Select -ExpandProperty Name

#Remove Limited Access

$PermissionLevels = ($PermissionLevels | Where { $_ -ne "Limited Access"}) -join ","

#Leave Principals with no Permissions

If($PermissionLevels.Length -eq 0) {Continue}

#Get SharePoint group members

If($PermissionType -eq "SharePointGroup")

        {

#Get Group Members

$GroupMembers = Get-PnPGroupMembers -Identity $RoleAssignment.Member.LoginName

#Leave Empty Groups

If($GroupMembers.count -eq 0){Continue}

$GroupUsers = ($GroupMembers | Select -ExpandProperty Title) -join ","

#Add the Data to Object

$Permissions = New-Object PSObject

$Permissions | Add-Member NoteProperty Object($ObjectType)

$Permissions | Add-Member NoteProperty Title($ObjectTitle)

$Permissions | Add-Member NoteProperty URL($ObjectURL)

$Permissions | Add-Member NoteProperty HasUniquePermissions($HasUniquePermissions)

$Permissions | Add-Member NoteProperty Users($GroupUsers)

$Permissions | Add-Member NoteProperty Type($PermissionType)

$Permissions | Add-Member NoteProperty Permissions($PermissionLevels)

$Permissions | Add-Member NoteProperty GrantedThrough("SharePoint Group: $($RoleAssignment.Member.LoginName)")

$PermissionCollection += $Permissions

        }

Else

        {

#Add the Data to Object

$Permissions = New-Object PSObject

$Permissions | Add-Member NoteProperty Object($ObjectType)

$Permissions | Add-Member NoteProperty Title($ObjectTitle)

$Permissions | Add-Member NoteProperty URL($ObjectURL)

$Permissions | Add-Member NoteProperty HasUniquePermissions($HasUniquePermissions)

$Permissions | Add-Member NoteProperty Users($RoleAssignment.Member.Title)

$Permissions | Add-Member NoteProperty Type($PermissionType)

$Permissions | Add-Member NoteProperty Permissions($PermissionLevels)

$Permissions | Add-Member NoteProperty GrantedThrough("Direct Permissions")

$PermissionCollection += $Permissions

        }

    }

#Export Permissions to CSV File

$PermissionCollection | Export-CSV $ReportFile -NoTypeInformation -Append

}

#Function to get sharepoint online site permissions report

Function Generate-PnPSitePermissionRpt()

{

[cmdletbinding()]

Param

    (   

[Parameter(Mandatory=$false)] [String] $SiteURL,

[Parameter(Mandatory=$false)] [String] $ReportFile,

[Parameter(Mandatory=$false)] [switch] $Recursive,

[Parameter(Mandatory=$false)] [switch] $ScanItemLevel,

[Parameter(Mandatory=$false)] [switch] $IncludeInheritedPermissions

    ) 

Try {

#Connect to the Site

Connect-PnPOnline -URL $SiteURL -UseWebLogin

#Get the Web

$Web = Get-PnPWeb

Write-host -f Yellow "Getting Site Collection Administrators..."

#Get Site Collection Administrators

$SiteAdmins = Get-PnPSiteCollectionAdmin

$SiteCollectionAdmins = ($SiteAdmins | Select -ExpandProperty Title) -join ","

#Add the Data to Object

$Permissions = New-Object PSObject

$Permissions | Add-Member NoteProperty Object("Site Collection")

$Permissions | Add-Member NoteProperty Title($Web.Title)

$Permissions | Add-Member NoteProperty URL($Web.URL)

$Permissions | Add-Member NoteProperty HasUniquePermissions("TRUE")

$Permissions | Add-Member NoteProperty Users($SiteCollectionAdmins)

$Permissions | Add-Member NoteProperty Type("Site Collection Administrators")

$Permissions | Add-Member NoteProperty Permissions("Site Owner")

$Permissions | Add-Member NoteProperty GrantedThrough("Direct Permissions")

#Export Permissions to CSV File

$Permissions | Export-CSV $ReportFile -NoTypeInformation

#Function to Get Permissions of All List Items of a given List

Function Get-PnPListItemsPermission([Microsoft.SharePoint.Client.List]$List)

        {

Write-host -f Yellow "`t `t Getting Permissions of List Items in the List:"$List.Title

#Get All Items from List in batches

$ListItems = Get-PnPListItem -List $List -PageSize 500

$ItemCounter = 0

#Loop through each List item

ForEach($ListItem in $ListItems)

            {

#Get Objects with Unique Permissions or Inherited Permissions based on 'IncludeInheritedPermissions' switch

If($IncludeInheritedPermissions)

                {

Get-PnPPermissions -Object $ListItem

                }

Else

                {

#Check if List Item has unique permissions

$HasUniquePermissions = Get-PnPProperty -ClientObject $ListItem -Property HasUniqueRoleAssignments

If($HasUniquePermissions -eq $True)

                    {

#Call the function to generate Permission report

Get-PnPPermissions -Object $ListItem

                    }

                }

$ItemCounter++

Write-Progress -PercentComplete ($ItemCounter / ($List.ItemCount) * 100) -Activity "Processing Items $ItemCounter of $($List.ItemCount)" -Status "Searching Unique Permissions in List Items of '$($List.Title)'"

            }

        }

#Function to Get Permissions of all lists from the given web

Function Get-PnPListPermission([Microsoft.SharePoint.Client.Web]$Web)

        {

#Get All Lists from the web

$Lists = Get-PnPProperty -ClientObject $Web -Property Lists

#Exclude system lists

$ExcludedLists = @("Access Requests","App Packages","appdata","appfiles","Apps in Testing","Cache Profiles","Composed Looks","Content and Structure Reports","Content type publishing error log","Converted Forms",

"Device Channels","Form Templates","fpdatasources","Get started with Apps for Office and SharePoint","List Template Gallery", "Long Running Operation Status","Maintenance Log Library", "Images", "site collection images"

,"Master Docs","Master Page Gallery","MicroFeed","NintexFormXml","Quick Deploy Items","Relationships List","Reusable Content","Reporting Metadata", "Reporting Templates", "Search Config List","Site Assets","Preservation Hold Library",

"Site Pages", "Solution Gallery","Style Library","Suggested Content Browser Locations","Theme Gallery", "TaxonomyHiddenList","User Information List","Web Part Gallery","wfpub","wfsvc","Workflow History","Workflow Tasks", "Pages")

$Counter = 0

#Get all lists from the web  

ForEach($List in $Lists)

            {

#Exclude System Lists

If($List.Hidden -eq $False -and $ExcludedLists -notcontains $List.Title)

                {

$Counter++

Write-Progress -PercentComplete ($Counter / ($Lists.Count) * 100) -Activity "Exporting Permissions from List '$($List.Title)' in $($Web.URL)" -Status "Processing Lists $Counter of $($Lists.Count)"

#Get Item Level Permissions if 'ScanItemLevel' switch present

If($ScanItemLevel)

                    {

#Get List Items Permissions

Get-PnPListItemsPermission -List $List

                    }

#Get Lists with Unique Permissions or Inherited Permissions based on 'IncludeInheritedPermissions' switch

If($IncludeInheritedPermissions)

                    {

Get-PnPPermissions -Object $List

                    }

Else

                    {

#Check if List has unique permissions

$HasUniquePermissions = Get-PnPProperty -ClientObject $List -Property HasUniqueRoleAssignments

If($HasUniquePermissions -eq $True)

                        {

#Call the function to check permissions

Get-PnPPermissions -Object $List

                        }

                    }

                }

            }

        }

#Function to Get Webs's Permissions from given URL

Function Get-PnPWebPermission([Microsoft.SharePoint.Client.Web]$Web)

        {

#Call the function to Get permissions of the web

Write-host -f Yellow "Getting Permissions of the Web: $($Web.URL)..."

Get-PnPPermissions -Object $Web

#Get List Permissions

Write-host -f Yellow "`t Getting Permissions of Lists and Libraries..."

Get-PnPListPermission($Web)

#Recursively get permissions from all sub-webs based on the "Recursive" Switch

If($Recursive)

            {

#Get Subwebs of the Web

$Subwebs = Get-PnPProperty -ClientObject $Web -Property Webs

#Iterate through each subsite in the current web

Foreach ($Subweb in $web.Webs)

                {

#Get Webs with Unique Permissions or Inherited Permissions based on 'IncludeInheritedPermissions' switch

If($IncludeInheritedPermissions)

                    {

Get-PnPWebPermission($Subweb)

                    }

Else

                    {

#Check if the Web has unique permissions

$HasUniquePermissions = Get-PnPProperty -ClientObject $SubWeb -Property HasUniqueRoleAssignments

#Get the Web's Permissions

If($HasUniquePermissions -eq $true)

                        {

#Call the function recursively                           

Get-PnPWebPermission($Subweb)

                        }

                    }

                }

            }

        }

#Call the function with RootWeb to get site collection permissions

Get-PnPWebPermission $Web

Write-host -f Green "`n*** Site Permission Report Generated Successfully!***"

     }

Catch {

write-host -f Red "Error Generating Site Permission Report!" $_.Exception.Message

   }

}

#region ***Parameters***

$SiteURL="https://contoso.sharepoint.com/"

$ReportFile="C:\temp\SitePermissionRepor.csv"

#endregion

#Call the function to generate permission report

#Generate-PnPSitePermissionRpt -SiteURL $SiteURL -ReportFile $ReportFile -Recursive

Generate-PnPSitePermissionRpt -SiteURL $SiteURL -ReportFile $ReportFile -Recursive -ScanItemLevel

Thursday, May 28, 2020

Creating a VNet Peering (Virtual Network Peering) across different subscriptions and Azure Active Directory tenants

I was recently asked to assist with establishing a connection between a client’s Azure tenant with a partner’s tenant and as the two organizations are different companies with no ties, their tenants were in different subscriptions. Prior to November 2019, the only option to achieve this was through the use of a site-to-site VPN but Microsoft has since released the feature to configure VNet Peering across subscriptions that allows organizations to enjoy all the performance benefits of VNet Peering such as traversing through the Azure backbone network rather than the internet (Virtual network peering across Azure Active Directory tenants: https://azure.microsoft.com/en-us/updates/cross-aad-vnet-peering/).

The configuration outlined in the following document was very straight forward:

Create a virtual network peering - Resource Manager, different subscriptions and Azure Active Directory tenants
https://docs.microsoft.com/en-gb/azure/virtual-network/create-peering-different-subscriptions

However, both the administrator and I became lost when we reached step 21 just after entering the Resource ID:

image

The documentation did not mention what we were supposed to enter or select for the Directory and when we clicked on the dropdown box, no options were displayed:

image

We went through the documentation together but couldn’t figure out what we were supposed to fill in for the Directory so I ended up opening a support case with Microsoft. The support engineer suggested that we tried to use PowerShell to create the VNet Peering but it did not resolve the issue. It was by chance that I decided to log into the email of the account I used, which had Azure Global Administrator permissions, to see if there was some sort of an invite when the administrator added my account as a Network contributor was when I realized an invitation was sent and required to be accepted:

image

Accepting the invitation and attempting to create the VNet Peering now displayed the other organization’s directory in the dropdown box:

image

Selecting the Directory and completing the configuration established the VNet Peering.

Notes

Notes that I feel are worth mentioning are as follows:

  1. The account you use provide the other tenant’s administrator to be granted Network contributor may not be an account that is regularly used and therefore may not have a mailbox so ensure that you use one that has one
  2. The account you use isn’t going to be used as a service account so don’t create a dedicated account for this operation
  3. The guest account you grant Network contributor role from the other tenant can be removed from your Azure AD after the VNet Peering has established (we tested connectivity after removing the account and the peering still works)
  4. Network Security Groups (NSG) are only can only be associated to NICs or Subnets in your own tenant so to secure your tenant from the peered tenant’s virtual network will require NSGs to be applied to the resources you have in your tenant (you cannot apply an NSG to, say, the peered tenant’s VNet)

Hope this helps anyone who may encounter the same problem as I experienced.

Sunday, May 24, 2020

Deploying Azure AD Connect for Office 365 with AD FS for authentication

One of the methods for providing authentication for Office 365 services is to redirect users back to an on-premise AD FS (Active Directory Federation Services) portal so that authentication can be handled by the local infrastructure with Domain Controllers. Some organizations prefer this route because they may already have AD FS setup for multiple services with a MFA solution configured and would like to unify authentication requests to their on-premise infrastructure because they have yet to migrate their infrastructure to the Azure cloud. In other instances, the organization may already have most of their infrastructure migrated to the Azure cloud but would like to leverage the additional capabilities of AD FS. I won’t go into the details of each option but refer to the following documentation for more information:

Azure AD Connect user sign-in options
https://docs.microsoft.com/en-us/azure/active-directory/hybrid/plan-connect-user-signin#federation-that-uses-a-new-or-existing-farm-with-ad-fs-in-windows-server-2012-r2

I’ve come across many organizations who have their AD Connect installed on a domain controller but it is actually not recommended by Microsoft:

https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-install-prerequisites

Installing Azure AD Connect on a Domain Controller is not recommended due to security practices and more restrictive settings that can prevent Azure AD Connect from installing correctly.

Other security concerns are as follows:

  • Restarts of the server for troubleshooting AD Connect would affect domain controller services, DNS or other roles that may be on the server
  • DR for domain controllers would not be as straightforward with the additional AD Connect service installed and the same will be for the AD Connect
  • AD Connect installs a version of SQL Server 2012 Express Edition database which complicates the demotion of a domain controller if that is to be done in the future
  • SQL Server 2012 is an additional component that can raise security concerns when on a domain controller
  • Extra application or agent increases the attack surface (SQL Server are known for vulnerabilities)
  • Azure AD Connect service accounts requiring administrative permissions are added locally to the server which means it would be placed into the Builtin\Administrators group thus resulting it having administrative privileges to the AD Domain
  • Local install of SQL Server would consume additional memory thus resulting in extra memory consumption contending with the domain controller’s use of RAM to cache the ntds.dit database
  • If the domain controller AD Connect is installed on is not a GC then that can cause issues

I would suggest reviewing the Microsoft provided documentation so that you can have the information required to make the best decision that meets the organization’s requirements.

With the above stated, the purpose of this post will be to demonstrate the process of installing and setting up Azure AD Connect to use AD FS as the user sign-in method for the organization on a Windows Server 2019 server with an already deployed AD FS on Windows Server 2019 farm.

For more information about deploying AD FS on Windows Server 2019, refer to my previous blog posts:

Deploying a redundant Active Directory Federation Services (ADFS) farm on Windows Server 2019
http://terenceluk.blogspot.com/2020/04/deploying-redundant-active-directory.html

Deploying a redundant Active Directory Federation Services (ADFS) Web Application Proxy servers on Windows Server 2019
http://terenceluk.blogspot.com/2020/04/deploying-redundant-active-directory_21.html

Custom Domain Prerequisite

Begin by ensure that the organization’s sign-in domain (typically the primary SMTP domain) has been added as a custom domain and verified with the required TXT record in your Azure tenant:

image

Proceed to download the latest Azure AD Connect from the Azure Active Directory portal:

image

In the event where the organization’s Active Directory domain is non-routable (e.g. contoso.local), you will need to prepare the domain for directory synchronization as outlined in the following documentation.

Prepare a non-routable domain for directory synchronization

https://docs.microsoft.com/en-us/office365/enterprise/prepare-a-non-routable-domain-for-directory-synchronization

Install Azure AD Connect

Launch the downloaded AzureADConnect.msi file to start the installer:

image

Proceed to install Azure AD Connect:

imageimage

Configure Azure AD Connect

image

I usually recommend to never go with Express settings as this configures Azure AD Connect with default settings, which most administrations may not go back to review the documentation to understand what it does and may have unanticipated consequences in the future.

I would like to encourage everyone who needs to set up AD Connect to go through all the following documentation that will outline the configuration parameters for a custom installation:

Custom installation of Azure AD Connect
https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-install-custom

Setting up AD FS for sign-in also is not available via the Express Settings so select the Customize button:

image

By leaving all of the optional settings unchecked, AD Connect will set up a SQL Server 2012 Express LocalDB instance, create the appropriate groups, and assign permissions without intervention. For more information about the optional settings, please refer to the following table:

Use an existing SQL Server

Allows you to specify the SQL Server name and the instance name. Choose this option if you already have a database server that you would like to use. Enter the instance name followed by a comma and port number in Instance Name if your SQL Server does not have browsing enabled. Then specify the name of the Azure AD Connect database. Your SQL privileges determine whether a new database will be created or your SQL administrator must create the database in advance. If you have SQL SA permissions see How to install using an existing database. If you have been delegated permissions (DBO) see Install Azure AD Connect with SQL delegated administrator permissions.

Use an existing service account

By default Azure AD Connect uses a virtual service account for the synchronization services to use. If you use a remote SQL server or use a proxy that requires authentication, you need to use a managed service account or use a service account in the domain and know the password. In those cases, enter the account to use. Make sure the user running the installation is an SA in SQL so a login for the service account can be created. See Azure AD Connect accounts and permissions.
With the latest build, provisioning the database can now be performed out of band by the SQL administrator and then installed by the Azure AD Connect administrator with database owner rights. For more information see Install Azure AD Connect using SQL delegated administrator permissions.

Specify custom sync groups

By default Azure AD Connect creates four groups local to the server when the synchronization services are installed. These groups are: Administrators group, Operators group, Browse group, and the Password Reset Group. You can specify your own groups here. The groups must be local on the server and cannot be located in the domain.

We will be using a local SQL Express database (installed by AD Connect) to store the data for AD Connect so proceed by clicking on the Install button:

imageimage

Once Azure AD Connect has been installed, you will be presented with the following User sign-in options:

image

Password Hash Synchronization is the default option as it is for the Express settings and given that we are configuring AD FS as the sign-in option, proceed by selecting Federation with AD FS:

image

Proceed by entering the credentials for an account that has global administrator permissions for the Azure tenant:

imageimage

Select the domain in the forest that Azure AD Connect will be synchronization from the FOREST drop down menu:

**Note that the domain in this example has a non-routable internal domain (.local suffix) but a UPN suffix with the SMTP domain the organization will be used to sign into resources have already been added as a custom domain and verified.

image

Select Create new AD account if a service account has not already been created for the AD Connect Synchronization application:

image

AD Connect will validate the Enterprise admin credentials to ensure that it is able to connect to the selected domain:

image

Upon successful completion, the selected domain will be listed under the CONFIGURED DIRECTORIES heading with a green check mark beside it:

image

Clicking Next will allow AD Connect to retrieve the directory schema of the domain:

image

Since the Active Directory domain uses a non-routable suffix but an additional UPN has already been configured, the wizard will indicate that it is not added (it isn’t possible to do so) but the UPN suffix has been verified:

image

For referencing the following are attributes that are available:

image

Proceed with using having the userPrincipalname selected for the USER PRINCIPAL NAME drop box menu and select Continue without matching all UPN suffixes to verified domains (this needs to be selected as there is a non-routable domain listed):

image

The next Domain/OU Filtering page is where the configuration for whether AD Connect will synchronize the whole domain or only selected domains and OUs is configured. Be cognizant of whether the whole domain should be synchronized or not as this as it is best practice to only synchronize OUs that are required especially if the domain has a lot of unused objects. Selectively synchronizing only the objects that is needed will optimize the performance. With that said, if the OU structure isn’t organized well with objects scattered across everywhere then it may be best to synchronize the whole domain to avoid missing critical objects.

image

Uniquely identifying users isn’t as important for a single forest with single domain as users typically have only one identity but having multiple forests and domains usually means a single user could have multiple identities. If an organization with multiple forests and domains is being configured, decide multiple identities will be identified as described in the following table.

Setting

Description

Users are only represented once across all forests

All users are created as individual objects in Azure AD. The objects are not joined in the metaverse.

Mail attribute

This option joins users and contacts if the mail attribute has the same value in different forests. Use this option when your contacts have been created using GALSync. If this option is chosen, User objects whose Mail attribute aren't populated will not be synchronized to Azure AD.

ObjectSID and msExchangeMasterAccountSID/ msRTCSIP-OriginatorSid

This option joins an enabled user in an account forest with a disabled user in a resource forest. In Exchange, this configuration is known as a linked mailbox. This option can also be used if you only use Lync and Exchange is not present in the resource forest.

sAMAccountName and MailNickName This option joins on attributes where it is expected the sign-in ID for the user can be found.
A specific attribute This option allows you to select your own attribute. If this option is chosen, User objects whose (selected) attribute aren't populated will not be synchronized to Azure AD. Limitation: Make sure to pick an attribute that already can be found in the metaverse. If you pick a custom attribute (not in the metaverse), the wizard cannot complete.

For the purpose of this example, only one domain in a forest will be synchronized so the Users are represented only once across all directories will be selected:

image

For reference, a few of the options for attributes that can be used to identify users are as follows:

image

The Filter users and devices is great for AD Connect pilots where the OU structure does not permit the synchronization of objects that are selected for the pilot. With the filtering option, an administrator can create a group and add all the objects in so these objects are the only ones that get synchronized into Azure AD. Note that nested groups are not allowed so all the objects in the group must be direct members.

image

I won’t go write an explanation as to what each optional feature provides as the table from the documentation does a great job explaining it:

Optional Features

Description

Exchange Hybrid Deployment

The Exchange Hybrid Deployment feature allows for the co-existence of Exchange mailboxes both on-premises and in Office 365. Azure AD Connect is synchronizing a specific set of attributes from Azure AD back into your on-premises directory.

Exchange Mail Public Folders

The Exchange Mail Public Folders feature allows you to synchronize mail-enabled Public Folder objects from your on-premises Active Directory to Azure AD.

Azure AD app and attribute filtering

By enabling Azure AD app and attribute filtering, the set of synchronized attributes can be tailored. This option adds two more configuration pages to the wizard. For more information, see Azure AD app and attribute filtering.

Password hash synchronization

If you selected federation as the sign-in solution, then you can enable this option. Password hash synchronization can then be used as a backup option. For additional information, see Password hash synchronization.
If you selected Pass-through Authentication this option can also be enabled to ensure support for legacy clients and as a backup option. For additional information, see Password hash synchronization.

Password writeback

By enabling password writeback, password changes that originate in Azure AD is written back to your on-premises directory. For more information, see Getting started with password management.

Group writeback

If you use the Office 365 Groups feature, then you can have these groups represented in your on-premises Active Directory. This option is only available if you have Exchange present in your on-premises Active Directory.

Device writeback

Allows you to writeback device objects in Azure AD to your on-premises Active Directory for Conditional Access scenarios. For more information, see Enabling device writeback in Azure AD Connect.

Directory extension attribute sync

By enabling directory extensions attribute sync, attributes specified are synced to Azure AD. For more information, see Directory extensions.

image

As AD FS is going to be configured, we will enabled Password has synchronization as a fallback if the federation service is not available:

Implement password hash synchronization with Azure AD Connect sync
https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-password-hash-synchronization

Password hash synchronization can also be enabled in addition to federation. It may be used as a fallback if your federation service experiences an outage.

image

Enter an account with domain administrator rights for the Azure AD Connect to perform the configuration changes:

image

Note that the account needs to be a local administrator on the AD FS servers that will be used. Domain Administrators group is usually a part of the administrator group on the servers but if they are not, ensure that you add this account onto the servers:

image

Configure AD FS Farm

The AD Connect wizard can actually create and configure an AD FS farm but this example already has an AD FS farm configured so the Use an existing AD FS farm will be selected:

image

image

image

Specify the FQDN of the primary server in the AD FS farm:

image

The wizard will attempt to validate the AD FS farm:

image

Upon successfully validating the farm, select the domain to federate with Azure AD:

image

Allow AD Connect to perform the configuration:

image

Once the configuration has completed, allow AD Connect to start the synchronization:

image

Verifying synchronization service connectivity to Azure Active Directory

image

Creating the Azure Active Directory Synchronization Account

image

Installing Azure AD Connect Health agent for sync

image

Azure AD Connection configuration has now completed:

image

Verify Internal and External AD FS Access

If an existing AD FS farm was used then the DNS records for intranet and internet access should have been configured so proceed to run both of the Verify federation connectivity tests:

imageimage

Verify Azure AD Connect Configuration for Azure Active Directory

Switching back to the Azure portal’s Azure Active Directory will display the Status as Enabled for Azure AD Connect:

image

Verify Azure AD Connect Synchronization Service

Launching the Synchronization Service Manager on the AD Connect server will show that a Full Import, Full Synchronization and Export is ran:

image

Test Office 365 Sign-in AD FS Redirection

Attempting to sign in through https://login.microsoftonline.com should not bring you to the AD FS login page:

image

However, you will be redirected the AD FS sign page once the email address (UPN) is entered as the identity:

image

image

Verify Relying Party Trusts Configuration for O365 in AD FS

Logging onto the AD FS management console on the AD FS server will show that a Microsoft Office 365 Identity Platform Worldwide was configured in the Relying Party Trusts by the Azure AD Connect wizard:

image

Turn on MFA for O365 Sign-in

If a MFA solution such as Duo in this example is deployed, it can be turned on by right clicking on Microsoft Office 365 Identity Platform Worldwide and selecting Edit Access Control Policy…:

image

Click on Use access control policy link:

image

Select Permit everyone and require MFA:

image

image

image

MFA will now be required when users sign into Office 365 via the AD FS sign-in portal.