Skip to content

raman1236/azure_vm_tags

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

azure_vm_tags

Table of Contents

  1. Description
  2. Why Managed Identity?
  3. Setup - Getting started with azure_vm_tags
  4. Usage - How to use the module
  5. How Authentication Works
  6. Local Testing on Azure VMs
  7. Limitations
  8. Development
  9. Reference

Description

This Puppet module allows you to manage tags on Azure Virtual Machines using the Azure REST API and Managed Identity authentication. It provides a custom type (azure_vm_tag) with a provider (v1) that retrieves and updates tags on Azure VMs directly from within the VM itself.

Why Managed Identity?

This module uses Azure Managed Identity for authentication, which provides significant security and operational benefits:

  • âś… No credentials to manage - No client secrets, passwords, certificates, or API keys required
  • âś… Automatic token management - Azure handles token generation, rotation, and expiration
  • âś… Secure by default - Tokens are obtained from Azure Instance Metadata Service (IMDS), only accessible from within the VM
  • âś…Provider Testing on a Node (Local T-id>/resourceGroups//providers/Microsoft.Compute/virtualMachines/

#### 3. Verify Facter Facts

Ensure that the following fact is available via Facter:
- `az_metadata` - Must include `compute.resourceId` (the full Azure resource ID of the VM)

You can verify this by running:
```bash
facter az_metadata

Usage

Basic Tag Management

# Set a tag with a simple value
azure_vm_tag { 'Environment':
  ensure => present,
  value  => 'production',
}

# Set multiple tags
azure_vm_tag { 'Owner':
  ensure => present,
  value  => 'DevOps Team',
}

azure_vm_tag { 'CostCenter':
  ensure => present,
  value  => 'Engineering',
}

azure_vm_tag { 'Application':
  ensure => present,
  value  => 'WebServer',
}

Using Facts in Tag Values

# Use Facter facts dynamically
azure_vm_tag { 'FQDN':
  ensure => present,
  value  => $facts['fqdn'],
}

azure_vm_tag { 'Hostname':
  ensure => present,
  value  => $facts['hostname'],
}

azure_vm_tag { 'OS':
  ensure => present,
  value  => "${facts['os']['name']} ${facts['os']['release']['major']}",
}

azure_vm_tag { 'PuppetVersion':
  ensure => present,
  value  => $facts['puppetversion'],
}

Removing Tags

# Remove a tag
azure_vm_tag { 'Temporary':
  ensure => absent,
}

azure_vm_tag { 'OldTag':
  ensure => absent,
}

Complete Class Example

class profile::azure_tags {
  # Standard organizational tags
  azure_vm_tag { 'Environment':
    ensure => present,
    value  => lookup('azure_environment', String, 'first', 'production'),
  }

  azure_vm_tag { 'Role':
    ensure => present,
    value  => lookup('azure_role', String, 'first', 'webserver'),
  }

  azure_vm_tag { 'Owner':
    ensure => present,
    value  => lookup('team_owner', String, 'first', 'DevOps'),
  }

  # Automated tags from facts
  azure_vm_tag { 'FQDN':
    ensure => present,
    value  => $facts['fqdn'],
  }

  azure_vm_tag { 'ManagedBy':
    ensure => present,
    value  => 'Puppet',
  }

  azure_vm_tag { 'LastPuppetRun':
    ensure => present,
    value  => strftime('%Y-%m-%d %H:%M:%S'),
  }
}

Then include the profile in your node classification:

node 'myserver.example.com' {
  include profile::azure_tags
}

How Authentication Works

Authentication Flow

  1. Puppet agent starts on the Azure VM
  2. Provider requests token from Azure IMDS endpoint: http://169.254.169.254/metadata/identity/oauth2/token
  3. Azure validates that the request originated from within the VM with Managed Identity
  4. IMDS returns an OAuth 2.0 Bearer token scoped for Azure Resource Manager (https://management.azure.com/)
  5. Provider uses token to authenticate REST API calls to Azure Resource Manager
  6. Tags are read/updated via HTTP GET and PATCH requests to the Azure REST API

Technical Details

  • Authentication Method: OAuth 2.0 Bearer Token
  • Token Source: Azure Instance Metadata Service (IMDS)
  • IMDS Endpoint: http://169.254.169.254/metadata/identity/oauth2/token
  • IMDS API Version: 2018-02-01
  • Resource Scope: https://management.azure.com/
  • Token Lifetime: Typically ~24 hours (automatically refreshed on each Puppet run)
  • Timeout: 5 seconds for both connection and read operations
  • Required IAM Role: Tag Contributor or Contributor on the VM resource
  • Supported Identity Types: System-assigned and user-assigned managed identities
  • No External Dependencies: Uses only Ruby standard library (net/http, json)
  • No Token Caching: Each Puppet run requests a fresh token (IMDS response time: ~50-100ms)

Local Testing on Azure VMs

Test the module directly on an Azure VM with Managed Identity for quick validation.

Prerequisites

  1. Azure VM with Managed Identity:

    az vm identity assign --name <vm-name> --resource-group <resource-group>
  2. IAM Permissions:

    az role assignment create --assignee <managed-identity-principal-id> \
      --role "Tag Contributor" --scope /subscriptions/<sub-id>/resourceGroups/<rg>
  3. Puppet agent and Facter: Verify facter az_metadata returns compute.resourceId

Setup

Create module structure on the VM:

sudo mkdir -p /etc/puppetlabs/code/environments/production/modules/azure_vm_tag/{lib/puppet/{type,provider/azure_vm_tag},manifests}

# Copy module files
sudo cp azure_vm_tag.rb /etc/puppetlabs/code/environments/production/modules/azure_vm_tag/lib/puppet/type/
sudo cp v1.rb /etc/puppetlabs/code/environments/production/modules/azure_vm_tag/lib/puppet/provider/azure_vm_tag/

Create manifests/init.pp:

class azure_vm_tag (
  Enum['present', 'absent'] $ensure = 'present',
) {
  azure_vm_tag { 'FQDN':
    ensure => $ensure,
    value  => $facts['fqdn'],
  }

  azure_vm_tag { 'Environment':
    ensure => $ensure,
    value  => 'testing',
  }
}

Test Scenarios

Scenario Manifest Change Expected Result
Create tags ensure => 'present' with new values Notice: .../ensure: created
Update values Change value parameter Notice: .../value: value changed 'old' to 'new'
Remove tags ensure => 'absent' Notice: .../ensure: removed
Idempotency Run twice with no changes Second run: Applied catalog in 0.30 seconds (no changes)

Test command:

cd /etc/puppetlabs/code/environments/production/modules
puppet apply --modulepath=. -e 'include azure_vm_tag'

Troubleshooting

Issue Solution
"Could not determine resourceId" Verify facter az_metadata returns compute.resourceId
"Timeout connecting to IMDS" Ensure Managed Identity is enabled
403 error Verify IAM role: Tag Contributor or higher

Performance: First run ~1-2s (API calls), subsequent idempotent runs ~0.3s.

Limitations

This module has the following limitations:

Platform Requirements

  • Azure Only: This module only works on Azure Virtual Machines running in Azure. It does not support:
    • On-premises virtual machines
    • VMs running in other cloud providers (AWS, GCP, etc.)
    • Local development machines

Authentication

  • Managed Identity Only: By design, this module only supports Azure Managed Identity authentication. It intentionally does not support:
    • Service Principal authentication (less secure, requires credential management)
    • Azure Arc-enabled servers (may be added in a future version)
    • Certificate-based authentication

Supported Resources

  • VM Tags Only: Currently supports managing tags on the VM resource itself. Does not support:
    • Tags on other Azure resources (storage accounts, networks, etc.)
    • Resource Group tags
    • Subscription tags

Puppet Server Location

  • Agent-Side Only: This module runs on the Puppet agent (the Azure VM itself). If your Puppet server is running outside of Azure:
    • The module will still work on Azure VMs with Managed Identity
    • Consider using Azure Arc if you need Managed Identity for hybrid scenarios
    • Alternatively, run your Puppet server in Azure

Other Limitations

  • No Bulk Operations: Each tag is managed individually (this is by design for idempotency)
  • Case Sensitivity: Tag names are case-insensitive in Azure, but the prefetch method handles this automatically
  • No Tag Validation: Azure tag naming restrictions are not validated client-side (the API will return errors if invalid)

Future Enhancements

Features being considered for future versions:

  • Support for Azure Arc-enabled servers
  • Support for managing tags on other Azure resources
  • Bulk tag operations
  • Tag validation before API calls

Development

Contributions are welcome! Please follow these guidelines:

  1. Fork and clone the repository
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Install dependencies: bundle install
  4. Run tests before submitting:
    bundle exec rake validate  # Validate syntax
    bundle exec rake lint      # Check style
    bundle exec rake spec      # Run RSpec tests
  5. Submit a Pull Request with:
    • Clear description of changes
    • Reference to related issues
    • Passing test results

Code Standards

Reporting Issues

Use the GitHub issue tracker. Include:

  • Puppet and module versions
  • OS and version
  • Steps to reproduce
  • Error messages/logs

Reference

Custom Type: azure_vm_tag

Manages tags on the current Azure VM.

Properties

  • ensure - Whether the tag should exist. Valid values: present, absent. Default: present
  • name - (namevar) The name of the tag. Tag names in Azure:
    • Can contain alphanumeric characters, spaces, and these special characters: + - = . _ : /
    • Maximum length: 512 characters
    • Are case-insensitive (but case is preserved)
  • value - The value of the tag. Required when ensure => present.
    • Maximum length: 256 characters
    • Can contain most characters

Provider: v1

The default (and only) provider for managing Azure VM tags.

  • Uses Azure Managed Identity for authentication
  • Retrieves tokens from Azure Instance Metadata Service (IMDS)
  • Makes REST API calls to Azure Resource Manager
  • Implements idempotent tag operations

Examples

See the Usage section above for complete examples.

Functions

This module does not provide any Puppet functions.

Facts

This module relies on the az_metadata fact provided by Facter, which should include the VM's compute.resourceId.


Module Version: 0.1.0 License: Apache-2.0 Supported Puppet Versions: 6.0.0 and later

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages