mirror of
https://github.com/inspec/inspec
synced 2024-11-10 23:24:18 +00:00
Added new resources
Allows testing of network configurations Closes #2 Signed-off-by: Russell Seymour <russell.seymour@turtlesystems.co.uk>
This commit is contained in:
parent
1f53a1649e
commit
de1b7134ef
6 changed files with 225 additions and 12 deletions
|
@ -15,6 +15,8 @@ Encoding:
|
|||
Enabled: true
|
||||
HashSyntax:
|
||||
Enabled: true
|
||||
ClassLength:
|
||||
Max: 200
|
||||
LineLength:
|
||||
Enabled: false
|
||||
EmptyLinesAroundBlockBody:
|
||||
|
|
13
README.md
13
README.md
|
@ -166,14 +166,23 @@ end
|
|||
| | sku | The SKU being used |
|
||||
| | size | The size of the machine |
|
||||
| | location | Where the machine has been deployed |
|
||||
| | boot_diagnostics? | Whether boot diagnostics have been enabled or not |
|
||||
| | has_boot_diagnostics? | Whether boot diagnostics have been enabled or not |
|
||||
| | nic_count | How many network cards are attached to the machine |
|
||||
| | admin_username | The admin username that has been assigned to the machine |
|
||||
| | computername | Computer name of the machine in the operating system. This maybe different to the VM name as seen in Azure |
|
||||
| | hostname | Alias for computername |
|
||||
| | password_authentication? | If password authentication is enabled. For Windows machines this is always true |
|
||||
| | ssh_key_count | How many SSH public keys have been added to the machine. For Windows this is always 0 |
|
||||
| | os_type | Tyep type of operating system. Linux or Windows |
|
||||
| | os_type | The type of operating system. Linux or Windows |
|
||||
| | private_ipaddresses | Returns an array of all the IP addresses for all the NICs on the machine |
|
||||
| | has_public_ipaddress? | Whether the machine has been allocated an IP address or not |
|
||||
| | domain_name_label | If the machine has a public IP address then return the domain name label it has been assigned |
|
||||
|
||||
For the resources that start with `has_` the following construct can be used
|
||||
|
||||
```ruby
|
||||
it { should have_boot_diagnostics }
|
||||
```
|
||||
|
||||
- `azure_vm_datadisks` - Resource to read the data disks for a machine and check that they are of the correct size etc
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@ where
|
|||
- `password_authentication?`
|
||||
- `ssh_key_count`
|
||||
- `os_type`
|
||||
- `private_ipaddresses`
|
||||
- `has_public_ipaddress?`
|
||||
- `domain_name_label`
|
||||
* `value` is the expected output from the matcher
|
||||
|
||||
For example:
|
||||
|
@ -97,6 +100,10 @@ its('location') { should eq 'West Europe' }
|
|||
|
||||
Boolean test to see if boot diagnostics have been enabled on the machine
|
||||
|
||||
```ruby
|
||||
it { should have_boot_diagnostics }
|
||||
```
|
||||
|
||||
### nic_count
|
||||
|
||||
The number of network interface cards that have been attached to the machine
|
||||
|
@ -135,6 +142,26 @@ This only applies to Linux machines and will always return `0` on Windows.
|
|||
|
||||
Generic test that returns either `Linux` or `Windows`.
|
||||
|
||||
### private_ipaddresses
|
||||
|
||||
Returns an array of all the private IP addresses that are assigned to the machine. This is because a machine can multiple NICs and each NIC can have multiple IP Configurations.
|
||||
|
||||
```ruby
|
||||
its('private_ipaddresses') { should include '10.1.1.10' }
|
||||
```
|
||||
|
||||
### has_public_ipaddress?
|
||||
|
||||
Returns boolean to state if the machine has been allocated a Public IP Address.
|
||||
|
||||
```ruby
|
||||
it { should have_public_ip_address }
|
||||
```
|
||||
|
||||
### domain_name_label
|
||||
|
||||
If a machine has been allocated a Public IP Addresse test to see what domain name label has been set.
|
||||
|
||||
## Examples
|
||||
|
||||
The following examples show how to use this InSpec audit resource.
|
||||
|
|
|
@ -19,7 +19,7 @@ class AzureVm < Inspec.resource(1)
|
|||
end
|
||||
"
|
||||
|
||||
attr_accessor :vm
|
||||
attr_accessor :vm, :nics, :helpers
|
||||
|
||||
# Constructor to retrieve the VM from Azure
|
||||
#
|
||||
|
@ -30,13 +30,28 @@ class AzureVm < Inspec.resource(1)
|
|||
# opts[:resource_group] Name of the resource group in which the host will be found
|
||||
def initialize(opts)
|
||||
opts = opts
|
||||
helpers = Helpers.new
|
||||
@helpers = Helpers.new
|
||||
@vm = helpers.get_vm(opts[:name], opts[:resource_group])
|
||||
|
||||
# Ensure that the vm is an object
|
||||
raise format('An error has occured: %s', vm) if vm.instance_of?(String)
|
||||
|
||||
# Parse the Network Interface Cards attached to the machine
|
||||
@nics = parse_nics(vm.network_profile.network_interfaces)
|
||||
end
|
||||
|
||||
filter = FilterTable.create
|
||||
filter.add_accessor(:where)
|
||||
.add_accessor(:entries)
|
||||
.add(:accelerated_networking, field: 'enable_accelerated_networking')
|
||||
.add(:ip_forwarding, field: 'enable_ip_forwarding')
|
||||
.add(:location, field: 'location')
|
||||
.add(:name, field: 'name')
|
||||
.add(:primary, field: 'primary')
|
||||
.add(:ip_configurations, field: 'ip_configurations')
|
||||
|
||||
filter.connect(self, :nics)
|
||||
|
||||
# Determine the SKU used to create the machine
|
||||
#
|
||||
# @return [String] Showing the sku, e.g. 16.04.0-LTS
|
||||
|
@ -81,7 +96,7 @@ class AzureVm < Inspec.resource(1)
|
|||
#
|
||||
# @return [Boolean]
|
||||
#
|
||||
def boot_diagnostics?
|
||||
def has_boot_diagnostics?
|
||||
if vm.diagnostics_profile
|
||||
vm.diagnostics_profile.boot_diagnostics.enabled
|
||||
else
|
||||
|
@ -156,4 +171,149 @@ class AzureVm < Inspec.resource(1)
|
|||
def os_type
|
||||
vm.storage_profile.os_disk.os_type
|
||||
end
|
||||
|
||||
# Return an array of the private IP addresses so that it is possible
|
||||
# to check if the machine has the correct assigned address
|
||||
#
|
||||
# @return [Array] Array of private ip addresses
|
||||
#
|
||||
def private_ipaddresses
|
||||
# Create an array to hold the addresses
|
||||
addresses = []
|
||||
|
||||
# Iterate around the filter that has been populated
|
||||
entries.each do |entry|
|
||||
entry.ip_configurations.each do |ip_config|
|
||||
addresses << ip_config['private_ipaddress']
|
||||
end
|
||||
end
|
||||
|
||||
# return the array to the calling function
|
||||
addresses
|
||||
end
|
||||
|
||||
# Boolean test to check that the machine has a public IP address
|
||||
#
|
||||
# @return [boolean]
|
||||
#
|
||||
def has_public_ip_address?
|
||||
# Define the test value
|
||||
test = false
|
||||
|
||||
entries.each do |entry|
|
||||
entry.ip_configurations.each do |ip_config|
|
||||
if ip_config['public_ipaddress']['attached']
|
||||
test = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test
|
||||
end
|
||||
|
||||
# Return the domain name label that has been assigned to the machine
|
||||
#
|
||||
# @return [String] The domain name label
|
||||
#
|
||||
def domain_name_label
|
||||
label = nil
|
||||
entries.each do |entry|
|
||||
entry.ip_configurations.each do |ip_config|
|
||||
if ip_config['public_ipaddress']['attached']
|
||||
label = ip_config['public_ipaddress']['domain_name_label']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
label
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Parse the array of NICs attached to the machine
|
||||
#
|
||||
# @return [Array] Array of all the NICs
|
||||
#
|
||||
def parse_nics(attached_nics)
|
||||
# Iterate around the attached NICs
|
||||
attached_nics.each.map do |attached_nic|
|
||||
|
||||
# Get the name of the resource group and the name of the NIC
|
||||
# This is required as the card might be in a different resource group
|
||||
nic_raw = attached_nic.id.split(%r{/})
|
||||
nic_resource_group_name = nic_raw[4]
|
||||
nic_name = nic_raw.last
|
||||
|
||||
# Interrogate Azure for the NIC details
|
||||
nic = helpers.network_mgmt.client.network_interfaces.get(nic_resource_group_name, nic_name)
|
||||
|
||||
# Parse the NIC
|
||||
parse_nic(nic)
|
||||
end.compact
|
||||
end
|
||||
|
||||
# Parse the indivdual NIC
|
||||
#
|
||||
# @return [Hash] Properties of the indvidual NIC
|
||||
#
|
||||
def parse_nic(nic)
|
||||
# Create the hash table that contains all the information about the NIC
|
||||
{
|
||||
'enable_accelerated_networking' => nic.enable_accelerated_networking,
|
||||
'enable_ip_forwarding' => nic.enable_ipforwarding,
|
||||
'location' => nic.location,
|
||||
'name' => nic.name,
|
||||
'primary' => nic.primary,
|
||||
|
||||
# Parse all the IP configurations for the NIC
|
||||
'ip_configurations' => parse_ip_configurations(nic.ip_configurations),
|
||||
}
|
||||
end
|
||||
|
||||
# Parse the array of IP configurations that are applied to the NIC
|
||||
#
|
||||
# @returns [Array] Array of all the IP configurations
|
||||
#
|
||||
def parse_ip_configurations(ip_configurations)
|
||||
# Iterate around all of the IP configurations
|
||||
ip_configurations.each.map do |ip_configuration|
|
||||
parse_ip_configuration(ip_configuration)
|
||||
end.compact
|
||||
end
|
||||
|
||||
# Parse the IP configuration item
|
||||
#
|
||||
# @return [Hash] Hashtable of the ip_configuration attributes
|
||||
#
|
||||
def parse_ip_configuration(ip_configuration)
|
||||
config = {
|
||||
'name' => ip_configuration.name,
|
||||
'primary' => ip_configuration.primary,
|
||||
'private_ipaddress' => ip_configuration.private_ipaddress,
|
||||
'public_ipaddress' => {
|
||||
'attached' => !ip_configuration.public_ipaddress.nil?,
|
||||
},
|
||||
}
|
||||
|
||||
# if there is a public IP address attached get its details
|
||||
if config['public_ipaddress']['attached']
|
||||
|
||||
# Get the name of the resource group and the name of the NIC
|
||||
# This is required as the card might be in a different resource group
|
||||
public_ip_raw = ip_configuration.public_ipaddress.id.split(%r{/})
|
||||
public_ip_resource_group_name = public_ip_raw[4]
|
||||
public_ip_name = public_ip_raw.last
|
||||
|
||||
# Interrogate Azure for the NIC details
|
||||
public_ip = helpers.network_mgmt.client.public_ipaddresses.get(public_ip_resource_group_name, public_ip_name)
|
||||
|
||||
# update the config with the information about the public IP
|
||||
config['public_ipaddress']['domain_name_label'] = public_ip.dns_settings.domain_name_label
|
||||
config['public_ipaddress']['dns_fqdn'] = public_ip.dns_settings.fqdn
|
||||
end
|
||||
|
||||
# return object
|
||||
config
|
||||
end
|
||||
end
|
||||
|
|
|
@ -47,7 +47,7 @@ resource "azurerm_public_ip" "public_ip_1" {
|
|||
location = "${var.location}"
|
||||
resource_group_name = "${azurerm_resource_group.rg.name}"
|
||||
public_ip_address_allocation = "dynamic"
|
||||
domain_name_label = "linux-inspec-1"
|
||||
domain_name_label = "linux-external-1"
|
||||
}
|
||||
|
||||
# Create the virtual network for the machines
|
||||
|
@ -66,7 +66,8 @@ resource "azurerm_subnet" "subnet" {
|
|||
address_prefix = "10.1.1.0/24"
|
||||
}
|
||||
|
||||
# Create the NIC for the machine
|
||||
# Create the NIC for the internal machine
|
||||
# Give the machine a static IP Address
|
||||
resource "azurerm_network_interface" "nic1" {
|
||||
name = "Inspec-NIC-1"
|
||||
location = "${var.location}"
|
||||
|
@ -75,7 +76,8 @@ resource "azurerm_network_interface" "nic1" {
|
|||
ip_configuration {
|
||||
name = "ipConfiguration1"
|
||||
subnet_id = "${azurerm_subnet.subnet.id}"
|
||||
private_ip_address_allocation = "dynamic"
|
||||
private_ip_address_allocation = "static"
|
||||
private_ip_address = "10.1.1.10"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
title 'Virtual Machine Properties'
|
||||
|
||||
control 'azure-vm-1.0' do
|
||||
control 'azure-vm-internal-1.0' do
|
||||
|
||||
impact 1.0
|
||||
title 'Ensure VM was built with the correct Image and has the correct properties'
|
||||
title 'Ensure Internal VM was built with the correct Image and has the correct properties'
|
||||
|
||||
# Ensure that the virtual machine has been created with the correct attributes
|
||||
describe azure_virtual_machine(name: 'Linux-Internal-VM', resource_group: 'Inspec-Azure') do
|
||||
|
@ -13,12 +13,25 @@ control 'azure-vm-1.0' do
|
|||
its('offer') { should eq 'UbuntuServer' }
|
||||
its('size') { should eq 'Standard_DS2_v2' }
|
||||
its('location') { should eq 'westeurope' }
|
||||
its('boot_diagnostics?') { should be false }
|
||||
it { should_not have_boot_diagnostics }
|
||||
its('nic_count') { should eq 1 }
|
||||
its('admin_username') { should eq 'azure' }
|
||||
its('password_authentication?') { should be true }
|
||||
its('ssh_key_count') { should eq 0 }
|
||||
its('os_type') { should eq 'Linux' }
|
||||
its('os_type') { should eq 'Linux' }
|
||||
its('private_ipaddresses') { should include '10.1.1.10' }
|
||||
it { should_not have_public_ip_address }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
control 'azure-vm-external-1.0' do
|
||||
|
||||
impact 1.0
|
||||
title 'Ensure External VM has external access'
|
||||
|
||||
describe azure_virtual_machine(name: 'Linux-External-VM', resource_group: 'Inspec-Azure') do
|
||||
it { should have_public_ip_address }
|
||||
its('domain_name_label') { should eq 'linux-external-1' }
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue