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) ID
- ARM_CLIENT_SECRET: Service Principal Password
- ARM_SUBSCRIPTION_ID: Your Azure Subscription ID
- ARM_TENANT_ID: Your Azure Tenant ID
 
Port Configurationโ
Import Azure resources into your Port account using the Azure Exporter
- Create the azureStorageblueprint.- Head to the Builder page.
- Click on the + Blueprintbutton.
- Click on the {...} Edit JSONbutton.
- 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 Actionbutton.
- Click on the {...} Edit JSONbutton.
- 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
}
GitHub Workflowโ
- Terraform
- Azure CLI
- 
Update the following Terraform templates in the terraformfolder 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 named- resource_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.ymlwith the following content:
GitHub workflow script
Replace the following variables for the terraform init step:
- RESOURCE_GROUP_NAMEwith 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_CREDENTIALSwith 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.ymlwith 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 workflow 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.