Create Azure virtual machines with Managed Service Identity using Ruby

Última actualización: 16/10/2017
Editar en GitHub

This sample demonstrates how to create your Azure virtual machines with Managed Service Identity using the Ruby SDK.

On this page

Run this sample

  1. If you don't already have it, install Ruby and the Ruby DevKit.

  2. If you don't have bundler, install it.

    gem install bundler
  3. Clone the repository.

    git clone
  4. Install the dependencies using bundle.

    cd compute-ruby-msi-vm
    bundle install
  5. Create an Azure service principal either through

    Azure CLI, PowerShell or the portal.

    :exclamation: NOTE :exclamation: Please make sure to create an role assignment with Owner role. In case of insufficient permissions, role assignment may fail for this sample.

  6. Set the following environment variables using the information from the service principle that you created.

    export AZURE_TENANT_ID={your tenant id}
    export AZURE_CLIENT_ID={your client id}
    export AZURE_CLIENT_SECRET={your client secret}
    export AZURE_SUBSCRIPTION_ID={your subscription id}

    [AZURE.NOTE] On Windows, use set instead of export.

  7. Run the sample.

    bundle exec ruby example.rb

What does example.rb doing?

This sample starts by setting up ResourceManagementClient, the resource provider clients, a resource group, and a storage account using your subscription and credentials.

subscription_id = ENV['AZURE_SUBSCRIPTION_ID'] || '11111111-1111-1111-1111-111111111111' # your Azure Subscription Id
  provider =
  credentials =
  resource_client =
  resource_client.subscription_id = subscription_id
  network_client =
  network_client.subscription_id = subscription_id
  storage_client =
  storage_client.subscription_id = subscription_id
  compute_client =
  compute_client.subscription_id = subscription_id

  # Managing resource groups
  resource_group_params = do |rg|
    rg.location = WEST_US

  # Create Resource group
  puts 'Create Resource Group'
  print_group resource_client.resource_groups.create_or_update(GROUP_NAME, resource_group_params)

  postfix = rand(1000)
  storage_account_name = "rubystor#{postfix}"
  puts "Creating a premium storage account with encryption off named #{storage_account_name} in resource group #{GROUP_NAME}"
  storage_create_params = do |account|
    account.location = WEST_US
    account.sku = do |sku| = StorageModels::SkuName::PremiumLRS
      sku.tier = StorageModels::SkuTier::Premium
    account.kind = StorageModels::Kind::Storage
    account.encryption = do |encrypt| = do |services|
        services.blob = do |service|
          service.enabled = false
  print_item storage_account = storage_client.storage_accounts.create(GROUP_NAME, storage_account_name, storage_create_params)

Create a virtual network

Now, we will create a virtual network and configure subnet for the virtual machine.

