inspec 4.22.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +63 -0
- data/inspec.gemspec +36 -0
- data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/Gemfile +11 -0
- data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/inspec-plugin-template.gemspec +43 -0
- data/lib/plugins/inspec-init/templates/profiles/aws/README.md +192 -0
- data/lib/plugins/inspec-init/templates/profiles/aws/attributes.yml +2 -0
- data/lib/plugins/inspec-init/templates/profiles/aws/controls/example.rb +39 -0
- data/lib/plugins/inspec-init/templates/profiles/aws/inspec.yml +22 -0
- data/lib/plugins/inspec-init/templates/profiles/azure/README.md +56 -0
- data/lib/plugins/inspec-init/templates/profiles/azure/controls/example.rb +14 -0
- data/lib/plugins/inspec-init/templates/profiles/azure/inspec.yml +14 -0
- data/lib/plugins/inspec-init/templates/profiles/gcp/README.md +66 -0
- data/lib/plugins/inspec-init/templates/profiles/gcp/attributes.yml +2 -0
- data/lib/plugins/inspec-init/templates/profiles/gcp/controls/example.rb +27 -0
- data/lib/plugins/inspec-init/templates/profiles/gcp/inspec.yml +19 -0
- data/lib/resource_support/aws.rb +76 -0
- data/lib/resource_support/aws/aws_backend_base.rb +12 -0
- data/lib/resource_support/aws/aws_backend_factory_mixin.rb +12 -0
- data/lib/resource_support/aws/aws_plural_resource_mixin.rb +24 -0
- data/lib/resource_support/aws/aws_resource_mixin.rb +69 -0
- data/lib/resource_support/aws/aws_singular_resource_mixin.rb +27 -0
- data/lib/resources/aws/aws_billing_report.rb +107 -0
- data/lib/resources/aws/aws_billing_reports.rb +74 -0
- data/lib/resources/aws/aws_cloudtrail_trail.rb +97 -0
- data/lib/resources/aws/aws_cloudtrail_trails.rb +51 -0
- data/lib/resources/aws/aws_cloudwatch_alarm.rb +67 -0
- data/lib/resources/aws/aws_cloudwatch_log_metric_filter.rb +105 -0
- data/lib/resources/aws/aws_config_delivery_channel.rb +74 -0
- data/lib/resources/aws/aws_config_recorder.rb +99 -0
- data/lib/resources/aws/aws_ebs_volume.rb +127 -0
- data/lib/resources/aws/aws_ebs_volumes.rb +69 -0
- data/lib/resources/aws/aws_ec2_instance.rb +162 -0
- data/lib/resources/aws/aws_ec2_instances.rb +69 -0
- data/lib/resources/aws/aws_ecs_cluster.rb +88 -0
- data/lib/resources/aws/aws_eks_cluster.rb +105 -0
- data/lib/resources/aws/aws_elb.rb +85 -0
- data/lib/resources/aws/aws_elbs.rb +84 -0
- data/lib/resources/aws/aws_flow_log.rb +106 -0
- data/lib/resources/aws/aws_iam_access_key.rb +112 -0
- data/lib/resources/aws/aws_iam_access_keys.rb +153 -0
- data/lib/resources/aws/aws_iam_group.rb +62 -0
- data/lib/resources/aws/aws_iam_groups.rb +56 -0
- data/lib/resources/aws/aws_iam_password_policy.rb +121 -0
- data/lib/resources/aws/aws_iam_policies.rb +57 -0
- data/lib/resources/aws/aws_iam_policy.rb +311 -0
- data/lib/resources/aws/aws_iam_role.rb +60 -0
- data/lib/resources/aws/aws_iam_root_user.rb +82 -0
- data/lib/resources/aws/aws_iam_user.rb +145 -0
- data/lib/resources/aws/aws_iam_users.rb +160 -0
- data/lib/resources/aws/aws_kms_key.rb +100 -0
- data/lib/resources/aws/aws_kms_keys.rb +58 -0
- data/lib/resources/aws/aws_rds_instance.rb +74 -0
- data/lib/resources/aws/aws_route_table.rb +67 -0
- data/lib/resources/aws/aws_route_tables.rb +64 -0
- data/lib/resources/aws/aws_s3_bucket.rb +142 -0
- data/lib/resources/aws/aws_s3_bucket_object.rb +87 -0
- data/lib/resources/aws/aws_s3_buckets.rb +52 -0
- data/lib/resources/aws/aws_security_group.rb +314 -0
- data/lib/resources/aws/aws_security_groups.rb +71 -0
- data/lib/resources/aws/aws_sns_subscription.rb +82 -0
- data/lib/resources/aws/aws_sns_topic.rb +57 -0
- data/lib/resources/aws/aws_sns_topics.rb +60 -0
- data/lib/resources/aws/aws_sqs_queue.rb +66 -0
- data/lib/resources/aws/aws_subnet.rb +92 -0
- data/lib/resources/aws/aws_subnets.rb +56 -0
- data/lib/resources/aws/aws_vpc.rb +77 -0
- data/lib/resources/aws/aws_vpcs.rb +55 -0
- data/lib/resources/azure/azure_backend.rb +379 -0
- data/lib/resources/azure/azure_generic_resource.rb +55 -0
- data/lib/resources/azure/azure_resource_group.rb +151 -0
- data/lib/resources/azure/azure_virtual_machine.rb +262 -0
- data/lib/resources/azure/azure_virtual_machine_data_disk.rb +131 -0
- 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
|