Pages

Thursday, April 1, 2021

Configuring Azure Service Endpoints and Private Endpoints

One of the common questions I am asked about accessing Azure services is the concept of service endpoints and/or private endpoints in Azure. To put it simply, Azure is a public cloud service, which means it is inherently designed to allow its services to be publicly accessed through the internet. This often instills quite a bit of fear to security experts (or anyone in IT for that matter) as they decide to move on-premises workloads to the cloud. Microsoft is aware of this potential road block for organizations and thus provides service endpoints and private endpoints to limit public access to Azure services.

In this blog post, I will attempt to provide a summarized explanation of Service Endpoints and Private Endpoints, then demonstrate the configuration. For more in-depth information on these two services, please see the official Microsoft documentation. I would highly recommend reading the documentation if you decide to read through this blog post.

Virtual Network service endpoints
https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-service-endpoints-overview

What is Azure Private Endpoint?
https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-overview

Service Endpoints

Service endpoints allows an administrator to lock down the Azure resource such as a storage account to a VNet (all of its subnets), a specific VNet’s subnet, or a public IP. The locking down via public IP is an easy to grasp concept so we’ll look at how locking down with a VNet’s subnet works. When a VNet’s subnet is selected, the routing table on the subnet is updated to route traffic to the service endpoint before routing to the internet. The traffic from the subnet still accesses the storage account by its public IP address but the traffic will flow through the faster Azure backbone network rather than the internet thus enjoying better performance and arguably better security.

The following are some key items to note about Service Endpoints:

  • The resource will continue to have a public IP address (it does not get a private IP address)
  • The public IP will continue to be resolved by the DNS provided by Microsoft
  • It is not accessible from the on-premise network through, say, a site-to-site VPN because the service endpoint does not actually have a private IP so if an on-premise device needs to access the resource then the on-premise public IP will need to be added to the service endpoint (the on-premise device will use the internet to reach the resource)
  • If there is an ExpressRoute connecting an on-premise network to Azure, then the NAT IP addresses can be added to allow access: https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-service-endpoints-overview#secure-azure-service-access-from-on-premises

The following is a diagram demonstrating the traffic flow of a service endpoint configured for a storage account:

**Note that the device attempting to access the storage account will continue to reach it via its public IP address but the originating IP address seen by the storage account will be the device’s private IP address. This is the important difference to highlight for service endpoints. Also, as the public IP address of the storage account is being used as the destination, any restrictive NSGs applied to the traffic flowing outbound will need to be configured to allow traffic to reach the public IP address of the storage account.

image

**Note that Service Endpoints is not available for all services. The current services it support are as follows:

Generally available

Public Preview

  • Azure Container Registry (Microsoft.ContainerRegistry): Preview available in limited Azure regions where Azure Container Registry is available.

Private Endpoints

Private Endpoints adds a virtual network interface to the resource that connects to the VNet. The network interface will then have a private IP address and behaves like a device on the network. Having a private IP presence on the VNet will mean that on-premise devices traversing through a site-to-site VPN or express route can now access the resource via its private IP address through the private connection.

The following are some key items to note about Private Endpoints:

  • All public IP address access can be blocked because a private IP is available to access the resource
  • Azure internal DNS will now resolve the resource’s hostname to its private IP address
  • Network Security Groups (NSG) will not be applied to the private endpoint’s network interface

· If there is a desire to block other network resources to the private endpoint, then outbound NSG security groups assigned to the source can be used to block access

The following is a diagram demonstrating the traffic flow of a private endpoint configured for a storage account:

**Note that this example places the endpoint directly into the subnet where the virtual machines are located but it is also possible to place the endpoint into its own subnet within the same VNET as the other subnets that will access the endpoint. It is important to note that subnets within the same VNET as the subnet containing the endpoint will have Azure DNS resolve the internal IP address of the private endpoint. The public IP will be returned when resolving the DNS name outside of the VNet.

image

As with Service Endpoints, Private Endpoints are only available for a set of services as listed here: https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-overview#private-link-resource

With a brief overview of what a Service Endpoints and Private Endpoints are, let’s have a look at what the configuration would look like.

I’ve configured two storage accounts to demonstrate the Service Endpoint and Private Endpoint.

Configuring a Service Endpoint

The storage account we’ll be using for the service endpoint is named sgserviceendpoint:

image

I’ve created a container and uploaded a text file:

image

Without a service endpoint configured, access to the container is available from anywhere on the internet with authentication because of the access level I’ve configured:

image

I can access the container with Azure Storage Explorer from my home computer over internet and connect to a Blob container with a generated shared access signature:

image

image

image

image

image

image

To create a service endpoint simply navigating to the Networking configuration for the storage account and select Firewalls and virtual networks:

image

Change Allow access from the configuration All networks to Selected networks, select Add existing virtual network, then in the right blade, add the subnet or subnets that you want to access the storage group via the service endpoint:

image

Notice that the following information message is displayed:

The following networks don’t have service endpoints enabled for 'Microsoft.Storage'. Enabling access will take up to 15 minutes to complete. After starting this operation, it is safe to leave and return later if you do not wish to wait.

This is because the Microsoft.Storage service needs to be enabled for the service endpoint as we are accessing a storage account. Azure noticed that it is not enabled and therefore will be enable it for you.

image

Click on the Save button to apply the changes once the subnet has been added but note that saving the configuration will update the routing table on the subnet and may cause a disruption on any connections for the subnet (best to make this change on a scheduled maintenance window):

image

Now when you navigate to the VNet containing the subnet that was enabled for the service endpoint, you’ll be able to see the configuration added to the Service endpoints setting:

image

Navigating into the Subnets configuration and clicking on the subnet configured for the service endpoint will also show that Microsoft.Storage is listed:

image

Access to the container should no longer accessible via the internet as this is what is displayed when I hit the refresh button from my laptop:

This request is not authorized to perform this operation. RequestId:44c96890-501e-0053-310c-254d92000000 Time:2021-03-30T02:31:40.6499686Z

image

Attempting to use Azure Storage Explorer from a server in the subnet defined in the service endpoint will be continued to be allowed:

image

You will also notice that attempting to resolve the sgserviceendpoint.blob.core.windows.net address representing the container resolves to a public IP address and not a private IP address:

image

Configuring a Private Endpoint

The storage account we’ll be using for the private endpoint is named sgprivateendpoint. To create a private endpoint representing this storage account, navigate to the Networking configuration under Settings, click on the Private endpoint connections tab, then Private endpoint:

image

Select the subscription, resource group, provide a name for the logical private endpoint (what the private endpoint will be named in Azure), and the region it should reside in:

image

Select the appropriate resource for the Target sub-resource field:

**Note that if you want to provide blob and another resource such as file access then you’ll need to add the additional resource(s) afterwards one at a time.

image

Proceed to select the appropriate subnet you want to place the private endpoint in:

**Note the Private DNS integration remark below the Networking configuration. We will discuss this in more depth after the initial configuration

image

Add additional tags if necessary:

image

Proceed to create the private endpoint:

image

Clicking into the Private Endpoint resource once it has been created will display the following information:

image

Clicking into the DNS configuration under Settings will display the FQDN and the private IP address assigned to the private endpoint:

FQDN: sgprivateendpoint.privatelink.blob.core.windows.net

IP address: 10.248.1.7

image

Navigating into the VNet where the private endpoint was created will display the private endpoint that was just created:

image

Navigating into the resource group containing the private endpoint will display the private endpoint object as well as a NIC created:

image

Clicking into the NIC representing the private endpoint will show that the settings are the same as any other NIC adapter:

image

This private endpoint configuration is depicted in the diagram I included earlier in the blog post and pasted again here:

image

Private Endpoints and DNS

With the private endpoint created, the next important configuration is to ensure that DNS resolution resolves as it is supposed to in various places. The following are 3 common places you may want to access the private endpoint:

#1 - Within the same subnet where the private endpoint resides:

image

#2 - Within a subnet residing in the same VNet where the private endpoint resides:

image

#3 - From an on-premise network connected to Azure via ExpressRoute or VPN:

image

The URL to access the storage account’s blog service is:

sgprivateendpoint.blob.core.windows.net

image

Attempting to perform an nslookup from a machine using internet DNS will resolve the public IP along with two aliases where one represented the private endpoint. Attempting to lookup the public or private endpoint alias will return the public IP:

