inspec 3.9.3 → 4.1.4.preview

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +2 -7
  3. data/README.md +1 -2
  4. data/etc/deprecations.json +88 -6
  5. data/inspec.gemspec +4 -2
  6. data/lib/inspec/base_cli.rb +5 -5
  7. data/lib/inspec/cli.rb +39 -9
  8. data/lib/inspec/config.rb +2 -2
  9. data/lib/inspec/metadata.rb +3 -5
  10. data/lib/inspec/plugin/v1/plugin_types/resource.rb +4 -1
  11. data/lib/inspec/ui.rb +1 -0
  12. data/lib/inspec/version.rb +1 -6
  13. data/lib/matchers/matchers.rb +1 -0
  14. data/lib/plugins/inspec-init/templates/profiles/aws/README.md +164 -26
  15. data/lib/plugins/inspec-init/templates/profiles/aws/controls/example.rb +18 -4
  16. data/lib/plugins/inspec-init/templates/profiles/aws/inspec.yml +10 -4
  17. data/lib/resource_support/aws.rb +17 -1
  18. data/lib/resources/apache.rb +1 -1
  19. data/lib/resources/apt.rb +1 -3
  20. data/lib/resources/aws/aws_iam_user.rb +3 -3
  21. data/lib/resources/azure/azure_generic_resource.rb +1 -1
  22. data/lib/resources/file.rb +34 -1
  23. data/lib/resources/filesystem.rb +1 -1
  24. data/lib/resources/host.rb +2 -2
  25. data/lib/resources/iis_site.rb +1 -1
  26. data/lib/resources/interface.rb +75 -1
  27. data/lib/resources/kernel_parameter.rb +2 -7
  28. data/lib/resources/mssql_session.rb +1 -1
  29. data/lib/resources/oracledb_session.rb +1 -1
  30. data/lib/resources/powershell.rb +1 -5
  31. data/lib/resources/processes.rb +1 -1
  32. data/lib/resources/registry_key.rb +1 -7
  33. data/lib/resources/shadow.rb +5 -10
  34. data/lib/resources/users.rb +6 -10
  35. data/lib/resources/wmi.rb +1 -2
  36. data/lib/utils/deprecation/deprecator.rb +9 -8
  37. data/lib/utils/deprecation/global_method.rb +1 -1
  38. data/lib/utils/parser.rb +1 -1
  39. metadata +37 -14
@@ -3,12 +3,13 @@
3
3
 
4
4
  title 'Sample Section'
5
5
 
6
- aws_vpc_id = attribute('aws_vpc_id')
6
+ aws_vpc_id = attribute('aws_vpc_id', default: '', description: 'Optional AWS VPC identifier.')
7
7
 
8
- # you add controls here
9
- control 'aws-vpc-check' do # A unique ID for this control.
8
+ # You add controls here
9
+ control 'aws-single-vpc-exists-check' do # A unique ID for this control.
10
+ only_if { aws_vpc_id != ''} # Only run this control if the `aws_vpc_id` attribute is provided.
10
11
  impact 1.0 # The criticality, if this control fails.
11
- title 'Check to see if custom VPC exists.' # A human-readable title
12
+ title 'Check to see if custom VPC exists.' # A human-readable title.
12
13
  describe aws_vpc(aws_vpc_id) do # The test itself.
13
14
  it { should exist }
14
15
  end
@@ -24,3 +25,16 @@ control 'aws-vpcs-check' do
24
25
  end
25
26
  end
26
27
  end
28
+
29
+ control 'aws-vpcs-multi-region-status-check' do # A unique ID for this control.
30
+ impact 1.0 # The criticality, if this control fails.
31
+ title 'Check AWS VPCs in all regions have status "available"' # A human-readable title.
32
+ aws_regions.region_names.each do |region| # Loop over all available AWS regions
33
+ aws_vpcs(aws_region: region).vpc_ids.each do |vpc| # Find all VPCs in a single AWS region
34
+ describe aws_vpc(aws_region: region, vpc_id: vpc) do # The test itself.
35
+ it { should exist } # Confirms AWS VPC exists
36
+ it { should be_available } # Confirms AWS VPC has status "available"
37
+ end
38
+ end
39
+ end
40
+ end
@@ -6,11 +6,17 @@ copyright_email: you@example.com
6
6
  license: Apache-2.0
