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.
148 149 150 151 |
# File 'lib/resources/port.rb', line 148 def initialize(inspec, lsofpath = nil) @lsof = lsofpath || 'lsof' super(inspec) end |
Instance Attribute Details
#lsof ⇒ Object (readonly)
Returns the value of attribute lsof.
146 147 148 |
# File 'lib/resources/port.rb', line 146 def lsof @lsof end |
Instance Method Details
#info ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/resources/port.rb', line 153 def info ports = [] # check that lsof is available, otherwise fail fail '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
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 |
# File 'lib/resources/port.rb', line 183 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 |