> sgprivateendpoint.blob.core.windows.net

Server: dns.google

Address: 8.8.8.8

Non-authoritative answer:

Name: blob.blz22prdstr18a.store.core.windows.net

Address: 20.60.7.100

Aliases: sgprivateendpoint.blob.core.windows.net

sgprivateendpoint.privatelink.blob.core.windows.net

> sgprivateendpoint.privatelink.blob.core.windows.net

Server: dns.google

Address: 8.8.8.8

Non-authoritative answer:

Name: blob.blz22prdstr18a.store.core.windows.net

Address: 20.60.7.100

Aliases: sgprivateendpoint.privatelink.blob.core.windows.net

image

Alternatively, if an nslookup is used with an Azure DNS server (168.63.129.16) within the same VNET, the link will return the private link alias with the private IP:

C:\>nslookup

Default Server: UnKnown

Address: ::1

> server 168.63.129.16

Default Server: [168.63.129.16]

Address: 168.63.129.16

> sgprivateendpoint.blob.core.windows.net

Server: [168.63.129.16]

Address: 168.63.129.16

Non-authoritative answer:

Name: sgprivateendpoint.privatelink.blob.core.windows.net

Address: 10.248.1.7

Aliases: sgprivateendpoint.blob.core.windows.net

image

As most administrators will immediately know, many of the environments in Azure does not use Azure DNS because they would typically use Active Directory domain DNS. To get around this issue, we can simply add the private link as a zone in the internal DNS and a corresponding A record representing the storage account. The following is a demonstration of how this would be configured.

Launch DNS Manager on your DNS server (usually a domain controller) and create a new zone:

image

Select Primary zone:

image

Whether to replicate to all the DCs in the forest or domain would be your choice:

image

Create a zone representing the private link without the storage account name:

image

Select the desired dynamic update configuration and create the zone:

image

With the zone configured, create a new A record to represent the storage account (the private link alias):

image

Add the appropriate private IP:

image

image

Now when you initiate a nslookup against the internal Active Directory domain controller, the private IP will be returned:

C:\>nslookup

Default Server: UnKnown

Address: ::1

> server 10.248.1.250

Default Server: [10.248.1.250]

Address: 10.248.1.250

> sgprivateendpoint.blob.core.windows.net

Server: [10.248.1.250]

Address: 10.248.1.250

Non-authoritative answer:

Name: sgprivateendpoint.privatelink.blob.core.windows.net

Address: 10.248.1.7

Aliases: sgprivateendpoint.blob.core.windows.net

image

Note that this example configured blob storage so if you require, say, file storage access then an additional forward lookup zone will need to be created.

More information about private link DNS configuration can be found here:

Azure Private Endpoint DNS configuration
https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns

Preventing Access to Storage Account with Private Endpoint

Unlike a service endpoint, configuring a private endpoint does not prevent access to the storage account so if that is a requirement then you will need to mimic what you would normally do to configure a service endpoint by selecting Selected networks but do not add any virtual networks or IP ranges:

image