7
7
  summary: An InSpec Compliance Profile For AWS
8
8
  version: 0.1.0
9
- inspec_version: '>= 2.3.5'
9
+ inspec_version: '~> 4'
10
10
  attributes:
11
11
  - name: aws_vpc_id
12
- required: true
13
- description: 'The Custom AWS VPC Id'
12
+ required: false
13
+ # Below is deliberately left as a default empty string to allow the profile to run when this is not provided.
14
+ # Please see the README for more details.
15
+ default: ''
16
+ description: 'Optional Custom AWS VPC Id'
14
17
  type: string
18
+ depends:
19
+ - name: inspec-aws
20
+ url: https://github.com/inspec/inspec-aws/archive/master.tar.gz
15
21
  supports:
16
- - platform: aws
22
+ - platform: aws
@@ -1,7 +1,23 @@
1
1
  # Main AWS loader file. The intent is for this to be
2
2
  # loaded only if AWS resources are needed.
3
3
 
4
- require 'aws-sdk' # TODO: split once ADK v3 is in use
4
+ require 'aws-sdk-core'
5
+
6
+ require 'aws-sdk-cloudtrail'
7
+ require 'aws-sdk-cloudwatch'
8
+ require 'aws-sdk-cloudwatchlogs'
9
+ require 'aws-sdk-costandusagereportservice'
10
+ require 'aws-sdk-configservice'
11
+ require 'aws-sdk-ec2'
12
+ require 'aws-sdk-ecs'
13
+ require 'aws-sdk-eks'
14
+ require 'aws-sdk-elasticloadbalancing'
15
+ require 'aws-sdk-iam'
16
+ require 'aws-sdk-kms'
17
+ require 'aws-sdk-rds'
18
+ require 'aws-sdk-s3'
19
+ require 'aws-sdk-sqs'
20
+ require 'aws-sdk-sns'
5
21
 
6
22
  require 'resource_support/aws/aws_backend_factory_mixin'
7
23
  require 'resource_support/aws/aws_resource_mixin'
@@ -26,7 +26,7 @@ module Inspec::Resources
26
26
 
27
27
  attr_reader :service, :conf_dir, :conf_path, :user
28
28
  def initialize
29
- warn '[DEPRECATED] The `apache` resource is deprecated and will be removed in InSpec 4.0'
29
+ Inspec.deprecate(:resource_apache, 'The apache resource is deprecated')
30
30
 
31
31
  if inspec.os.debian?
32
32
  @service = 'apache2'
@@ -127,8 +127,6 @@ module Inspec::Resources
127
127
  end
128
128
  end
129
129
 
130
- # for compatability with serverspec
131
- # this is deprecated syntax and will be removed in future versions
132
130
  class PpaRepository < AptRepository
133
131
  name 'ppa'
134
132
 
@@ -143,7 +141,7 @@ module Inspec::Resources
143
141
  end
144
142
 
145
143
  def deprecated
146
- warn '[DEPRECATION] `ppa(reponame)` is deprecated. Please use `apt(reponame)` instead.'
144
+ Inspec.deprecate(:resource_ppa, 'The `ppa` resource is deprecated. Please use `apt`')
147
145
  end
148
146
  end
149
147
  end
@@ -22,7 +22,7 @@ class AwsIamUser < Inspec.resource(1)
22
22
  alias has_console_password? has_console_password
23
23
 
24
24
  def name
25
- warn "[DEPRECATION] - Property ':name' is deprecated on the aws_iam_user resource. Use ':username' instead."
25
+ Inspec.deprecate(:properties_aws_iam_user, 'The aws_iam_user `name` property is deprecated. Please use `username` instead')
26
26
  username
27
27
  end
28
28
 
@@ -51,13 +51,13 @@ class AwsIamUser < Inspec.resource(1)
51
51
  )
52
52
  # If someone passed :name, rename it to :username
53
53
  if validated_params.key?(:name)
