mirror of
https://github.com/inspec/inspec
synced 2024-11-10 23:24:18 +00:00
Added integration tests for current resources
Closes #19 Signed-off-by: Russell Seymour <russell.seymour@turtlesystems.co.uk>
This commit is contained in:
parent
668b4086f3
commit
ec072cadd3
14 changed files with 334 additions and 77 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,3 +4,5 @@
|
|||
Gemfile.lock
|
||||
inspec.lock
|
||||
.kitchen
|
||||
*.plan
|
||||
*.tfstate*
|
||||
|
|
1
Gemfile
1
Gemfile
|
@ -11,6 +11,7 @@ group :development do
|
|||
gem 'rubocop'
|
||||
gem 'github_changelog_generator'
|
||||
gem 'pry-coolline'
|
||||
gem 'passgen'
|
||||
end
|
||||
|
||||
group :inspec do
|
||||
|
|
15
README.md
15
README.md
|
@ -4,8 +4,8 @@ This resource pack provides resources for Azure Resources. It will ship with th
|
|||
|
||||
```
|
||||
├── README.md - this readme
|
||||
├── controls - contains example controls
|
||||
└── libraries - contains Azure resources
|
||||
└── test - contains integration tests
|
||||
```
|
||||
|
||||
## Get Started
|
||||
|
@ -212,14 +212,21 @@ control 'azure-1' do
|
|||
end
|
||||
```
|
||||
|
||||
### Using the example controls
|
||||
## Testing
|
||||
|
||||
There a number of example controls that have been added to this resource. They are driven by environment variables to make them easier to run. For example the following would test a machine called `example-01` in the resource group `exmaple-rg`.
|
||||
The `test/integration/verify/controls` directory contains all of the tests that are run during integration tests. These can be used as examples of how to use this resource pack.
|
||||
|
||||
Rake tasks have been configured to enable the running of the integration tests:
|
||||
|
||||
```bash
|
||||
$> AZURE_VM_NAME='example-01' AZURE_RESOURCE_GROUP_NAME='example-rg' bundle exec inspec exec .
|
||||
rake changelog # Generate a Change log from GitHub
|
||||
rake lint # Run robocop linter
|
||||
rake rubocop # Run Rubocop lint checks
|
||||
rake test:integration # Perform Integration Tests
|
||||
```
|
||||
|
||||
As with using the resources themselves the integration tests rely on a Service Principal Name being defined. Please see the information at the start of this page on how to generate this.
|
||||
|
||||
## License
|
||||
|
||||
| | |
|
||||
|
|
58
Rakefile
58
Rakefile
|
@ -2,6 +2,9 @@
|
|||
|
||||
require 'rake/testtask'
|
||||
require 'rubocop/rake_task'
|
||||
require 'inifile'
|
||||
require 'passgen'
|
||||
require_relative 'libraries/azure_backend'
|
||||
|
||||
# Rubocop
|
||||
desc 'Run Rubocop lint checks'
|
||||
|
@ -17,10 +20,59 @@ task lint: [:rubocop]
|
|||
task default: [:lint]
|
||||
|
||||
namespace :test do
|
||||
|
||||
# Specify the directory for the integration tests
|
||||
integration_dir = "test/integration"
|
||||
|
||||
# run inspec check to verify that the profile is properly configured
|
||||
task :check do
|
||||
dir = File.join(File.dirname(__FILE__))
|
||||
sh("bundle exec inspec check #{dir}")
|
||||
#task :check do
|
||||
# dir = File.join(File.dirname(__FILE__))
|
||||
# sh("bundle exec inspec check #{dir}")
|
||||
#end
|
||||
|
||||
task :setup_integration_tests do
|
||||
|
||||
azure_backend = AzureConnection.new
|
||||
creds = azure_backend.spn
|
||||
|
||||
# Determine the storage account name and the admin password
|
||||
sa_name = (0...15).map { (65 + rand(26)).chr }.join.downcase
|
||||
admin_password = Passgen::generate(length: 12, uppercase: true, lowercase: true, symbols: true, digits: true)
|
||||
|
||||
puts "----> Setup"
|
||||
# Create the plan that can be applied to Azure
|
||||
cmd = format("cd %s/build/ && terraform plan -var 'subscription_id=%s' -var 'client_id=%s' -var 'client_secret=%s' -var 'tenant_id=%s' -var='storage_account_name=%s' -var='admin_password=%s' -out inspec-azure.plan", integration_dir, creds[:subscription_id], creds[:client_id], creds[:client_secret], creds[:tenant_id], sa_name, admin_password)
|
||||
sh(cmd)
|
||||
|
||||
# Apply the plan on Azure
|
||||
cmd = format("cd %s/build/ && terraform apply inspec-azure.plan", integration_dir)
|
||||
sh(cmd)
|
||||
end
|
||||
|
||||
task :run_integration_tests do
|
||||
puts "----> Run"
|
||||
|
||||
cmd = format("bundle exec inspec exec %s/verify", integration_dir)
|
||||
sh(cmd)
|
||||
end
|
||||
|
||||
task :cleanup_integration_tests do
|
||||
|
||||
azure_backend = AzureConnection.new
|
||||
creds = azure_backend.spn
|
||||
|
||||
puts "----> Cleanup"
|
||||
cmd = format("cd %s/build/ && terraform destroy -force -var 'subscription_id=%s' -var 'client_id=%s' -var 'client_secret=%s' -var 'tenant_id=%s' -var='admin_password=dummy' -var='storage_account_name=dummy'", integration_dir, creds[:subscription_id], creds[:client_id], creds[:client_secret], creds[:tenant_id])
|
||||
sh(cmd)
|
||||
|
||||
end
|
||||
|
||||
desc "Perform Integration Tests"
|
||||
task :integration do
|
||||
Rake::Task["test:cleanup_integration_tests"].execute
|
||||
Rake::Task["test:setup_integration_tests"].execute
|
||||
Rake::Task["test:run_integration_tests"].execute
|
||||
Rake::Task["test:cleanup_integration_tests"].execute
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
title 'Sample profile to test names resource group'
|
||||
|
||||
control 'azure-rg-1.0' do
|
||||
impact 1.0
|
||||
title 'Ensure that a resource group has the correct resources'
|
||||
|
||||
resource_group_name = ENV['AZURE_RESOURCE_GROUP_NAME']
|
||||
|
||||
describe azure_rg(name: resource_group_name) do
|
||||
its('total') { should be >= 7 }
|
||||
its('vm_count') { should eq 1 }
|
||||
end
|
||||
|
||||
describe azure_rg(name: resource_group_name).where { type == 'Microsoft.Storage/storageAccounts' }.entries do
|
||||
its('count') { should eq 1 }
|
||||
end
|
||||
|
||||
describe azure_rg(name: resource_group_name).contains(parameter: 'name', value: 'example-VM-ip') do
|
||||
it { should be true }
|
||||
end
|
||||
end
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
title 'Sample profile to test the data disks of a vm'
|
||||
|
||||
control 'azure-vm-datadisks-1.0' do
|
||||
impact 1.0
|
||||
title 'Ensure that the machine has 1 data disk'
|
||||
|
||||
hostname = ENV['AZURE_VM_NAME']
|
||||
resource_group_name = ENV['AZURE_RESOURCE_GROUP_NAME']
|
||||
|
||||
describe azure_vm_datadisks(host: hostname, resource_group: resource_group_name) do
|
||||
its('has_disks?') { should be true }
|
||||
its('count') { should eq 1 }
|
||||
end
|
||||
|
||||
describe azure_vm_datadisks(host: hostname, resource_group: resource_group_name).where { disk.zero? and size > 10 } do
|
||||
its('entries') { should_not be_empty }
|
||||
end
|
||||
end
|
|
@ -1,24 +0,0 @@
|
|||
|
||||
title 'Sample profile to test the Image SKU of a vm'
|
||||
|
||||
control 'azure-vm-1.0' do
|
||||
impact 1.0
|
||||
title 'Ensure that the machine has an image SKU of 16.04.0-LTS'
|
||||
|
||||
hostname = ENV['AZURE_VM_NAME']
|
||||
resource_group_name = ENV['AZURE_RESOURCE_GROUP_NAME']
|
||||
|
||||
describe azure_vm(host: hostname, resource_group: resource_group_name) do
|
||||
its('sku') { should eq '16.04-LTS' }
|
||||
its('publisher') { should eq 'Canonical' }
|
||||
its('offer') { should eq 'UbuntuServer' }
|
||||
its('size') { should eq 'Standard_DS1_v2' }
|
||||
its('location') { should eq 'westeurope' }
|
||||
its('boot_diagnostics?') { should be true }
|
||||
its('nic_count') { should eq 1 }
|
||||
its('username') { should eq 'azure' }
|
||||
its('password_authentication?') { should be false }
|
||||
its('ssh_key_count') { should eq 1 }
|
||||
its('os_type') { should eq 'Linux' }
|
||||
end
|
||||
end
|
|
@ -40,6 +40,19 @@ class AzureConnection
|
|||
# If a connection already exists then return it
|
||||
return @conn if defined?(@conn)
|
||||
|
||||
creds = spn
|
||||
|
||||
# Create a new connection
|
||||
token_provider = MsRestAzure::ApplicationTokenProvider.new(creds[:tenant_id], creds[:client_id], creds[:client_secret])
|
||||
@conn = MsRest::TokenCredentials.new(token_provider)
|
||||
end
|
||||
|
||||
# Method to retrieve the SPN credentials
|
||||
# This is also used by the Rakefile to get the necessary creds to run the tests on the environment
|
||||
# that has been created
|
||||
#
|
||||
# @author Russell Seymour
|
||||
def spn
|
||||
@subscription_id = azure_subscription_id
|
||||
|
||||
# Check that the credential exists
|
||||
|
@ -50,9 +63,8 @@ class AzureConnection
|
|||
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)
|
||||
# Return hash of the SPN information
|
||||
{ subscription_id: subscription_id, client_id: client_id, client_secret: client_secret, tenant_id: tenant_id }
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -82,7 +82,11 @@ class AzureVm < Inspec.resource(1)
|
|||
# @return [Boolean]
|
||||
#
|
||||
def boot_diagnostics?
|
||||
vm.diagnostics_profile.boot_diagnostics.enabled
|
||||
if vm.diagnostics_profile
|
||||
vm.diagnostics_profile.boot_diagnostics.enabled
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
# Determine how many network cards are connected to the machine
|
||||
|
@ -138,7 +142,7 @@ class AzureVm < Inspec.resource(1)
|
|||
# @return [Integer]
|
||||
#
|
||||
def ssh_key_count
|
||||
if !vm.os_profile.linux_configuration.nil?
|
||||
if !vm.os_profile.linux_configuration.nil? && !vm.os_profile.linux_configuration.ssh.nil?
|
||||
vm.os_profile.linux_configuration.ssh.public_keys.length
|
||||
else
|
||||
0
|
||||
|
|
173
test/integration/azure/build/azure.tf
Normal file
173
test/integration/azure/build/azure.tf
Normal file
|
@ -0,0 +1,173 @@
|
|||
# Configure variables
|
||||
variable "storage_account_name" {}
|
||||
variable "admin_password" {}
|
||||
|
||||
variable "subscription_id" {}
|
||||
variable "client_id" {}
|
||||
variable "client_secret" {}
|
||||
variable "tenant_id" {}
|
||||
|
||||
variable "location" {
|
||||
default = "West Europe"
|
||||
}
|
||||
|
||||
# Configure the Azure RM provider
|
||||
provider "azurerm" {
|
||||
subscription_id = "${var.subscription_id}"
|
||||
client_id = "${var.client_id}"
|
||||
client_secret = "${var.client_secret}"
|
||||
tenant_id = "${var.tenant_id}"
|
||||
}
|
||||
|
||||
# Create a resource group for the machine to be created in
|
||||
resource "azurerm_resource_group" "rg" {
|
||||
name = "Inspec-Azure"
|
||||
location = "${var.location}"
|
||||
}
|
||||
|
||||
# Create the storage account to be used
|
||||
resource "azurerm_storage_account" "sa" {
|
||||
name = "${var.storage_account_name}"
|
||||
location = "${var.location}"
|
||||
resource_group_name = "${azurerm_resource_group.rg.name}"
|
||||
account_type = "Standard_LRS"
|
||||
}
|
||||
|
||||
# Create the container in which the hard disks for the machine(s) will be stored
|
||||
resource "azurerm_storage_container" "container" {
|
||||
name = "vhds"
|
||||
resource_group_name = "${azurerm_resource_group.rg.name}"
|
||||
storage_account_name = "${azurerm_storage_account.sa.name}"
|
||||
container_access_type = "private"
|
||||
}
|
||||
|
||||
# Create a Public IP
|
||||
resource "azurerm_public_ip" "public_ip_1" {
|
||||
name = "Inspec-PublicIP-1"
|
||||
location = "${var.location}"
|
||||
resource_group_name = "${azurerm_resource_group.rg.name}"
|
||||
public_ip_address_allocation = "dynamic"
|
||||
domain_name_label = "linux-inspec-1"
|
||||
}
|
||||
|
||||
# Create the virtual network for the machines
|
||||
resource "azurerm_virtual_network" "vnet" {
|
||||
name = "Inspec-VNet"
|
||||
address_space = ["10.1.1.0/24"]
|
||||
location = "${var.location}"
|
||||
resource_group_name = "${azurerm_resource_group.rg.name}"
|
||||
}
|
||||
|
||||
# Create the subnet
|
||||
resource "azurerm_subnet" "subnet" {
|
||||
name = "Inspec-Subnet"
|
||||
resource_group_name = "${azurerm_resource_group.rg.name}"
|
||||
virtual_network_name = "${azurerm_virtual_network.vnet.name}"
|
||||
address_prefix = "10.1.1.0/24"
|
||||
}
|
||||
|
||||
# Create the NIC for the machine
|
||||
resource "azurerm_network_interface" "nic1" {
|
||||
name = "Inspec-NIC-1"
|
||||
location = "${var.location}"
|
||||
resource_group_name = "${azurerm_resource_group.rg.name}"
|
||||
|
||||
ip_configuration {
|
||||
name = "ipConfiguration1"
|
||||
subnet_id = "${azurerm_subnet.subnet.id}"
|
||||
private_ip_address_allocation = "dynamic"
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_network_interface" "nic2" {
|
||||
name = "Inspec-NIC-2"
|
||||
location = "${var.location}"
|
||||
resource_group_name = "${azurerm_resource_group.rg.name}"
|
||||
|
||||
ip_configuration {
|
||||
name = "ipConfiguration1"
|
||||
subnet_id = "${azurerm_subnet.subnet.id}"
|
||||
private_ip_address_allocation = "dynamic"
|
||||
public_ip_address_id = "${azurerm_public_ip.public_ip_1.id}"
|
||||
}
|
||||
}
|
||||
|
||||
# Create the machine for testing
|
||||
resource "azurerm_virtual_machine" "vm_linux_internal" {
|
||||
name = "Linux-Internal-VM"
|
||||
location = "${var.location}"
|
||||
resource_group_name = "${azurerm_resource_group.rg.name}"
|
||||
network_interface_ids = ["${azurerm_network_interface.nic1.id}"]
|
||||
vm_size = "Standard_DS2_v2"
|
||||
|
||||
# Configure machine with Ubuntu
|
||||
storage_image_reference {
|
||||
publisher = "Canonical"
|
||||
offer = "UbuntuServer"
|
||||
sku = "16.04.0-LTS"
|
||||
version = "latest"
|
||||
}
|
||||
|
||||
# Create the OS disk
|
||||
storage_os_disk {
|
||||
name = "linux-internal-osdisk"
|
||||
vhd_uri = "${azurerm_storage_account.sa.primary_blob_endpoint}${azurerm_storage_container.container.name}/linux-internal-osdisk.vhd"
|
||||
caching = "ReadWrite"
|
||||
create_option = "FromImage"
|
||||
}
|
||||
|
||||
# Create 1 data disk to be used for testing
|
||||
storage_data_disk {
|
||||
name = "linux-datadisk-1"
|
||||
vhd_uri = "${azurerm_storage_account.sa.primary_blob_endpoint}${azurerm_storage_container.container.name}/linux-internal-datadisk-1.vhd"
|
||||
disk_size_gb = 15
|
||||
create_option = "empty"
|
||||
lun = 0
|
||||
}
|
||||
|
||||
# Specify the name of the machine and the access credentials
|
||||
os_profile {
|
||||
computer_name = "linux-internal-1"
|
||||
admin_username = "azure"
|
||||
admin_password = "${var.admin_password}"
|
||||
}
|
||||
|
||||
os_profile_linux_config {
|
||||
disable_password_authentication = false
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_virtual_machine" "vm_linux_external" {
|
||||
name = "Linux-External-VM"
|
||||
location = "${var.location}"
|
||||
resource_group_name = "${azurerm_resource_group.rg.name}"
|
||||
network_interface_ids = ["${azurerm_network_interface.nic2.id}"]
|
||||
vm_size = "Standard_DS2_v2"
|
||||
|
||||
# Configure machine with Ubuntu
|
||||
storage_image_reference {
|
||||
publisher = "Canonical"
|
||||
offer = "UbuntuServer"
|
||||
sku = "16.04.0-LTS"
|
||||
version = "latest"
|
||||
}
|
||||
|
||||
# Create the OS disk
|
||||
storage_os_disk {
|
||||
name = "linux-external-osdisk"
|
||||
vhd_uri = "${azurerm_storage_account.sa.primary_blob_endpoint}${azurerm_storage_container.container.name}/linux-external-osdisk.vhd"
|
||||
caching = "ReadWrite"
|
||||
create_option = "FromImage"
|
||||
}
|
||||
|
||||
# Specify the name of the machine and the access credentials
|
||||
os_profile {
|
||||
computer_name = "linux-external-1"
|
||||
admin_username = "azure"
|
||||
admin_password = "${var.admin_password}"
|
||||
}
|
||||
|
||||
os_profile_linux_config {
|
||||
disable_password_authentication = false
|
||||
}
|
||||
}
|
24
test/integration/azure/verify/controls/datadisks.rb
Normal file
24
test/integration/azure/verify/controls/datadisks.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
title 'Virtual Machine Data Disks'
|
||||
|
||||
control 'azure-vm-datadisks-1.0' do
|
||||
|
||||
impact 1.0
|
||||
title 'Ensure VM has 1 data disk and it is of the correct size'
|
||||
|
||||
# Set the name of the vm and resource_group
|
||||
vm_internal = 'Linux-Internal-VM'
|
||||
resource_group_name = 'Inspec-Azure'
|
||||
|
||||
# Ensure that the named machine has 1 data disk
|
||||
describe azure_vm_datadisks(host: vm_internal, resource_group: resource_group_name) do
|
||||
its('has_disks?') { should be true }
|
||||
its('count') { should eq 1 }
|
||||
end
|
||||
|
||||
# Ensure that the first data disk on the same machine size is greater than 10gb
|
||||
describe azure_vm_datadisks(host: vm_internal, resource_group: resource_group_name).where { disk.zero? and size > 10 } do
|
||||
its('entries') { should_not be_empty }
|
||||
end
|
||||
|
||||
end
|
19
test/integration/azure/verify/controls/resources.rb
Normal file
19
test/integration/azure/verify/controls/resources.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
title 'Check Azure Resources'
|
||||
|
||||
control 'azure-resources-1.0' do
|
||||
|
||||
impact 1.0
|
||||
title 'Check that the resource group has the correct resources'
|
||||
|
||||
# Ensure that the expected resources have been deployed
|
||||
describe azure_rg(name: 'Inspec-Azure') do
|
||||
its('total') { should eq 7 }
|
||||
its('vm_count') { should eq 2 }
|
||||
its('nic_count') { should eq 2 }
|
||||
its('public_ip_count') { should eq 1 }
|
||||
its('sa_count') { should eq 1 }
|
||||
its('vnet_count') { should eq 1 }
|
||||
end
|
||||
|
||||
end
|
24
test/integration/azure/verify/controls/vm.rb
Normal file
24
test/integration/azure/verify/controls/vm.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
title 'Virtual Machine Properties'
|
||||
|
||||
control 'azure-vm-1.0' do
|
||||
|
||||
impact 1.0
|
||||
title 'Ensure 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_vm(host: 'Linux-Internal-VM', resource_group: 'Inspec-Azure') do
|
||||
its('sku') { should eq '16.04.0-LTS' }
|
||||
its('publisher') { should eq 'Canonical' }
|
||||
its('offer') { should eq 'UbuntuServer' }
|
||||
its('size') { should eq 'Standard_DS2_v2' }
|
||||
its('location') { should eq 'westeurope' }
|
||||
its('boot_diagnostics?') { should be false }
|
||||
its('nic_count') { should eq 1 }
|
||||
its('username') { should eq 'azure' }
|
||||
its('password_authentication?') { should be true }
|
||||
its('ssh_key_count') { should eq 0 }
|
||||
its('os_type') { should eq 'Linux' }
|
||||
end
|
||||
|
||||
end
|
4
test/integration/azure/verify/inspec.yml
Normal file
4
test/integration/azure/verify/inspec.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
name: inspec-azure-integration-tests
|
||||
depends:
|
||||
- name: azure
|
||||
path: ../../../
|
Loading…
Reference in a new issue