Hope this helps anyone who may be looking for information on service endpoints and private endpoints. Note that service endpoints have no extra cost while private endpoints do (https://azure.microsoft.com/en-ca/pricing/details/private-link/)

Thursday, March 11, 2021

Using Azure Files SMB access with Windows on-premise Active Directory NTFS permissions

Years ago when I first started working with Azure, I was very excited about the release of Azure Files because it would allow migrating traditional Windows file servers to the cloud without having an IaaS Windows server providing the service. What I quickly realized was that it did not support the use of NTFS permissions and therefore was not a possible replacement. Fast forward to a few years later, the support for traditional NTFS permissions with on-premise Active Directory is finally available. I’ve been meaning to write a blog post to demonstrate the configuration so this post serves as a continuation to my previous post on how we can leverage Azure Files to replace traditional Windows Server file services.

Configuring and accessing Microsoft Azure Files
http://terenceluk.blogspot.com/2021/03/configuring-and-accessing-azure-files.html

I won’t go into too much detail about how the integration works as the information can be found in the following Microsoft documentation:

Overview - on-premises Active Directory Domain Services authentication over SMB for Azure file shares
https://docs.microsoft.com/en-us/azure/storage/files/storage-files-identity-auth-active-directory-enable

What I will do is highlight the items we need to configure it.

Topology

The environment I will be working with will be the following simple topology where an on-premise network is connected to Azure East US through a site-to-site VPN and an Azure Files configured:

clip_image002

Prerequisites

The following are the prerequisites for enabling AD DS authentication for Azure file shares:

  1. The on-premise Active Directory Domain Services will need to be synced into Azure AD with Azure AD Connect
  2. The identities that will be used for accessing the Azure Files need to be synced to Azure AD if filtering is applied
  3. The endpoint accessing the file share in Azure Files need to be able to traverse over via port 445
  4. A storage account name that will be less than 15 characters as that is the limit for the on-premise Active Directory SamAccountName

Step #1 – Create the Azure Storage Account and Azure File share

Begin by creating a new storage account with a name that has less than 15 characters:

image

With the storage account successfully created, open the new storage account and navigate to the File shares menu option:

image

Click on the + File share button to create a new file share:

image

Configure the new file share with the settings required.

I won’t go into the details of the Tiers but will provide this reference link for more information: https://docs.microsoft.com/en-us/azure/storage/files/storage-files-planning?WT.mc_id=Portal-Microsoft_Azure_FileStorage#storage-tiers

image

Complete creating the file share by clicking on the Create button.

With the test File share created, click to open it:

image

You can directly upload files into the file share, modify the tier, configure various operations and retrieve information pertaining to the file share.

image

Azure Storage Explorer can also be used to manage the file share.

image

You may notice that clicking into the Access Control (IAM) menu option will display the following:

Identity-based authentication (Active Directory) for Azure file shares

To give individual accounts access to the file share (Kerberos), enable identity-based authentication for the storage account. Learn more

image

This is where you would configure the Share permissions for Active Directory account access and will be configured in the following steps.

Step #2 – Enable AD DS authentication on the storage account

How Azure Files and on-premise authorization works

Unlike traditional Windows Servers, you can’t join an Azure storage account to an on-premise Active Directory so the way in which this is achieved is by registering the storage account with AD DS by creating an account representing it in AD DS. The account that will be created in the on-premise AD can be a user account or a computer account and if you are familiar with on-premise AD, you’ll immediately recognize that both of these accounts have passwords. Failure to update the password will cause authentication to Azure Files to fail.

Computer accounts – these accounts have a default password expiration age of 30 days
User accounts – these accounts have password expiration age set based on the password policy applied

The easy way to get around password expiration is to use a user account and set the password to never expire but doing so will likely get any administrator in trouble. The better method is to use Update-AzStorageAccountADObjectPassword cmdlet (https://docs.microsoft.com/en-us/azure/storage/files/storage-files-identity-ad-ds-update-password) to manually update the account’s password before it expires. There are several ways to automate this with either something as simple as a Windows task scheduler task or an enterprise management application to run it on a schedule.

Using AzFilesHybrid to create the on-premise account representing Azure Files

Proceed to download the latest AzFilesHybrid PowerShell module at the following URL: https://github.com/Azure-Samples/azure-files-samples/releases

image

Unpacking the ZIP file will provide the following 3 files:

  • AzFilesHybrid.psd1
  • AzFilesHybrid.psm1
  • CopyToPSPath.ps1

image

Before executing the script, you’ll need to use an account with the following properties and permissions:

  1. Replicated to Azure AD
  2. Permissions to modify create a user or computer object to the on-premise Active Directory
  3. Storage Account Owner or Contributor permissions

The account I’ll be using is a Domain admin and Global Admin rights.

From a domain joined computer where you are logged in with the required on-premise Active Directory account, launch PowerShell or PowerShell ISE and begin by setting the execution policy to unrestricted so we can run the AzFilesHybrid PowerShell scripts:

Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser

Navigate to the directory containing the unzipped scripts and execute:

.\CopyToPSPath.ps1

Import the AzFilesHybrid module by executing:

Import-Module -Name AzFilesHybrid

Connect to the Azure tenant:

Connect-AzAccount

image

Set up the variables for the subscription ID, the resource group name and storage account name:

$SubscriptionId = "<SubscriptionID>"

$ResourceGroupName = "<resourceGroupName>"

$StorageAccountName = "<storageAccountName>"

As you can have more than one subscription in a tenant, select the subscription containing the resources by executing:

Select-AzSubscription -SubscriptionId $SubscriptionId

image

With the prerequisites executed, we can now use the Join-AzStorageAccountForAuth cmdlet to create the account in the on-premise AD that represents the storage account in Azure:

Join-AzStorageAccountForAuth `

-ResourceGroupName $ResourceGroupName `

-Name $StorageAccountName `

-DomainAccountType "<ComputerAccount or ServiceLogonAccount>" `

## You can either specify the OU name or DN of the OU

-OrganizationalUnitName "<Name of OU>" `

-OrganizationalUnitDistinguishedName "<DN of OU>"

The following is an example:

Join-AzStorageAccountForAuth `

-ResourceGroupName $ResourceGroupName `

-Name $StorageAccountName `

-DomainAccountType "ServiceLogonAccount" `

-OrganizationalUnitDistinguishedName "OU=AzureFiles,DC=contoso,DC=com"

**Note that there are backticks (the character sharing the tilde character on the keyboard) used, which is used as an word-wrap operator. It allows the command to be written in multiple lines.

-----------------------------------------------------------------------------------------------------------------------

If your storage account is longer than 15 character then you’ll get an error:

WARNING: Parameter -DomainAccountType is 'ServiceLogonAccount', which will not be supported AES256 encryption for Kerberos tickets.

Join-AzStorageAccountForAuth : Parameter -StorageAccountName 'steastusserviceendpoint' has more than 15 characters, which is not supported to be used

as the SamAccountName to create an Active Directory object for the storage account. Azure Files will be supporting AES256 encryption for Kerberos

tickets, which requires that the SamAccountName match the storage account name. Please consider using a storage account with a shorter name.

At line:1 char:1

+ Join-AzStorageAccountForAuth `

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException

+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Join-AzStorageAccount

-----------------------------------------------------------------------------------------------------------------------

Successful execution of the Join-AzStorageAccountForAuth will display the following:

PS C:\AzFilesHybrid> Join-AzStorageAccountForAuth `

-ResourceGroupName $ResourceGroupName `

-Name $StorageAccountName `

-DomainAccountType "ServiceLogonAccount" `

-OrganizationalUnitDistinguishedName "OU=AzureFiles,DC=contoso,DC=com"

WARNING: Parameter -DomainAccountType is 'ServiceLogonAccount', which will not be supported AES256 encryption for Kerberos tickets.

StorageAccountName ResourceGroupName PrimaryLocation SkuName Kind AccessTier CreationTime ProvisioningState EnableHttpsTrafficOnly

------------------ ----------------- --------------- ------- ---- ---------- ------------ ----------------- ----------------------

stfsreplacement rg-prod-infraServers eastus Standard_LRS StorageV2 Hot 3/8/2021 11:30:02 AM Succeeded True

PS C:\AzFilesHybrid>

image

The corresponding object (in this case a user object) should also be created in the specified OU:

image

Notice how the password is automatically set to not expire:

image

We can also verify the configuration with the following PowerShell cmdlets:

Obtain the storage account and store it as a variable:

$storageAccount = Get-AzStorageAccount `

-ResourceGroupName $ResourceGroupName `

-Name $StorageAccountName

List the directory domain information of the storage account has enabled AD DS authentication for file shares

$storageAccount.AzureFilesIdentityBasedAuth.ActiveDirectoryProperties

https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.management.storage.models.azurefilesidentitybasedauthentication.activedirectoryproperties?view=azure-dotnet

View the directory service of the storage:

$storeageAccount.AzureFilesIdentityBasedAuth.DirectoryServiceOptions

https://docs.microsoft.com/en-us/java/api/com.microsoft.azure.management.storage.azurefilesidentitybasedauthentication.directoryserviceoptions?view=azure-java-stable

image

Step #3 – Configure On-Premise AD Groups for Azure Files Access (Share Permissions)

With the AD DS authentication integration setup for the storage account, the next step is to configure the on-premise Active Directory groups that will be granted access to the Azure Files file share. Think of this step as how we would configure Share permissions on a folder so we can then proceed to configure the NTFS permissions.

There are 3 predefined RBAC roles provided by Azure that will map to the on-premise AD groups and they are as follows:

Storage File Data SMB Share Contributor – Allows for read, write, and delete access in Azure Storage file shares over SMB.

Storage File Data SMB Share Elevated Contributor – Allows for read, write, delete and modify NTFS permissions access in Azure Storage file shares over SMB.

Storage File Data SMB Share Reader – Allows for read access to Azure File Share over SMB.

image

The following are the mappings that I have planned:

Azure Role: Storage File Data SMB Share Contributor
On-premise AD group: AzFileShareContributor

Azure Role: Storage File Data SMB Share Elevated Contributor
On-premise AD group: AzFileShareElevContributor

Azure Role: Storage File Data SMB Share Reader
On-premise AD group: AzFileShareReader

Proceed to create the groups in the on-premise Active Directory:

image

Then log into the Azure portal and navigate to the storage account > File Shares then click on the file share that has been created:

image

From within the file share, click on Access Control (IAM) and then Add role assignments:

image

Configure the appropriate mapping for the 3 on-premise AD groups and the Azure roles:

image

image

image

Step #4 – Mount the Azure Files file share with full permissions and configure NTFS permissions

With the share permissions set, we can now configure the NTFS permissions on the file share. There isn’t a way to perform this from within the Azure portal so we will need to mount an Azure file share to a VM joined to the on-premise Active Directory.

The UNC path for accessing the Azure Files share would be as follows:

\\<storageAccountName>.file.core.windows.net\<shareName> <storageAccountKey> /user:Azure\<storageAccountName>

You can use the net use <driveLetter>: command to mount the drive as such:

net use z: \\<storageAccountName>.file.core.windows.net\<shareName> <storageAccountKey> /user:Azure\<storageAccountName>

net use z: \\stfsreplacement.file.core.windows.net\test N2PrIm73/xHNPxe7BoVyNHBdjU3HBPpQg33Z+PeKmjy8nxUMSeOG4Azfnknyn+up2pQpOinUJ/FWl9ceeGz/bQ== /user:Azure\stfsreplacement

image

Note that the storage account key can be obtained here:

image

Or as an alternative, you can also retrieve a full PowerShell cmdlet to map the drive by using the Connect button for the file share:

image

With the file share mapped as a drive, we can now assign the appropriate NTFS permissions for the groups we created earlier:

Azure Role: Storage File Data SMB Share Contributor
On-premise AD group: AzFileShareContributor
Permissions:

  • Modify
  • Read & execute
  • List folder contents
  • Read

Azure Role: Storage File Data SMB Share Elevated Contributor
On-premise AD group: AzFileShareElevContributor
Permissions:

  • Full control
  • Modify
  • Read & execute
  • List folder contents
  • Read

Azure Role: Storage File Data SMB Share Reader
On-premise AD group: AzFileShareReader
Permissions:

  • Read & execute
  • List folder contents
  • Read
image

Step #5 – Mount the Azure Files file share as an on-premise Active Directory User

Now that the share and NTFS permissions have been set, we can proceed to mount the share as users who are placed into one of the 3 groups to test.

Step #6 – Update the password of the storage account identity in the on-premise Active Directory DS

The last action is how we would change/update the password on the account object representing storage account to enable Kerberos authentication. The following is a snippet from the Microsoft documentation: https://docs.microsoft.com/en-us/azure/storage/files/storage-files-identity-ad-ds-update-password

If you registered the Active Directory Domain Services (AD DS) identity/account that represents your storage account in an organizational unit or domain that enforces password expiration time, you must change the password before the maximum password age. Your organization may run automated cleanup scripts that delete accounts once their password expires. Because of this, if you do not change your password before it expires, your account could be deleted, which will cause you to lose access to your Azure file shares.

To trigger password rotation, you can run the Update-AzStorageAccountADObjectPassword command from the AzFilesHybrid module. This command must be run in an on-premises AD DS-joined environment using a hybrid user with owner permission to the storage account and AD DS permissions to change the password of the identity representing the storage account. The command performs actions similar to storage account key rotation. Specifically, it gets the second Kerberos key of the storage account, and uses it to update the password of the registered account in AD DS. Then, it regenerates the target Kerberos key of the storage account, and updates the password of the registered account in AD DS. You must run this command in an on-premises AD DS-joined environment.

The syntax for the Update-AzStorageAdccountADObjectPassword cmdlet to perform this will look as follows:

Update-AzStorageAccountADObjectPassword `

-RotateToKerbKey kerb2 `

-ResourceGroupName "<resourceGroupName>" `

-StorageAccountName "<storageAccountName>"

If you are continuing the configuration from the beginning of this blog post then the resource group and storage accounts are already stored in a variable so you can just call them as such:

Update-AzStorageAccountADObjectPassword `

-RotateToKerbKey kerb2 `

-ResourceGroupName $ResourceGroupName `

-StorageAccountName $StorageAccountName

image

Hope this helps anyone looking for a step by step demonstration on how to setup Azure Files for SMB accessing using on-premise AD NTFS permissions.

Accessing Exchange Server 2019 /OWA and /ECP throws the errors: "Status code: 500" and "Could not load file or assembly 'Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies."

Problem

You’ve noticed that after patching Exchange Server 2019 servers (for this example, the patch for HAFNIUM was applied), access to /OWA and /ECP now displays the following errors:

OWA

:-(

Something went wrong

Your request couldn't be completed. HTTP Status code: 500.

X-ClientId: F8E662D41996402E8660EEEB0976EA50

request-id a5077939-13bd-4032-9471-d6c8dc221d5a

X-OWA-Error System.Web.HttpUnhandledException

X-OWA-Version 15.2.721.13

X-FEServer Exch01

X-BEServer Exch02

Date:3/8/2021 12:31:53 PM

InnerException: System.IO.DirectoryNotFoundException

Fewer details...

Refresh the page

image

ECP

Server Error in '/ecp' Application.

_______________________________________

Could not load file or assembly 'Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Assembly Load Trace: The following information can be helpful to determine why the assembly 'Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' could not be loaded.

WRN: Assembly binding logging is turned OFF.

To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.

Note: There is some performance penalty associated with assembly bind failure logging.

To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].

Stack Trace:

[FileNotFoundException: Could not load file or assembly 'Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.]

System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type) +0

System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName) +96

System.Type.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase) +65

