inspec 0.14.8 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -2
  3. data/bin/inspec +3 -4
  4. data/examples/inheritance/README.md +19 -0
  5. data/examples/inheritance/controls/example.rb +11 -0
  6. data/examples/inheritance/inspec.yml +10 -0
  7. data/lib/bundles/inspec-compliance/cli.rb +1 -4
  8. data/lib/bundles/inspec-supermarket/cli.rb +1 -4
  9. data/lib/inspec/dsl.rb +48 -55
  10. data/lib/inspec/profile.rb +6 -2
  11. data/lib/inspec/profile_context.rb +21 -8
  12. data/lib/inspec/runner.rb +17 -12
  13. data/lib/inspec/runner_rspec.rb +1 -0
  14. data/lib/inspec/version.rb +1 -1
  15. data/lib/resources/apache.rb +20 -18
  16. data/lib/resources/apache_conf.rb +92 -90
  17. data/lib/resources/apt.rb +92 -90
  18. data/lib/resources/audit_policy.rb +35 -33
  19. data/lib/resources/auditd_conf.rb +41 -39
  20. data/lib/resources/auditd_rules.rb +155 -153
  21. data/lib/resources/bond.rb +1 -1
  22. data/lib/resources/bridge.rb +97 -95
  23. data/lib/resources/command.rb +47 -45
  24. data/lib/resources/csv.rb +23 -21
  25. data/lib/resources/directory.rb +1 -1
  26. data/lib/resources/etc_group.rb +116 -114
  27. data/lib/resources/file.rb +1 -1
  28. data/lib/resources/gem.rb +39 -37
  29. data/lib/resources/group.rb +100 -98
  30. data/lib/resources/host.rb +103 -101
  31. data/lib/resources/inetd_conf.rb +42 -40
  32. data/lib/resources/ini.rb +15 -13
  33. data/lib/resources/interface.rb +106 -104
  34. data/lib/resources/iptables.rb +36 -34
  35. data/lib/resources/json.rb +64 -62
  36. data/lib/resources/kernel_module.rb +30 -28
  37. data/lib/resources/kernel_parameter.rb +44 -42
  38. data/lib/resources/limits_conf.rb +41 -39
  39. data/lib/resources/login_def.rb +38 -36
  40. data/lib/resources/mount.rb +43 -41
  41. data/lib/resources/mysql.rb +67 -65
  42. data/lib/resources/mysql_conf.rb +89 -87
  43. data/lib/resources/mysql_session.rb +46 -44
  44. data/lib/resources/npm.rb +35 -33
  45. data/lib/resources/ntp_conf.rb +44 -42
  46. data/lib/resources/oneget.rb +46 -44
  47. data/lib/resources/os.rb +22 -20
  48. data/lib/resources/os_env.rb +47 -45
  49. data/lib/resources/package.rb +213 -211
  50. data/lib/resources/parse_config.rb +59 -57
  51. data/lib/resources/passwd.rb +89 -87
  52. data/lib/resources/pip.rb +60 -58
  53. data/lib/resources/port.rb +352 -350
  54. data/lib/resources/postgres.rb +26 -24
  55. data/lib/resources/postgres_conf.rb +66 -64
  56. data/lib/resources/postgres_session.rb +47 -45
  57. data/lib/resources/processes.rb +56 -54
  58. data/lib/resources/registry_key.rb +150 -148
  59. data/lib/resources/script.rb +30 -28
  60. data/lib/resources/security_policy.rb +56 -54
  61. data/lib/resources/service.rb +638 -636
  62. data/lib/resources/shadow.rb +98 -96
  63. data/lib/resources/ssh_conf.rb +58 -56
  64. data/lib/resources/user.rb +363 -361
  65. data/lib/resources/windows_feature.rb +46 -44
  66. data/lib/resources/xinetd.rb +111 -109
  67. data/lib/resources/yaml.rb +16 -14
  68. data/lib/resources/yum.rb +107 -105
  69. data/lib/utils/base_cli.rb +18 -0
  70. data/test/helper.rb +2 -2
  71. data/test/unit/profile_context_test.rb +1 -1
  72. data/test/unit/resources/file_test.rb +1 -1
  73. data/test/unit/resources/mount_test.rb +1 -1
  74. metadata +5 -2
@@ -17,413 +17,415 @@ require 'utils/parser'
17
17
  #
