Class: Inspec::Resources::LsofPorts
- Defined in:
- lib/resources/port.rb
Overview
extracts udp and tcp ports from the lsof command
Instance Attribute Summary collapse
-
#lsof ⇒ Object
readonly
Returns the value of attribute lsof.
Attributes inherited from PortsInfo
Instance Method Summary collapse
- #info ⇒ Object
-
#initialize(inspec, lsofpath = nil) ⇒ LsofPorts
constructor
A new instance of LsofPorts.
-
#lsof_parser(lsof_cmd) ⇒ Object
rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/AbcSize.
Constructor Details
#initialize(inspec, lsofpath = nil) ⇒ LsofPorts
Returns a new instance of LsofPorts.
166 167 168 169 |
# File 'lib/resources/port.rb', line 166 def initialize(inspec, lsofpath = nil) @lsof = lsofpath || 'lsof' super(inspec) end |
Instance Attribute Details
#lsof ⇒ Object (readonly)
Returns the value of attribute lsof.
164 165 166 |
# File 'lib/resources/port.rb', line 164 def lsof @lsof end |
Instance Method Details
#info ⇒ Object
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/resources/port.rb', line 171 def info ports = [] # check that lsof is available, otherwise fail raise 'Please ensure `lsof` is available on the machine.' if !inspec.command(@lsof.to_s).exist? # -F p=pid, c=command, P=protocol name, t=type, n=internet addresses # see 'OUTPUT FOR OTHER PROGRAMS' in LSOF(8) lsof_cmd = inspec.command("#{@lsof} -nP -i -FpctPn") return nil if lsof_cmd.exit_status.to_i != 0 # map to desired return struct lsof_parser(lsof_cmd).each do |process, port_ids| pid, cmd = process.split(':') port_ids.each do |port_str| # should not break on ipv6 addresses ipv, proto, port, host = port_str.split(':', 4) ports.push({ 'port' => port.to_i, 'address' => host, 'protocol' => ipv == 'ipv6' ? proto + '6' : proto, 'process' => cmd, 'pid' => pid.to_i }) end end ports end |
#lsof_parser(lsof_cmd) ⇒ Object
rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/AbcSize
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/resources/port.rb', line 201 def lsof_parser(lsof_cmd) procs = {} # build this with formatted output (-F) from lsof # procs = { # '123:sshd' => [ # 'ipv4:tcp:22:127.0.0.1', # 'ipv6:tcp:22:::1', # 'ipv4:tcp:*', # 'ipv6:tcp:*', # ], # '456:ntpd' => [ # 'ipv4:udp:123:*', # 'ipv6:udp:123:*', # ] # } proc_id = port_id = nil lsof_cmd.stdout.each_line do |line| line.chomp! key = line.slice!(0) case key when 'p' proc_id = line port_id = nil when 'c' proc_id += ':' + line when 't' port_id = line.downcase when 'P' port_id += ':' + line.downcase when 'n' src, dst = line.split('->') # skip active comm streams next if dst host, port = /^(\S+):(\d+|\*)$/.match(src)[1, 2] # skip channels from port 0 - what does this mean? next if port == '*' # create new array stub if !exist? procs[proc_id] = [] unless procs.key?(proc_id) # change address '*' to zero host = port_id =~ /^ipv6:/ ? '[::]' : '0.0.0.0' if host == '*' # entrust URI to scrub the host and port begin uri = URI("addr://#{host}:#{port}") uri.host && uri.port rescue => e warn "could not parse URI 'addr://#{host}:#{port}' - #{e}" next end # e.g. 'ipv4:tcp:22:127.0.0.1' # strip ipv6 squares for inspec port_id += ':' + port + ':' + host.gsub(/^\[|\]$/, '') # lsof will give us another port unless it's done procs[proc_id] << port_id end end procs end |