A real-world working AwsIamUsers (#71)

* Add aws_iam_users

Signed-off-by: Chris Redekop <chris.redekop@d2l.com>

* Adding Filter table and Collect User Details to aws_iam_users.rb

Signed-off-by: Chris Redekop <chris.redekop@d2l.com>

* Adding Filter table and Collect User Details to aws_iam_users.rb

Signed-off-by: Chris Redekop <chris.redekop@d2l.com>

* Adding Filter table and Collect User Details to aws_iam_users.rb

Signed-off-by: Chris Redekop <chris.redekop@d2l.com>

* Get an aws_iam_users integration test to pass

Signed-off-by: Chris Redekop <chris.redekop@d2l.com>

* Fix RuboCop issues and tests

Signed-off-by: Chris Redekop <chris.redekop@d2l.com>

* Improving code based on PR feedback

Signed-off-by: Chris Redekop <chris.redekop@d2l.com>
This commit is contained in:
Chris Redekop 2017-08-08 09:50:35 -04:00 committed by Christoph Hartmann
parent 660ab99d98
commit 033bc13aa0
8 changed files with 193 additions and 21 deletions

View file

@ -7,16 +7,18 @@ class AwsIamUser < Inspec.resource(1)
name 'aws_iam_user'
desc 'Verifies settings for AWS IAM user'
example "
describe aws_iam_user('test_user_name') do
describe aws_iam_user(name: 'test_user_name') do
its('has_mfa_enabled?') { should be false }
its('has_console_password?') { should be true }
end
"
def initialize(name, aws_user_provider = AwsIam::UserProvider.new,
access_key_factory = AwsIamAccessKeyFactory.new)
@name = name
@user = aws_user_provider.user(name)
def initialize(
opts,
aws_user_provider = AwsIam::UserProvider.new,
access_key_factory = AwsIamAccessKeyFactory.new
)
@user = opts[:user]
@user = aws_user_provider.user(opts[:name]) if @user.nil?
@access_key_factory = access_key_factory
end
@ -34,8 +36,12 @@ class AwsIamUser < Inspec.resource(1)
}
end
def name
@user[:name]
end
def to_s
"IAM User #{@name}"
"IAM User #{name}"
end
class AwsIamAccessKeyFactory

View file