18
18
  # TODO: currently we return local ip only
19
19
  # TODO: improve handling of same port on multiple interfaces
20
- class Port < Inspec.resource(1)
21
- name 'port'
22
- desc "Use the port InSpec audit resource to test basic port properties, such as port, process, if it's listening."
23
- example "
24
- describe port(80) do
25
- it { should be_listening }
26
- its('protocols') {should eq ['tcp']}
27
- end
28
- "
29
-
30
- def initialize(ip = nil, port) # rubocop:disable OptionalArguments
31
- @ip = ip
32
- @port = port
33
- @port_manager = nil
34
- @cache = nil
35
- os = inspec.os
36
- if os.linux?
37
- @port_manager = LinuxPorts.new(inspec)
38
- elsif %w{darwin aix}.include?(os[:family])
39
- # AIX: see http://www.ibm.com/developerworks/aix/library/au-lsof.html#resources
40
- # and https://www-01.ibm.com/marketing/iwm/iwm/web/reg/pick.do?source=aixbp
41
- # Darwin: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/lsof.8.html
42
- @port_manager = LsofPorts.new(inspec)
43
- elsif os.windows?
44
- @port_manager = WindowsPorts.new(inspec)
45
- elsif ['freebsd'].include?(os[:family])
46
- @port_manager = FreeBsdPorts.new(inspec)
47
- elsif os.solaris?
48
- @port_manager = SolarisPorts.new(inspec)
49
- else
50
- return skip_resource 'The `port` resource is not supported on your OS yet.'
20
+ module Inspec::Resources
21
+ class Port < Inspec.resource(1)
22
+ name 'port'
23
+ desc "Use the port InSpec audit resource to test basic port properties, such as port, process, if it's listening."
24
+ example "
25
+ describe port(80) do
26
+ it { should be_listening }
27
+ its('protocols') {should eq ['tcp']}
28
+ end
29
+ "
30
+
31
+ def initialize(ip = nil, port) # rubocop:disable OptionalArguments
32
+ @ip = ip
33
+ @port = port
34
+ @port_manager = nil
35
+ @cache = nil
36
+ os = inspec.os
37
+ if os.linux?
38
+ @port_manager = LinuxPorts.new(inspec)
39
+ elsif %w{darwin aix}.include?(os[:family])
40
+ # AIX: see http://www.ibm.com/developerworks/aix/library/au-lsof.html#resources
41
+ # and https://www-01.ibm.com/marketing/iwm/iwm/web/reg/pick.do?source=aixbp
42
+ # Darwin: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/lsof.8.html
43
+ @port_manager = LsofPorts.new(inspec)
44
+ elsif os.windows?
45
+ @port_manager = WindowsPorts.new(inspec)
46
+ elsif ['freebsd'].include?(os[:family])
47
+ @port_manager = FreeBsdPorts.new(inspec)
48
+ elsif os.solaris?
49
+ @port_manager = SolarisPorts.new(inspec)
50
+ else
51
+ return skip_resource 'The `port` resource is not supported on your OS yet.'
52
+ end
51
53
  end
52
- end
53
54
 
54
- def listening?(_protocol = nil, _local_address = nil)
55
- info.size > 0
56
- end
55
+ def listening?(_protocol = nil, _local_address = nil)
56
+ info.size > 0
57
+ end
57
58
 
58
- def protocols
59
- res = info.map { |x| x[:protocol] }.uniq.compact
60
- res.size > 0 ? res : nil
61
- end
59
+ def protocols
60
+ res = info.map { |x| x[:protocol] }.uniq.compact
61
+ res.size > 0 ? res : nil
62
+ end
62
63
 
63
- def processes
64
- res = info.map { |x| x[:process] }.uniq.compact
65
- res.size > 0 ? res : nil
66
- end
64
+ def processes
65
+ res = info.map { |x| x[:process] }.uniq.compact
66
+ res.size > 0 ? res : nil
67
+ end
67
68
 
68
- def pids
69
- res = info.map { |x| x[:pid] }.uniq.compact
70
- res.size > 0 ? res : nil
71
- end
69
+ def pids
70
+ res = info.map { |x| x[:pid] }.uniq.compact
71
+ res.size > 0 ? res : nil
72
+ end
72
73
 
