mirror of
https://github.com/inspec/inspec
synced 2024-11-27 23:20:33 +00:00
Merge pull request #94 from chef/interface
Merged change ff4b5b58-4dbe-4acd-8a36-8f11e1a7db0d From review branch interface into master Signed-off-by: drichter <drichter@chef.io>
This commit is contained in:
commit
6799af8ce5
6 changed files with 222 additions and 3 deletions
122
lib/resources/interface.rb
Normal file
122
lib/resources/interface.rb
Normal file
|
@ -0,0 +1,122 @@
|
|||
# encoding: utf-8
|
||||
# author: Christoph Hartmann
|
||||
# author: Dominik Richter
|
||||
|
||||
# Usage:
|
||||
# describe interface('eth0') do
|
||||
# it { should exist }
|
||||
# it { should be_up }
|
||||
# its(:speed) { should eq 1000 }
|
||||
# end
|
||||
|
||||
require 'utils/convert'
|
||||
|
||||
class NetworkInterface < Vulcano.resource(1)
|
||||
name 'interface'
|
||||
|
||||
def initialize(iface)
|
||||
@iface = iface
|
||||
|
||||
@interface_provider = nil
|
||||
if vulcano.os.linux?
|
||||
@interface_provider = LinuxInterface.new(vulcano)
|
||||
elsif vulcano.os.windows?
|
||||
@interface_provider = WindowsInterface.new(vulcano)
|
||||
else
|
||||
return skip_resource 'The `interface` resource is not supported on your OS yet.'
|
||||
end
|
||||
end
|
||||
|
||||
def exists?
|
||||
!interface_info.nil? && !interface_info[:name].nil?
|
||||
end
|
||||
|
||||
def up?
|
||||
interface_info.nil? ? false : interface_info[:up]
|
||||
end
|
||||
|
||||
# returns link speed in Mbits/sec
|
||||
def speed
|
||||
interface_info.nil? ? nil : interface_info[:speed]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def interface_info
|
||||
return @cache if defined?(@cache)
|
||||
@cache = @interface_provider.interface_info(@iface) if !@interface_provider.nil?
|
||||
end
|
||||
end
|
||||
|
||||
class InterfaceInfo
|
||||
include Converter
|
||||
def initialize(vulcano)
|
||||
@vulcano = vulcano
|
||||
end
|
||||
end
|
||||
|
||||
class LinuxInterface < InterfaceInfo
|
||||
def interface_info(iface)
|
||||
# will return "[mtu]\n1500\n[type]\n1"
|
||||
cmd = @vulcano.command("find /sys/class/net/#{iface}/ -type f -maxdepth 1 -exec sh -c 'echo \"[$(basename {})]\"; cat {} || echo -n' \\;")
|
||||
return nil if cmd.exit_status.to_i != 0
|
||||
|
||||
# parse values, we only recieve values, therefore we threat them as keys
|
||||
params = SimpleConfig.new(cmd.stdout.chomp).params
|
||||
|
||||
# abort if we got an empty result-set
|
||||
return nil if params.empty?
|
||||
|
||||
# parse state
|
||||
state = false
|
||||
if params.key?('operstate')
|
||||
operstate, _value = params['operstate'].first
|
||||
state = operstate == 'up'
|
||||
end
|
||||
|
||||
# parse speed
|
||||
speed = nil
|
||||
if params.key?('speed')
|
||||
speed, _value = params['speed'].first
|
||||
speed = convert_to_i(speed)
|
||||
end
|
||||
|
||||
{
|
||||
name: iface,
|
||||
up: state,
|
||||
speed: speed,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
class WindowsInterface < InterfaceInfo
|
||||
def interface_info(iface)
|
||||
# gather all network interfaces
|
||||
cmd = @vulcano.command('Get-NetAdapter | Select-Object -Property Name, InterfaceDescription, Status, State, MacAddress, LinkSpeed, ReceiveLinkSpeed, TransmitLinkSpeed, Virtual | ConvertTo-Json')
|
||||
|
||||
# filter network interface
|
||||
begin
|
||||
net_adapter = JSON.parse(cmd.stdout)
|
||||
rescue JSON::ParserError => _e
|
||||
return nil
|
||||
end
|
||||
|
||||
# ensure we have an array of groups
|
||||
net_adapter = [net_adapter] if !net_adapter.is_a?(Array)
|
||||
|
||||
# select the requested interface
|
||||
adapters = net_adapter.each_with_object([]) do |adapter, adapter_collection|
|
||||
# map object
|
||||
info = {
|
||||
name: adapter['Name'],
|
||||
up: adapter['State'] == 2,
|
||||
speed: adapter['ReceiveLinkSpeed'] / 1000,
|
||||
}
|
||||
adapter_collection.push(info) if info[:name].casecmp(iface) == 0
|
||||
end
|
||||
|
||||
return nil if adapters.size == 0
|
||||
warn "[Possible Error] detected multiple network interfaces with the name #{iface}" if adapters.size > 1
|
||||
adapters[0]
|
||||
end
|
||||
end
|
|
@ -34,6 +34,7 @@ require 'resources/gem'
|
|||
require 'resources/group'
|
||||
require 'resources/group_policy'
|
||||
require 'resources/inetd_conf'
|
||||
require 'resources/interface'
|
||||
require 'resources/json'
|
||||
require 'resources/kernel_module'
|
||||
require 'resources/kernel_parameter'
|
||||
|
|
|
@ -79,6 +79,11 @@ class MockLoader
|
|||
stdout = ::File.read(::File.join(scriptpath, '/unit/mock/cmd/'+x))
|
||||
mock.mock_command(stdout, '', 0)
|
||||
}
|
||||
|
||||
empty = lambda {
|
||||
mock.mock_command('', '', 0)
|
||||
}
|
||||
|
||||
mock.commands = {
|
||||
'ps aux' => cmd.call('ps-aux'),
|
||||
'type win_secpol.cfg' => cmd.call('secedit-export'),
|
||||
|
@ -124,12 +129,12 @@ class MockLoader
|
|||
'service sendmail onestatus' => cmd.call('service-sendmail-onestatus'),
|
||||
# services for system 5 e.g. centos6, debian 6
|
||||
'service sshd status' => cmd.call('service-sshd-status'),
|
||||
'find /etc/rc*.d -name S*' => cmd.call('find-etc-rc-d-name-S'),
|
||||
'find /etc/rc*.d -name S*' => cmd.call('find-etc-rc-d-name-S'),
|
||||
'ls -1 /etc/init.d/' => cmd.call('ls-1-etc-init.d'),
|
||||
# user information for linux
|
||||
'id root' => cmd.call('id-root'),
|
||||
'getent passwd root' => cmd.call('getent-passwd-root'),
|
||||
'chage -l root' => cmd.call('chage-l-root'),
|
||||
'chage -l root' => cmd.call('chage-l-root'),
|
||||
# user info for mac
|
||||
'id chartmann' => cmd.call('id-chartmann'),
|
||||
'dscl -q . -read /Users/chartmann NFSHomeDirectory PrimaryGroupID RecordName UniqueID UserShell' => cmd.call('dscl'),
|
||||
|
@ -138,7 +143,11 @@ class MockLoader
|
|||
# user info for windows
|
||||
'650b6b72a66316418b25421a54afe21a230704558082914c54711904bb10e370' => cmd.call('GetUserAccount'),
|
||||
# group info for windows
|
||||
'Get-WmiObject Win32_Group | Select-Object -Property Caption, Domain, Name, SID, LocalAccount | ConvertTo-Json' => cmd.call('GetWin32Group'),
|
||||
'Get-WmiObject Win32_Group | Select-Object -Property Caption, Domain, Name, SID, LocalAccount | ConvertTo-Json' => cmd.call('GetWin32Group'),
|
||||
# network interface
|
||||
'9e80f048a1af5a0f6ab8a465e46ea5ed5ba6587e9b5e54a7a0c0a1a02bb6f663' => cmd.call('find-net-interface'),
|
||||
'c33821dece09c8b334e03a5bb9daefdf622007f73af4932605e758506584ec3f' => empty.call,
|
||||
'Get-NetAdapter | Select-Object -Property Name, InterfaceDescription, Status, State, MacAddress, LinkSpeed, ReceiveLinkSpeed, TransmitLinkSpeed, Virtual | ConvertTo-Json' => cmd.call('Get-NetAdapter'),
|
||||
}
|
||||
|
||||
# set os emulation
|
||||
|
|
24
test/unit/mock/cmd/Get-NetAdapter
Normal file
24
test/unit/mock/cmd/Get-NetAdapter
Normal file
|
@ -0,0 +1,24 @@
|
|||
[
|
||||
{
|
||||
"Name": "vEthernet (Intel(R) PRO 1000 MT Network Connection - Virtual Switch)",
|
||||
"InterfaceDescription": "Hyper-V Virtual Ethernet Adapter #2",
|
||||
"Status": "Up",
|
||||
"State": 2,
|
||||
"MacAddress": "00-0C-29-E3-48-9B",
|
||||
"LinkSpeed": "10 Gbps",
|
||||
"ReceiveLinkSpeed": 10000000000,
|
||||
"TransmitLinkSpeed": 10000000000,
|
||||
"Virtual": true
|
||||
},
|
||||
{
|
||||
"Name": "Ethernet0",
|
||||
"InterfaceDescription": "Intel(R) PRO/1000 MT Network Connection",
|
||||
"Status": "Not Present",
|
||||
"State": 3,
|
||||
"MacAddress": "00-0C-29-E3-48-9B",
|
||||
"LinkSpeed": "0 bps",
|
||||
"ReceiveLinkSpeed": 0,
|
||||
"TransmitLinkSpeed": 0,
|
||||
"Virtual": false
|
||||
}
|
||||
]
|
9
test/unit/mock/cmd/find-net-interface
Normal file
9
test/unit/mock/cmd/find-net-interface
Normal file
|
@ -0,0 +1,9 @@
|
|||
[speed]
|
||||
10000
|
||||
[phys_switch_id]
|
||||
[duplex]
|
||||
full
|
||||
[address]
|
||||
02:42:ac:11:00:11
|
||||
[operstate]
|
||||
up
|
54
test/unit/resource_interface_test.rb
Normal file
54
test/unit/resource_interface_test.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
# encoding: utf-8
|
||||
# author: Christoph Hartmann
|
||||
# author: Dominik Richter
|
||||
|
||||
require 'helper'
|
||||
require 'vulcano/resource'
|
||||
|
||||
describe 'Vulcano::Resources::Group' do
|
||||
|
||||
# ubuntu 14.04
|
||||
it 'verify interface on ubuntu' do
|
||||
resource = MockLoader.new(:ubuntu1404).load_resource('interface', 'eth0')
|
||||
_(resource.exists?).must_equal true
|
||||
_(resource.up?).must_equal true
|
||||
_(resource.speed).must_equal 10000
|
||||
end
|
||||
|
||||
it 'verify invalid interface on ubuntu' do
|
||||
resource = MockLoader.new(:ubuntu1404).load_resource('interface', 'eth1')
|
||||
_(resource.exists?).must_equal false
|
||||
_(resource.up?).must_equal false
|
||||
_(resource.speed).must_equal nil
|
||||
end
|
||||
|
||||
it 'verify interface on windows' do
|
||||
resource = MockLoader.new(:windows).load_resource('interface', 'ethernet0')
|
||||
_(resource.exists?).must_equal true
|
||||
_(resource.up?).must_equal false
|
||||
_(resource.speed).must_equal 0
|
||||
end
|
||||
|
||||
it 'verify interface on windows' do
|
||||
resource = MockLoader.new(:windows).load_resource('interface', 'vEthernet (Intel(R) PRO 1000 MT Network Connection - Virtual Switch)')
|
||||
_(resource.exists?).must_equal true
|
||||
_(resource.up?).must_equal true
|
||||
_(resource.speed).must_equal 10000000
|
||||
end
|
||||
|
||||
it 'verify invalid interface on windows' do
|
||||
resource = MockLoader.new(:windows).load_resource('interface', 'eth1')
|
||||
_(resource.exists?).must_equal false
|
||||
_(resource.up?).must_equal false
|
||||
_(resource.speed).must_equal nil
|
||||
end
|
||||
|
||||
# undefined
|
||||
it 'verify interface on unsupported os' do
|
||||
resource = MockLoader.new(:undefined).load_resource('interface', 'eth0')
|
||||
_(resource.exists?).must_equal false
|
||||
_(resource.up?).must_equal false
|
||||
_(resource.speed).must_equal nil
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in a new issue