System.Web.Compilation.BuildManager.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase) +62

System.Web.Configuration.ConfigUtil.GetType(String typeName, String propertyName, ConfigurationElement configElement, XmlNode node, Boolean checkAptcaBit, Boolean ignoreCase) +50

[ConfigurationErrorsException: Could not load file or assembly 'Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.]

System.Web.Configuration.ConfigUtil.GetType(String typeName, String propertyName, ConfigurationElement configElement, XmlNode node, Boolean checkAptcaBit, Boolean ignoreCase) +572

System.Web.Configuration.ConfigUtil.GetType(String typeName, String propertyName, ConfigurationElement configElement, Boolean checkAptcaBit) +31

System.Web.Configuration.Common.ModulesEntry.SecureGetType(String typeName, String propertyName, ConfigurationElement configElement) +59

System.Web.Configuration.Common.ModulesEntry..ctor(String name, String typeName, String propertyName, ConfigurationElement configElement) +59

System.Web.HttpApplication.BuildIntegratedModuleCollection(List`1 moduleList) +221

System.Web.HttpApplication.GetModuleCollection(IntPtr appContext) +1103

System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +122

System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +173

System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +255

System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +347

[HttpException (0x80004005): Could not load file or assembly 'Microsoft.Exchange.Common, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.]

System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +552

System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +122

System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +737

image

You’ve noticed that reviewing the BinSearchFolders application settings for ecp folder in the Exchange Back End website shows that the Value is configured with %ExchangeInstallDir%:

image

Changing this to the path without using the variable appears to fix the ECP page but not OWA:

image

Solution

One of the possible solutions to correct the issue is to use the UpdateCas.ps1 script located in the \Microsoft\Exchange Server\V15\Bin folder to rebuild the /OWA and /ECP directory:

image

image

Proceed to test the /owa and /ecp directories once the PowerShell completes.