73
- def to_s
74
- "Port #{@port}"
75
- end
74
+ def to_s
75
+ "Port #{@port}"
76
+ end
76
77
 
77
- private
78
+ private
78
79
 
79
- def info
80
- return @cache if !@cache.nil?
81
- # abort if os detection has not worked
82
- return @cache = [] if @port_manager.nil?
83
- # query ports
84
- ports = @port_manager.info || []
85
- @cache = ports.select { |p| p[:port] == @port && (!@ip || p[:address] == @ip) }
80
+ def info
81
+ return @cache if !@cache.nil?
82
+ # abort if os detection has not worked
83
+ return @cache = [] if @port_manager.nil?
84
+ # query ports
85
+ ports = @port_manager.info || []
86
+ @cache = ports.select { |p| p[:port] == @port && (!@ip || p[:address] == @ip) }
87
+ end
86
88
  end
87
- end
88
89
 
89
- # implements an info method and returns all ip adresses and protocols for
90
- # each port
91
- # [{
92
- # port: 22,
93
- # address: '0.0.0.0'
94
- # protocol: 'tcp'
95
- # },
96
- # {
97
- # port: 22,
98
- # address: '::'
99
- # protocol: 'tcp6'
100
- # }]
101
- class PortsInfo
102
- attr_reader :inspec
103
- def initialize(inspec)
104
- @inspec = inspec
90
+ # implements an info method and returns all ip adresses and protocols for
91
+ # each port
92
+ # [{
93
+ # port: 22,
94
+ # address: '0.0.0.0'
95
+ # protocol: 'tcp'
96
+ # },
97
+ # {
98
+ # port: 22,
99
+ # address: '::'
100
+ # protocol: 'tcp6'
101
+ # }]
102
+ class PortsInfo
103
+ attr_reader :inspec
104
+ def initialize(inspec)
105
+ @inspec = inspec
106
+ end
105
107
  end
106
- end
107
108
 
108
- # TODO: Add UDP infromation Get-NetUDPEndpoint
109
- # TODO: currently Windows only supports tcp ports
110
- # TODO: Get-NetTCPConnection does not return PIDs
111
- # TODO: double-check output with 'netstat -ano'
112
- # @see https://connect.microsoft.com/PowerShell/feedback/details/1349420/get-nettcpconnection-does-not-show-processid
113
- class WindowsPorts < PortsInfo
114
- def info
115
- # get all port information
116
- cmd = inspec.command('Get-NetTCPConnection | Select-Object -Property State, Caption, Description, LocalAddress, LocalPort, RemoteAddress, RemotePort, DisplayName, Status | ConvertTo-Json')
117
-
118
- begin
119
- ports = JSON.parse(cmd.stdout)
120
- rescue JSON::ParserError => _e
121
- return nil
122
- end
109
+ # TODO: Add UDP infromation Get-NetUDPEndpoint
110
+ # TODO: currently Windows only supports tcp ports
111
+ # TODO: Get-NetTCPConnection does not return PIDs
112
+ # TODO: double-check output with 'netstat -ano'
113
+ # @see https://connect.microsoft.com/PowerShell/feedback/details/1349420/get-nettcpconnection-does-not-show-processid
114
+ class WindowsPorts < PortsInfo
115
+ def info
116
+ # get all port information
117
+ cmd = inspec.command('Get-NetTCPConnection | Select-Object -Property State, Caption, Description, LocalAddress, LocalPort, RemoteAddress, RemotePort, DisplayName, Status | ConvertTo-Json')
118
+
119
+ begin
120
+ ports = JSON.parse(cmd.stdout)
121
+ rescue JSON::ParserError => _e
122
+ return nil
123
+ end
123
124
 
124
- return nil if ports.nil?
125
+ return nil if ports.nil?
125
126
 
