How to get the creation timestamp of an Azure resource

How to get the creation timestamp of an Azure resource

Introduction

There are situations where we would like to know when a resource was created in an Azure subscription.

Unfortunately the Properties blade of a resource doesn't reveal the creation timestamp from within the Azure Portal.

The same situation applies when we try to apply our Azure PowerShell or Azure CLI kata. For example the following commands wont give us
the required information.

C:\> Get-AzResource -Name nic-1

Name              : nic-1
ResourceGroupName : rg-virtual-machines
ResourceType      : Microsoft.Network/networkInterfaces
Location          : westeurope
ResourceId        : /subscriptions/{subscription}/resourceGroups/rg-virtual-machines/providers/Microsoft.Network/networkInterfaces/nic-1
Tags              :

Naa, not helpful... What properties are there?

C:\> Get-AzResource -Name nic-1 | get-member

   TypeName: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.PSResource

Name                  MemberType Definition
----                  ---------- ----------
[...]
CreatedTime           Property   System.Nullable[datetime] CreatedTime {get;set;}
[...]

Interessting. There is a member called CreatedTime, let's inspect that one.

C:\> (Get-AzResource -Name nic-1).CreatedTime
C:\>

Hm seems to be empty 😪 Okay, how about expanding the query?

C:\> (Get-AzResource -Name nic-1 -ExpandProperties).CreatedTime
C:\>

Nope, still no luck. How about Azure CLI?

$ az resource show \
    --name nic-1 \
    --resource-group rg-virtual-machines \
    --resource-type Microsoft.Network/networkInterfaces \
    --output jsonc \
    --query createdTime 
$ 

And again, nothing! 😫 Okay there MUST be a way to get to that piece of information.

Let's see what happens if query the Azure REST API manually which is available at https://management.azure.com. Let's get to it.

Edit & TLDR

I have just found a way which is ways more comfortable than the instructions given below.

The key here is the the magic az rest command, which allows us to send custom requests and handles all of the authentication & authorization stuff for use.

az rest \
    --method GET \
    --url "https://management.azure.com/subscriptions/{subscription-id}/resources" \
    --url-parameters api-version=2020-06-01 \$expand=createdTime \$select=name,createdTime

Querying the Azure REST API

Steps involved

  • Create a service principal
  • Request an access token
  • Use that token to request data from API

Create a service principal

Run the following command to create a service principal and make a note of the output. We are going to need that SP to request an access token from the token endpoit, that we later can use to request data from the management API.

As we are only going to need a read-only access there is no need to give the contributor role to that SP (which is the default, if the --role parameter is ommited).

az ad sp create-for-rbac --name postman --role reader 

{
  "appId": "{app-guid}",
  "displayName": "postman",
  "name": "http://postman",
  "password": "auto-generated-password",
  "tenant": "{tenant-guid}"
}

Request an access token

POST https://login.microsoftonline.com/{tenantId}/oauth2/token

Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&
client_id={appId}&
client_secret={password}&
resource=https://management.azure.com/

This is going to give us an access token.

{
    "token_type": "Bearer",
    "expires_in": "3599",
    "ext_expires_in": "3599",
    "expires_on": "1604357538",
    "not_before": "1604353638",
    "resource": "https://management.azure.com/",
    "access_token": "eyJ0eXAi[...]"
}

As a side note, we are using the OAuth 2.0 Client Credentials Flow here.

Request property

Now that we have an access token we can call the list action and set the authorization key in the header.

Please note, that using the Get or Get By Id methods wont work, as it doesn't allow the use of the $expand parameter that is required to retrieve the createdTime property!

GET https://management.azure.com/subscriptions/{subscriptionId}/resources

Authorization: Bearer eyJ0eXAi[...]

api-version=2020-06-01&
$filter=name eq 'nic-1'&
$expand=createdTime&
$select=name,createdTime

Finally! 🙄

{
    "value": [
        {
            "id": "/subscriptions/{subscriptionId}/resourceGroups/rg-virtual-machines/providers/Microsoft.Network/networkInterfaces/nic-1",
            "name": "nic-1",
            "type": "Microsoft.Network/networkInterfaces",
            "location": "westeurope",
            "createdTime": "2020-10-30T21:24:04.4488198Z",
            "tags": {}
        }
    ]
}

Conclusion

That was pretty time consuming 😫 It seems that the Get and Get By Id methods of the Azure REST API are getting used behind the scenes when using Get-AzResource or az resource, which doesn't allow the usage of the $expand parameter.

Maybe I find some spare time in the future and wrap this into a script.