inspec/lib/resources/azure/azure_virtual_machine.rb

265 lines
7.6 KiB
Ruby
Raw Normal View History

# encoding: utf-8
require 'resources/azure/azure_backend'
module Inspec::Resources
class AzureVirtualMachine < AzureResourceBase
name 'azure_virtual_machine'
desc '
InSpec Resource to test Azure Virtual Machines
'
supports platform: 'azure'
# Constructor for the resource. This calls the parent constructor to
# get the generic resource for the specified machine. This will provide
# static methods that are documented
#
# @author Russell Seymour
def initialize(opts = {})
# The generic resource needs to pass back a Microsoft.Compute/virtualMachines object so force it
opts[:type] = 'Microsoft.Compute/virtualMachines'
super(opts)
# Find the virtual machines
resources
create_tag_methods
end
# Method to catch calls that are not explicitly defined.
# This allows the simple attributes of the virtual machine to be read without having
# to define each one in turn.
#
# rubocop:disable Metrics/AbcSize
#
# @param symobl method_id The symbol of the method that has been called
#
# @return Value of attribute that has been called
def method_missing(method_id)
# Depending on the method that has been called, determine what value should be returned
# These are set as camel case methods to comply with rubocop
image_reference_attrs = %w{sku publisher offer}
osdisk_attrs = %w{os_type caching create_option disk_size_gb}
hardware_profile_attrs = %w{vm_size}
os_profile_attrs = %w{computer_name admin_username}
osdisk_managed_disk_attrs = %w{storage_account_type}
# determine the method name to call by converting the snake_case to camelCase
# method_name = self.camel_case(method_id.to_s)
method_name = method_id.to_s.split('_').inject([]) { |buffer, e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
method_name.end_with?('Gb') ? method_name.gsub!(/Gb/, &:upcase) : false
if image_reference_attrs.include?(method_id.to_s)
properties.storageProfile.imageReference.send(method_name)
elsif osdisk_attrs.include?(method_id.to_s)
properties.storageProfile.osDisk.send(method_name)
elsif hardware_profile_attrs.include?(method_id.to_s)
properties.hardwareProfile.send(method_name)
elsif os_profile_attrs.include?(method_id.to_s)
properties.osProfile.send(method_name)
elsif osdisk_managed_disk_attrs.include?(method_id.to_s)
properties.storageProfile.osDisk.managedDisk.send(method_name)
end
end
# Return the name of the os disk
#
# @return string Name of the OS disk
def os_disk_name
properties.storageProfile.osDisk.name
end
# Determine if the OS disk is a managed disk
#
# @return boolean
def has_managed_osdisk?
defined?(properties.storageProfile.osDisk.managedDisk)
end
# Does the machine have any NICs connected
#
# @return boolean
def has_nics?
properties.networkProfile.networkInterfaces.count != 0
end
# How many NICs are connected to the machine
#
# @return integer
def nic_count
properties.networkProfile.networkInterfaces.count
end
# Return an array of the connected NICs so that it can be tested to ensure
# the machine is connected properly
#
# @return array Array of NIC names connected to the machine
def connected_nics
nic_names = []
properties.networkProfile.networkInterfaces.each do |nic|
nic_names << nic.id.split(%r{/}).last
end
nic_names
end
# Whether the machine has data disks or not
#
# @return boolean
def has_data_disks?
properties.storageProfile.dataDisks.count != 0
end
# How many data disks are connected
#
# @return integer
def data_disk_count
properties.storageProfile.dataDisks.count
end
# Does the machine allow password authentication
#
# This allows the use of
# it { should have_password_authentication }
# within the InSpec profile
#
# @return boolean
def has_password_authentication?
password_authentication?
end
# Deteremine if the machine allows password authentication
#
# @return boolean
def password_authentication?
# if the osProfile property has a linuxConfiguration section then interrogate that
# otherwise it is a Windows machine and that always has password auth
if defined?(properties.osProfile.linuxConfiguration)
!properties.osProfile.linuxConfiguration.disablePasswordAuthentication
else
true
end
end
# Has the machine been given Custom Data at creation
#
# This allows the use of
# it { should have_custom_data }
# within the InSpec Profile
#
# @return boolean
def has_custom_data?
custom_data?
end
# Determine if custom data has been set
#
# @return boolean
def custom_data?
if defined?(properties.osProfile.CustomData)
true
else
false
end
end
# Are any SSH Keys assigned to the machine
#
# This allows the use of
# it { should have_ssh_keys }
# within the InSpec Profile
#
# @return boolean
def has_ssh_keys?
ssh_keys?
end
# Determine if any ssh keys have been asigned to the machine
#
# @return boolean
def ssh_keys?
if defined?(properties.osProfile.linuxConfiguration.ssh)
properties.osProfile.linuxConfiguration.ssh.publicKeys != 0
else
false
end
end
# Return the number of ssh keys that have been assigned to the machine
#
# @return integer
def ssh_key_count
if defined?(properties.osProfile.linuxConfiguration.ssh)
properties.osProfile.linuxConfiguration.ssh.publicKeys.count
else
0
end
end
# Determine is the specified key is in the ssh_keys list
#
# @return array Array of the public keys that are assigned to allow for testing of that key
def ssh_keys
# iterate around the keys
keys = []
properties.osProfile.linuxConfiguration.ssh.publicKeys.each do |key|
keys << key.keyData
end
keys
end
# Does the machine have boot diagnostics enabled
#
# @return boolean
def has_boot_diagnostics?
if defined?(properties.diagnosticsProfile)
properties.diagnosticsProfile.bootDiagnostics.enabled
else
false
end
end
# Return the URI that has been set for the boot diagnostics storage
#
# @return string
def boot_diagnostics_storage_uri
properties.diagnosticsProfile.bootDiagnostics.storageUri
end
# If this is a windows machine, returns whether the agent was provisioned or not
#
# @return boolean
def has_provision_vmagent?
if defined?(properties.osProfile.windowsConfiguration)
properties.osProfile.windowsConfiguration.provisionVMAgent
else
false
end
end
# If a windows machine see if automatic updates for the agent are enabled
#
# @return boolean
def has_automatic_agent_update?
if defined?(properties.osProfile.windowsConfiguration)
properties.osProfile.windowsConfiguration.enableAutomaticUpdates
else
false
end
end
# If this is a windows machine return a boolean to state of the WinRM options
# have been set
#
# @return boolean
def has_winrm_options?
if defined?(properties.osProfile.windowsConfiguration) && defined?(properties.osProfile.windowsConfiguration.winrm)
properties.osProfile.windowsConfiguration.winrm.protocol
else
false
end
end
end
end