inspec 4.22.1

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 +7 -0
  2. data/Gemfile +63 -0
  3. data/inspec.gemspec +36 -0
  4. data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/Gemfile +11 -0
  5. data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/inspec-plugin-template.gemspec +43 -0
  6. data/lib/plugins/inspec-init/templates/profiles/aws/README.md +192 -0
  7. data/lib/plugins/inspec-init/templates/profiles/aws/attributes.yml +2 -0
  8. data/lib/plugins/inspec-init/templates/profiles/aws/controls/example.rb +39 -0
  9. data/lib/plugins/inspec-init/templates/profiles/aws/inspec.yml +22 -0
  10. data/lib/plugins/inspec-init/templates/profiles/azure/README.md +56 -0
  11. data/lib/plugins/inspec-init/templates/profiles/azure/controls/example.rb +14 -0
  12. data/lib/plugins/inspec-init/templates/profiles/azure/inspec.yml +14 -0
  13. data/lib/plugins/inspec-init/templates/profiles/gcp/README.md +66 -0
  14. data/lib/plugins/inspec-init/templates/profiles/gcp/attributes.yml +2 -0
  15. data/lib/plugins/inspec-init/templates/profiles/gcp/controls/example.rb +27 -0
  16. data/lib/plugins/inspec-init/templates/profiles/gcp/inspec.yml +19 -0
  17. data/lib/resource_support/aws.rb +76 -0
  18. data/lib/resource_support/aws/aws_backend_base.rb +12 -0
  19. data/lib/resource_support/aws/aws_backend_factory_mixin.rb +12 -0
  20. data/lib/resource_support/aws/aws_plural_resource_mixin.rb +24 -0
  21. data/lib/resource_support/aws/aws_resource_mixin.rb +69 -0
  22. data/lib/resource_support/aws/aws_singular_resource_mixin.rb +27 -0
  23. data/lib/resources/aws/aws_billing_report.rb +107 -0
  24. data/lib/resources/aws/aws_billing_reports.rb +74 -0
  25. data/lib/resources/aws/aws_cloudtrail_trail.rb +97 -0
  26. data/lib/resources/aws/aws_cloudtrail_trails.rb +51 -0
  27. data/lib/resources/aws/aws_cloudwatch_alarm.rb +67 -0
  28. data/lib/resources/aws/aws_cloudwatch_log_metric_filter.rb +105 -0
  29. data/lib/resources/aws/aws_config_delivery_channel.rb +74 -0
  30. data/lib/resources/aws/aws_config_recorder.rb +99 -0
  31. data/lib/resources/aws/aws_ebs_volume.rb +127 -0
  32. data/lib/resources/aws/aws_ebs_volumes.rb +69 -0
  33. data/lib/resources/aws/aws_ec2_instance.rb +162 -0
  34. data/lib/resources/aws/aws_ec2_instances.rb +69 -0
  35. data/lib/resources/aws/aws_ecs_cluster.rb +88 -0
  36. data/lib/resources/aws/aws_eks_cluster.rb +105 -0
  37. data/lib/resources/aws/aws_elb.rb +85 -0
  38. data/lib/resources/aws/aws_elbs.rb +84 -0
  39. data/lib/resources/aws/aws_flow_log.rb +106 -0
  40. data/lib/resources/aws/aws_iam_access_key.rb +112 -0
  41. data/lib/resources/aws/aws_iam_access_keys.rb +153 -0
  42. data/lib/resources/aws/aws_iam_group.rb +62 -0
  43. data/lib/resources/aws/aws_iam_groups.rb +56 -0
  44. data/lib/resources/aws/aws_iam_password_policy.rb +121 -0
  45. data/lib/resources/aws/aws_iam_policies.rb +57 -0
  46. data/lib/resources/aws/aws_iam_policy.rb +311 -0
  47. data/lib/resources/aws/aws_iam_role.rb +60 -0
  48. data/lib/resources/aws/aws_iam_root_user.rb +82 -0
  49. data/lib/resources/aws/aws_iam_user.rb +145 -0
  50. data/lib/resources/aws/aws_iam_users.rb +160 -0
  51. data/lib/resources/aws/aws_kms_key.rb +100 -0
  52. data/lib/resources/aws/aws_kms_keys.rb +58 -0
  53. data/lib/resources/aws/aws_rds_instance.rb +74 -0
  54. data/lib/resources/aws/aws_route_table.rb +67 -0
  55. data/lib/resources/aws/aws_route_tables.rb +64 -0
  56. data/lib/resources/aws/aws_s3_bucket.rb +142 -0
  57. data/lib/resources/aws/aws_s3_bucket_object.rb +87 -0
  58. data/lib/resources/aws/aws_s3_buckets.rb +52 -0
  59. data/lib/resources/aws/aws_security_group.rb +314 -0
  60. data/lib/resources/aws/aws_security_groups.rb +71 -0
  61. data/lib/resources/aws/aws_sns_subscription.rb +82 -0
  62. data/lib/resources/aws/aws_sns_topic.rb +57 -0
  63. data/lib/resources/aws/aws_sns_topics.rb +60 -0
  64. data/lib/resources/aws/aws_sqs_queue.rb +66 -0
  65. data/lib/resources/aws/aws_subnet.rb +92 -0
  66. data/lib/resources/aws/aws_subnets.rb +56 -0
  67. data/lib/resources/aws/aws_vpc.rb +77 -0
  68. data/lib/resources/aws/aws_vpcs.rb +55 -0
  69. data/lib/resources/azure/azure_backend.rb +379 -0
  70. data/lib/resources/azure/azure_generic_resource.rb +55 -0
  71. data/lib/resources/azure/azure_resource_group.rb +151 -0
  72. data/lib/resources/azure/azure_virtual_machine.rb +262 -0
  73. data/lib/resources/azure/azure_virtual_machine_data_disk.rb +131 -0
  74. metadata +202 -0
