inspec/lib/resources/aws/aws_iam_users.rb
Richard Nixon 47e4c578e0 Fix aws-iam-users pagination (#2761)
* Fix aws-iam-users pagination

PROBLEM: aws-iam-users resource only retrieves 100 records due to pagination
in the AWS IAM list_users function.

FIX: Iterate over all the pages using the AWS pagination variables `marker`
and `is_truncated`

Signed-off-by: Richard Nixon <richard.nixon@btinternet.com>
2018-03-02 09:14:05 -05:00

108 lines
3.3 KiB
Ruby

# author: Alex Bedley
# author: Steffanie Freeman
# author: Simon Varlow
# author: Chris Redekop
class AwsIamUsers < Inspec.resource(1)
name 'aws_iam_users'
desc 'Verifies settings for AWS IAM users'
example '
describe aws_iam_users.where(has_mfa_enabled?: false) do
it { should_not exist }
end
describe aws_iam_users.where(has_console_password?: true) do
it { should exist }
end
'
supports platform: 'aws'
include AwsPluralResourceMixin
filter = FilterTable.create
filter.add_accessor(:where)
.add_accessor(:entries)
.add(:exists?) { |x| !x.entries.empty? }
.add(:has_mfa_enabled?, field: :has_mfa_enabled)
.add(:has_console_password?, field: :has_console_password)
.add(:password_ever_used?, field: :password_ever_used?)
.add(:password_never_used?, field: :password_never_used?)
.add(:password_last_used_days_ago, field: :password_last_used_days_ago)
.add(:username, field: :user_name)
filter.connect(self, :table)
def validate_params(raw_params)
# No params yet
unless raw_params.empty?
raise ArgumentError, 'aws_iam_users does not accept resource parameters'
end
raw_params
end
def fetch_from_api_paginated(backend)
table = []
page_marker = nil
loop do
api_result = backend.list_users(marker: page_marker)
table += api_result.users.map(&:to_h)
page_marker = api_result.marker
break unless api_result.is_truncated
end
table
end
def fetch_from_api
backend = BackendFactory.create(inspec_runner)
@table = fetch_from_api_paginated(backend)
# TODO: lazy columns - https://github.com/chef/inspec-aws/issues/100
@table.each do |user|
begin
_login_profile = backend.get_login_profile(user_name: user[:user_name])
user[:has_console_password] = true
rescue Aws::IAM::Errors::NoSuchEntity
user[:has_console_password] = false
end
user[:has_console_password?] = user[:has_console_password]
begin
aws_mfa_devices = backend.list_mfa_devices(user_name: user[:user_name])
user[:has_mfa_enabled] = !aws_mfa_devices.mfa_devices.empty?
rescue Aws::IAM::Errors::NoSuchEntity
user[:has_mfa_enabled] = false
end
user[:has_mfa_enabled?] = user[:has_mfa_enabled]
password_last_used = user[:password_last_used]
user[:password_ever_used?] = !password_last_used.nil?
user[:password_never_used?] = password_last_used.nil?
next unless user[:password_ever_used?]
user[:password_last_used_days_ago] = ((Time.now - password_last_used) / (24*60*60)).to_i
end
@table
end
def to_s
'IAM Users'
end
#===========================================================================#
# Backend Implementation
#===========================================================================#
class Backend
class AwsClientApi < AwsBackendBase
BackendFactory.set_default_backend(self)
self.aws_client_class = Aws::IAM::Client
# TODO: delegate this out
def list_users(query = {})
aws_service_client.list_users(query)
end
def get_login_profile(query)
aws_service_client.get_login_profile(query)
end
def list_mfa_devices(query)
aws_service_client.list_mfa_devices(query)
end
end
end
end