126
- ports.map { |x|
127
- {
128
- port: x['LocalPort'],
129
- address: x['LocalAddress'],
130
- protocol: 'tcp',
131
- process: nil,
132
- pid: nil,
127
+ ports.map { |x|
128
+ {
129
+ port: x['LocalPort'],
130
+ address: x['LocalAddress'],
131
+ protocol: 'tcp',
132
+ process: nil,
133
+ pid: nil,
134
+ }
133
135
  }
134
- }
136
+ end
135
137
  end
136
- end
137
-
138
- # extracts udp and tcp ports from the lsof command
139
- class LsofPorts < PortsInfo
140
- attr_reader :lsof
141
138
 
142
- def initialize(inspec, lsofpath = nil)
143
- @lsof = lsofpath || 'lsof'
144
- super(inspec)
145
- end
139
+ # extracts udp and tcp ports from the lsof command
140
+ class LsofPorts < PortsInfo
141
+ attr_reader :lsof
146
142
 
147
- def info
148
- ports = []
149
-
150
- # check that lsof is available, otherwise fail
151
- fail 'Please ensure `lsof` is available on the machine.' if !inspec.command(@lsof.to_s).exist?
152
-
153
- # -F p=pid, c=command, P=protocol name, t=type, n=internet addresses
154
- # see 'OUTPUT FOR OTHER PROGRAMS' in LSOF(8)
155
- lsof_cmd = inspec.command("#{@lsof} -nP -i -FpctPn")
156
- return nil if lsof_cmd.exit_status.to_i != 0
157
-
158
- # map to desired return struct
159
- lsof_parser(lsof_cmd).each do |process, port_ids|
160
- pid, cmd = process.split(':')
161
- port_ids.each do |port_str|
162
- # should not break on ipv6 addresses
163
- ipv, proto, port, host = port_str.split(':', 4)
164
- ports.push({ port: port.to_i,
165
- address: host,
166
- protocol: ipv == 'ipv6' ? proto + '6' : proto,
167
- process: cmd,
168
- pid: pid.to_i })
169
- end
143
+ def initialize(inspec, lsofpath = nil)
144
+ @lsof = lsofpath || 'lsof'
145
+ super(inspec)
170
146
  end
171
147
 
172
- ports
173
- end
174
-
175
- # rubocop:disable Metrics/CyclomaticComplexity
176
- # rubocop:disable Metrics/AbcSize
177
- def lsof_parser(lsof_cmd)
178
- procs = {}
179
- # build this with formatted output (-F) from lsof
180
- # procs = {
181
- # '123:sshd' => [
182
- # 'ipv4:tcp:22:127.0.0.1',
183
- # 'ipv6:tcp:22:::1',
184
- # 'ipv4:tcp:*',
185
- # 'ipv6:tcp:*',
186
- # ],
187
- # '456:ntpd' => [
188
- # 'ipv4:udp:123:*',
189
- # 'ipv6:udp:123:*',
190
- # ]
191
- # }
192
- proc_id = port_id = nil
193
- lsof_cmd.stdout.each_line do |line|
194
- line.chomp!
195
- key = line.slice!(0)
196
- case key
197
- when 'p'
198
- proc_id = line
199
- port_id = nil
200
- when 'c'
201
- proc_id += ':' + line
202
- when 't'
203
- port_id = line.downcase
204
- when 'P'
205
- port_id += ':' + line.downcase
206
- when 'n'
207
- src, dst = line.split('->')
208
-
209
- # skip active comm streams
210
- next if dst
211
-
212
- host, port = /^(\S+):(\d+|\*)$/.match(src)[1, 2]
213
-
214
- # skip channels from port 0 - what does this mean?
215
- next if port == '*'
216
-
217
- # create new array stub if !exist?
218
- procs[proc_id] = [] unless procs.key?(proc_id)
219
-
220
- # change address '*' to zero
221
- host = (port_id =~ /^ipv6:/) ? '[::]' : '0.0.0.0' if host == '*'
222
- # entrust URI to scrub the host and port
223
- begin
224
- uri = URI("addr://#{host}:#{port}")
225
- uri.host && uri.port
226
- rescue => e
227
- warn "could not parse URI 'addr://#{host}:#{port}' - #{e}"
228
- next
148
+ def info
149
+ ports = []
150
+
151
+ # check that lsof is available, otherwise fail
152
+ fail 'Please ensure `lsof` is available on the machine.' if !inspec.command(@lsof.to_s).exist?
153
+
154
+ # -F p=pid, c=command, P=protocol name, t=type, n=internet addresses
155
+ # see 'OUTPUT FOR OTHER PROGRAMS' in LSOF(8)
156
+ lsof_cmd = inspec.command("#{@lsof} -nP -i -FpctPn")
157
+ return nil if lsof_cmd.exit_status.to_i != 0
158
+
159
+ # map to desired return struct
160
+ lsof_parser(lsof_cmd).each do |process, port_ids|
161
+ pid, cmd = process.split(':')
162
+ port_ids.each do |port_str|
163
+ # should not break on ipv6 addresses
164
+ ipv, proto, port, host = port_str.split(':', 4)
165
+ ports.push({ port: port.to_i,
166
+ address: host,
167
+ protocol: ipv == 'ipv6' ? proto + '6' : proto,
168
+ process: cmd,
169
+ pid: pid.to_i })
229
170
  end
171
+ end
230
172
 
231
- # e.g. 'ipv4:tcp:22:127.0.0.1'
232
- # strip ipv6 squares for inspec
233
- port_id += ':' + port + ':' + host.gsub(/^\[|\]$/, '')
173
+ ports
174
+ end
234
175
 
235
- # lsof will give us another port unless it's done
236
- procs[proc_id] << port_id
176
+ # rubocop:disable Metrics/CyclomaticComplexity
177
+ # rubocop:disable Metrics/AbcSize
178
+ def lsof_parser(lsof_cmd)
179
+ procs = {}
180
+ # build this with formatted output (-F) from lsof
181
+ # procs = {
182
+ # '123:sshd' => [
183
+ # 'ipv4:tcp:22:127.0.0.1',
184
+ # 'ipv6:tcp:22:::1',
185
+ # 'ipv4:tcp:*',
186
+ # 'ipv6:tcp:*',
187
+ # ],
188
+ # '456:ntpd' => [
189
+ # 'ipv4:udp:123:*',
190
+ # 'ipv6:udp:123:*',
191
+ # ]
192
+ # }
193
+ proc_id = port_id = nil
194
+ lsof_cmd.stdout.each_line do |line|
195
+ line.chomp!
196
+ key = line.slice!(0)
197
+ case key
198
+ when 'p'
199
+ proc_id = line
200
+ port_id = nil
201
+ when 'c'
202
+ proc_id += ':' + line
203
+ when 't'
204
+ port_id = line.downcase
205
+ when 'P'
206
+ port_id += ':' + line.downcase
207
+ when 'n'
208
+ src, dst = line.split('->')
209
+
210
+ # skip active comm streams
211
+ next if dst
212
+
213
+ host, port = /^(\S+):(\d+|\*)$/.match(src)[1, 2]
214
+
215
+ # skip channels from port 0 - what does this mean?
216
+ next if port == '*'
217
+
218
+ # create new array stub if !exist?
219
+ procs[proc_id] = [] unless procs.key?(proc_id)
220
+
221
+ # change address '*' to zero
222
+ host = (port_id =~ /^ipv6:/) ? '[::]' : '0.0.0.0' if host == '*'
223
+ # entrust URI to scrub the host and port
224
+ begin
225
+ uri = URI("addr://#{host}:#{port}")
226
+ uri.host && uri.port
227
+ rescue => e
228
+ warn "could not parse URI 'addr://#{host}:#{port}' - #{e}"
229
+ next
230
+ end
231
+
232
+ # e.g. 'ipv4:tcp:22:127.0.0.1'
233
+ # strip ipv6 squares for inspec
234
+ port_id += ':' + port + ':' + host.gsub(/^\[|\]$/, '')
235
+
236
+ # lsof will give us another port unless it's done
237
+ procs[proc_id] << port_id
238
+ end
237
239
  end
238
- end
239
240
 
240
- procs
241
+ procs
242
+ end
241
243
  end
242
- end
243
244
 
244
- # extract port information from netstat
245
- class LinuxPorts < PortsInfo
246
- def info
247
- cmd = inspec.command('netstat -tulpen')
248
- return nil if cmd.exit_status.to_i != 0
245
+ # extract port information from netstat
246
+ class LinuxPorts < PortsInfo
247
+ def info
248
+ cmd = inspec.command('netstat -tulpen')
249
+ return nil if cmd.exit_status.to_i != 0
249
250
 
250
- ports = []
251
- # parse all lines
252
- cmd.stdout.each_line do |line|
253
- port_info = parse_netstat_line(line)
251
+ ports = []
252
+ # parse all lines
253
+ cmd.stdout.each_line do |line|
254
+ port_info = parse_netstat_line(line)
254
255
 
255
- # only push protocols we are interested in
256
- next unless %w{tcp tcp6 udp udp6}.include?(port_info[:protocol])
257
- ports.push(port_info)
256
+ # only push protocols we are interested in
257
+ next unless %w{tcp tcp6 udp udp6}.include?(port_info[:protocol])
258
+ ports.push(port_info)
259
+ end
260
+ ports
258
261
  end
259
- ports
260
- end
261
262
 
262
- def parse_net_address(net_addr, protocol)
263
- if protocol.eql?('tcp6') || protocol.eql?('udp6')
264
- # prep for URI parsing, parse ip6 port
265
- ip6 = /^(\S+):(\d+)$/.match(net_addr)
266
- ip6addr = ip6[1]
267
- ip6addr = '::' if ip6addr =~ /^:::$/
268
- # build uri
269
- ip_addr = URI("addr://[#{ip6addr}]:#{ip6[2]}")
270
- # replace []
271
- host = ip_addr.host[1..ip_addr.host.size-2]
272
- else
273
- ip_addr = URI('addr://'+net_addr)
274
- host = ip_addr.host
275
- end
263
+ def parse_net_address(net_addr, protocol)
264
+ if protocol.eql?('tcp6') || protocol.eql?('udp6')
265
+ # prep for URI parsing, parse ip6 port
266
+ ip6 = /^(\S+):(\d+)$/.match(net_addr)
267
+ ip6addr = ip6[1]
268
+ ip6addr = '::' if ip6addr =~ /^:::$/
269
+ # build uri
270
+ ip_addr = URI("addr://[#{ip6addr}]:#{ip6[2]}")
271
+ # replace []
272
+ host = ip_addr.host[1..ip_addr.host.size-2]
273
+ else
274
+ ip_addr = URI('addr://'+net_addr)
275
+ host = ip_addr.host
276
+ end
276
277
 
277
- port = ip_addr.port
278
+ port = ip_addr.port
278
279
 
279
- [host, port]
280
- rescue URI::InvalidURIError => e
281
- warn "Could not parse #{net_addr}, #{e}"
282
- nil
283
- end
280
+ [host, port]
281
+ rescue URI::InvalidURIError => e
282
+ warn "Could not parse #{net_addr}, #{e}"
283
+ nil
284
+ end
284
285
 
285
- def parse_netstat_line(line)
286
- # parse each line
287
- # 1 - Proto, 2 - Recv-Q, 3 - Send-Q, 4 - Local Address, 5 - Foreign Address, 6 - State, 7 - Inode, 8 - PID/Program name
288
- parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)?\s+(\S+)\s+(\S+)\s+(\S+)/.match(line)
286
+ def parse_netstat_line(line)
287
+ # parse each line
288
+ # 1 - Proto, 2 - Recv-Q, 3 - Send-Q, 4 - Local Address, 5 - Foreign Address, 6 - State, 7 - Inode, 8 - PID/Program name
289
+ parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)?\s+(\S+)\s+(\S+)\s+(\S+)/.match(line)
289
290
 