54
- warn "[DEPRECATION] - Resource parameter ':name' is deprecated on the aws_iam_user resource. Use ':username' instead."
54
+ Inspec.deprecate(:properties_aws_iam_user, 'The aws_iam_users `name` property is deprecated. Please use `username` instead')
55
55
  validated_params[:username] = validated_params.delete(:name)
56
56
  end
57
57
 
58
58
  # If someone passed :user, rename it to :aws_user_struct
59
59
  if validated_params.key?(:user)
60
- warn "[DEPRECATION] - Resource parameter ':user' is deprecated on the aws_iam_user resource. Use ':aws_user_struct' instead."
60
+ Inspec.deprecate(:properties_aws_iam_user, 'The aws_iam_users `user` property is deprecated. Please use `aws_user_struct` instead')
61
61
  validated_params[:aws_user_struct] = validated_params.delete(:user)
62
62
  end
63
63
 
@@ -16,7 +16,7 @@ module Inspec::Resources
16
16
  attr_accessor :filter, :total, :counts, :name, :type, :location, :probes
17
17
 
18
18
  def initialize(opts = {})
19
- warn "[DEPRECATED] use a specific azure resources instead of 'azure_generic_resource'. See https://github.com/inspec/inspec/issues/3131"
19
+ Inspec.deprecate(:resource_azure_generic_resource)
20
20
 
21
21
  # Call the parent class constructor
22
22
  super(opts)
@@ -98,7 +98,7 @@ module Inspec::Resources
98
98
  return file.mounted? if expected_options.nil?
99
99
 
100
100
  # deprecation warning, this functionality will be removed in future version
101
- warn "[DEPRECATION] `be_mounted.with and be_mounted.only_with` are deprecated. Please use `mount('#{source_path}')` instead."
101
+ Inspec.deprecate(:file_resource_be_mounted_matchers, 'The file resource `be_mounted.with` and `be_mounted.only_with` matchers are deprecated. Please use the `mount` resource instead')
102
102
 
103
103
  # we cannot read mount data on non-Linux systems
104
104
  return nil if !inspec.os.linux?
@@ -133,6 +133,35 @@ module Inspec::Resources
133
133
 
134
134
  alias sticky? sticky
135
135
 
136
+ def more_permissive_than?(max_mode = nil)
137
+ raise Inspec::Exceptions::ResourceFailed, 'The file' + file.path + 'doesn\'t seem to exist' unless exist?
138
+ raise ArgumentError, 'You must proivde a value for the `maximum allowable permission` for the file.' if max_mode.nil?
139
+ raise ArgumentError, 'You must proivde the `maximum permission target` as a `String`, you provided: ' + max_mode.class.to_s unless max_mode.is_a?(String)
140
+ raise ArgumentError, 'The value of the `maximum permission target` should be a valid file mode in 4-ditgit octal format: for example, `0644` or `0777`' unless /(0)?([0-7])([0-7])([0-7])/.match?(max_mode)
141
+
142
+ # Using the files mode and a few bit-wise calculations we can ensure a
143
+ # file is no more permisive than desired.
144
+ #
145
+ # 1. Calculate the inverse of the desired mode (e.g., 0644) by XOR it with
146
+ # 0777 (all 1s). We are interested in the bits that are currently 0 since
147
+ # it indicates that the actual mode is more permissive than the desired mode.
148
+ # Conversely, we dont care about the bits that are currently 1 because they
149
+ # cannot be any more permissive and we can safely ignore them.
150
+ #
151
+ # 2. Calculate the above result of ANDing the actual mode and the inverse
152
+ # mode. This will determine if any of the bits that would indicate a more
153
+ # permissive mode are set in the actual mode.
154
+ #
155
+ # 3. If the result is 0000, the files mode is equal
156
+ # to or less permissive than the desired mode (PASS). Otherwise, the files
157
+ # mode is more permissive than the desired mode (FAIL).
158
+
159
+ max_mode = max_mode.rjust(4, '0')
160
+ binary_desired_mode = format('%04b', max_mode).to_i(2)
161
+ desired_mode_inverse = (binary_desired_mode ^ 0b111111111)
162
+ (desired_mode_inverse & file.mode).zero? ? false : true
163
+ end
164
+
136
165
  def to_s
137
166
  "File #{source_path}"
