Add Tags to Azure Resource
In the following guide, you are going to create a self-service action in Port that executes a GitHub workflow to add tags to a storage account.
Organize and manage your Azure resources effectively by adding tags directly through Port.
- Cost Accounting: Categorize resources by department, project, or cost center for accurate billing analysis.
- Governance: Label resources based on criticality, compliance requirements, or ownership.
- Search & Filtering: Use tags to link the azure resource to other objects in your Port account.
Prerequisites
- Azure Subscription: An active Azure subscription is required to deploy the storage account.
- Port Actions Knowledge: Understanding how to create and use Port actions is necessary. Learn the basics here.
- GitHub Repository: A repository to store your GitHub workflow file for this action.
GitHub Secrets
To successfully execute this workflow, we will add the following secrets to the GitHub repository containing the workflow:
1. GitHub Action Secrets
- Navigate to your GitHub repository's "Settings" tab.
- Select "Secrets" and then "Actions" from the side menu.
- Create the following secrets:
PORT_CLIENT_ID
: Your Port Client ID learn more.PORT_CLIENT_SECRET
: Your Port Client Secret learn more.
2. Azure Cloud Credentials
For secure Azure interactions, we'll use a Service Principal. If you need help creating one, follow this guide
- Once you have your Service Principal, create these GitHub Action secrets:
ARM_CLIENT_ID
: Service Principal Application (Client) IDARM_CLIENT_SECRET
: Service Principal PasswordARM_SUBSCRIPTION_ID
: Your Azure Subscription IDARM_TENANT_ID
: Your Azure Tenant ID
Port Configuration
Import Azure resources into your Port account using the Azure Exporter
- Create the
azureStorage
blueprint.- Head to the Builder page.
- Click on the
+ Blueprint
button. - Click on the
{...} Edit JSON
button. - Copy and paste the following JSON configuration into the editor.
Port Blueprint: Azure Storage Account
Keep in mind that this can be any blueprint you require; the provided example is just for reference.
{
"identifier": "azureStorage",
"title": "Azure Storage Account",
"icon": "Azure",
"schema": {
"properties": {
"storage_name": {
"title": "Account Name",
"type": "string",
"minLength": 3,
"maxLength": 63,
"icon": "DefaultProperty"
},
"storage_location": {
"icon": "DefaultProperty",
"title": "Location",
"type": "string"
},
"url": {
"title": "URL",
"format": "url",
"type": "string",
"icon": "DefaultProperty"
}
},
"required": [
"storage_name",
"storage_location"
]
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
- To create the Port action:
- Head to the self-service page.
- Click on the
+ New Action
button. - Click on the
{...} Edit JSON
button. - Copy and paste the following JSON configuration into the editor.
Port Action: Add Tags to Azure Storage
<GITHUB-ORG>
- your GitHub organization or user name.<GITHUB-REPO-NAME>
- your GitHub repository name.
{
"identifier": "service_add_tags_to_azure_storage",
"title": "Add Tags to Azure Storage",
"icon": "Azure",
"description": "Add tags to azure storage account",
"trigger": {
"type": "self-service",
"operation": "DAY-2",
"userInputs": {
"properties": {
"tags": {
"title": "Tags",
"type": "object"
}
},
"required": [
"tags"
],
"order": []
},
"blueprintIdentifier": "azureStorage"
},
"invocationMethod": {
"type": "GITHUB",
"org": "<GITHUB-ORG>",
"repo": "<GITHUB-REPO-NAME>",
"workflow": "tag-azure-resource.yml",
"workflowInputs": {
"tags": "{{ .inputs.\"tags\" }}",
"port_context": {
"entity": "{{ .entity }}",
"blueprint": "{{ .action.blueprint }}",
"runId": "{{ .run.id }}",
"trigger": "{{ .trigger }}"
}
},
"reportWorkflowStatus": true
},
"requiredApproval": false,
"publish": true
}
GitHub Workflow
- Terraform
- Azure CLI
-
Update the following Terraform templates in the
terraform
folder at the root of your GitHub repository:tipFork our example repository to get started.
main.tf
- Include a tags field within the configuration of the storage account resource.variables.tf
– Introduce a new variable namedresource_tags
.
main.tf
...
resource "azurerm_storage_account" "storage_account" {
name = var.storage_account_name
resource_group_name = var.resource_group_name
location = var.location
account_tier = "Standard"
account_replication_type = "LRS"
account_kind = "StorageV2"
tags = var.resource_tags
}
...
variables.tf
// ...
variable "resource_tags" {
type = map(string)
default = {
Environment = "Production"
}
}
// ...
- Create a workflow file under
.github/workflows/tag-azure-resource.yml
with the following content:
GitHub workflow script
Replace the following variables for the terraform init
step:
RESOURCE_GROUP_NAME
with a resource group from your Azure account. Check this guide to find your resource groups.STORAGE_ACCOUNT_NAME
: The storage account containing.TF_STATE_CONTAINER
: The name of the container used for storing the Terraform state files.TF_STATE_KEY
: Indicate the key that uniquely identifies the configuration file.
name: "Tag Azure Resource"
on:
workflow_dispatch:
inputs:
tags:
required: true
type: string
port_context:
required: true
type: string
description: >-
Action and general context (blueprint, run id, etc...)
env:
TF_LOG: INFO
TF_INPUT: false
jobs:
terraform:
name: "Add Tags to Azure Resource"
runs-on: ubuntu-latest
defaults:
run:
shell: bash
working-directory: ./terraform
steps:
- name: Inform starting of action
uses: port-labs/port-github-action@v1
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
operation: PATCH_RUN
runId: ${{ fromJson(inputs.port_context).runId }}
logMessage: |
Starting a GitHub workflow to tag the Azure resource: ${{ fromJson(inputs.port_context).entity.identifier }} ... ⛴️
- name: Checkout the repository to the runner
uses: actions/checkout@v4
- name: Setup Terraform with specified version on the runner
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.6.0
- name: Terraform init
id: init
env:
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
RESOURCE_GROUP_NAME: YourResourceGroup
STORAGE_ACCOUNT_NAME: YourStorageAccount
TF_STATE_CONTAINER: tfstate
TF_STATE_KEY: terraform.tfstate
run: |
terraform init \
-backend-config="resource_group_name=$RESOURCE_GROUP_NAME" \
-backend-config="storage_account_name=$STORAGE_ACCOUNT_NAME" \
-backend-config="container_name=$TF_STATE_CONTAINER" \
-backend-config="key=$TF_STATE_KEY" \
-input=false
- name: Terraform format
id: fmt
run: terraform fmt -check
- name: Terraform validate
id: validate
run: terraform validate
- name: Run Terraform Plan and Apply (Azure)
id: plan-azure
env:
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
TF_VAR_port_client_id: ${{ secrets.PORT_CLIENT_ID }}
TF_VAR_port_client_secret: ${{ secrets.PORT_CLIENT_SECRET }}
TF_VAR_port_run_id: ${{ fromJson(inputs.port_context).runId }}
TF_VAR_storage_account_name: ${{ fromJson(inputs.port_context).entity.identifier }}
TF_VAR_resource_tags: ${{ github.event.inputs.tags }}
run: |
terraform plan \
-input=false \
-out=tfazure-${GITHUB_RUN_NUMBER}.tfplan
terraform apply -auto-approve -input=false tfazure-${GITHUB_RUN_NUMBER}.tfplan
- name: Create a failure log message
if: steps.plan-azure.outcome == 'failure'
uses: port-labs/port-github-action@v1
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
baseUrl: https://api.getport.io
operation: PATCH_RUN
runId: ${{fromJson(inputs.port_context).runId}}
logMessage: Failed to tag azure resource ${{ fromJson(inputs.port_context).entity.identifier }}
- name: Create a log message
uses: port-labs/port-github-action@v1
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
baseUrl: https://api.getport.io
operation: PATCH_RUN
runId: ${{fromJson(inputs.port_context).runId}}
logMessage: Added tags to ${{ fromJson(inputs.port_context).entity.identifier }}
- Create a GitHub Action secret
AZURE_CREDENTIALS
with the value like below: (Refer to Using secrets in GitHub Actions.)
AZURE_CREDENTIALS = {
"clientSecret": "******",
"subscriptionId": "******",
"tenantId": "******",
"clientId": "******"
}
- Create a workflow file under
.github/workflows/tag-azure-resource.yml
with the following content:
GitHub workflow script
Replace the RESOURCE_GROUP_NAME
with a resource group from your Azure account. Check this guide to find your resource groups.
name: "Tag Azure Resource CLI"
on:
workflow_dispatch:
inputs:
tags:
required: true
type: string
port_context:
required: true
description:
Details for who triggered the action and general context (blueprint, run id, etc...)
type: string
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Inform starting of action
uses: port-labs/port-github-action@v1
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
operation: PATCH_RUN
runId: ${{ fromJson(inputs.port_context).runId }}
logMessage: |
Starting a GitHub worklfow to tag the Azure resource: ${{fromJson(inputs.port_context).entity.identifier}} ... ⛴️
- uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Azure CLI script
uses: azure/CLI@v1
env:
RESOURCE_GROUP: YourResourceGroup
STORAGE_NAME: ${{ fromJson(inputs.port_context).entity.identifier }}
TAGS: ${{ github.event.inputs.tags }}
with:
azcliversion: latest
inlineScript: |
az account show
resource=$(az resource show -g ${RESOURCE_GROUP} -n ${STORAGE_NAME} --resource-type Microsoft.Storage/storageAccounts --query "id" --output tsv)
tags=$(echo ${TAGS} | jq -r 'to_entries|map("\(.key)=\(.value|tojson)")|join(" ")')
az tag create --resource-id $resource --tags $tags
- name: Create a log message
uses: port-labs/port-github-action@v1
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
baseUrl: https://api.getport.io
operation: PATCH_RUN
runId: ${{fromJson(inputs.port_context).runId}}
logMessage: Added tags to ${{fromJson(inputs.port_context).entity.identifier}}
Let's Test It!
- On the self-service page, select the action and fill in the properties.
- Click the execute button to trigger the GitHub workflow.