290
- return {} if parsed.nil? || line.match(/^proto/i)
291
+ return {} if parsed.nil? || line.match(/^proto/i)
291
292
 
292
- # parse ip4 and ip6 addresses
293
- protocol = parsed[1].downcase
293
+ # parse ip4 and ip6 addresses
294
+ protocol = parsed[1].downcase
294
295
 
295
- # detect protocol if not provided
296
- protocol += '6' if parsed[4].count(':') > 1 && %w{tcp udp}.include?(protocol)
296
+ # detect protocol if not provided
297
+ protocol += '6' if parsed[4].count(':') > 1 && %w{tcp udp}.include?(protocol)
297
298
 
298
- # extract host and port information
299
- host, port = parse_net_address(parsed[4], protocol)
299
+ # extract host and port information
300
+ host, port = parse_net_address(parsed[4], protocol)
300
301
 
301
- # extract PID
302
- process = parsed[9].split('/')
303
- pid = process[0]
304
- pid = pid.to_i if pid =~ /^\d+$/
305
- process = process[1]
302
+ # extract PID
303
+ process = parsed[9].split('/')
304
+ pid = process[0]
305
+ pid = pid.to_i if pid =~ /^\d+$/
306
+ process = process[1]
306
307
 
307
- # map data
308
- {
309
- port: port,
310
- address: host,
311
- protocol: protocol,
312
- process: process,
313
- pid: pid,
314
- }
308
+ # map data
309
+ {
310
+ port: port,
311
+ address: host,
312
+ protocol: protocol,
313
+ process: process,
314
+ pid: pid,
315
+ }
316
+ end
315
317
  end