138
167
  end
@@ -212,6 +241,10 @@ module Inspec::Resources
212
241
  raise '`check_file_permission_by_mask` is not supported on Windows'
213
242
  end
214
243
 
244
+ def more_permissive_than?(*)
245
+ raise Inspec::Exceptions::ResourceSkipped, 'The `more_permissive_than?` matcher is not supported on your OS yet.'
246
+ end
247
+
215
248
  def check_file_permission_by_user(access_type, user, path)
216
249
  access_rule = translate_perm_names(access_type)
217
250
  access_rule = convert_to_powershell_array(access_rule)
@@ -52,7 +52,7 @@ module Inspec::Resources
52
52
  end
53
53
 
54
54
  def size
55
- Inspec.deprecate(:filesystem_property_size, 'The `size` property did not reliably use the correct units. Please use `size_kb` instead.')
55
+ Inspec.deprecate(:property_filesystem_size, 'The `size` property did not reliably use the correct units. Please use `size_kb` instead.')
56
56
  if inspec.os.windows?
57
57
  # On windows, we had a bug prior to #3767 in which the
58
58
  # 'size' value was be scaled to GB in powershell.
@@ -49,7 +49,7 @@ module Inspec::Resources
49
49
  @port = params[:port]
50
50
 
51
51
  if params[:proto]
52
- warn '[DEPRECATION] The `proto` parameter is deprecated. Use `protocol` instead.'
52
+ Inspec.deprecate(:host_resource_proto_usage, 'The `host` resource `proto` resource parameter is deprecated. Please use `protocol`.')
53
53
  @protocol = params[:proto]
54
54
  else
55
55
  @protocol = params.fetch(:protocol, 'icmp')
@@ -75,7 +75,7 @@ module Inspec::Resources
75
75
  end
76
76
 
77
77
  def proto
78
- warn '[DEPRECATION] The `proto` method is deprecated. Use `protocol` instead.'
78
+ Inspec.deprecate(:host_resource_proto_usage, 'The host resource `proto` method is deprecated. Please use `protocol`.')
79
79
  protocol
80
80
  end
81
81
 
@@ -134,8 +134,8 @@ module Inspec::Resources
134
134
  EXAMPLE
135
135
 
136
136
  def initialize(site_name)
137
+ Inspec.deprecate(:resource_iis_website, 'The `iis_website` resource is deprecated. Please use `iis_site` instead.')
137
138
  super(site_name)
138
- warn '[DEPRECATION] `iis_website(site_name)` is deprecated. Please use `iis_site(site_name)` instead.'
139
139
  end
140
140
 
141
141
  def in_app_pool?(app_pool)
@@ -13,6 +13,8 @@ module Inspec::Resources
13
13
  it { should exist }
14
14
  it { should be_up }
15
15
  its('speed') { should eq 1000 }
16
+ its('ipv4_addresses') { should include '127.0.0.1' }
17
+ its('ipv6_cidrs') { should include '::1/128' }
16
18
  end
17
19
  EXAMPLE
18
20
  def initialize(iface)
@@ -41,6 +43,42 @@ module Inspec::Resources
41
43
  interface_info.nil? ? nil : interface_info[:speed]
42
44
  end
43
45
 
46
+ def ipv4_address?
47
+ !ipv4_addresses.nil? && !ipv4_addresses.empty?
48
+ end
49
+
50
+ def ipv6_address?
51
+ !ipv6_addresses.nil? && !ipv6_addresses.empty?
52
+ end
53
+
54
+ def ipv4_addresses
55
+ ipv4_cidrs.map { |i| i.split('/')[0] }
56
+ end
57
+
58
+ def ipv6_addresses
59
+ ipv6_cidrs.map { |i| i.split('/')[0] }
60
+ end
61
+
62
+ def ipv4_addresses_netmask
63
+ ipv4_cidrs.map { |i| i.split('/') }.map do |addr, netlen|
64
+ binmask = "#{'1' * netlen.to_i}#{'0' * (32 - netlen.to_i)}".to_i(2)
65
+ netmask = []
66
+ (1..4).each do |_byte|
67
+ netmask.unshift(binmask & 255)
68
+ binmask = binmask >> 8
69
+ end
70
+ "#{addr}/#{netmask.join('.')}"
71
+ end
72
+ end
73
+
74
+ def ipv4_cidrs
75
+ interface_info.nil? ? [] : interface_info[:ipv4_addresses]
76
+ end
77
+
78
+ def ipv6_cidrs
79
+ interface_info.nil? ? [] : interface_info[:ipv6_addresses]
80
+ end
81
+
44
82
  def to_s
