/
azure_virtual_machine.rb
264 lines (234 loc) · 7.61 KB
/
azure_virtual_machine.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# 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