2017-02-23 12:46:15 +00:00
require 'ms_rest_azure'
require 'azure_mgmt_resources'
require 'azure_mgmt_compute'
require 'azure_mgmt_network'
require 'inifile'
# Class to manage the connection to Azure to retrieve the information required about the resources
#
# @author Russell Seymour
#
# @attr_reader [String] subscription_id ID of the subscription in which resources are to be tested
class AzureConnection
attr_reader :subscription_id
# Constructor which reads in the credentials file
#
# @author Russell Seymour
def initialize
# If an INSPEC_AZURE_CREDS environment has been specified set the
# the credentials file to that, otherwise set the one in home
azure_creds_file = ENV [ 'AZURE_CREDS_FILE' ]
if azure_creds_file . nil?
# The environment file has not be set, so default to one in the home directory
azure_creds_file = File . join ( Dir . home , '.azure' , 'credentials' )
end
# Check to see if the credentials file exists
if File . file? ( azure_creds_file )
@credentials = IniFile . load ( File . expand_path ( azure_creds_file ) )
else
warn format ( '%s was not found or not accessible' , azure_creds_file )
end
end
# Connect to Azure using the specified credentials
#
# @author Russell Seymour
def connection
# If a connection already exists then return it
return @conn if defined? ( @conn )
2017-02-23 14:34:41 +00:00
@subscription_id = azure_subscription_id
# Check that the credential exists
raise format ( 'The specified Azure Subscription cannot be found in your credentials: %s' , subscription_id ) unless @credentials . sections . include? ( subscription_id )
# Determine the client_id, tenant_id and the client_secret
tenant_id = ENV [ 'AZURE_TENANT_ID' ] || @credentials [ subscription_id ] [ 'tenant_id' ]
client_id = ENV [ 'AZURE_CLIENT_ID' ] || @credentials [ subscription_id ] [ 'client_id' ]
client_secret = ENV [ 'AZURE_CLIENT_SECRET' ] || @credentials [ subscription_id ] [ 'client_secret' ]
# Create a new connection
token_provider = MsRestAzure :: ApplicationTokenProvider . new ( tenant_id , client_id , client_secret )
@conn = MsRest :: TokenCredentials . new ( token_provider )
end
private
# Return the subscrtiption ID to use
#
# @author Russell Seymour
def azure_subscription_id
2017-02-23 14:24:18 +00:00
# If a subscription has been specified as an environment variable use that
# If an index has been specified with AZURE_SUBSCRIPTION_INDEX attempt to use that value
# Otherwise use the first entry in the file
2017-02-23 14:13:32 +00:00
if ! ENV [ 'AZURE_SUBSCRIPTION_ID' ] . nil?
2017-02-23 14:34:41 +00:00
id = ENV [ 'AZURE_SUBSCRIPTION_ID' ]
2017-02-23 14:24:18 +00:00
elsif ! ENV [ 'AZURE_SUBSCRIPTION_NUMBER' ] . nil?
subscription_number = ENV [ 'AZURE_SUBSCRIPTION_NUMBER' ] . to_i
subscription_index = subscription_number - 1
# Check that the specified index is not greater than the number of subscriptions
2017-02-23 14:34:41 +00:00
if subscription_number > @credentials . sections . length
2017-02-23 14:24:18 +00:00
raise format ( 'Your credentials file only contains %s subscriptions. You specified number %s.' , @credentials . sections . length , subscription_number )
end
2017-02-23 14:34:41 +00:00
id = @credentials . sections [ subscription_index ]
2017-02-23 14:13:32 +00:00
else
2017-02-23 14:34:41 +00:00
id = @credentials . sections [ 0 ]
2017-02-23 12:46:15 +00:00
end
2017-02-23 14:34:41 +00:00
# Return the ID to the calling function
id
2017-02-23 12:46:15 +00:00
end
end
# Helper class to configure and give access to the various management components of Azure
# Also provides shortcuts for certain components, such as returing the VM object and performing
# all the checks that need to be done before retrieving the VM
#
# @author Russell Seymour
# @attr_reader [MsRest::TokenCredentials] azure Azure connection credentials
# @attr_reader [ComputeManagement] compute_mgmt Compute object for retrieving details about VMs
# @attr_reader [ResourceManagement] resource_mgmt Resource object for accessing specific resources and resoure groups
# @attr_reader [NetworkManagement] network_mgmt Network object for retrieving all information about Network cards and IP configurations
class Helpers
attr_reader :azure , :compute_mgmt , :resource_mgmt , :network_mgmt
# Constructor to configure the various objects that are required for Inspec testing
#
# @author Russell Seymour
def initialize
# Azure connection
@azure = AzureConnection . new
# Create the necessary clients
@compute_mgmt = ComputeManagement . new ( azure )
@resource_mgmt = ResourceManagement . new ( azure )
@network_mgmt = NetworkManagement . new ( azure )
end
# Retrieve the named virtual machine from Azure
#
# This is specified here as it combines two different resource types, Compute and Resource Groups
#
# @author Russell Seymour
#
# @return [] VM object
#
def get_vm ( name , rg_name )
# Ensure that the resource group exists
unless resource_mgmt . client . resource_groups . check_existence ( rg_name )
raise " The Resource group cannot be found: #{ rg_name } "
end
2017-02-23 12:59:22 +00:00
# Return if no name has been specified
return if name . nil?
2017-02-23 12:46:15 +00:00
# get a vm from the named resource group
begin
compute_mgmt . client . virtual_machines . get ( rg_name , name )
rescue = > e
e . error_message
end
end
end
# Class to return a NetworkManagement client for use with NICs and Public IP Addresses
#
# @author Russell Seymour
# @attr_reader [Azure::ARM::Network::NetworkManagementClient] client Azure Network Management cient
class ResourceManagement
attr_reader :client
# Constructor for the class. Creates the new Network Management client object
#
# @author Russell Seymour
#
# @param [MsRest::TokenCredentials] azure Connection object for Azure
def initialize ( azure )
@client = Azure :: ARM :: Resources :: ResourceManagementClient . new ( azure . connection )
client . subscription_id = azure . subscription_id
end
# Determine if the specified resource group exists in the subscription_id
#
# @author Russell Seymour
#
# @param [String] name Name of the resource group
#
# @return [Boolean] Whether the resource group exists or not
def exists ( name )
client . resource_groups . check_existence ( name )
end
# Retrieve the named resource group if it exists
#
# @author Russell Seymour
#
# @param [String] name Name of the resource group
#
# @return [Azure::ARM::Resources::Models::ResourceGroup] Object containing information about the resource group
def get_resource_group ( name )
client . resource_groups . get ( name ) if exists ( name )
end
# Get all of the resources that are contained within the resource group if it exists
#
# @author Russell Seymour
#
# @param [String] name Name of the resource group
#
# @return [Azure::ARM::Resources::Models::ResourceListResult] Object containing array of all the resources
def get_resources ( name )
client . resource_groups . list_resources_as_lazy ( name ) if exists ( name )
end
end
# Class to return a ComputeManagement client to get information about VMs
#
# @author Russell Seymour
#
# @attr_reader [Azure::ARM::Compute::ComputeManagementClient] client ComputeManagement client object
class ComputeManagement
attr_reader :client
# Constructor for the class. Creates the new Network Management client object
#
# @author Russell Seymour
#
# @param [MsRest::TokenCredentials] azure Connection object for Azure
def initialize ( azure )
@client = Azure :: ARM :: Compute :: ComputeManagementClient . new ( azure . connection )
client . subscription_id = azure . subscription_id
end
end
# Class to return a NetworkManagement client for use with NICs and Public IP Addresses
#
# @author Russell Seymour
# @attr_reader [Azure::ARM::Network::NetworkManagementClient] client Azure Network Management cient
class NetworkManagement
attr_reader :client
# Constructor for the class. Creates the new Network Management client object
#
# @author Russell Seymour
#
# @param [MsRest::TokenCredentials] azure Connection object for Azure
def initialize ( azure )
@client = Azure :: ARM :: Network :: NetworkManagementClient . new ( azure . connection )
client . subscription_id = azure . subscription_id
end
end