import datetime import os # These imports may show as linting errors in local IDE but will work in the test environment # pylint: disable=missing-module-docstring,unused-argument,redefined-outer-name import boto3 import pytest # Import moto for AWS service mocking import moto # Import AWS Lambda handler functions from src.handler import get_all_users, get_tags_for_user, \ get_tag_value_by_key, get_user_access_keys from config import Config from src.utils import days_diff # Create a global mock fixture for AWS mocks @pytest.fixture(scope='session', autouse=True) def aws_credentials(): """Set up mock AWS credentials for moto.""" os.environ["AWS_ACCESS_KEY_ID"] = "testing" os.environ["AWS_SECRET_ACCESS_KEY"] = "testing" os.environ["AWS_SECURITY_TOKEN"] = "testing" os.environ["AWS_SESSION_TOKEN"] = "testing" os.environ["AWS_DEFAULT_REGION"] = "us-east-1" # This makes moto work properly with latest boto os.environ["BOTO_CONFIG"] = "/dev/null" yield # AWS client fixtures @pytest.fixture(scope='function') def iam_client_fixture(): """Provide a mocked IAM client for testing.""" with moto.mock_aws(): # Return IAM client for testing yield boto3.client('iam', region_name='us-east-1') @pytest.fixture(scope='function') def ses_client_fixture(): """Provide a mocked SES client for testing.""" with moto.mock_ses(): # Return SES client for testing yield boto3.client('ses', region_name='us-east-1') @pytest.fixture def iam_user_name_fixture(): """Provide a sample IAM user name.""" return "bbabii" @pytest.fixture def iam_user_tags_fixture(): """Provide sample IAM user tags.""" return [ {"Key": "Name", "Value": "Borys Babii"}, {"Key": "Email", "Value": "boris.babii.sme@sonymusic.com"} ] @pytest.fixture(scope='function') def iam_test_fixture(iam_client_fixture): """Create test users with tags for IAM testing.""" config = Config() human_user_role = 'tech-user' # Example non-service role # Create users with tags - using prefix _ to mark as deliberately unused _ = iam_client_fixture.create_user( UserName='user1', Tags=[ {"Key": config.TAG_NAME_FULLNAME, "Value": "Shannon R. Larson"}, # Use config default 'name' {"Key": config.TAG_NAME_EMAIL, "Value": "user1@sonymusic.com"}, # Use config default 'email' {"Key": "watchdog_enabled", "Value": "always"}, {"Key": "notification_enabled", "Value": "always"}, {"Key": config.TAG_NAME_ROLE, "Value": human_user_role} ] ) _ = iam_client_fixture.create_user( UserName='user2', Tags=[ {"Key": config.TAG_NAME_FULLNAME, "Value": "James M. McClanahan"}, {"Key": config.TAG_NAME_EMAIL, "Value": "user2@sonymusic.com"}, {"Key": "watchdog_enabled", "Value": "always"}, {"Key": "notification_enabled", "Value": "always"}, {"Key": config.TAG_NAME_ROLE, "Value": human_user_role} ] ) _ = iam_client_fixture.create_user( UserName='user3', Tags=[ {"Key": config.TAG_NAME_FULLNAME, "Value": "User Three"}, # Changed name for uniqueness {"Key": config.TAG_NAME_EMAIL, "Value": "user3@sonymusic.com"}, # Changed email for uniqueness {"Key": config.TAG_NAME_ROLE, "Value": human_user_role} ] ) # Create a service user _ = iam_client_fixture.create_user( UserName='service_account_user', Tags=[ {"Key": config.TAG_NAME_FULLNAME, "Value": "Service Bot Account"}, {"Key": config.TAG_NAME_EMAIL, "Value": "servicebot@sonymusic.com"}, {"Key": config.TAG_NAME_ROLE, "Value": config.SERVICE_USER_VALUE} # e.g., 'service-user' ] ) # Create access key for user1 for testing _ = iam_client_fixture.create_access_key( UserName='user1' ) # Create access key for service_account_user for testing _ = iam_client_fixture.create_access_key( UserName='service_account_user' ) # Create login profile for user2 _ = iam_client_fixture.create_login_profile( UserName='user2', Password='12345', PasswordResetRequired=False ) yield # pylint: disable=unused-argument def test_get_all_users(iam_client_fixture, iam_test_fixture): """Test retrieving all IAM users from the AWS account.""" config = Config() users_data = get_all_users(iam_client_fixture, config=config) assert len(users_data) == 4 # Now expecting 3 human + 1 service user found_user1 = False found_user2 = False found_user3 = False found_service_user = False for user in users_data: if user['name'] == 'user1': found_user1 = True assert not user['IsServiceUser'] assert user['email'] == 'user1@sonymusic.com' assert user['FullName'] == 'Shannon R. Larson' assert user['Role'] == 'tech-user' elif user['name'] == 'user2': found_user2 = True assert not user['IsServiceUser'] assert user['email'] == 'user2@sonymusic.com' assert user['FullName'] == 'James M. McClanahan' elif user['name'] == 'user3': found_user3 = True assert not user['IsServiceUser'] assert user['email'] == 'user3@sonymusic.com' assert user['FullName'] == 'User Three' elif user['name'] == 'service_account_user': found_service_user = True assert user['IsServiceUser'] assert user['email'] == 'servicebot@sonymusic.com' assert user['FullName'] == 'Service Bot Account' assert user['Role'] == config.SERVICE_USER_VALUE assert found_user1, "user1 not found or processed correctly" assert found_user2, "user2 not found or processed correctly" assert found_user3, "user3 not found or processed correctly" assert found_service_user, "service_account_user not found or processed correctly" # pylint: disable=unused-argument def test_get_user_tags(iam_client_fixture, iam_test_fixture): """Test retrieving tags for specific IAM users.""" tags_user_1 = get_tags_for_user(iam_client_fixture, 'user1') tags_user_2 = get_tags_for_user(iam_client_fixture, 'user2') tags_user_3 = get_tags_for_user(iam_client_fixture, 'user3') assert len(tags_user_1) == 5 assert len(tags_user_2) == 5 assert len(tags_user_3) == 3 def test_get_tag_value_by_key(): """Test retrieving a specific tag value by its key from a list of tags.""" tags = [ {"Key": "Name", "Value": "James M. McClanahan"}, {"Key": "Email", "Value": "user2@sonymusic.com"} ] value = get_tag_value_by_key(tags, 'Name') assert value == 'James M. McClanahan' # pylint: disable=unused-argument def test_get_user_access_keys(iam_client_fixture, iam_test_fixture): """Test retrieving access keys for specific IAM users.""" access_keys_user1 = get_user_access_keys(iam_client_fixture, 'user1') access_keys_user2 = get_user_access_keys(iam_client_fixture, 'user2') assert access_keys_user2 == [] assert len(access_keys_user1) == 1 def test_days_diff(): """Test calculating the difference in days between two dates.""" start_date = datetime.datetime.now() end_date = start_date - datetime.timedelta(days=90) assert days_diff(start_date, end_date) == 90