@ -20,6 +20,10 @@ module AwsIam
end
class << self
def name(aws_user)
aws_user.name
end
def has_mfa_enabled?(aws_user)
!aws_user.mfa_devices.first.nil?
end
@ -36,6 +40,7 @@ module AwsIam
def convert(aws_user)
{
name: name(aws_user),
has_mfa_enabled?: has_mfa_enabled?(aws_user),
has_console_password?: has_console_password?(aws_user),
access_keys: access_keys(aws_user),

View file

@ -0,0 +1,51 @@
# 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
'
filter = FilterTable.create
filter.add_accessor(:where)
.add_accessor(:entries)
.add(:exists?) { |x| !x.entries.empty? }
filter.connect(self, :collect_user_details)
def initialize(aws_user_provider = AwsIam::UserProvider.new,
user_factory = AwsIamUserFactory.new)
@user_provider = aws_user_provider
@user_factory = user_factory
end
def collect_user_details
@users_cache ||= @user_provider.list_users unless @user_provider.nil?
end
def users
users = []
users ||= @user_provider.list_users unless @user_provider.nil?
users.map { |user|
@user_factory.create_user(user)
}
end
def to_s
'IAM Users'
end
class AwsIamUserFactory
def create_user(user)
AwsIamUser.new(user: user)
end
end
end

View file

@ -13,16 +13,16 @@ access_key_user = attribute(
default: 'default.access_key_user',
description: 'Name of IAM user access_key_user')
describe aws_iam_user(mfa_not_enabled_user) do
describe aws_iam_user(name: mfa_not_enabled_user) do
it { should_not have_mfa_enabled }
it { should_not have_console_password }
end
describe aws_iam_user(console_password_enabled_user) do
describe aws_iam_user(name: console_password_enabled_user) do
it { should have_console_password }
end
aws_iam_user(access_key_user).access_keys.each { |access_key|
aws_iam_user(name: access_key_user).access_keys.each { |access_key|
describe access_key do
it { should be_active }
end

View file

@ -0,0 +1,3 @@
describe aws_iam_users.where(has_console_password?: true).where(has_mfa_enabled?: false) do
it { should exist }
end

View file

@ -24,15 +24,15 @@ class AwsIamUserProviderTest < Minitest::Test
def test_list_users
@mock_iam_resource.expect(
:users,
[create_mock_user, create_mock_user, create_mock_user],
[create_mock_user, create_mock_user],
)
mock_user_output = {
name: Username,
has_mfa_enabled?: true,
has_console_password?: true,
access_keys: [],
}
assert @user_provider.list_users == [mock_user_output, mock_user_output,
mock_user_output]
assert @user_provider.list_users == [mock_user_output, mock_user_output]
end
def test_list_users_no_users
@ -107,6 +107,7 @@ class AwsIamUserProviderTest < Minitest::Test
mock_login_profile.expect :create_date, has_console_password ? 'date' : nil
mock_user = Minitest::Mock.new
mock_user.expect :name, Username
mock_user.expect :mfa_devices, has_mfa_enabled ? ['device'] : []
mock_user.expect :login_profile, mock_login_profile
mock_user.expect :access_keys, access_keys
@ -119,6 +120,7 @@ class AwsIamUserProviderTest < Minitest::Test
end
mock_user = Minitest::Mock.new
mock_user.expect :name, Username
mock_user.expect :mfa_devices, []
mock_user.expect :login_profile, mock_login_profile
mock_user.expect :access_keys, []

View file

@ -16,7 +16,12 @@ class AwsIamUserTest < Minitest::Test
{ has_mfa_enabled?: true },
[Username],
)
assert AwsIamUser.new(Username, @mock_user_provider).has_mfa_enabled?
assert(
AwsIamUser.new(
{ name: Username },
@mock_user_provider,
).has_mfa_enabled?,
)
end
def test_mfa_enabled_returns_false_if_mfa_is_not_enabled
@ -25,7 +30,12 @@ class AwsIamUserTest < Minitest::Test
{ has_mfa_enabled?: false },
[Username],
)
refute AwsIamUser.new(Username, @mock_user_provider).has_mfa_enabled?
refute(
AwsIamUser.new(
{ name: Username },
@mock_user_provider,
).has_mfa_enabled?,
)
end
def test_console_password_returns_true_if_console_password_has_been_set
@ -34,7 +44,12 @@ class AwsIamUserTest < Minitest::Test
{ has_console_password?: true },
[Username],
)
assert AwsIamUser.new(Username, @mock_user_provider).has_console_password?
assert(
AwsIamUser.new(
{ name: Username },
@mock_user_provider,
).has_console_password?,
)
end
def test_console_password_returns_false_if_console_password_has_not_been_set
@ -43,7 +58,12 @@ class AwsIamUserTest < Minitest::Test
{ has_console_password?: false },
[Username],
)
refute AwsIamUser.new(Username, @mock_user_provider).has_console_password?
refute(
AwsIamUser.new(
{ name: Username },
@mock_user_provider,
).has_console_password?,
)
end
def test_that_access_keys_returns_aws_iam_access_key_resources
@ -65,7 +85,7 @@ class AwsIamUserTest < Minitest::Test
assert_equal(
stub_access_key_resource,
AwsIamUser.new(
Username,
{ name: Username },
@mock_user_provider,
mock_access_key_factory,
).access_keys[0],
@ -75,9 +95,13 @@ class AwsIamUserTest < Minitest::Test
end
def test_to_s
@mock_user_provider.expect :user, { has_mfa_enabled?: true }, [Username]
expected = 'IAM User test'
test = AwsIamUser.new(Username, @mock_user_provider).to_s
@mock_user_provider.expect(
:user,
{ name: Username, has_mfa_enabled?: true },
[Username],
)
expected = "IAM User #{Username}"
test = AwsIamUser.new({ name: Username }, @mock_user_provider).to_s
assert_equal expected, test
end
end

View file

@ -0,0 +1,81 @@
# author: Adnan Duric
# author: Steffanie Freeman
# author: Simon Varlow
# author: Chris Redekop
require 'aws-sdk'
require 'helper'
require 'aws_iam_users'
class AwsIamUsersTest < Minitest::Test
def setup
@mock_user_factory = Minitest::Mock.new
end
def test_users_nil_user_provider_returns_empty_list
cut = AwsIamUsers.new(nil, @mock_user_factory)
assert_equal(cut.users, [])
end
def test_users_empty_list_user_provider_returns_empty_list
cut = AwsIamUsers.new(create_mock_user_provider, @mock_user_factory)
assert_equal(cut.users, [])
end
def test_users_returns_true_for_all_users_if_mfa_enabled
cut = AwsIamUsers.new(
create_mock_user_provider(create_mock_users([true, true])),
@mock_user_factory,
)
cut.users.each do |user|
assert user.has_mfa_enabled?
end
end
[
{
name: 'test_where_returns_no_matching_rows',
user_material: [false],
}, {
name: 'test_where_returns_some_matching_rows',
user_material: [true, false],
}, {
name: 'test_where_returns_all_matching_rows',
user_material: [true],
}
].each do |test_material|
define_method(test_material[:name]) do
cut = AwsIamUsers.new(
create_mock_user_provider(
create_mock_users(test_material[:user_material]),
),
@mock_user_factory,
)
results = cut.where(has_mfa_enabled?: true)
expected_count = test_material[:user_material].count { |x| x }
assert_equal expected_count > 0, results.exists?
assert_equal expected_count, results.entries.length
end
end
def create_mock_user_provider(user_list = [])
mock_user_provider = Minitest::Mock.new
mock_user_provider.expect :list_users, user_list
mock_user_provider.expect :nil?, false
mock_user_provider
end
def create_mock_users(has_mfa_enableds = [])
has_mfa_enableds.map { |x| create_mock_user(x) }
end
def create_mock_user(has_mfa_enabled = true)
{ has_mfa_enabled?: has_mfa_enabled }
end
end