316
- end
317
318
 
318
- # extracts information from sockstat
319
- class FreeBsdPorts < PortsInfo
320
- def info
321
- cmd = inspec.command('sockstat -46l')
322
- return nil if cmd.exit_status.to_i != 0
319
+ # extracts information from sockstat
320
+ class FreeBsdPorts < PortsInfo
321
+ def info
322
+ cmd = inspec.command('sockstat -46l')
323
+ return nil if cmd.exit_status.to_i != 0
323
324
 
324
- ports = []
325
- # split on each newline
326
- cmd.stdout.each_line do |line|
327
- port_info = parse_sockstat_line(line)
325
+ ports = []
326
+ # split on each newline
327
+ cmd.stdout.each_line do |line|
328
+ port_info = parse_sockstat_line(line)
328
329
 
329
- # push data, if not headerfile
330
- next unless %w{tcp tcp6 udp udp6}.include?(port_info[:protocol])
331
- ports.push(port_info)
330
+ # push data, if not headerfile
331
+ next unless %w{tcp tcp6 udp udp6}.include?(port_info[:protocol])
332
+ ports.push(port_info)
333
+ end
334
+ ports
332
335
  end
333
- ports
334
- end
335
336
 
336
- def parse_net_address(net_addr, protocol)
337
- case protocol
338
- when 'tcp4', 'udp4', 'tcp', 'udp'
339
- # replace * with 0.0.0.0
340
- net_addr = net_addr.gsub(/^\*:/, '0.0.0.0:') if net_addr =~ /^*:(\d+)$/
341
- ip_addr = URI('addr://'+net_addr)
342
- host = ip_addr.host
343
- port = ip_addr.port
344
- when 'tcp6', 'udp6'
345
- return [] if net_addr == '*:*' # abort for now
346
- # replace * with 0:0:0:0:0:0:0:0
347
- net_addr = net_addr.gsub(/^\*:/, '0:0:0:0:0:0:0:0:') if net_addr =~ /^*:(\d+)$/
348
- # extract port
349
- ip6 = /^(\S+):(\d+)$/.match(net_addr)
350
- ip6addr = ip6[1]
351
- ip_addr = URI("addr://[#{ip6addr}]:#{ip6[2]}")
352
- # replace []
353
- host = ip_addr.host[1..ip_addr.host.size-2]
354
- port = ip_addr.port
337
+ def parse_net_address(net_addr, protocol)
338
+ case protocol
339
+ when 'tcp4', 'udp4', 'tcp', 'udp'
340
+ # replace * with 0.0.0.0
341
+ net_addr = net_addr.gsub(/^\*:/, '0.0.0.0:') if net_addr =~ /^*:(\d+)$/
342
+ ip_addr = URI('addr://'+net_addr)
343
+ host = ip_addr.host
344
+ port = ip_addr.port
345
+ when 'tcp6', 'udp6'
346
+ return [] if net_addr == '*:*' # abort for now
347
+ # replace * with 0:0:0:0:0:0:0:0
348
+ net_addr = net_addr.gsub(/^\*:/, '0:0:0:0:0:0:0:0:') if net_addr =~ /^*:(\d+)$/
349
+ # extract port
350
+ ip6 = /^(\S+):(\d+)$/.match(net_addr)
351
+ ip6addr = ip6[1]
352
+ ip_addr = URI("addr://[#{ip6addr}]:#{ip6[2]}")
353
+ # replace []
354
+ host = ip_addr.host[1..ip_addr.host.size-2]
355
+ port = ip_addr.port
356
+ end
357
+ [host, port]
358
+ rescue URI::InvalidURIError => e
359
+ warn "Could not parse #{net_addr}, #{e}"
360
+ nil
355
361
  end
