Mapping Extra Resources
As you've probably looked at the Resource Templates page, you've noticed that the Azure Exporter supports many Azure resources, but not all of them are documented in the Resource Templates page.
This page will help you understand what kind of Azure resources are supported by the Azure integration and how to map them into Port.
Is the resource supported by the Azure Exporter?โ
The Azure Exporter relies on the Base Azure Resource to have a List API by subscription to get all the resources of a specific type.
If it is a resource that is not documented in the Resource Templates page, you can map it to Port by following these steps:
- Find the resource in the Azure REST API reference.
 - If it's a base resource (in the format of 
Microsoft.<Provider>/<resourceName>) can be found in the type example response and in the API URL 
- If it has a List API by subscription it will be supported by the Azure Exporter.
 
- If it's an extension resource (in the format of 
Microsoft.<Provider>/<resourceName>/<extensionName>) such asMicrosoft.Storage/storageAccounts/blobServices/containers.- Then, if the base resource is supported by the Azure Exporter, the extension resource will be supported as well.
 
 
Mapping the resource to Portโ
After you've found the resource in the Azure REST API reference and you've confirmed that it is supported by the Azure Exporter, you can map it to Port by following these steps:
Blueprintโ
Create a Port blueprint definition for the resource. The blueprint definition is based on the resource API response in the Azure REST API reference.
Azure Storage Account Rest API Response Example
{
  "value": [
    {
      "id": "/subscriptions/{subscription-id}/resourceGroups/res2627/providers/Microsoft.Storage/storageAccounts/sto1125",
      "kind": "Storage",
      "location": "eastus",
      "name": "sto1125",
      "properties": {
        "isHnsEnabled": true,
        "creationTime": "2017-05-24T13:28:53.4540398Z",
        "primaryEndpoints": {
          "web": "https://sto1125.web.core.windows.net/",
          "dfs": "https://sto1125.dfs.core.windows.net/",
          "blob": "https://sto1125.blob.core.windows.net/",
          "file": "https://sto1125.file.core.windows.net/",
          "queue": "https://sto1125.queue.core.windows.net/",
          "table": "https://sto1125.table.core.windows.net/",
          "microsoftEndpoints": {
            "web": "https://sto1125-microsoftrouting.web.core.windows.net/",
            "dfs": "https://sto1125-microsoftrouting.dfs.core.windows.net/",
            "blob": "https://sto1125-microsoftrouting.blob.core.windows.net/",
            "file": "https://sto1125-microsoftrouting.file.core.windows.net/",
            "queue": "https://sto1125-microsoftrouting.queue.core.windows.net/",
            "table": "https://sto1125-microsoftrouting.table.core.windows.net/"
          },
          "internetEndpoints": {
            "web": "https://sto1125-internetrouting.web.core.windows.net/",
            "dfs": "https://sto1125-internetrouting.dfs.core.windows.net/",
            "blob": "https://sto1125-internetrouting.blob.core.windows.net/",
            "file": "https://sto1125-internetrouting.file.core.windows.net/"
          }
        },
        "primaryLocation": "eastus",
        "provisioningState": "Succeeded",
        "routingPreference": {
          "routingChoice": "MicrosoftRouting",
          "publishMicrosoftEndpoints": true,
          "publishInternetEndpoints": true
        },
        "encryption": {
          "services": {
            "file": {
              "keyType": "Account",
              "enabled": true,
              "lastEnabledTime": "2019-12-11T20:49:31.7036140Z"
            },
            "blob": {
              "keyType": "Account",
              "enabled": true,
              "lastEnabledTime": "2019-12-11T20:49:31.7036140Z"
            }
          },
          "keySource": "Microsoft.Storage"
        },
        "secondaryLocation": "centraluseuap",
        "statusOfPrimary": "available",
        "statusOfSecondary": "available",
        "supportsHttpsTrafficOnly": false
      },
      "sku": {
        "name": "Standard_GRS",
        "tier": "Standard"
      },
      "tags": {
        "key1": "value1",
        "key2": "value2"
      },
      "type": "Microsoft.Storage/storageAccounts"
    }
  ]
}
Based on the API response, you can create a Port blueprint definition for the resource.
Storage Account Blueprint
{
  "identifier": "azureStorageAccount",
  "description": "This blueprint represents an Azure Storage Account in our software catalog",
  "title": "Storage Account",
  "icon": "Azure",
  "schema": {
    "properties": {
      "location": {
        "title": "Location",
        "type": "string"
      },
      "provisioningState": {
        "title": "Provisioning State",
        "type": "string",
        "enum": ["Creating", "ResolvingDNS", "Succeeded"]
      },
      "creationTime": {
        "title": "Creation Time",
        "type": "string",
        "format": "date-time"
      },
      "isHnsEnabled": {
        "title": "Is HNS Enabled",
        "type": "boolean",
        "default": false
      },
      "fileEncryptionEnabled": {
        "title": "File Encryption Enabled",
        "type": "boolean"
      },
      "blobEncryptionEnabled": {
        "title": "Blob Encryption Enabled",
        "type": "boolean"
      },
      "primaryLocation": {
        "title": "Primary Location",
        "type": "string"
      },
      "secondaryLocation": {
        "title": "Secondary Location",
        "type": "string"
      },
      "statusOfPrimary": {
        "title": "Status of Primary",
        "type": "string",
        "enum": ["available", "unavailable"],
        "enumColors": {
          "unavailable": "red",
          "available": "green"
        }
      },
      "statusOfSecondary": {
        "title": "Status of Secondary",
        "type": "string",
        "enum": ["available", "unavailable"],
        "enumColors": {
          "unavailable": "red",
          "available": "green"
        }
      },
      "tags": {
        "title": "Tags",
        "type": "object"
      },
      "allowBlobPublicAccess": {
        "title": "Allow Blob Public Access",
        "type": "boolean"
      }
    },
    "required": []
  },
  "mirrorProperties": {},
  "calculationProperties": {},
  "relations": {
    "resourceGroup": {
      "target": "azureResourceGroup",
      "title": "Resource Group",
      "required": false,
      "many": false
    }
  }
}
Integration configurationโ
Create an integration configuration for the resource. The integration configuration is a YAML file that describes the ETL process to load data into the developer portal.
Mapping configuration for Storage Account and Storage Container
resources:
  - kind: Microsoft.Storage/storageAccounts
    selector:
      query: "true"
      # azure resource api version to query
      apiVersion: "2023-01-01"
    port:
      entity:
        mappings:
          # lowercase only the resourceGroups namespace and name to align how azure API returns the resource group reference
          identifier: '.id | split("/") | .[3] |= ascii_downcase |.[4] |= ascii_downcase | join("/")'
          title: .name
          blueprint: '"azureStorageAccount"'
          properties:
            location: .location
            provisioningState: .properties.provisioningState
            creationTime: .properties.creationTime
            isHnsEnabled: .properties.isHnsEnabled
            fileEncryptionEnabled: .properties.encryption.services.file.enabled
            blobEncryptionEnabled: .properties.encryption.services.blob.enabled
            primaryLocation: .properties.primaryLocation
            secondaryLocation: .properties.secondaryLocation
            statusOfPrimary: .properties.statusOfPrimary
            statusOfSecondary: .properties.statusOfSecondary
            allowBlobPublicAccess: .properties.allowBlobPublicAccess
            tags: .tags
          relations:
            # resolve resource group id from storage account id
            resourceGroup: '.id | split("/") | .[3] |= ascii_downcase |.[4] |= ascii_downcase | .[:5] |join("/")'
  - kind: Microsoft.Storage/storageAccounts/blobServices/containers
    selector:
      query: "true"
      # azure resource api version to query
      apiVersion: "2023-01-01"
    port:
      entity:
        mappings:
          identifier: '.id | split("/") | .[3] |= ascii_downcase |.[4] |= ascii_downcase | join("/")'
          title: .name
          blueprint: '"azureStorageContainer"'
          properties:
            publicAccess: .properties.publicAccess
            hasImmutabilityPolicy: .properties.hasImmutabilityPolicy
            hasLegalHold: .properties.hasLegalHold
            deleted: .properties.deleted
            deletedTime: .properties.deletedTime
            remainingRetentionDays: .properties.remainingRetentionDays
            leaseStatus: .properties.leaseStatus
            leaseState: .properties.leaseState
            defaultEncryptionScope: .properties.defaultEncryptionScope
            version: .properties.version
          relations:
            # resolve storage account id from container id
            storageAccount: '.id | split("/") | .[3] |= ascii_downcase | .[4] |= ascii_downcase | .[:-4] | join("/")'
