inspec 4.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|