356
- [host, port]
357
- rescue URI::InvalidURIError => e
358
- warn "Could not parse #{net_addr}, #{e}"
359
- nil
360
- end
361
-
362
- def parse_sockstat_line(line)
363
- # 1 - USER, 2 - COMMAND, 3 - PID, 4 - FD 5 - PROTO, 6 - LOCAL ADDRESS, 7 - FOREIGN ADDRESS
364
- parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/.match(line)
365
- return {} if parsed.nil?
366
-
367
- # extract ip information
368
- protocol = parsed[5].downcase
369
- host, port = parse_net_address(parsed[6], protocol)
370
- return {} if host.nil? or port.nil?
371
-
372
- # extract process
373
- process = parsed[2]
374
-
375
- # extract PID
376
- pid = parsed[3]
377
- pid = pid.to_i if pid =~ /^\d+$/
378
-
379
- # map tcp4 and udp4
380
- protocol = 'tcp' if protocol.eql?('tcp4')
381
- protocol = 'udp' if protocol.eql?('udp4')
382
-
383
- # map data
384
- {
385
- port: port,
386
- address: host,
387
- protocol: protocol,
388
- process: process,
389
- pid: pid,
390
- }
391
- end
392
- end
393
362
 
394
- class SolarisPorts < FreeBsdPorts
395
- include SolarisNetstatParser
363
+ def parse_sockstat_line(line)
364
+ # 1 - USER, 2 - COMMAND, 3 - PID, 4 - FD 5 - PROTO, 6 - LOCAL ADDRESS, 7 - FOREIGN ADDRESS
365
+ parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/.match(line)
366
+ return {} if parsed.nil?
396
367
 
