mirror of
https://github.com/inspec/inspec
synced 2024-09-21 06:51:56 +00:00
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:
parent
660ab99d98
commit
033bc13aa0
8 changed files with 193 additions and 21 deletions
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
51
libraries/aws_iam_users.rb
Normal file
51
libraries/aws_iam_users.rb
Normal 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
|
|
@ -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
|
||||
|
|
3
test/integration/verify/controls/aws_iam_users.rb
Normal file
3
test/integration/verify/controls/aws_iam_users.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
describe aws_iam_users.where(has_console_password?: true).where(has_mfa_enabled?: false) do
|
||||
it { should exist }
|
||||
end
|
|
@ -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, []
|
||||
|
|
|
@ -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
|
||||
|
|
81
test/unit/resources/aws_iam_users_test.rb
Normal file
81
test/unit/resources/aws_iam_users_test.rb
Normal 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
|
Loading…
Reference in a new issue