The integration configuration structureโ
- 
The
kindfield describes the Azure resource type to be ingested into Port. Thekindfield should be set to the Azure resource type as it appears in the resource guide. e.g. The resource type for theStorage Accountcould be found here as well with the resource object structure.resources:
- kind: Microsoft.Storage/storageAccounts
selector:
... - 
The
selectorfield describes the Azure resource selection criteria.resources:
- kind: Microsoft.Storage/storageAccounts
selector:
query: "true" # JQ boolean expression. If evaluated to false - this object will be skipped.
apiVersion: "2023-01-01" # Azure API version to use to fetch the resource
port:- The 
queryfield is a JQ boolean query, if evaluated tofalse- the resource will be skipped. Example use case - skip syncing resources that are not in a specific region.query: .location == "eastus2" - The 
apiVersionfield is the Azure API version to use to fetch the resource. This field is required for all resources. For example, the API versions for thestorageAccountresource was found in the Storage Account Rest APIapiVersion: "2023-01-01"
 
 - The 
 - 
The
portfield describes the Port entity to be created from the Azure resource.resources:
- kind: Microsoft.Storage/storageAccounts
selector:
query: "true" # JQ boolean query. If evaluated to false - skip syncing the object.
apiVersion: "2023-01-01" # Azure API version to use to fetch the resource
port:
entity:
mappings: # Mappings between one Azure object to a Port entity. Each value is a JQ query.
identifier: .id
title: .name
blueprint: '"azureStorageAccount"'
properties:
location: .location
provisioningState: .properties.provisioningState- 
The
entityfield describes the Port entity to be created from the Azure resource.- 
The
mappingsfield describes the mapping between the Azure resource and the Port entity.- 
The
identifierfield describes the Azure resource identifier. This field is required for all resources.mappings:
identifier: .id - 
The
titlefield describes the Azure resource title. This field is required for all resources.mappings:
title: .name - 
The
blueprintfield describes the Port blueprint to be used to create the Port entity. This field is required for all resources.mappings:
blueprint: '"azureStorageAccount"' - 
The
propertiesfield describes the Azure resource properties to be mapped to the Portmappings:
identifier: .id
title: .name
blueprint: '"azureStorageAccount"'
properties:
location: .location
provisioningState: .properties.provisioningState 
 - 
 
 - 
 
 -