@@ -0,0 +1,145 @@
1
+ require "resource_support/aws/aws_singular_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-iam"
4
+
5
+ class AwsIamUser < Inspec.resource(1)
6
+ name "aws_iam_user"
7
+ desc "Verifies settings for AWS IAM user"
8
+ example <<~EXAMPLE
9
+ describe aws_iam_user(username: 'test_user') do
10
+ it { should have_mfa_enabled }
11
+ it { should_not have_console_password }
12
+ it { should_not have_inline_user_policies }
13
+ it { should_not have_attached_user_policies }
14
+ end
15
+ EXAMPLE
16
+ supports platform: "aws"
17
+
18
+ include AwsSingularResourceMixin
19
+ attr_reader :access_keys, :attached_policy_names, :attached_policy_arns, \
20
+ :has_console_password, :has_mfa_enabled, :inline_policy_names, :username
21
+ alias has_mfa_enabled? has_mfa_enabled
22
+ alias has_console_password? has_console_password
23
+
24
+ def name
25
+ Inspec.deprecate(:properties_aws_iam_user, "The aws_iam_user `name` property is deprecated. Please use `username` instead")
26
+ username
27
+ end
28
+
29
+ def to_s
30
+ "IAM User #{username}"
31
+ end
32
+
33
+ def has_attached_policies?
34
+ return nil unless exists?
35
+
36
+ !attached_policy_names.empty?
37
+ end
38
+
39
+ def has_inline_policies?
40
+ return nil unless exists?
41
+
42
+ !inline_policy_names.empty?
43
+ end
44
+
45
+ private
46
+
47
+ def validate_params(raw_params)
48
+ validated_params = check_resource_param_names(
49
+ raw_params: raw_params,
50
+ allowed_params: %i{username aws_user_struct name user},
51
+ allowed_scalar_name: :username,
52
+ allowed_scalar_type: String
53
+ )
54
+ # If someone passed :name, rename it to :username
55
+ if validated_params.key?(:name)
56
+ Inspec.deprecate(:properties_aws_iam_user, "The aws_iam_users `name` property is deprecated. Please use `username` instead")
57
+ validated_params[:username] = validated_params.delete(:name)
58
+ end
59
+
60
+ # If someone passed :user, rename it to :aws_user_struct
61
+ if validated_params.key?(:user)
62
+ Inspec.deprecate(:properties_aws_iam_user, "The aws_iam_users `user` property is deprecated. Please use `aws_user_struct` instead")
63
+ validated_params[:aws_user_struct] = validated_params.delete(:user)
64
+ end
65
+
66
+ if validated_params.empty?
67
+ raise ArgumentError, "You must provide a username to aws_iam_user."
68
+ end
69
+
70
+ validated_params
71
+ end
72
+
73
+ def fetch_from_api
74
+ backend = BackendFactory.create(inspec_runner)
75
+ @aws_user_struct ||= nil # silence unitialized warning
76
+ unless @aws_user_struct
77
+ begin
78
+ @aws_user_struct = backend.get_user(user_name: username)
79
+ rescue Aws::IAM::Errors::NoSuchEntity
80
+ @exists = false
81
+ @access_keys = []
82
+ @inline_policy_names = []
83
+ @attached_policy_arns = []
84
+ @attached_policy_names = []
85
+ return
86
+ end
87
+ end
88
+ # TODO: extract properties from aws_user_struct?
89
+
90
+ @exists = true
91
+
92
+ begin
93
+ _login_profile = backend.get_login_profile(user_name: username)
94
+ @has_console_password = true
95
+ # Password age also available here
96
+ rescue Aws::IAM::Errors::NoSuchEntity
97
+ @has_console_password = false
98
+ end
99
+
100
+ mfa_info = backend.list_mfa_devices(user_name: username)
101
+ @has_mfa_enabled = !mfa_info.mfa_devices.empty?
102
+
103
+ # TODO: consider returning InSpec AwsIamAccessKey objects
104
+ @access_keys = backend.list_access_keys(user_name: username).access_key_metadata
105
+ # If the above call fails, we get nil here; but we promise access_keys will be an array.
106
+ @access_keys ||= []
107
+
108
+ @inline_policy_names = backend.list_user_policies(user_name: username).policy_names
109
+
110
+ attached_policies = backend.list_attached_user_policies(user_name: username).attached_policies
111
+ @attached_policy_arns = attached_policies.map { |p| p[:policy_arn] }
112
+ @attached_policy_names = attached_policies.map { |p| p[:policy_name] }
113
+ end
114
+
115
+ class Backend
116
+ class AwsClientApi < AwsBackendBase
117
+ BackendFactory.set_default_backend(self)
118
+ self.aws_client_class = Aws::IAM::Client
119
+
120
+ def get_user(criteria)
121
+ aws_service_client.get_user(criteria)
122
+ end
123
+
124
+ def get_login_profile(criteria)
125
+ aws_service_client.get_login_profile(criteria)
126
+ end
127
+
128
+ def list_mfa_devices(criteria)
129
+ aws_service_client.list_mfa_devices(criteria)
130
+ end
131
+
132
+ def list_access_keys(criteria)
133
+ aws_service_client.list_access_keys(criteria)
134
+ end
135
+
136
+ def list_user_policies(criteria)
137
+ aws_service_client.list_user_policies(criteria)
138
+ end
139
+
140
+ def list_attached_user_policies(criteria)
141
+ aws_service_client.list_attached_user_policies(criteria)
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,160 @@
1
+ require "resource_support/aws/aws_plural_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-iam"
4
+
5
+ class AwsIamUsers < Inspec.resource(1)
6
+ name "aws_iam_users"
7
+ desc "Verifies settings for AWS IAM users"
8
+ example <<~EXAMPLE
9
+ describe aws_iam_users.where(has_mfa_enabled?: false) do
10
+ it { should_not exist }
11
+ end
12
+ describe aws_iam_users.where(has_console_password?: true) do
13
+ it { should exist }
14
+ end
15
+ describe aws_iam_users.where(has_inline_policies?: true) do
16
+ it { should_not exist }
17
+ end
18
+ describe aws_iam_users.where(has_attached_policies?: true) do
19
+ it { should_not exist }
20
+ end
21
+ EXAMPLE
22
+ supports platform: "aws"
23
+
24
+ include AwsPluralResourceMixin
25
+
26
+ def self.lazy_get_login_profile(row, _criterion, table)
27
+ backend = BackendFactory.create(table.resource.inspec_runner)
28
+ begin
29
+ _login_profile = backend.get_login_profile(user_name: row[:user_name])
30
+ row[:has_console_password] = true
31
+ rescue Aws::IAM::Errors::NoSuchEntity
32
+ row[:has_console_password] = false
33
+ end
34
+ row[:has_console_password?] = row[:has_console_password]
35
+ end
36
+
37
+ def self.lazy_list_mfa_devices(row, _criterion, table)
38
+ backend = BackendFactory.create(table.resource.inspec_runner)
39
+ begin
40
+ aws_mfa_devices = backend.list_mfa_devices(user_name: row[:user_name])
41
+ row[:has_mfa_enabled] = !aws_mfa_devices.mfa_devices.empty?
42
+ rescue Aws::IAM::Errors::NoSuchEntity
43
+ row[:has_mfa_enabled] = false
44
+ end
45
+ row[:has_mfa_enabled?] = row[:has_mfa_enabled]
46
+ end
47
+
48
+ def self.lazy_list_user_policies(row, _criterion, table)
49
+ backend = BackendFactory.create(table.resource.inspec_runner)
50
+ row[:inline_policy_names] = backend.list_user_policies(user_name: row[:user_name]).policy_names
51
+ row[:has_inline_policies] = !row[:inline_policy_names].empty?
52
+ row[:has_inline_policies?] = row[:has_inline_policies]
53
+ end
54
+
55
+ def self.lazy_list_attached_policies(row, _criterion, table)
56
+ backend = BackendFactory.create(table.resource.inspec_runner)
57
+ attached_policies = backend.list_attached_user_policies(user_name: row[:user_name]).attached_policies
58
+ row[:has_attached_policies] = !attached_policies.empty?
59
+ row[:has_attached_policies?] = row[:has_attached_policies]
60
+ row[:attached_policy_names] = attached_policies.map { |p| p[:policy_name] }
61
+ row[:attached_policy_arns] = attached_policies.map { |p| p[:policy_arn] }
62
+ end
63
+
64
+ filter = FilterTable.create
65
+
66
+ # These are included on the initial fetch
67
+ filter.register_column(:usernames, field: :user_name)
68
+ .register_column(:username) { |res| res.entries.map { |row| row[:user_name] } } # We should deprecate this; plural resources get plural properties
69
+ .register_column(:password_ever_used?, field: :password_ever_used?)
70
+ .register_column(:password_never_used?, field: :password_never_used?)
71
+ .register_column(:password_last_used_days_ago, field: :password_last_used_days_ago)
72
+
73
+ # Remaining properties / criteria are handled lazily, grouped by fetcher
74
+ filter.register_column(:has_console_password?, field: :has_console_password?, lazy: method(:lazy_get_login_profile))
75
+ .register_column(:has_console_password, field: :has_console_password, lazy: method(:lazy_get_login_profile))
76
+
77
+ filter.register_column(:has_mfa_enabled?, field: :has_mfa_enabled?, lazy: method(:lazy_list_mfa_devices))
78
+ .register_column(:has_mfa_enabled, field: :has_mfa_enabled, lazy: method(:lazy_list_mfa_devices))
79
+
80
+ filter.register_column(:has_inline_policies?, field: :has_inline_policies?, lazy: method(:lazy_list_user_policies))
81
+ .register_column(:has_inline_policies, field: :has_inline_policies, lazy: method(:lazy_list_user_policies))
82
+ .register_column(:inline_policy_names, field: :inline_policy_names, style: :simple, lazy: method(:lazy_list_user_policies))
83
+
84
+ filter.register_column(:has_attached_policies?, field: :has_attached_policies?, lazy: method(:lazy_list_attached_policies))
85
+ .register_column(:has_attached_policies, field: :has_attached_policies, lazy: method(:lazy_list_attached_policies))
86
+ .register_column(:attached_policy_names, field: :attached_policy_names, style: :simple, lazy: method(:lazy_list_attached_policies))
87
+ .register_column(:attached_policy_arns, field: :attached_policy_arns, style: :simple, lazy: method(:lazy_list_attached_policies))
88
+ filter.install_filter_methods_on_resource(self, :table)
89
+
90
+ def validate_params(raw_params)
91
+ # No params yet
92
+ unless raw_params.empty?
93
+ raise ArgumentError, "aws_iam_users does not accept resource parameters"
94
+ end
95
+
96
+ raw_params
97
+ end
98
+
99
+ def fetch_from_api_paginated(backend)
100
+ table = []
101
+ page_marker = nil
102
+ loop do
103
+ api_result = backend.list_users(marker: page_marker)
104
+ table += api_result.users.map(&:to_h)
105
+ page_marker = api_result.marker
106
+ break unless api_result.is_truncated
107
+ end
108
+ table
109
+ end
110
+
111
+ def fetch_from_api
112
+ backend = BackendFactory.create(inspec_runner)
113
+ @table = fetch_from_api_paginated(backend)
114
+
115
+ @table.each do |user|
116
+ password_last_used = user[:password_last_used]
117
+ user[:password_ever_used?] = !password_last_used.nil?
118
+ user[:password_never_used?] = password_last_used.nil?
119
+ if user[:password_ever_used?]
120
+ user[:password_last_used_days_ago] = ((Time.now - password_last_used) / (24 * 60 * 60)).to_i
121
+ end
122
+ end
123
+ @table
124
+ end
125
+
126
+ def to_s
127
+ "IAM Users"
128
+ end
129
+
130
+ #===========================================================================#
131
+ # Backend Implementation
132
+ #===========================================================================#
133
+ class Backend
134
+ class AwsClientApi < AwsBackendBase
135
+ BackendFactory.set_default_backend(self)
136
+ self.aws_client_class = Aws::IAM::Client
137
+
138
+ # TODO: delegate this out
139
+ def list_users(query = {})
140
+ aws_service_client.list_users(query)
141
+ end
142
+
143
+ def get_login_profile(query)
144
+ aws_service_client.get_login_profile(query)
145
+ end
146
+
147
+ def list_mfa_devices(query)
148
+ aws_service_client.list_mfa_devices(query)
149
+ end
150
+
151
+ def list_user_policies(query)
152
+ aws_service_client.list_user_policies(query)
153
+ end
154
+
155
+ def list_attached_user_policies(query)
156
+ aws_service_client.list_attached_user_policies(query)
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,100 @@
1
+ require "resource_support/aws/aws_singular_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-kms"
4
+
5
+ class AwsKmsKey < Inspec.resource(1)
6
+ name "aws_kms_key"
7
+ desc "Verifies settings for an individual AWS KMS Key"
8
+ example <<~EXAMPLE
9
+ describe aws_kms_key('arn:aws:kms:us-east-1::key/4321dcba-21io-23de-85he-ab0987654321') do
10
+ it { should exist }
11
+ end
12
+ EXAMPLE
13
+
14
+ supports platform: "aws"
15
+
16
+ include AwsSingularResourceMixin
17
+ attr_reader :key_id, :arn, :creation_date, :key_usage, :key_state, :description,
18
+ :deletion_date, :valid_to, :external, :has_key_expiration, :managed_by_aws,
19
+ :has_rotation_enabled, :enabled
20
+ # Use aliases for matchers
21
+ alias deletion_time deletion_date
22
+ alias invalidation_time valid_to
23
+ alias external? external
24
+ alias enabled? enabled
25
+ alias managed_by_aws? managed_by_aws
26
+ alias has_key_expiration? has_key_expiration
27
+ alias has_rotation_enabled? has_rotation_enabled
28
+
29
+ def to_s
30
+ "KMS Key #{@key_id}"
31
+ end
32
+
33
+ def created_days_ago
34
+ ((Time.now - creation_date) / (24 * 60 * 60)).to_i unless creation_date.nil?
35
+ end
36
+
37
+ private
38
+
39
+ def validate_params(raw_params)
40
+ validated_params = check_resource_param_names(
41
+ raw_params: raw_params,
42
+ allowed_params: [:key_id],
43
+ allowed_scalar_name: :key_id,
44
+ allowed_scalar_type: String
45
+ )
46
+
47
+ if validated_params.empty?
48
+ raise ArgumentError, "You must provide the parameter 'key_id' to aws_kms_key."
49
+ end
50
+
51
+ validated_params
52
+ end
53
+
54
+ def fetch_from_api
55
+ backend = BackendFactory.create(inspec_runner)
56
+
57
+ query = { key_id: @key_id }
58
+ catch_aws_errors do
59
+ begin
60
+ resp = backend.describe_key(query)
61
+
62
+ @exists = true
63
+ @key = resp.key_metadata.to_h
64
+ @key_id = @key[:key_id]
65
+ @arn = @key[:arn]
66
+ @creation_date = @key[:creation_date]
67
+ @enabled = @key[:enabled]
68
+ @description = @key[:description]
69
+ @key_usage = @key[:key_usage]
70
+ @key_state = @key[:key_state]
71
+ @deletion_date = @key[:deletion_date]
72
+ @valid_to = @key[:valid_to]
73
+ @external = @key[:origin] == "EXTERNAL"
74
+ @has_key_expiration = @key[:expiration_model] == "KEY_MATERIAL_EXPIRES"
75
+ @managed_by_aws = @key[:key_manager] == "AWS"
76
+
77
+ resp = backend.get_key_rotation_status(query)
78
+ @has_rotation_enabled = resp.key_rotation_enabled unless resp.empty?
79
+ rescue Aws::KMS::Errors::NotFoundException
80
+ @exists = false
81
+ return
82
+ end
83
+ end
84
+ end
85
+
86
+ class Backend
87
+ class AwsClientApi < AwsBackendBase
88
+ BackendFactory.set_default_backend(self)
89
+ self.aws_client_class = Aws::KMS::Client
90
+
91
+ def describe_key(query)
92
+ aws_service_client.describe_key(query)
93
+ end
94
+
95
+ def get_key_rotation_status(query)
96
+ aws_service_client.get_key_rotation_status(query)
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,58 @@
1
+ require "resource_support/aws/aws_plural_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-kms"
4
+
5
+ class AwsKmsKeys < Inspec.resource(1)
6
+ name "aws_kms_keys"
7
+ desc "Verifies settings for AWS KMS Keys in bulk"
8
+ example <<~EXAMPLE
9
+ describe aws_kms_keys do
10
+ it { should exist }
11
+ end
12
+ EXAMPLE
13
+ supports platform: "aws"
14
+
15
+ include AwsPluralResourceMixin
16
+ def validate_params(resource_params)
17
+ unless resource_params.empty?
18
+ raise ArgumentError, "aws_kms_keys does not accept resource parameters."
19
+ end
20
+
21
+ resource_params
22
+ end
23
+
24
+ # Underlying FilterTable implementation.
25
+ filter = FilterTable.create
26
+ filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
27
+ filter.register_column(:key_arns, field: :key_arn)
28
+ .register_column(:key_ids, field: :key_id)
29
+ filter.install_filter_methods_on_resource(self, :table)
30
+
31
+ def to_s
32
+ "KMS Keys"
33
+ end
34
+
35
+ def fetch_from_api
36
+ backend = BackendFactory.create(inspec_runner)
37
+ @table = []
38
+ pagination_opts = { limit: 1000 }
39
+ loop do
40
+ api_result = backend.list_keys(pagination_opts)
41
+ @table += api_result.keys.map(&:to_h)
42
+ break unless api_result.truncated
43
+
44
+ pagination_opts = { marker: api_result.next_marker }
45
+ end
46
+ end
47
+
48
+ class Backend
49
+ class AwsClientApi < AwsBackendBase
50
+ BackendFactory.set_default_backend(self)
51
+ self.aws_client_class = Aws::KMS::Client
52
+
53
+ def list_keys(query = {})
54
+ aws_service_client.list_keys(query)
55
+ end
56
+ end
57
+ end
58
+ end