require "helper" require "inspec/resource" require "resources/aws/aws_iam_users" require "resource_support/aws" # Maiusb = Mock AwsIamUsers::BackendFactory # Abbreviation not used outside of this file class AwsIamUsersTestConstructor < Minitest::Test def setup AwsIamUsers::BackendFactory.select(Maiusb::Empty) end def test_users_no_params_does_not_explode AwsIamUsers.new end def test_users_all_params_rejected assert_raises(ArgumentError) { AwsIamUsers.new(something: "somevalue") } end end class AwsIamUsersTestFilterCriteria < Minitest::Test def setup # Reset to empty, that's harmless AwsIamUsers::BackendFactory.select(Maiusb::Empty) end #------------------------------------------# # Open Filter #------------------------------------------# def test_users_empty_result_when_no_users_no_criteria users = AwsIamUsers.new.where {} assert users.entries.empty? end def test_users_all_returned_when_some_users_no_criteria AwsIamUsers::BackendFactory.select(Maiusb::Basic) users = AwsIamUsers.new.where {} assert(3, users.entries.count) end #------------------------------------------# # has_mfa_enabled? #------------------------------------------# def test_users_criteria_has_mfa_enabled AwsIamUsers::BackendFactory.select(Maiusb::Basic) users = AwsIamUsers.new.where { has_mfa_enabled } assert(1, users.entries.count) assert_includes users.usernames, "carol" refute_includes users.usernames, "alice" end #------------------------------------------# # has_console_password? #------------------------------------------# def test_users_criteria_has_console_password? AwsIamUsers::BackendFactory.select(Maiusb::Basic) users = AwsIamUsers.new.where { has_console_password } assert(2, users.entries.count) assert_includes users.usernames, "carol" refute_includes users.usernames, "alice" end #------------------------------------------# # password_ever_used? #------------------------------------------# def test_users_criteria_password_ever_used? AwsIamUsers::BackendFactory.select(Maiusb::Basic) users = AwsIamUsers.new.where { password_ever_used? } assert(2, users.entries.count) assert_includes users.usernames, "carol" refute_includes users.usernames, "alice" end #------------------------------------------# # password_never_used? #------------------------------------------# def test_users_criteria_password_never_used? AwsIamUsers::BackendFactory.select(Maiusb::Basic) users = AwsIamUsers.new.where { password_never_used? } assert(1, users.entries.count) assert_includes users.usernames, "alice" refute_includes users.usernames, "carol" end #------------------------------------------# # password_last_used_days_ago #------------------------------------------# def test_users_criteria_has_password_last_used_days_ago_10 AwsIamUsers::BackendFactory.select(Maiusb::Basic) users = AwsIamUsers.new.where(password_last_used_days_ago: 10) assert(1, users.entries.count) assert_includes users.usernames, "bob" refute_includes users.usernames, "alice" end #------------------------------------------# # has_inline_policies #------------------------------------------# def test_users_have_inline_policies AwsIamUsers::BackendFactory.select(Maiusb::Basic) users = AwsIamUsers.new.where(has_inline_policies?: true) assert_equal(2, users.entries.count) assert_includes users.usernames, "bob" assert_includes users.usernames, "carol" refute_includes users.usernames, "alice" users.inline_policy_names.each do |name| assert_kind_of(String, name) end assert_includes users.inline_policy_names, "bob-inline-01" assert_includes users.inline_policy_names, "bob-inline-02" assert_includes users.inline_policy_names, "carol-inline-01" assert_equal(3, users.inline_policy_names.count) end #------------------------------------------# # has_attached_policies #------------------------------------------# def test_users_have_attached_policies AwsIamUsers::BackendFactory.select(Maiusb::Basic) users = AwsIamUsers.new.where(has_attached_policies: true) assert_equal(2, users.entries.count) assert_includes users.usernames, "bob" assert_includes users.usernames, "carol" refute_includes users.usernames, "alice" users.attached_policy_names.each do |name| assert_kind_of(String, name) end assert_includes users.attached_policy_names, "AdministratorAccess" assert_includes users.attached_policy_names, "ReadOnlyAccess" assert_equal(2, users.attached_policy_names.count) users.attached_policy_arns.each do |arn| assert_kind_of(String, arn) end assert_includes users.attached_policy_arns, "arn:aws:iam::aws:policy/ReadOnlyAccess" assert_equal(3, users.attached_policy_arns.count) end end #=============================================================================# # Test Fixture Classes #=============================================================================# module Maiusb # -------------------------------- # Empty - No users # -------------------------------- class Empty < AwsBackendBase def list_users(criteria = {}) OpenStruct.new({ users: [], }) end def get_login_profile(criteria) raise Aws::IAM::Errors::NoSuchEntity.new("No login profile for #{criteria[:user_name]}", "Nope") end def list_mfa_devices(_criteria) OpenStruct.new({ mfa_devices: [], }) end end # -------------------------------- # Basic - 3 Users # -------------------------------- # Alice has no password or MFA device # Bob has a password but no MFA device # Carol has a password and MFA device class Basic < AwsBackendBase # arn, path, user_id omitted def list_users(criteria = {}) OpenStruct.new({ users: [ OpenStruct.new({ user_name: "alice", create_date: DateTime.parse("2017-10-10T16:19:30Z"), # Password last used is absent, never logged in w/ password }), OpenStruct.new({ user_name: "bob", create_date: DateTime.parse("2017-11-06T16:19:30Z"), password_last_used: Time.now - 10 * 24 * 60 * 60, }), OpenStruct.new({ user_name: "carol", create_date: DateTime.parse("2017-10-10T16:19:30Z"), password_last_used: Time.now - 91 * 24 * 60 * 60, }), ], }) end def get_login_profile(criteria) if %w{bob carol}.include?(criteria[:user_name]) OpenStruct.new({ login_profile: OpenStruct.new({ user_name: criteria[:user_name], created_date: DateTime.parse("2017-10-10T16:19:30Z"), }), }) else raise Aws::IAM::Errors::NoSuchEntity.new("No login profile for #{criteria[:user_name]}", "Nope") end end def list_mfa_devices(criteria) if ["carol"].include?(criteria[:user_name]) OpenStruct.new({ mfa_devices: [ OpenStruct.new({ user_name: criteria[:user_name], serial_number: "1234567890", enable_date: DateTime.parse("2017-10-10T16:19:30Z"), }), ], }) else OpenStruct.new({ mfa_devices: [], }) end end def list_user_policies(query) people = { "alice" => Aws::IAM::Types::ListUserPoliciesResponse.new( policy_names: [] ), "bob" => Aws::IAM::Types::ListUserPoliciesResponse.new( policy_names: %w{bob-inline-01 bob-inline-02} ), "carol" => Aws::IAM::Types::ListUserPoliciesResponse.new( policy_names: ["carol-inline-01"] ), } people[query[:user_name]] end def list_attached_user_policies(query) people = { "alice" => Aws::IAM::Types::ListAttachedUserPoliciesResponse.new( attached_policies: [] ), "bob" => Aws::IAM::Types::ListAttachedUserPoliciesResponse.new( attached_policies: [ { policy_arn: "arn:aws:iam::aws:policy/AdministratorAccess", policy_name: "AdministratorAccess", }, ] ), "carol" => Aws::IAM::Types::ListAttachedUserPoliciesResponse.new( attached_policies: [ { policy_arn: "arn:aws:iam::aws:policy/ReadOnlyAccess", policy_name: "ReadOnlyAccess", }, { policy_arn: "arn:aws:iam::123456789012:policy/some-policy", policy_name: "AdministratorAccess", }, ] ), } people[query[:user_name]] end end end