Key Vault logging (preview) now available

[Updated: 5/4/2016 - Fixed "What is logged?"]

Hello folks,

Today we are announcing public preview of Azure Key Vault logging. Logging is an often requested feature and several customers have told us that it is very critical for them to have logging available so they can use key vault effectively. We are excited to have this very important feature available as a preview. Over next few weeks we want to log feedback (pun intended) from you to make sure key vault logging meets your needs. So give it a try and let us know.

Below Amit provides detailed instructions on how to enable logging and then access the logs.

As usual, we value your input so please take a moment to follow us, join our advisory boardsend us private feedback,and/or visit our forum .   


Hello Amit here! So you have been using Key Vault, but you also would like to monitor how/when key vault is accessed, and by who. So let's see how to do that.

When you create a key vault, logging is disabled by default. To turn logging on you need to run a Azure PowerShell command and provide a storage account where the logs will be stored. Once logging is turned on for a key vault, all operations for that key vault will be logged in the storage account you provide. A new container named 'insights-logs-auditevent' will be automatically created under the provided storage account. Same storage account can be used for collecting logs for multiple key vaults. So let's see how to turn logging on for a key vault and then access those logs from the storage account. Later I'll also explain which operations are logged and the log format in detail.

So let's get started.

To enable logging for a key vault, you need to download and install Azure PowerShell 1.0.1 or later. Download it here.

Note: With the Azure PowerShell version 1.0.0 and later, you'll notice a few changes to the Azure Key Vault cmdlets. We're planning to write a separate blog soon to explain all these changes.

Step 1:

First create a key vault if you don't have one already. You can also use an existing key vault. Simply run '$kv = Get-AzureRmKeyVault -VaultName <your vault name>' instead of the commands below and then skip to Step 2.

