Set the thumbnailPhoto in Active Directory with PowerShell

For years and years, as @LupoLoopy could probably attest to, I have been a fan of dumping user photos into Active Directory. Even as far back as Exchange 2010 we have been able to light up Outlook with user photos downloaded as part of the Global Address List and today; with the likes of Azure AD, Office 365, and more; the users’ photo is more and more prominent. Over the years, I have relied on a tool from Cjwdev called AD Photo Edit, however, only this week, I discovered that we can actually do this natively with PowerShell negating the need for the tool to be used at all.

The PowerShell for this requires you to have the Active Directory PowerShell Module imported but other than that, there are no complex requirements.

$photo = [byte[]](Get-Content "" -Encoding byte)
Set-ADUser  -Replace @{thumbnailPhoto=$photo}

It really is that simple! I do, however, have a segway here: there still, to this day, does not seem to be a way to reverse the flow of profile pictures with Azure AD Connect. It is possible and always has been to export the thumbnailPhoto attribute from Active Directory to Azure AD for use in Office 365. There does not, however, seem to be a way to have Azure AD and Office 365 act as the image source and have them imported into Active Directory from the cloud. This is a shame because in Azure AD and Office 365 we have native interface elements that allow the user to self-service upload and edit their own user photo but the same tools don’t exist on-premises. One day, I hope, we will have the ability to import to AD from AAD but until that time comes, I am planning on looking into building a really small web application that will execute the PowerShell code behind the scenes and allow users to self-service their images.

Azure Route-based VPN with a Cisco ASA 5505

I haven’t posted here for a while and I have a bit of a success story that I thought I would share and hopefully help somebody else encountering the same issues.

Over the last few weeks, I have been working with a customer: the customer has a Cisco ASA 5505 firewall in a co-lo datacentre operated by a third-party whose name is something like (big metal thing that vertically stores servers)(the place where Jean-Luc Picard travels around). The customer has started to consume some Azure IaaS VMs and wanted to be able to establish a VPN to the co-lo to enable them to hop from one location to the other; a VPN connection from Azure was already in place to the office site which means we needed to use a multi-site VPN to Azure.

With the VPN to the office already working, we knew that the VPN Gateway and Virtual Network in Azure were sound. A multi-site Azure VPN requires a Route-based connection, not the basic Policy-based connection. We got the VPN Gateway all set up for Route-based connections and confirmed that was still working; no dramas. After doing this, we started speaking to the co-lo. The first response from the co-lo was that the ASA 5505 didn’t support a Route-based VPN which put us in dangerous territory. Reading the Azure documentation, there are a few articles that seem to contradict and conflict and having the right documents to hand helped enormously.

The first article you will probably encounter is the generic supported devices list for Azure VPN with caveats around Policy-based only or only supported Route-based in specific circumstances which are at https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-vpn-devices. This article used to state that the ASA 5505 did not support Route-based connections but it no longer does state this. If your vendor is telling you otherwise, direct them to the article in the first instance. For the ASA 5505, we need to ensure that it is running ASA OS 8.4 or above; this added supported to IKEv2 which is a requirement for Route-based connections to Azure.

With the first hump over, we initially struggled to get the connection up and running which is where the next articles come in. Firstly, direct the vendor to https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-3rdparty-device-config-cisco-asa. This article is a specific example of the ASA 5505 using IKEv2 without BGP for a Route-based VPN. Once the vendor was on-board, we started to make progress, however, there are changes you will need to make in Azure too! Firstly, the implementation of a Route-based VPN with an ASA 5505 requires the use of Traffic Policy Selectors. When configured, this requires you to define a custom IPSec Policy in Azure for the connection and then apply the policy and the Use Traffic Policy Selectors option to the connection. The second part is that both these features require a Standard VPN Gateway and will not work with a Basic VPN Gateway. For this configuration, follow the guidance of https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-ipsecikepolicy-rm-powershell#workflow.

By the end of this, hopefully, you have a working VPN connection to an ASA 5505 using a multi-site Route-based Azure VPN, however, if you do not, here are a few things to check:

  1. Verify the pre-shared key at both ends of the connection matches
  2. Verify that the custom IPSec Policy in Azure matches that on the firewall
  3. Verify that the correct Traffic Policy Selectors are applied on the firewall
  4. Verify that the Azure Virtual Network and Azure VPN Connections have the correct address ranges configured

Any of the above will cause the connection to fail. If the connection still refuses to establish, you can enable the Azure Network Watcher feature and enable diagnostics for the VPN Connection. The diagnostic logging will generate a .zip file which contains two files of interest: ConnectionStats.txt and IKEError.txt. Below are the outputs for both files from my real-world scenario. As you will observe, IKEErrors.txt reported a generic authentication failed error and suggests checking the pre-shared key, crypto algorithms and the SA lifetimes, however, the ConnectionStats.txt file shows a more specific “Packets Dropped due to Traffic Selector Mismatch” error.

 

Error: Authenticated failed. Check keys and auth type offers. 
	 based on log : Peer sent AUTHENTICATION_FAILED notify
Error: Authentication failed. Check shared key. Check crypto. Check lifetimes. 
	 based on log : Peer failed with Windows error 13801(ERROR_IPSEC_IKE_AUTH_FAIL)

 

Connectivity State : Connecting
Remote Tunnel Endpoint : 1.2.3.4
Ingress Bytes (since last connected) : 0 B
Egress Bytes (since last connected) : 0 B
Ingress Packets (since last connected) : 0 Packets
Egress Packets (since last connected) : 0 Packets
Ingress Packets Dropped due to Traffic Selector Mismatch (since last connected) : 0 Packets
Egress Packets Dropped due to Traffic Selector Mismatch (since last connected) : 0 Packets
Bandwidth : 0 b/s
Peak Bandwidth : 0 b/s
Connected Since : 1/1/0001 12:00:00 AM