mirror of
https://github.com/inspec/inspec
synced 2024-11-30 08:30:39 +00:00
2bbcdbde9b
* Remove deprecated yumrepo. (#3435) * Remove deprecations for cli `--format` and metadata.rb (#3452) * Remove deprecated database_helpers stderr/stdout methods. Update deprecation text for processes/apache. * Remove deprecations for `--format` and metadata.rb Remove deprecated `format` code. Remove deprecated code test and change json-config format test to use reporter. Remove deprecated metadata.rb code Remove deprecation notice for old supports syntax. Deprecate metadata.rb from source_reader Remove rubocop disables as they are no longer required for this code block. Remove deprecated legacy metadata.rb mock profiles. Remove deprecated metadata.rb profile tests. Remove deprecated yumrepo test. * Allow inspec-3.0 branch to be tested. * Allow appveyor to test inspec-3.0 branch * Change runner tests to use reporter rather than format. Remove deprecated `supports: linux` tests. * Remove skip from inherited profiles from showing up in reporting (breaking change) (#3332) * Skip loading dependency profiles if they are unsupported on the current platform. Skip loading dependencies if they are unsupported on the current platform. Wrap our log and next in a conditional checking if the platform is supported. Change a `if !` into a `unless` Check if the backend is a Train Mock Connection and if so say that the profile does support the platform. While iterating through tests being loaded skip when the platform is unsupported. We now log a WARN when a profile is skipped due to unsupported platform, so lets check that. Modified existing test to log that there are 0 skipped tests, instead of 2. Add functional test that loads profile-support-skip with a json reporter to check that our controls are not loaded and that stderr contains our warning. * Rather than iterating through each test return before recursion if the platform is unsupported. * Resolve tests using a supported platform different from testing platform Add a control to `test/unit/mock/profiles/complete-profile` that would work on any OS with a Internet connection. This allows the profile to execute on any OS with success. `filesystem_spec.rb` was a control that would only work on Linux and some BSD's. We want profile tests to consistently work across development and testing platforms, and not get 'skipped' in some cases. Travis-CI tests on Linux, Inspec Dev team uses Linux and MacOS, Appveyor tests on Windows Also Updated `file_provider_test.rb` for `complete-profile` content changes. If you `MockLoader.load_profile` on a unsupported platform you might not hit the usual skip. Lets handle situations where the tests array in Profile#load_checks_params could be nil. * Use safe navigation rather than checking if tests is nil. Update tests to point to unsupported_inspec and account for WARN changes. Make unsupported_inspec profile support os-family 'unsupported_inspec' * Fix skip bug when using include/require controls. (#3487) * Fix skip bug when using include/require controls. * fix test and feedback. * Remove need for UUID detection for Automate report (#3507) * Add json metadata for skipped profiles (#3495) * Add skip metadata to json reports * Unify skip messages. * Update with status field. * Add testing. * Fix tests. * lint * Add skip exit codes for profile skips. * Update website for 3.0 launch Add `plugins` to sidebar. Change 2.0 -> 3.0 in slim files. Update 3.0 features list. * Fix comments * Update float to numeric. * Change Float to numeric. * updated feature list and impact doc * Change "What's new in InSpec 3.0" -> "Announcing InSpec 3.0" * Bump VERSION to 3.0.0 (#3511) * Remove 3.0 testing checks. * Fix azure link.
218 lines
6.7 KiB
Ruby
218 lines
6.7 KiB
Ruby
# encoding: utf-8
|
|
# copyright: 2015, Vulcano Security GmbH
|
|
|
|
require 'utils/filter'
|
|
require 'ostruct'
|
|
|
|
module Inspec::Resources
|
|
class Processes < Inspec.resource(1)
|
|
name 'processes'
|
|
supports platform: 'unix'
|
|
supports platform: 'windows'
|
|
desc 'Use the processes InSpec audit resource to test properties for programs that are running on the system.'
|
|
example "
|
|
describe processes('mysqld') do
|
|
its('entries.length') { should eq 1 }
|
|
its('users') { should eq ['mysql'] }
|
|
its('states') { should include 'S' }
|
|
end
|
|
|
|
describe processes(/.+/).where { label != 'unconfined' && pid < 1000 } do
|
|
its('users') { should cmp [] }
|
|
end
|
|
|
|
# work with all processes
|
|
describe processes do
|
|
its('entries.length') { should be <= 100 }
|
|
end
|
|
"
|
|
|
|
def initialize(grep = /.*/)
|
|
@grep = grep
|
|
# turn into a regexp if it isn't one yet
|
|
if grep.class == String
|
|
# if windows ignore case as we can't make up our minds
|
|
if inspec.os.windows?
|
|
grep = '(?i)' + grep
|
|
else
|
|
grep = '(/[^/]*)*' + grep unless grep[0] == '/'
|
|
grep = '^' + grep + '(\s|$)'
|
|
end
|
|
grep = Regexp.new(grep)
|
|
end
|
|
|
|
all_cmds = ps_axo
|
|
@list = all_cmds.find_all do |hm|
|
|
hm[:command] =~ grep
|
|
end
|
|
end
|
|
|
|
def exists?
|
|
!@list.empty?
|
|
end
|
|
|
|
def to_s
|
|
"Processes #{@grep.class == String ? @grep : @grep.inspect}"
|
|
end
|
|
|
|
def list
|
|
warn '[DEPRECATION] `processes.list` is deprecated. Please use `processes.entries` instead. It will be removed in version 4.0.'
|
|
@list
|
|
end
|
|
|
|
filter = FilterTable.create
|
|
filter.register_column(:labels, field: 'label')
|
|
.register_column(:pids, field: 'pid')
|
|
.register_column(:cpus, field: 'cpu')
|
|
.register_column(:mem, field: 'mem')
|
|
.register_column(:vsz, field: 'vsz')
|
|
.register_column(:rss, field: 'rss')
|
|
.register_column(:tty, field: 'tty')
|
|
.register_column(:states, field: 'stat')
|
|
.register_column(:start, field: 'start')
|
|
.register_column(:time, field: 'time')
|
|
.register_column(:users, field: 'user')
|
|
.register_column(:commands, field: 'command')
|
|
.install_filter_methods_on_resource(self, :filtered_processes)
|
|
|
|
private
|
|
|
|
def filtered_processes
|
|
@list
|
|
end
|
|
|
|
def ps_axo
|
|
os = inspec.os
|
|
|
|
if os.linux?
|
|
command, regex, field_map = ps_configuration_for_linux
|
|
elsif os.windows?
|
|
command = '$Proc = Get-Process -IncludeUserName | Where-Object {$_.Path -ne $null } | Select-Object PriorityClass,Id,CPU,PM,VirtualMemorySize,NPM,SessionId,Responding,StartTime,TotalProcessorTime,UserName,Path | ConvertTo-Csv -NoTypeInformation;$Proc.Replace("""","").Replace("`r`n","`n")'
|
|
# Wanted to use /(?:^|,)([^,]*)/; works on rubular.com not sure why here?
|
|
regex = /^(.+),(.+),(.+),(.+),(.+),(.+),(.+),(.+),(.+),(.+),(.+),(.+)$/
|
|
field_map = {
|
|
pid: 2,
|
|
cpu: 3,
|
|
mem: 4,
|
|
vsz: 5,
|
|
rss: 6,
|
|
tty: 7,
|
|
stat: 8,
|
|
start: 9,
|
|
time: 10,
|
|
user: 11,
|
|
command: 12,
|
|
}
|
|
else
|
|
command = 'ps axo pid,pcpu,pmem,vsz,rss,tty,stat,start,time,user,command'
|
|
regex = /^\s*([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+(.*)$/
|
|
field_map = {
|
|
pid: 1,
|
|
cpu: 2,
|
|
mem: 3,
|
|
vsz: 4,
|
|
rss: 5,
|
|
tty: 6,
|
|
stat: 7,
|
|
start: 8,
|
|
time: 9,
|
|
user: 10,
|
|
command: 11,
|
|
}
|
|
end
|
|
build_process_list(command, regex, field_map)
|
|
end
|
|
|
|
def ps_configuration_for_linux
|
|
if busybox_ps?
|
|
command = 'ps -o pid,vsz,rss,tty,stat,time,ruser,args'
|
|
regex = /^\s*(\d+)\s+(\d+(?:\.\d+)?[gm]?)\s+(\d+(?:\.\d+)?[gm]?)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/
|
|
field_map = {
|
|
pid: 1,
|
|
vsz: 2,
|
|
rss: 3,
|
|
tty: 4,
|
|
stat: 5,
|
|
time: 6,
|
|
user: 7,
|
|
command: 8,
|
|
}
|
|
else
|
|
command = 'ps axo label,pid,pcpu,pmem,vsz,rss,tty,stat,start,time,user:32,command'
|
|
regex = /^(.+?)\s+(\d+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+(\w{3} \d{2}|\d{2}:\d{2}:\d{2})\s+([^ ]+)\s+([^ ]+)\s+(.*)$/
|
|
field_map = {
|
|
label: 1,
|
|
pid: 2,
|
|
cpu: 3,
|
|
mem: 4,
|
|
vsz: 5,
|
|
rss: 6,
|
|
tty: 7,
|
|
stat: 8,
|
|
start: 9,
|
|
time: 10,
|
|
user: 11,
|
|
command: 12,
|
|
}
|
|
end
|
|
|
|
[command, regex, field_map]
|
|
end
|
|
|
|
def busybox_ps?
|
|
@busybox_ps ||= inspec.command('ps --help').stderr.include?('BusyBox')
|
|
end
|
|
|
|
def convert_to_kilobytes(param)
|
|
return param.to_i unless param.is_a?(String)
|
|
|
|
if param.end_with?('g')
|
|
(param[0..-2].to_f * 1024 * 1024).to_i
|
|
elsif param.end_with?('m')
|
|
(param[0..-2].to_f * 1024).to_i
|
|
else
|
|
param.to_i
|
|
end
|
|
end
|
|
|
|
def build_process_list(command, regex, field_map)
|
|
cmd = inspec.command(command)
|
|
all = cmd.stdout.split("\n")[1..-1]
|
|
return [] if all.nil?
|
|
|
|
# map all the process lines into match objects, fetch the available fields,
|
|
# and then build an OpenStruct of the process data for each process
|
|
all.map do |line|
|
|
line = line.match(regex)
|
|
|
|
# skip this line if we couldn't match the regular expression
|
|
next if line.nil?
|
|
|
|
# skip this entry if there's no command for this line
|
|
next if line[field_map[:command]].nil?
|
|
|
|
# build a hash of process data that we'll turn into a struct for FilterTable
|
|
process_data = {}
|
|
[:label, :pid, :cpu, :mem, :vsz, :rss, :tty, :stat, :start, :time, :user, :command].each do |param|
|
|
# not all operating systems support all fields, so skip the field if we don't have it
|
|
process_data[param] = line[field_map[param]] if field_map.key?(param)
|
|
end
|
|
|
|
# ensure pid, vsz, and rss are integers for backward compatibility
|
|
process_data[:pid] = process_data[:pid].to_i if process_data.key?(:pid)
|
|
|
|
# some ps variants (*cough* busybox) display vsz and rss as human readable MB or GB
|
|
[:vsz, :rss].each do |param|
|
|
next unless process_data.key?(param)
|
|
process_data[param] = convert_to_kilobytes(process_data[param])
|
|
end
|
|
|
|
# strip any newlines off the command
|
|
process_data[:command].strip!
|
|
|
|
# return an OpenStruct of the process for future use by FilterTable
|
|
OpenStruct.new(process_data)
|
|
end.compact
|
|
end
|
|
end
|
|
end
|