Skip to main content

Check out Port for yourselfย 

Azure Resource Graph (Beta)

Sync your Azure environment to Port at scale using Azure Resource Graph and Ocean framework. This integration is designed for high-volume data ingestion across multiple subscriptions, offering several key advantages:

  • Centralized Syncing: Ingest resources from all your Azure subscriptions with a single deployment.
  • High-Speed Ingestion: Leverage Azure Resource Graph to query and sync up to 5000 subscriptions simultaneously for maximum performance.
  • Customizable Mapping: Take full control over which resource types are ingested and how they are mapped to your software catalog.

Overviewโ€‹

This integration provides a robust solution for syncing your Azure resources to Port by leveraging our open-source Ocean framework. It uses the Azure SDK to efficiently query the Azure Resource Graph API, ensuring high-performance data ingestion even in large-scale environments.

On each run, the integration performs a full synchronization, so your software catalog always reflects the current state of your Azure resources. You can use declarative YAML mapping to transform raw data and model it according to your software catalog's structure.

The integration is packaged as a Docker container and can be deployed in any environment that supports it, such as Kubernetes or your CI/CD pipeline. This gives you full control over its execution schedule and operational management.

Supported resourcesโ€‹

The integration syncs data from two main Azure Resource Graph tables:

  • Resources: This table includes a wide array of Azure resources, such as virtual machines, storage accounts, network interfaces, and more. The integration syncs their properties, tags, and metadata.
  • ResourceContainers: This table contains management groups, subscriptions, and resource groups, providing the hierarchical context for your Azure resources.

Configurationโ€‹

Port integrations use a YAML mapping block to ingest data from the third-party api into Port.

The mapping makes use of the JQ JSON processor to select, modify, concatenate, transform and perform other operations on existing fields and values from the integration API.

Default mapping configurationโ€‹

This is the default mapping configuration you get after installing the Azure integration.

Default mapping configuration (Click to expand)
resources:
- kind: resource
selector:
query: 'true'
port:
entity:
mappings:
identifier: '.id | gsub(" ";"_")'
title: .name
blueprint: '"azureCloudResources"'
properties:
tags: .tags
type: .type
location: .location
- kind: resourceContainer
selector:
query: .type == "microsoft.resources/subscriptions"
port:
entity:
mappings:
identifier: '.id | gsub(" ";"_")'
title: .name
blueprint: '"azureSubscription"'
properties:
subscriptionId: .subscriptionId
location: .location
- kind: resourceContainer
selector:
query: .type == "microsoft.resources/subscriptions/resourcegroups"
port:
entity:
mappings:
identifier: '.id | gsub(" ";"_")'
title: .name
blueprint: '"azureResourceGroup"'
properties:
tags: .tags
location: .location
relations:
subscription: '("/subscriptions/" + .subscriptionId) | gsub(" ";"_")'

Setupโ€‹

To set up the Azure Resource Graph exporter, you'll need to configure both Port credentials and Azure app registration.

Port credentials

To get your Port credentials, go to your Port application, click on the ... button in the top right corner, and select Credentials. Here you can view and copy your CLIENT_ID and CLIENT_SECRET:

Azure setup

This integration requires the standard Azure app registration setup.

Keep the following credentials handy after setup:

  • AZURE_CLIENT_ID: The client ID of the Azure service principal
  • AZURE_CLIENT_SECRET: The client secret of the Azure service principal
  • AZURE_TENANT_ID: The tenant ID of the Azure service principal

Azure App Registration Setup

To ingest resources from Azure, you will need to create an Azure App Registration and assign it read permissions to the resources you want to ingest.

  1. Create an Azure App Registration in the Azure portal.





  2. Copy the Application (client) ID and Directory (tenant) ID from the App Registration.



  3. Create a client secret for the App Registration.



  4. Copy the Application (client) Secret from the App Registration.



  5. Create a new role assignment for the App Registration. Go to the Access control (IAM) section of the subscription you want to ingest resources from.

    Click on Add role assignment.

    Multi Account Support

    It is supported to ingest resources from multiple subscriptions, for that you will have to repeat the role assignment for each subscription you want to ingest resources from.



  6. Assign the Reader role to the App Registration.

    Permissions

    The Reader role is recommended for querying all resources in your Azure subscription. You can restrict permissions to specific resource groups or types by assigning a different role. If you do this, remember to adjust permissions when adding more resources to the catalog. Basic permissions required for ingesting resources from Azure include:

    • Microsoft.Resources/subscriptions/read (to list the accessible subscriptions)
    • Microsoft.Resources/subscriptions/resourceGroups/read (to list the accessible resource groups)
    • read/list permissions to the resources you want to ingest


Installationโ€‹

The Azure resource graph exporter is deployed using helm on kubernetes.

This way of deployment supports scheduled resyncs of resources from Azure to Port.

Prerequisites

Installation

Loading version...

Now that you have the Azure App Registration details, you can install the Azure exporter using Helm.

