Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ gem 'bundle'
# Note if the gem required is commented out, please raise a PR against the train-aws repo first
# In the mean time the gem can be added here for local development

# TODO: remove when https://github.com/inspec/train-aws/pull/457 is merged
gem 'aws-sdk-account', '~> 1.14'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inspec/train-aws#457 is merged.Please update Gemfile.


# Use Latest Inspec
gem 'inspec-bin'

Expand Down
48 changes: 48 additions & 0 deletions libraries/aws_account.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require "aws_backend"

class AwsAccount < AwsResourceBase
name "aws_account"
desc "Verifies contact information for an AWS Account."
example "
addr = { 'address_line_1' => '42 Wallaby Way', ... }
describe aws_account.contact_information do
it { should cmp addr }
end
"

def initialize(opts = {})
super(opts)
end

def resource_id
"AWS Account Contact Information"
end

def to_s
"AWS Account Contact Information"
end

def contact_information
@contact_information ||= catch_aws_errors do
@aws.account_client.get_contact_information.contact_information.to_h.transform_keys(&:to_s)
end
end

def billing_contact_information
@billing_contact_information ||= catch_aws_errors do
@aws.account_client.get_alternate_contact({alternate_contact_type: "BILLING"}).alternate_contact.to_h.transform_keys(&:to_s)
end
end

def operations_contact_information
@operations_contact_information ||= catch_aws_errors do
@aws.account_client.get_alternate_contact({alternate_contact_type: "OPERATIONS"}).alternate_contact.to_h.transform_keys(&:to_s)
end
end

def security_contact_information
@security_contact_information ||= catch_aws_errors do
@aws.account_client.get_alternate_contact({alternate_contact_type: "SECURITY"}).alternate_contact.to_h.transform_keys(&:to_s)
end
end
end
5 changes: 5 additions & 0 deletions libraries/aws_backend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
require "aws-sdk-waf"
require "aws-sdk-synthetics"
require "aws-sdk-apigatewayv2"
require "aws-sdk-account"

# AWS Inspec Backend Classes
#
Expand Down Expand Up @@ -337,6 +338,10 @@ def synthetics_client
def apigatewayv2_client
aws_client(Aws::ApiGatewayV2::Client)
end

def account_client
aws_client(Aws::Account::Client)
end
end

# Base class for AWS resources
Expand Down
74 changes: 74 additions & 0 deletions libraries/aws_iam_credential_report.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
require "csv"
require "aws_backend"

class AwsIamCredentialReport < AwsCollectionResourceBase
name "aws_iam_credential_report"
desc "Lists all users in the AWS account and the status of their credentials."

example "
describe aws_iam_credential_report.where(mfa_active: false) do
it { should_not exist }
end
"

attr_reader :table

FilterTable.create
.register_column(:user, field: :user)
.register_column(:arn, field: :arn)
.register_column(:user_creation_time, field: :user_creation_time)
.register_column(:password_enabled, field: :password_enabled)
.register_column(:password_last_used, field: :password_last_used)
.register_column(:password_last_changed, field: :password_last_changed)
.register_column(:password_next_rotation, field: :password_next_rotation)
.register_column(:mfa_active, field: :mfa_active)
.register_column(:access_key_1_active, field: :access_key_1_active)
.register_column(:access_key_1_last_rotated, field: :access_key_1_last_rotated)
.register_column(:access_key_1_last_used_date, field: :access_key_1_last_used_date)
.register_column(:access_key_1_last_used_region, field: :access_key_1_last_used_region)
.register_column(:access_key_1_last_used_service, field: :access_key_1_last_used_service)
.register_column(:access_key_2_active, field: :access_key_2_active)
.register_column(:access_key_2_last_rotated, field: :access_key_2_last_rotated)
.register_column(:access_key_2_last_used_date, field: :access_key_2_last_used_date)
.register_column(:access_key_2_last_used_region, field: :access_key_2_last_used_region)
.register_column(:access_key_2_last_used_service, field: :access_key_2_last_used_service)
.register_column(:cert_1_active, field: :cert_1_active)
.register_column(:cert_1_last_rotated, field: :cert_1_last_rotated)
.register_column(:cert_2_active, field: :cert_2_active)
.register_column(:cert_2_last_rotated, field: :cert_2_last_rotated)
.install_filter_methods_on_resource(self, :table)

def initialize(opts = {})
super(opts)
validate_parameters
@table = fetch_data
pp ["table", @table]
end

def to_s
"IAM Credential Report"
end

private

def fetch_data
catch_aws_errors do
@aws.iam_client.generate_credential_report
begin
attempts ||= 0
response = @aws.iam_client.get_credential_report
rescue Aws::IAM::Errors::ReportInProgress => e
if (attempts += 1) <= 5
Inspec::Log.warn "AWS IAM Credential Report still being generated - attempt #{attempts}/5."
sleep 5
retry
else
Inspec::Log.warn "AWS IAM Credential Report was not generated quickly enough."
raise e
end
end
report = CSV.parse(response.content, headers: true, header_converters: :symbol, converters: [:date_time, -> field { field == 'true' ? true : field == 'false' ? false : field }])
report.map(&:to_h)
end
end
end