@@ -341,3 +341,173 @@ def test_unexpected_error(self, mock_get_identity):
341341 assert has_access is False
342342 assert 'Unexpected error validating EKS access' in message
343343 assert 'Unexpected error' in message
344+
345+ def test_assumed_role_with_iam_api_success (self ):
346+ """Test assumed role with successful IAM API call (IDC role case)."""
347+ # Mock session with both STS and IAM clients
348+ mock_session = Mock ()
349+ mock_sts_client = Mock ()
350+ mock_iam_client = Mock ()
351+
352+ def mock_client (service ):
353+ if service == 'sts' :
354+ return mock_sts_client
355+ elif service == 'iam' :
356+ return mock_iam_client
357+
358+ mock_session .client .side_effect = mock_client
359+
360+ # Mock STS response for IDC assumed role
361+ mock_sts_client .get_caller_identity .return_value = {
362+ 'Arn' : 'arn:aws:sts::123456789012:assumed-role/AWSReservedSSO_AdministratorAccess_abc123/user-session'
363+ }
364+
365+ # Mock IAM response with correct base role ARN
366+ mock_iam_client .get_role .return_value = {
367+ 'Role' : {
368+ 'Arn' : 'arn:aws:iam::123456789012:role/aws-reserved/sso.amazonaws.com/us-west-2/AWSReservedSSO_AdministratorAccess_abc123'
369+ }
370+ }
371+
372+ # Call function
373+ arn , identity_type = _get_current_aws_identity (mock_session )
374+
375+ # Assertions
376+ assert arn == 'arn:aws:iam::123456789012:role/aws-reserved/sso.amazonaws.com/us-west-2/AWSReservedSSO_AdministratorAccess_abc123'
377+ assert identity_type == 'assumed-role'
378+ mock_iam_client .get_role .assert_called_once_with (RoleName = 'AWSReservedSSO_AdministratorAccess_abc123' )
379+
380+ def test_assumed_role_with_iam_api_access_denied (self ):
381+ """Test assumed role with IAM API access denied (fallback to string replacement)."""
382+ # Mock session with both STS and IAM clients
383+ mock_session = Mock ()
384+ mock_sts_client = Mock ()
385+ mock_iam_client = Mock ()
386+
387+ def mock_client (service ):
388+ if service == 'sts' :
389+ return mock_sts_client
390+ elif service == 'iam' :
391+ return mock_iam_client
392+
393+ mock_session .client .side_effect = mock_client
394+
395+ # Mock STS response
396+ mock_sts_client .get_caller_identity .return_value = {
397+ 'Arn' : 'arn:aws:sts::123456789012:assumed-role/MyRole/session-name'
398+ }
399+
400+ # Mock IAM API failure (access denied)
401+ mock_iam_client .get_role .side_effect = ClientError (
402+ error_response = {'Error' : {'Code' : 'AccessDenied' , 'Message' : 'Access denied' }},
403+ operation_name = 'GetRole'
404+ )
405+
406+ # Call function
407+ arn , identity_type = _get_current_aws_identity (mock_session )
408+
409+ # Assertions - should fall back to string replacement
410+ assert arn == 'arn:aws:iam::123456789012:role/MyRole'
411+ assert identity_type == 'assumed-role'
412+ mock_iam_client .get_role .assert_called_once_with (RoleName = 'MyRole' )
413+
414+ def test_assumed_role_with_iam_api_role_not_found (self ):
415+ """Test assumed role with IAM API role not found (fallback to string replacement)."""
416+ # Mock session with both STS and IAM clients
417+ mock_session = Mock ()
418+ mock_sts_client = Mock ()
419+ mock_iam_client = Mock ()
420+
421+ def mock_client (service ):
422+ if service == 'sts' :
423+ return mock_sts_client
424+ elif service == 'iam' :
425+ return mock_iam_client
426+
427+ mock_session .client .side_effect = mock_client
428+
429+ # Mock STS response
430+ mock_sts_client .get_caller_identity .return_value = {
431+ 'Arn' : 'arn:aws:sts::123456789012:assumed-role/CrossAccountRole/session-name'
432+ }
433+
434+ # Mock IAM API failure (role not found - cross-account case)
435+ mock_iam_client .get_role .side_effect = ClientError (
436+ error_response = {'Error' : {'Code' : 'NoSuchEntity' , 'Message' : 'Role not found' }},
437+ operation_name = 'GetRole'
438+ )
439+
440+ # Call function
441+ arn , identity_type = _get_current_aws_identity (mock_session )
442+
443+ # Assertions - should fall back to string replacement
444+ assert arn == 'arn:aws:iam::123456789012:role/CrossAccountRole'
445+ assert identity_type == 'assumed-role'
446+ mock_iam_client .get_role .assert_called_once_with (RoleName = 'CrossAccountRole' )
447+
448+ def test_assumed_role_with_iam_api_unexpected_error (self ):
449+ """Test assumed role with IAM API unexpected error (fallback to string replacement)."""
450+ # Mock session with both STS and IAM clients
451+ mock_session = Mock ()
452+ mock_sts_client = Mock ()
453+ mock_iam_client = Mock ()
454+
455+ def mock_client (service ):
456+ if service == 'sts' :
457+ return mock_sts_client
458+ elif service == 'iam' :
459+ return mock_iam_client
460+
461+ mock_session .client .side_effect = mock_client
462+
463+ # Mock STS response
464+ mock_sts_client .get_caller_identity .return_value = {
465+ 'Arn' : 'arn:aws:sts::123456789012:assumed-role/MyRole/session-name'
466+ }
467+
468+ # Mock IAM API unexpected error
469+ mock_iam_client .get_role .side_effect = Exception ('Network timeout' )
470+
471+ # Call function
472+ arn , identity_type = _get_current_aws_identity (mock_session )
473+
474+ # Assertions - should fall back to string replacement
475+ assert arn == 'arn:aws:iam::123456789012:role/MyRole'
476+ assert identity_type == 'assumed-role'
477+ mock_iam_client .get_role .assert_called_once_with (RoleName = 'MyRole' )
478+
479+ def test_assumed_role_with_custom_path_success (self ):
480+ """Test assumed role with custom path retrieved via IAM API."""
481+ # Mock session with both STS and IAM clients
482+ mock_session = Mock ()
483+ mock_sts_client = Mock ()
484+ mock_iam_client = Mock ()
485+
486+ def mock_client (service ):
487+ if service == 'sts' :
488+ return mock_sts_client
489+ elif service == 'iam' :
490+ return mock_iam_client
491+
492+ mock_session .client .side_effect = mock_client
493+
494+ # Mock STS response
495+ mock_sts_client .get_caller_identity .return_value = {
496+ 'Arn' : 'arn:aws:sts::123456789012:assumed-role/MyCustomRole/session-name'
497+ }
498+
499+ # Mock IAM response with custom path
500+ mock_iam_client .get_role .return_value = {
501+ 'Role' : {
502+ 'Arn' : 'arn:aws:iam::123456789012:role/custom/path/MyCustomRole'
503+ }
504+ }
505+
506+ # Call function
507+ arn , identity_type = _get_current_aws_identity (mock_session )
508+
509+ # Assertions
510+ assert arn == 'arn:aws:iam::123456789012:role/custom/path/MyCustomRole'
511+ assert identity_type == 'assumed-role'
512+ mock_iam_client .get_role .assert_called_once_with (RoleName = 'MyCustomRole' )
513+
0 commit comments