Using Azure Policy Sets

Azure Infrastructure

At Microsoft Ignite in September 2017, Ryan Jones (@rjmax) discussed Azure Resource Manager Policies and some enhancements coming soon. See this blog post about the public preview announcement. One of those, was Policy Sets. Policy Sets allow you to group several policies together and assign them as a group. There’s more information at In this blog post, we’re going to explore how to start using them.

Start with existing policies

In order to create a policy set, we need existing policy definitions. You can use some built-in ones but for this example, I’ve created 4 custom policies which are related to storage:

  1. Audit VM’s that don’t use Managed Disks
  2. Deny deployment if Storage Account Blob Encryption is not enabled.
  3. Deny deployment if Storage Account File Encryption is not enabled.
  4. Deny deployment if Storage Account https-only transport (secure transfer required) is not enabled.

The first thing we need to do is get the Policy Definition Id’s. We need the Policy Definition Name to get those. Here, I’ve looked up the names and created an array of the Policy Definitions that I want in my new Policy Set.

$policyNames = @( "audit-managedDisks", 

Next, I’m going to loop through those and get the Policy Definition Id and store it in a variable called $policyDefinitionId. Since I need to loop through each Policy Definition now, I’m also going to construct an object called $policySetDefinition which we’re going to use later.

$policyDefinitionIds = @()
$policyNames | 
    ForEach-Object {
        $policyDefinitionId = (Get-AzureRmPolicyDefinition -Name $_ | select -ExpandProperty PolicyDefinitionId)
        $TargetObject = New-Object PSObject –Property @{policyDefinitionId=$policyDefinitionId}
        $Target +=  $TargetObject
$policySetDefinition = $target | ConvertTo-Json


Define and Assign the Policy Set

Next we need to create the Policy Set Definition

$policySetParams = @{ 
Name = "policySet-Storage" 
DisplayName = "Storage: Policies to enhance security of Storage Accounts." 
Description = "This initiative contains several Storage Policies to be applied at the subscription level." 
PolicyDefinition = $policySetDefinition 
$policySet =  New-AzureRmPolicySetDefinition @policySetParams -Verbose

Notice that this command takes the $policySetDefinition we created earlier into the PolicyDefinition parameter. Now that we’ve created a Policy Set Definition, we can assign it.

For this example, I’m going to assign it to my Subscription but I need to exclude two Resource Groups. With the new policy language, that’s pretty easy to do. We are also going to define the Sku. The Sku is an object consisting of a name and tier. I’m going with Standard here because I want to enforce this policy set on existing resources. If you only wanted to enforce the policy set on new resources, set this to A0 and Free.

$ExcludedResourceGroup1 = Get-AzureRmResourceGroup -Name "rg-aad" 
$ExcludedResourceGroup2 = Get-AzureRmResourceGroup -Name "securitydata" 
$sku = @{ 

$policyAssignmentParams = @{ 
Name = "StoragePolicySetAssignment" 
DisplayName = "Storage Policy Set" 
Description = "This initiative contains several Storage Policies to be applied at the subscription level." 
PolicySetDefinition = $policySet 
Scope = "/subscriptions/{guid-of-subscription}" 
NotScope = $ExcludedResourceGroup1.ResourceId, $ExcludedResourceGroup2.ResourceId 
Sku = $sku 
$new = New-AzureRmPolicyAssignment @policyAssignmentParams


That’s it! Let’s take a look at how this appears in the new Policy UI. Here’s the Assignments blade:


And here’s the actual Assignment showing the scope, exclusions, and sku:

1 comment

Trusted Sites With IE ESC Turned On

Enterprise, Microsoft

When protecting users from malicious internet sites on servers, we can keep Internet Explorer Enhanced Security Configuration turned on (that’s the default). However, with the setting on, almost no modern website will properly load.

The solution is to add these sites you trust to your Trusted Sites zone. In an enterprise environment, we would leverage Active Directory Group Policy to do this. The way to add specific sites to a zone is well-documented. In short, we use the Sites to Zone Assignment List policy.

However, this doesn’t work with IE ESC turned on. This KB article hints at why. Although it says it applies to Windows Server 2003, I’m working with Windows Server 2016. My machine will be a Remote Desktop host and I want to lock it down. So, how can we keep IE ESC on and allow a specific list of sites to have looser security settings?

It seems there’s two ways this could work. In both cases, we still configure the Sites to Zone Assignment List:

1. Apply the Method 2 workaround listed in the KB article above. You may have to create the keys that are not present.


2. This one is much more complicated. We will configure the EscDomains registry key. This key is described in a support article:

The EscDomains key resembles the Domains key except that the EscDomains key applies to those protocols that are affected by the Enhanced Security Configuration (ESC). ESC is introduced in Microsoft Windows Server 2003.

We can use Group Policy Registry Settings to update the registry. Enter the values in HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\ESCDomains.  Once completed, it will look something like the below:

Group Policy view:


Registry view:


Regardless of method, you can load up one of your sites and click File, Properties. The Zone should show “Trusted Sites.”


One note, this machine also has other Group Policies applied from the Microsoft Security Guidance blog and other policies may change the behavior. Is there a better way? I don’t know, you tell me, comments below.


Managed Storage Account SAS Tokens

Azure Infrastructure


Building on the previous blog post where we configured Azure Key Vault to automatically rotate Storage Account Keys, this post will discuss SAS tokens (Shared Access Signatures). As a quick refresher, using SAS tokens is the recommended way to interact with your Storage Account. For more information see Using shared access signatures.

Create SAS Definition

In order to create a SAS definition, you will need the setsas permission. We can add this to the list of permissions we used in the previous blog post:

Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -ResourceGroupName $keyVaultResourceGroupName -UserPrincipalName $upn -PermissionsToStorage set, get, regeneratekey, setsas

Now, we can create a SAS definition. For my example, I want to:

  • Limit the SAS definition the Blob service (and not Tables, Queues, or Files).
  • Name it sas1
  • Limit to https only
  • Limit to only my current IP address (IP whitelist)
  • Limit the validity of the token to 5 days
  • Limit the permissions to Read and Write.

In the command below, I’m first getting my IP address using site. Then I’m using the Set-AzureKeyVaultManagedStorageSasDefinition to create a new definition.

$ip = Invoke-RestMethod | Select -ExpandProperty ip
$sasDefinition = Set-AzureKeyVaultManagedStorageSasDefinition `
-Service Blob `
-ResourceType Container,Object `
-VaultName $keyVaultName `
-AccountName $storageAccountName `
-Name 'sas1' `
-Protocol HttpsOnly `
-IPAddressOrRange $ip `
-ValidityPeriod ([System.Timespan]::FromDays(5)) `
-Permission Write,Read

Once you do this, you’ll see a new secret in your Key Vault. Now, let’s get the secret value.

$secret = Get-AzureKeyVaultSecret -VaultName $keyVaultName -Name ($sasDefinition.sid).Split("/")[-1]
$sasToken = $secret.SecretValueText

Use SAS Definition

That’s it! Now, let’s test this by uploading a file. There’s nothing new here, I’m simply using Set-AzureStorageBlobContent with a context. The context is generated from the SAS token we retrieved in the previous step.

$container = "docs"
$localFile = "C:\Temp\FUNDAMENTALS OF AZURE 2ND ED.pdf"
$blobName = "Fundamentals of Azure.pdf"
$ctx = New-AzureStorageContext -SasToken $sasToken -StorageAccountName $storageAccountName
Set-AzureStorageBlobContent -File $localFile -Container $container -Blob $blobName -Context $ctx –Verbose

There could be many use cases for this. For example, if several users need to upload files to blob storage, you can generate a unique SAS for each one. Another example could be an application querying Key Vault to get a SAS token. This one is documented on the official documentation here.


Azure Storage Account Keys Automatic Rotation

Azure Infrastructure


A new feature called Managed Storage Account Keys popped up last month that promises to make rotating Azure Storage Account Keys easier. I have to give a ton of credit to my colleague Dmitriy S. who helped with a lot of the discovery and troubleshooting.

Why rotate?

It is recommended to periodically rotate your Storage Account Keys. Storage Account Keys give the holder full access to your storage account and all data within it. Rotating the keys periodically help mitigate the risk of unauthorized access.

The old way

Previously, we had this article called “Set up Azure Key Vault with end-to-end key rotation and auditing,” which describes automation storage account key rotation. While that will still work, it’s very complex to setup, involves using an Automation Account and Runbook, Functions, and a Logic App. We now have a much easier way!

The new way

Using Managed Storage Account Keys, we can easily set up automatic key rotation by just deploying a Storage Account and a Key Vault. The article called Azure Key Vault Storage Account Keys describes the feature and developer experience. However, the “Getting started” section was a bit confusing, incomplete and it looks like it contains some errors. So, let’s go through it together.

Set-up permissions

I’m going to assume you have a Key Vault and Storage Account already and they have registered providers. The first thing we need is the ObjectId of Key Vault. Note, we need the ObjectId of the Key Vault service (“first party identity”), NOT your specific Key Vault. This object ID is different for each tenant. The instructions on the official documentation say:

Get-AzureRmADServicePrincipal -SearchString "AzureKeyVault"

However, that didn’t work for one of my tenants (which was a Enterprise Enrollment). A more accurate way to get the ObjectId is to first login using “Connect-AzureAD” and then using the following command:

$servicePrincipal = Get-AzureADServicePrincipal -Filter "AppId eq 'cfa8b339-82a2-471a-a3c9-0fc0be7a4093'"

This won’t work on MSDN Azure subscriptions, but neither did the first way. I’ve found that the AppId above is consistent across all of my tenants but could be different for AzureChina, AzureGov, etc. Next, we need to assign the “Storage Account Key Operator Service Role” role which gives the Key Vault list and regenerate permissions:

$storageAccountId = (Get-AzureRmStorageAccount -StorageAccountName wspladiag02 -ResourceGroupName wspla-rg).Id
New-AzureRmRoleAssignment -ObjectId $servicePrincipal.ObjectId -RoleDefinitionName 'Storage Account Key Operator Service Role' -Scope $storageAccountId

Storage account onboarding

The official documentation is unclear on the next steps, in my opinion. But, here’s how we set up daily key rotation using PowerShell. First, we need to make sure we (user performing operation) has “set” operation allowed within the Key Vault’s access policies. If you don’t, you’ll get this error later on:

Add-AzureKeyVaultManagedStorageAccount : Operation "set" is not allowed by vault policy

So to prevent that, let’s add the current user:

$keyVaultName = "kv-infra-secrets"
$keyVaultResourceGroupName = "RG-Infrastructure"
Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -ResourceGroupName $keyVaultResourceGroupName -UserPrincipalName "" -PermissionsToStorage set, get, regeneratekey

I gave the user get and regeneratekey also but those aren’t required unless you want to use other commands. Now let’s create a TimeSpan object:

$regenerationPeriod = [System.Timespan]::FromDays(1)

Next, we use a new command to add the Storage Account as “Managed” by this Key Vault. If you don’t have this command, remember to update to the latest Azure PowerShell.

$parameters = @{
VaultName = $keyVaultName
AccountResourceId = $storageAccountId
AccountName = "mystoragetest1"
ActiveKeyName = "key1"
RegenerationPeriod = $regenerationPeriod
Add-AzureKeyVaultManagedStorageAccount @parameters

That’s it! The Storage Account Key will be rotated on the schedule you set up. You can verify everything by using Get-AzureKeyVaultManagedStorageAccount. You can also regenerate the keys manually using Update-AzureKeyVaultManagedStorageAccountKey if you don’t want to wait.


Encrypt folders on Dropbox / OneDrive / GDrive with EncFS


One of the issues posed by storing sensitive information in the cloud is that the cloud provider, and by extension, other 3rd parties (hackers, governments) have access to that data. To work around this, we need to encrypt the data before it’s sent to the cloud provider. Tools like TrueCrypt / VeraCrypt are great for encrypting entire volumes but aren’t meant for this use case. If you stored a TrueCrypt volume in the cloud, a minor change on a small file would cause a full sync to occur. We need a better solution. Enter EncFS.

EncFS is available for Linux here: There was a Windows version called Encfs4win ( ) but hasn’t been updated. A new revival of that project exists that we’ll cover in this blog and use to encrypt files.

I’m using Windows 10 and Dropbox but this will work on Windows 7 and any other file share/sync provider such as OneDrive and Google Drive.


Our objective is to have a place to store files in a cloud service which has zero knowledge of the content we’re storing. Before we start, there are some alternatives:

Spideroak starts at $5 and has Enterprise products.

boxcryptor is (or was) based on encfs and has a free version.

There are also several blockchain-based file storage providers. I use Storj personally and might blog about these in another post.

While those alternatives are appealing, especially boxcryptor, the free version is limited and for what I’m using, the paid versions aren’t that valuable. So, how can we do this for free?


Let’s go back to the Windows port created by Charles Munson, a.k.a jetwhiz.


  1. Download the files, encfs-installer.exe and the hashes.asc from github:
  2. (optional) Verify hash (you can download QuickHash if you need a verification tool). Note, since this is a privacy focused blog post it would make sense to verify the hash to ensure the file that was downloaded hasn’t been modified in-transit or by some other program on your computer (malware/virus/etc.)
  1. Run the installer, keep all the defaults and it should be done within 2 minutes. Once completed, the binaries will be located in C:\Program Files (x86)\encfs.

Using it

First, we need to create an encrypted folder.

  1. Run C:\Program Files (x86)\encfs\encfsw.exe, this is the graphical interface. Nothing will pop-up, but you’ll see they “key” icon in your taskbar.
  1. We’re going to use the Open/Create option.
  2. Select a folder. In this example, I created a folder in my Dropbox called “encfs.” Specify the other options and press OK:

  3. After pressing OK, you should see another login prompt because encfsw is automatically mounting the new folder. Explorer should open the drive letter.
  4. Drag some files in there!

  5. Let’s see what the cloud provider (Dropbox in my case) sees:

  6. That’s it. Now we can install encfs (on Linux or Windows) to access these files anytime.

Best practices

Some of the best practices for using encfs are:

  1. Don’t put anything else in your encrypted folder. There should be the .xml file plus 1 encrypted file for each file you uploaded.
  2. When mounting the encrypted folder in Windows, use a drive letter versus a folder. The GUI enforces this but the command-line may not.

If you need mobile access, boxcrypter might be worth a look. I didn’t need that and the free version limited me to two devices which didn’t suffice. I’m also just storing sensitive information (like my ninjacat picture) in the encrypted folder. I can use the native Dropbox app to access my other folders that have non-sensitive information.