2015-10-07 21:47:57 +00:00
# encoding: utf-8
# author: Christoph Hartmann
# author: Dominik Richter
require 'utils/convert'
2015-10-26 03:04:18 +00:00
class NetworkInterface < Inspec . resource ( 1 )
2015-10-07 21:47:57 +00:00
name 'interface'
2015-11-27 13:02:38 +00:00
desc 'Use the interface InSpec audit resource to test basic network adapter properties, such as name, status, state, address, and link speed (in MB/sec).'
example "
describe interface ( 'eth0' ) do
it { should exist }
it { should be_up }
its ( :speed ) { should eq 1000 }
end
"
2015-10-07 21:47:57 +00:00
def initialize ( iface )
@iface = iface
2015-10-08 08:06:49 +00:00
@interface_provider = nil
2015-10-26 03:04:18 +00:00
if inspec . os . linux?
@interface_provider = LinuxInterface . new ( inspec )
elsif inspec . os . windows?
@interface_provider = WindowsInterface . new ( inspec )
2015-10-08 08:06:49 +00:00
else
return skip_resource 'The `interface` resource is not supported on your OS yet.'
end
2015-10-07 21:47:57 +00:00
end
def exists?
2015-10-08 10:11:55 +00:00
! interface_info . nil? && ! interface_info [ :name ] . nil?
2015-10-07 21:47:57 +00:00
end
def up?
2015-10-08 10:11:55 +00:00
interface_info . nil? ? false : interface_info [ :up ]
2015-10-07 21:47:57 +00:00
end
2015-10-08 08:06:49 +00:00
# returns link speed in Mbits/sec
2015-10-07 21:47:57 +00:00
def speed
2015-10-08 10:11:55 +00:00
interface_info . nil? ? nil : interface_info [ :speed ]
2015-10-07 21:47:57 +00:00
end
2015-10-12 11:01:58 +00:00
def to_s
" Interface #{ @iface } "
end
2015-10-07 21:47:57 +00:00
private
def interface_info
2015-10-08 10:11:55 +00:00
return @cache if defined? ( @cache )
2015-10-08 08:06:49 +00:00
@cache = @interface_provider . interface_info ( @iface ) if ! @interface_provider . nil?
end
end
class InterfaceInfo
2015-10-08 10:11:55 +00:00
include Converter
2015-10-26 03:04:18 +00:00
attr_reader :inspec
def initialize ( inspec )
@inspec = inspec
2015-10-08 08:06:49 +00:00
end
end
class LinuxInterface < InterfaceInfo
def interface_info ( iface )
2015-10-07 21:47:57 +00:00
# will return "[mtu]\n1500\n[type]\n1"
2015-10-26 03:04:18 +00:00
cmd = inspec . command ( " find /sys/class/net/ #{ iface } / -type f -maxdepth 1 -exec sh -c 'echo \" [$(basename {})] \" ; cat {} || echo -n' \\ ; " )
2015-10-07 21:47:57 +00:00
return nil if cmd . exit_status . to_i != 0
# parse values, we only recieve values, therefore we threat them as keys
2015-10-08 10:11:55 +00:00
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 ,
}
2015-10-07 21:47:57 +00:00
end
end
2015-10-08 11:01:09 +00:00
class WindowsInterface < InterfaceInfo
def interface_info ( iface )
# gather all network interfaces
2015-10-26 03:04:18 +00:00
cmd = inspec . command ( 'Get-NetAdapter | Select-Object -Property Name, InterfaceDescription, Status, State, MacAddress, LinkSpeed, ReceiveLinkSpeed, TransmitLinkSpeed, Virtual | ConvertTo-Json' )
2015-10-08 11:01:09 +00:00
# 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