You should have the following information ready:

  • Port API credentials, you can check out the Port API documentation.
    • PORT_CLIENT_ID
    • PORT_CLIENT_SECRET
  • Azure Credentials:
    • AZURE_CLIENT_ID: The Application (client) ID from the Azure App Registration.
    • AZURE_CLIENT_SECRET: The Application (client) Secret from the Azure App Registration.
    • AZURE_TENANT_ID: The Directory (tenant) ID from the Azure App Registration.
helm repo add --force-update port-labs https://port-labs.github.io/helm-charts
helm upgrade --install azure port-labs/port-ocean \
--set port.clientId="PORT_CLIENT_ID" \
--set port.clientSecret="PORT_CLIENT_SECRET" \
--set port.baseUrl="https://api.getport.io" \
--set initializePortResources=true \
--set sendRawDataExamples=true \
--set scheduledResyncInterval=1440 \
--set integration.type="azure-rg" \
--set integration.identifier="azure-resource-graph" \
--set integration.eventListener.type="POLLING" \
--set integration.config.azureClientId="<AZURE_CLIENT_ID>" \
--set integration.config.azureClientSecret="<AZURE_CLIENT_SECRET>" \
--set integration.config.azureTenantId="<AZURE_TENANT_ID>"
Selecting a Port API URL by account region

The port_region, port.baseUrl, portBaseUrl, port_base_url and OCEAN__PORT__BASE_URL parameters are used to select which instance of Port API will be used.

Port exposes two API instances, one for the EU region of Port, and one for the US region of Port.

Examplesโ€‹

Mapping Azure Cloud resourcesโ€‹

The following example demonstrates how to ingest your Azure Subscriptions to Port.
You can use the following Port blueprint definitions and integration configuration:

Blueprint (click to expand)
{
"identifier": "azureCloudResources",
"description": "This blueprint represents an Azure Cloud Resource in our software catalog",
"title": "Azure Cloud Resources",
"icon": "Azure",
"schema": {
"properties": {
"tags": {
"title": "Tags",
"type": "object"
},
"type": {
"title": "Type",
"type": "string"
},
"location": {
"title": "Location",
"type": "string"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {}
}
Mapping configuration (click to expand)
resources:
- kind: resource
selector:
query: 'true'
resource_types:
- microsoft.insights/datacollectionendpoints
port:
entity:
mappings:
identifier: .id | gsub(" ";"_")
title: .name
blueprint: '"azureCloudResources"'
properties:
tags: .tags
type: .type
location: .location
resource type filter

You can filter resources from Azure Resource Graph by specifying resource_types in the mapping configuration. This provides precise control over synced data, streamlining ingestion and keeping your catalog focused on relevant resources.

Mapping cloud resources and resource groupsโ€‹

The following example demonstrates how to ingest your Azure Subscriptions to Port.
You can use the following Port blueprint definitions and integration configuration:

Blueprints (click to expand)

[
{
"identifier": "azureResourceGroup",
"description": "This blueprint represents an Azure Resource Group in our software catalog",
"title": "Azure Resource Group",
"icon": "Azure",
"schema": {
"properties": {
"location": {
"title": "Location",
"type": "string"
},
"tags": {
"title": "Tags",
"type": "object"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {}
},
{
"identifier": "azureCloudResources",
"description": "This blueprint represents an AzureCloud Resource in our software catalog",
"title": "Azure Cloud Resources",
"icon": "Git",
"schema": {
"properties": {
"tags": {
"title": "Tags",
"type": "object"
},
"type": {
"title": "Type",
"type": "string"
},
"location": {
"title": "Location",
"type": "string"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {
"resource_group": {
"title": "Resource Group",
"target": "azureResourceGroup",
"required": false,
"many": false
}
}
}
]
Mapping configuration (click to expand)
resources:
- kind: resourceContainer
selector:
query: .type == "microsoft.resources/subscriptions/resourcegroups"
tags:
included:
environment: staging
exluded:
environment: production
port:
entity:
mappings:
identifier: .id | gsub(" ";"_")
title: .name
blueprint: '"azureResourceGroup"'
properties:
tags: .tags
location: .location

- kind: resource
selector:
query: 'true'
tags:
included:
environment: staging
exluded:
environment: production
port:
entity:
mappings:
identifier: .id | gsub(" ";"_")
title: .name
blueprint: '"azureCloudResources"'
properties:
tags: .tags
type: .type
location: .location
relations:
resource_group: >-
("/subscriptions/" + .subscriptionId + "/resourceGroups/" + .resourceGroup) | gsub(" ";"_")
resource group tags

You can filter Azure resources using tags from their parent resource groups. This allows you to define both inclusion and exclusion rules in a single configuration, giving you precise control over which resources are synchronized.

Frequently asked questionsโ€‹

Why should I filter resources by their resource group tags?โ€‹

Filtering resources by their parent resource group's tags simplifies management and synchronization for several reasons:

  • Simplified Tagging: Apply tags at the resource group level instead of to individual resources. This is more manageable and ensures resources share a common context.
  • Consistent Classification: Resource group tags are often more consistent than individual resource tags, allowing for reliable filtering of related resources.
  • Improved Efficiency: Filtering reduces the amount of data synced from Azure, speeding up ingestion and creating a more focused software catalog.