397
- def info
398
- # extract all port info
399
- cmd = inspec.command('netstat -an -f inet -f inet6')
400
- return nil if cmd.exit_status.to_i != 0
368
+ # extract ip information
369
+ protocol = parsed[5].downcase
370
+ host, port = parse_net_address(parsed[6], protocol)
371
+ return {} if host.nil? or port.nil?
401
372
 
402
- # parse the content
403
- netstat_ports = parse_netstat(cmd.stdout)
373
+ # extract process
374
+ process = parsed[2]
404
375
 
405
- # filter all ports, where we listen
406
- listen = netstat_ports.select { |val|
407
- !val['state'].nil? && 'listen'.casecmp(val['state']) == 0
408
- }
376
+ # extract PID
377
+ pid = parsed[3]
378
+ pid = pid.to_i if pid =~ /^\d+$/
409
379
 
410
- # map the data
411
- ports = listen.map { |val|
412
- protocol = val['protocol']
413
- local_addr = val['local-address']
380
+ # map tcp4 and udp4
381
+ protocol = 'tcp' if protocol.eql?('tcp4')
382
+ protocol = 'udp' if protocol.eql?('udp4')
414
383
 
415
- # solaris uses 127.0.0.1.57455 instead 127.0.0.1:57455, lets convert the
416
- # the last . to :
417
- local_addr[local_addr.rindex('.')] = ':'
418
- host, port = parse_net_address(local_addr, protocol)
384
+ # map data
419
385
  {
420
386
  port: port,
421
387
  address: host,
422
388
  protocol: protocol,
423
- process: nil, # we do not have pid on solaris
424
- pid: nil, # we do not have pid on solaris
389
+ process: process,
390
+ pid: pid,
391
+ }
392
+ end
393
+ end
394
+
395
+ class SolarisPorts < FreeBsdPorts
396
+ include SolarisNetstatParser
397
+
398
+ def info
399
+ # extract all port info
400
+ cmd = inspec.command('netstat -an -f inet -f inet6')
401
+ return nil if cmd.exit_status.to_i != 0
402
+
403
+ # parse the content
404
+ netstat_ports = parse_netstat(cmd.stdout)
405
+
406
+ # filter all ports, where we listen
407
+ listen = netstat_ports.select { |val|
408
+ !val['state'].nil? && 'listen'.casecmp(val['state']) == 0
409
+ }
410
+
411
+ # map the data
412
+ ports = listen.map { |val|
413
+ protocol = val['protocol']
414
+ local_addr = val['local-address']
415
+
416
+ # solaris uses 127.0.0.1.57455 instead 127.0.0.1:57455, lets convert the
417
+ # the last . to :
418
+ local_addr[local_addr.rindex('.')] = ':'
419
+ host, port = parse_net_address(local_addr, protocol)
420
+ {
421
+ port: port,
422
+ address: host,
423
+ protocol: protocol,
424
+ process: nil, # we do not have pid on solaris
425
+ pid: nil, # we do not have pid on solaris
426
+ }
425
427
  }
426
- }
427
- ports
428
+ ports
429
+ end
428
430
  end
429
431
  end