45
83
  "Interface #{@iface}"
46
84
  end
@@ -87,28 +125,54 @@ module Inspec::Resources
87
125
  speed = convert_to_i(speed)
88
126
  end
89
127
 
128
+ family_addresses = addresses(iface)
90
129
  {
91
130
  name: iface,
92
131
  up: state,
93
132
  speed: speed,
133
+ ipv4_addresses: family_addresses['inet'],
134
+ ipv6_addresses: family_addresses['inet6'],
94
135
  }
95
136
  end
137
+
138
+ private
139
+
140
+ def addresses(iface)
141
+ addrs_by_family = { 'inet6' => [], 'inet' => [] }
142
+ [4, 6].each do |v|
143
+ cmd = inspec.command("/sbin/ip -br -#{v} address show dev #{iface}")
144
+ next unless cmd.exit_status.to_i == 0
145
+ family = v == 6 ? 'inet6' : 'inet'
146
+
147
+ cmd.stdout.each_line do |line|
148
+ _dev, _state, *addrs = line.split(/\s+/)
149
+ addrs_by_family[family] = addrs
150
+ end
151
+ end
152
+ addrs_by_family
153
+ end
96
154
  end
97
155
 
98
156
  class WindowsInterface < InterfaceInfo
99
157
  def interface_info(iface)
100
158
  # gather all network interfaces
101
- cmd = inspec.command('Get-NetAdapter | Select-Object -Property Name, InterfaceDescription, Status, State, MacAddress, LinkSpeed, ReceiveLinkSpeed, TransmitLinkSpeed, Virtual | ConvertTo-Json')
159
+ cmd = inspec.command('Get-NetAdapter | Select-Object -Property Name, InterfaceDescription, Status, State, ' \
160
+ 'MacAddress, LinkSpeed, ReceiveLinkSpeed, TransmitLinkSpeed, Virtual | ConvertTo-Json')
161
+
162
+ addr_cmd = inspec.command('Get-NetIPAddress | Select-Object -Property IPv6Address, IPv4Address, InterfaceAlias,' \
163
+ ' PrefixLength | ConvertTo-Json')
102
164
 
103
165
  # filter network interface
104
166
  begin
105
167
  net_adapter = JSON.parse(cmd.stdout)
168
+ addresses = JSON.parse(addr_cmd.stdout)
106
169
  rescue JSON::ParserError => _e
107
170
  return nil
108
171
  end
109
172
 
110
173
  # ensure we have an array of groups
111
174
  net_adapter = [net_adapter] if !net_adapter.is_a?(Array)
175
+ addresses = [addresses] if !addresses.is_a?(Array)
112
176
 
113
177
  # select the requested interface
114
178
  adapters = net_adapter.each_with_object([]) do |adapter, adapter_collection|
@@ -117,6 +181,8 @@ module Inspec::Resources
117
181
  name: adapter['Name'],
118
182
  up: adapter['State'] == 2,
119
183
  speed: adapter['ReceiveLinkSpeed'] / 1000,
184
+ ipv4_addresses: addresses_for_proto(addresses, adapter['Name'], 'IPv4'),
185
+ ipv6_addresses: addresses_for_proto(addresses, adapter['Name'], 'IPv6'),
120
186
  }
121
187
  adapter_collection.push(info) if info[:name].casecmp(iface) == 0
122
188
  end
@@ -125,5 +191,13 @@ module Inspec::Resources
125
191
  warn "[Possible Error] detected multiple network interfaces with the name #{iface}" if adapters.size > 1
126
192
  adapters[0]
127
193
  end