puts 'Creating a virtual network for the VM'
vnet_create_params = do |vnet|
  vnet.location = WEST_US
  vnet.address_space = do |addr_space|
    addr_space.address_prefixes = ['']
  vnet.dhcp_options = do |dhcp|
    dhcp.dns_servers = ['']
  vnet.subnets = [ do |subnet| = 'rubySampleSubnet'
        subnet.address_prefix = ''
print_item vnet = network_client.virtual_networks.create_or_update(GROUP_NAME, 'sample-ruby-vnet', vnet_create_params)

Create a public IP address

Now, we will create a public IP address using dynamic IP allocation method for the Azure VM.

puts 'Creating a public IP address for the VM'
public_ip_params = do |ip|
    ip.location = WEST_US
    ip.public_ipallocation_method = NetworkModels::IPAllocationMethod::Dynamic
    ip.dns_settings = do |dns|
        dns.domain_name_label = 'msi-vm-domain-name-label'
print_item public_ip = network_client.public_ipaddresses.create_or_update(GROUP_NAME, 'sample-ruby-pubip', public_ip_params)

Create a network interface

Now, we will create a network interface and assign the public ip address created in previous step.

print_item nic = network_client.network_interfaces.create_or_update(
    "sample-ruby-nic-#{vm_name}", do |interface|
        interface.location = WEST_US
        interface.ip_configurations = [
   do |nic_conf|
       = "sample-ruby-nic-#{vm_name}"
                nic_conf.private_ipallocation_method = NetworkModels::IPAllocationMethod::Dynamic
                nic_conf.subnet = subnet
                nic_conf.public_ipaddress = public_ip

Create a virtual machine with system identity

Now, we will set virtual machine parameters like OSProfile, StorageProfile, OSDisk, HardwareProfile & NetworkProfile as usual. We will also set the VirtualMachineIdentity to be SystemAssigned specifically for creating managed service identity VM and then create the virtual machine.

puts 'Creating a Ubuntu 16.04.0-LTS Standard DS2 V2 virtual machine w/ a public IP'
vm_create_params = do |vm|
  vm.location = location
  vm.os_profile = do |os_profile|
    os_profile.computer_name = vm_name
    os_profile.admin_username = 'notAdmin'
    os_profile.admin_password = 'Pa$$w0rd92'

  vm.storage_profile = do |store_profile|
    store_profile.image_reference = do |ref|
      ref.publisher = 'canonical'
      ref.offer = 'UbuntuServer'
      ref.sku = '16.04.0-LTS'
      ref.version = 'latest'
    store_profile.os_disk = do |os_disk| = "sample-os-disk-#{vm_name}"
      os_disk.caching = ComputeModels::CachingTypes::None
      os_disk.create_option = ComputeModels::DiskCreateOptionTypes::FromImage
      os_disk.vhd = do |vhd|
        vhd.uri = "https://#{}{vm_name}.vhd"

  vm.hardware_profile = do |hardware|
    hardware.vm_size = ComputeModels::VirtualMachineSizeTypes::StandardDS2V2

  vm.network_profile = do |net_profile|
    net_profile.network_interfaces = [ do |ref|
          ref.primary = true

  # Use System Assigned Identity for the VM
  vm.identity = do |identity|
    identity.type = ComputeModels::ResourceIdentityType::SystemAssigned

ssh_pub_location = File.expand_path('~/.ssh/')
if File.exists? ssh_pub_location
  puts "Found SSH public key in #{ssh_pub_location}. Disabling password and enabling SSH authentication."
  key_data =
  puts "Using public key: #{key_data}"
  vm_create_params.os_profile.linux_configuration = do |linux|
    linux.disable_password_authentication = true
    linux.ssh = do |ssh_config|
      ssh_config.public_keys = [
 do |pub_key|
            pub_key.key_data = key_data
            pub_key.path = '/home/notAdmin/.ssh/authorized_keys'

print_item vm = compute_client.virtual_machines.create_or_update(GROUP_NAME, "sample-ruby-vm-#{vm_name}", vm_create_params)

Add MSI extension to the VM

Now, we will add an VM extension ManagedIdentityExtensionForLinux for Azure VM and configure it to run on port 50342.

puts "Install Managed Service Identity Extension"
ext_name = 'msiextension'
vm_extension = do |extension|
  extension.publisher = 'Microsoft.ManagedIdentity'
  extension.virtual_machine_extension_type = 'ManagedIdentityExtensionForLinux'
  extension.type_handler_version = '1.0'
  extension.auto_upgrade_minor_version = true
  extension.settings = do |settings|
    settings['port'] = '50342'
  extension.location = WEST_US

vm_ext = compute_client.virtual_machine_extensions.create_or_update(GROUP_NAME, "sample-ruby-vm-#{vm_name}", ext_name, vm_extension)

Create role assignment for the VM

Now, we will retrieve the default rbac role named as Contributor. To know more about the default roles please visit built-in-roles.

puts "Getting the Role ID of Contributor of a Resource group: #{GROUP_NAME}"
role_name = 'Contributor'
roles = authorization_client.role_definitions.list(, "roleName eq '#{role_name}'")
contributor_role = roles.first

Now, we will assign Contributor role at the resource group level to allow managing Azure resources inside this resource group.

puts 'Creating the role assignment for the VM'
role_assignment_params = do |role_param| = do |property|
    property.principal_id = vm.identity.principal_id
    property.role_definition_id =
authorization_client.role_assignments.create(, SecureRandom.uuid, role_assignment_params)

Verify MSI extension is running on VM by logging-in via ssh

Once the Azure VM has been created, we will verify that MSI extension is running on this VM. Managed Service Identity extension will run on localhost and configured port, here 50342. Follow example here to find out the usage.

ssh -p 22
notAdmin@msi-vm:~$ netstat -tlnp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0*               LISTEN      -               


Delete the resources

Now, we will delete all the resources created using this example. Please comment this out to keep the resources alive in you Azure subscription.