PS C:\> $rg = New-AzureRmResourceGroup -Name demo3333rg -Location westusResourceGroupName : demo3333rgLocation          : westusProvisioningState : SucceededTags              :ResourceId        : /subscriptions/361da5d4-a47a-4c79-afdd-xxxxxxxxxxxx/resourceGroups/demo3333rgPS C:\> $kv = New-AzureRmKeyVault -VaultName demo3333 -ResourceGroupName demo3333rg -Location westus -Sku premiumVault Name              : demo3333Resource Group Name     : demo3333rgLocation                : westusResource ID             : /subscriptions/361da5d4-a47a-4c79-afdd-xxxxxxxxxxxx/resourceGroups/demo3333rg/providers/Micro soft.KeyVault/vaults/demo3333Vault URI               : ID               : 766eaf62-faba-4a23-b8df-xxxxxxxxxxxxSKU                     : premiumEnabled For Deployment? : FalseAccess Policies         :                         Tenant ID              : 766eaf62-faba-4a23-b8df-xxxxxxxxxxxx                         Object ID              : d9da5048-2737-4770-bd64-xxxxxxxxxxxx                         Application ID         :                         Display Name           : User Bapat (                          (                         Permissions to Keys    : get, create, delete, list, update, import, backup, restore                         Permissions to Secrets : allTags :

Step 2:

We also need a storage account to store the logs. You can use existing storage account too. However, remember that you need a storage account created using Azure Resource Manager. A 'classic' storage account created using Azure Service Management interface will not work.

PS C:\> $sa = New-AzureRmStorageAccount -ResourceGroupName demo3333rg -Name demo3333logs -Type Standard_LRS -Location westus

Note that in the above command I've created the storage account under the same resource group as the key vault. This is not required but it makes life easy by putting all the related resources under same resource group.

For logging to work, the storage account and the key vault must be under same subscription.

Step 3:

Now enable logging for our key vault. We need to provide the Resource ID for the resource (key vault in this case) for which we need logs and the resource Id for the storage account. The -Enabled flag set to $true enables logging, and when set to $false disables logging. For Key Vault, we currently have only one category of logs, 'AuditEvent'.

PS C:\> Set-AzureRmDiagnosticSetting -ResourceId $kv.ResourceId -StorageAccountId $sa.Id -Enabled $true -Categories AuditEventStorageAccountId   : /subscriptions/361da5d4-a47a-4c79-afdd-xxxxxxxxxxxx/resourceGroups/demo3333rg/providers/Microsoft.Storage/storageAccounts/demo3333logsStorageAccountName :MetricsLogs    Enabled : True    Category : AuditEvent

That's it! You're done! Logging is turned on for our key vault 'demo3333' and now all the operations performed on the key vault will be logged to the designated storage account.

So what is logged?

All authenticated REST API requests are logged. This includes failed requests due to access permissions, system errors or bad requests.

Type of operations that are logged:

  1. All the key vault operations, like Key Vault create, Key Vault set access policy, Key Vault delete and updating other key vault attributes like tags etc. are logged.
  2. All Keys and Secrets operations like Create/Modify/Delete keys/secrets, sign/verify/encrypt/decrypt/wrap/unwrap keys, get secrets, list keys/secrets, list versions of keys/secrets etc. are logged.
  3. Unauthenticated requests that result in a 401 response (such as requests without a bearer token, malformed, expired, invalid token) are logged.

[Edited - fixed information about logging of unauthenticated requests]

Accessing logs

Now that we have seen how the logs are enabled, let's turn our attention to how to access these logs. Logs are stored in a container named 'insights-logs-auditevent' in the storage account you provide. Here's how you can list all the blobs in this container.

$container = "insights-logs-auditevent"PS C:\> Get-AzureStorageBlob -Container $container -Context $sa.Context Container Uri:

As you can see, the blobs follow a naming convention that can be summarized as follows:
           resourceId=<ARM resource ID>/y=<year>/m=<month>/d=<day of month>/h=<hour>/m=<minute>/filename.json

Note: All the date/time values used for blob names are UTC.

As mentioned earlier, same storage account can be used to collect logs for multiple resources. Thus the full resourceId in the blob name will be very handy to only access or download blobs that you need. First let us see how to download these blobs then we'll see how to use wild-cards to selectively download blobs that meet specific criteria.

First we create a directory where we would like to download our blobs.

PS C:\> New-Item -Path "C:\Users\username\KV-Demo3333-Logs" -ItemType Directory -ForceDirectory: C:\Users\usernameMode         LastWriteTime Length Name----         ------------- ------ ----d-----  11/5/2015 11:19 AM        KV-Demo3333-Logs

Now get a list of all blobs and pipe it through the 'Get-AzureStorageBlobContent' to download the blobs into our destination directory. The '/' delimiter in the blob names will be used to create a full directory structure under the destination directory to download and store the blobs as files.

PS C:\> $blobs = Get-AzureStorageBlob -Container $container -Context $sa.ContextPS C:\> $blobs | Get-AzureStorageBlobContent -Destination "C:\Users\username\KV-Demo3333-Logs"Container Uri: BlobType Length ContentType LastModified SnapshotTime---- -------- ------ ----------- ------------ ------------resourceId=/SUBSCRIPTIONS/361DA5D4-A47A-4C79-AFDD-XXXXXXXXXXXX/RESOURCEGROUPS/DEMO3333RG/PROVIDERS/MICROSOFT.KEYVAULT/VAULTS/DEMO3333/y=2015/m=11/d=05/h=01/m=00/PT1H.json BlockBlob 1122 application/octet-stream 11/5/2015 1:35:42 AM +00:00resourceId=/SUBSCRIPTIONS/361DA5D4-A47A-4C79-AFDD-XXXXXXXXXXXX/RESOURCEGROUPS/DEMO3333RG/PROVIDERS/MICROSOFT.KEYVAULT/VAULTS/DEMO3333/y=2015/m=11/d=05/h=02/m=00/PT1H.json BlockBlob 11886 application/octet-stream 11/5/2015 2:16:16 AM +00:00resourceId=/SUBSCRIPTIONS/361DA5D4-A47A-4C79-AFDD-XXXXXXXXXXXX/RESOURCEGROUPS/DEMO3333RG/PROVIDERS/MICROSOFT.KEYVAULT/VAULTS/DEMO3333/y=2015/m=11/d=05/h=18/m=00/PT1H.json BlockBlob 26595 application/octet-stream 11/5/2015 6:56:18 PM +00:00resourceId=/SUBSCRIPTIONS/361DA5D4-A47A-4C79-AFDD-XXXXXXXXXXXX/RESOURCEGROUPS/DEMO7815RG/PROVIDERS/MICROSOFT.KEYVAULT/VAULTS/DEMO7815/y=2015/m=11/d=05/h=20/m=00/PT1H.json BlockBlob 4809 application/octet-stream 11/5/2015 8:06:17 PM +00:00

In the above example, you'll notice that logs for two different key vaults are listed: demo3333 and demo7815. If you want to download logs for only 'demo7815' key vault, use a wild-card pattern for parameter -Blob.

PS C:\> Get-AzureStorageBlob -Container $container -Context $sa.Context -Blob '*/VAULTS/DEMO7815/*'Container Uri: BlobType Length ContentType LastModified SnapshotTime---- -------- ------ ----------- ------------ ------------resourceId=/SUBSCRIPTIONS/361DA5D4-A47A-4C79-AFDD-XXXXXXXXXXXX/RESOURCEGROUPS/DEMO7815RG/PROVIDERS/MICROSOFT.KEYVAULT/VAULTS/DEMO7815/y=2015/m=11/d=05/h=20/m=00/PT1H.json BlockBlob 4809 application/octet-stream 11/5/2015 8:06:17 PM +00:00

On similar lines, if you want to download logs for all the resources in a resource group, use -Blob '*/RESOURCEGROUPS/<resource group name>/*' pattern.

To download all the logs for the month of November 2015, use -Blob '*/year=2015/m=11/*' and so on.

Other cmdlets for Diagnostic Settings

To disable logging for a resource, use following command:

Set-AzureRmDiagnosticSetting -ResourceId $kv.ResourceId -StorageAccountId $sa.Id -Enabled $false -Categories AuditEvent

To query status of diagnostic settings for a resource, use following command:

PS C:\> Get-AzureRmDiagnosticSetting -ResourceId $kv.ResourceIdStorageAccountId : /subscriptions/361da5d4-a47a-4c79-afdd-xxxxxxxxxxxx/resourceGroups/demo3333rg/providers/Microsoft.Storage/storageAccounts/demo3333logsStorageAccountName :MetricsLogsEnabled : TrueCategory : AuditEvent

Log format

Individual blobs are stored as text formatted as a JSON blob. Here's an example of a log entry resulting from a 'Get-AzureRmKeyVault -VaultName demo3333' cmdlet.

{"records":[{"time": "2015-11-05T01:32:01.2691226Z","resourceId": "/SUBSCRIPTIONS/361DA5D4-A47A-4C79-AFDD-XXXXXXXXXXXX/RESOURCEGROUPS/DEMO3333RG/PROVIDERS/MICROSOFT.KEYVAULT/VAULTS/DEMO3333","operationName": "VaultGet","operationVersion": "2015-06-01","category": "AuditEvent","resultType": "Success","resultSignature": "OK","resultDescription": "","durationMs": "78","callerIpAddress": "104.xx.xx.xx","correlationId": "","identity": {"claim":{"":"d9da5048-2737-4770-bd64-XXXXXXXXXXXX","":"","appid":"1950a258-227b-4e31-a9cf-XXXXXXXXXXXX"}},"properties": {"clientInfo":"azure-resource-manager/2.0","requestUri":"","id":"","httpStatusCode":200}}    ]}

Let's look at the fields and what they mean.

Field Name



Date and Time. Always in UTC.


Azure Resource Manager Resource ID. In case of Key Vault logs, this will be Key Vault Resource ID.


Name of operation. These are in 'ObjectVerb' format. For example, all key vault operations are 'Vault<action>' format, such as 'VaultGet', 'VaultCreate' etc. All the Key operations are 'Key<action>' format, such as 'KeySign', 'KeyList' etc. And all Secret operations are 'Secret<action>' format, such as 'SecretGet', 'SecretListVersions' etc.


This is the REST API version requested by the client.


For Key Vault logs, only 'AuditEvent' is applicable.


Result of REST API request.


HTTP status.


Additional description about result when available.


Time it took to service the REST API request, in milliseconds. This does not include the network latency, so the time you measure on client side may not match this time.


IP address of the client who made the request.


An optional GUID that client can pass to correlate client side logs with service side (key vault side in this case) logs.


Identity from the token that was presented when making the REST API request. This is usually a 'user', a 'service principal' or a combo 'user+appId' as in case of a request resulting from a Azure PowerShell cmdlet.


This field will contain different information based on the operation (operationName). In most cases it will contain client info (the useragent string passed by the client), the exact REST API request URI and http status code. In additon We when an object is returned as a result of a request (for example, KeyCreate or VaultGet) it will also contain the Key URI (as 'id'), Vault URI or Secret URI.

Frequently Asked Questions with Answers

Q: How soon will the logs be available after a key vault operation has taken place?
A: SLA is 10 minutes. However we are targeting close to 6 minutes for most cases.

Q: How long will the logs be retained in the storage account?
A: Once the logs are written to your storage account, it's up to you to retain or delete them. In future we will add a feature that allows a user to set retention period so that logs older than 'X' days will be automatically pruned. Stay tuned.

Q: How do I control who can access the logs?
A: Logs are stored in a standard Azure Storage account. You can use standard Azure access control methods to limit access to this storage account.

Comments are disabled, head over to the Azure Key Vault forum to discuss about this blog.