194
+
195
+ private
196
+
197
+ def addresses_for_proto(all_addresses, iface, proto)
198
+ all_addresses.select { |i| i['InterfaceAlias'] == iface }
199
+ .map { |i| "#{i["#{proto}Address"]}/#{i['PrefixLength']}" unless i["#{proto}Address"].nil? }
200
+ .compact
201
+ end
128
202
  end
129
203
  end
@@ -33,24 +33,19 @@ module Inspec::Resources
33
33
  end
34
34
  end
35
35
 
36
- # for compatability with serverspec
37
- # this is deprecated syntax and will be removed in future versions
38
36
  class LinuxKernelParameter < KernelParameter
39
37
  name 'linux_kernel_parameter'
40
38
 
41
39
  def initialize(parameter)
40
+ Inspec.deprecate(:resource_linux_kernel_parameter, 'The `linux_kernel_parameter` resource is deprecated. Please use `kernel_parameter`')
42
41
  super(parameter)
43
42
  end
44
43
 
45
44
  def value
46
- deprecated
45
+ Inspec.deprecate(:resource_linux_kernel_parameter, 'The `linux_kernel_parameter` resource is deprecated. Please use `kernel_parameter`')
47
46
  super()
48
47
  end
49
48
 
50
- def deprecated
51
- warn '[DEPRECATION] `linux_kernel_parameter(parameter)` is deprecated. Please use `kernel_parameter(parameter)` instead.'
52
- end
53
-
54
49
  def to_s
55
50
  "Kernel Parameter #{@parameter}"
56
51
  end
@@ -34,7 +34,7 @@ module Inspec::Resources
34
34
  @user = opts[:user]
35
35
  @password = opts[:password] || opts[:pass]
36
36
  if opts[:pass]
37
- warn '[DEPRECATED] use `password` option to supply password instead of `pass`'
37
+ Inspec.deprecate(:mssql_session_pass_option, 'The mssql_session `pass` option is deprecated. Please use `password`.')
38
38
  end
39
39
  @local_mode = opts[:local_mode]
40
40
  unless local_mode?
@@ -28,7 +28,7 @@ module Inspec::Resources
28
28
  @user = opts[:user]
29
29
  @password = opts[:password] || opts[:pass]
30
30
  if opts[:pass]
31
- warn '[DEPRECATED] use `password` option to supply password instead of `pass`'
31
+ Inspec.deprecate(:oracledb_session_pass_option, 'The oracledb_session `pass` option is deprecated. Please use `password`.')
32
32
  end
33
33
 
34
34
  @host = opts[:host] || 'localhost'
@@ -56,12 +56,8 @@ module Inspec::Resources
56
56
  name 'script'
57
57
 
58
58
  def initialize(script)
59
- deprecated
59
+ Inspec.deprecate(:resource_script, 'The `script` resource is deprecated. Please use `powershell` instead.')
60
60
  super(script)
61
61
  end
62
-
63
- def deprecated
64
- warn '[DEPRECATION] `script(script)` is deprecated. Please use `powershell(script)` instead.'
65
- end
66
62
  end
67
63
  end
@@ -56,7 +56,7 @@ module Inspec::Resources
56
56
  end
57
57
 
58
58
  def list
59
- warn '[DEPRECATION] `processes.list` is deprecated. Please use `processes.entries` instead. It will be removed in version 4.0.'
59
+ Inspec.deprecate(:property_processes_list, 'The processes `list` property is deprecated. Please use `entries` instead.')
60
60
  @list
61
61
  end
62
62
 
@@ -280,18 +280,12 @@ module Inspec::Resources
280
280
  end
281
281
  end
282
282
 
283
- # for compatability with serverspec
284
- # this is deprecated syntax and will be removed in future versions
285
283
  class WindowsRegistryKey < RegistryKey
286
284
  name 'windows_registry_key'
287
285
 
288
286
  def initialize(name)
289
- deprecated
287
+ Inspec.deprecate(:resource_windows_registry_key, 'The `windows_registry_key` resource is deprecated. Please use `registry_key` instead.')
290
288
  super(name)
291
289
  end
292
-
293
- def deprecated
294
- warn '[DEPRECATION] `windows_registry_key(reg_key)` is deprecated. Please use `registry_key(\'path\to\key\')` instead.'
295
- end
296
290
  end
297
291
  end