1- from typing import Dict , Optional
1+ from typing import Any , Callable , Dict , List , Optional
22
33from samtranslator .internal .managed_policies import get_bundled_managed_policy_map
44from samtranslator .internal .types import GetManagedPolicyMap
@@ -60,6 +60,34 @@ def _get_managed_policy_arn(
6060 return name
6161
6262
63+ def _convert_intrinsic_if_values (
64+ intrinsic_if : Dict [str , List [Any ]], is_convertible : Callable [[Any ], Any ], convert : Callable [[Any ], Any ]
65+ ) -> Dict [str , List [Any ]]:
66+ """
67+ Convert the true and false value of the intrinsic if function according to
68+ `convert` function.
69+
70+ :param intrinsic_if: A dict of the form {"Fn::If": [condition, value_if_true, value_if_false]}
71+ :type intrinsic_if: Dict[str, List[Any]]
72+ :param is_convertible: The function used to decide if the value must be converted
73+ :type convert: Callable[[Any], Any]
74+ :param convert: The function used to make the conversion
75+ :type convert: Callable[[Any], Any]
76+ :return: The input dict with values converted
77+ :rtype: Dict[str, List[Any]]
78+ """
79+ value_if_true = intrinsic_if ["Fn::If" ][1 ]
80+ value_if_false = intrinsic_if ["Fn::If" ][2 ]
81+
82+ if is_convertible (value_if_true ):
83+ intrinsic_if ["Fn::If" ][1 ] = convert (value_if_true )
84+
85+ if is_convertible (value_if_false ):
86+ intrinsic_if ["Fn::If" ][2 ] = convert (value_if_false )
87+
88+ return intrinsic_if
89+
90+
6391def construct_role_for_resource ( # type: ignore[no-untyped-def] # noqa: PLR0913
6492 resource_logical_id ,
6593 attributes ,
@@ -102,23 +130,16 @@ def construct_role_for_resource( # type: ignore[no-untyped-def] # noqa: PLR0913
102130 for index , policy_entry in enumerate (resource_policies .get ()):
103131 if policy_entry .type is PolicyTypes .POLICY_STATEMENT :
104132 if is_intrinsic_if (policy_entry .data ):
105- intrinsic_if = policy_entry .data
106- then_statement = intrinsic_if ["Fn::If" ][1 ]
107- else_statement = intrinsic_if ["Fn::If" ][2 ]
108-
109- if not is_intrinsic_no_value (then_statement ):
110- then_statement = {
111- "PolicyName" : execution_role .logical_id + "Policy" + str (index ),
112- "PolicyDocument" : then_statement ,
113- }
114- intrinsic_if ["Fn::If" ][1 ] = then_statement
115-
116- if not is_intrinsic_no_value (else_statement ):
117- else_statement = {
118- "PolicyName" : execution_role .logical_id + "Policy" + str (index ),
119- "PolicyDocument" : else_statement ,
120- }
121- intrinsic_if ["Fn::If" ][2 ] = else_statement
133+ intrinsic_if = _convert_intrinsic_if_values (
134+ policy_entry .data ,
135+ lambda value : not is_intrinsic_no_value (value ),
136+ lambda value : (
137+ {
138+ "PolicyName" : execution_role .logical_id + "Policy" + str (index ), # noqa: B023
139+ "PolicyDocument" : value ,
140+ }
141+ ),
142+ )
122143
123144 policy_documents .append (intrinsic_if )
124145
@@ -134,7 +155,7 @@ def construct_role_for_resource( # type: ignore[no-untyped-def] # noqa: PLR0913
134155 # There are three options:
135156 # Managed Policy Name (string): Try to convert to Managed Policy ARN
136157 # Managed Policy Arn (string): Insert it directly into the list
137- # Intrinsic Function (dict): Insert it directly into the list
158+ # Intrinsic Function (dict): Try to convert each statement to Managed Policy Arn
138159 #
139160 # When you insert into managed_policy_arns list, de-dupe to prevent same ARN from showing up twice
140161 #
@@ -146,6 +167,12 @@ def construct_role_for_resource( # type: ignore[no-untyped-def] # noqa: PLR0913
146167 managed_policy_map ,
147168 get_managed_policy_map ,
148169 )
170+ elif is_intrinsic_if (policy_arn ):
171+ policy_arn = _convert_intrinsic_if_values (
172+ policy_arn ,
173+ lambda value : not is_intrinsic_no_value (value ) and isinstance (value , str ),
174+ lambda value : _get_managed_policy_arn (value , managed_policy_map , get_managed_policy_map ),
175+ )
149176
150177 # De-Duplicate managed policy arns before inserting. Mainly useful
151178 # when customer specifies a managed policy which is already inserted
0 commit comments