@@ -1522,24 +1522,27 @@ def _merge_s3_notification_config(self, existing_config, new_config):
15221522 final_config .append (new_config )
15231523 return final_config
15241524
1525- def add_permission_for_s3_event (self , bucket , function_arn ):
1526- # type: (str, str) -> None
1525+ def add_permission_for_s3_event (self , bucket , function_arn , account_id ):
1526+ # type: (str, str, str ) -> None
15271527 bucket_arn = 'arn:{partition}:s3:::{bucket}' .format (
15281528 partition = self .partition_name , bucket = bucket )
15291529 self ._add_lambda_permission_if_needed (
15301530 source_arn = bucket_arn ,
15311531 function_arn = function_arn ,
15321532 service_name = 's3' ,
1533+ source_account = account_id ,
15331534 )
15341535
1535- def remove_permission_for_s3_event (self , bucket , function_arn ):
1536- # type: (str, str) -> None
1536+ def remove_permission_for_s3_event (self , bucket , function_arn ,
1537+ account_id ):
1538+ # type: (str, str, str) -> None
15371539 bucket_arn = 'arn:{partition}:s3:::{bucket}' .format (
15381540 partition = self .partition_name , bucket = bucket )
15391541 self ._remove_lambda_permission_if_needed (
15401542 source_arn = bucket_arn ,
15411543 function_arn = function_arn ,
15421544 service_name = 's3' ,
1545+ source_account = account_id ,
15431546 )
15441547
15451548 def disconnect_s3_bucket_from_lambda (self , bucket , function_arn ):
@@ -1562,22 +1565,25 @@ def disconnect_s3_bucket_from_lambda(self, bucket, function_arn):
15621565 )
15631566
15641567 def _add_lambda_permission_if_needed (self , source_arn , function_arn ,
1565- service_name ):
1566- # type: (str, str, str) -> None
1568+ service_name , source_account = None ):
1569+ # type: (str, str, str, Optional[str] ) -> None
15671570 policy = self .get_function_policy (function_arn )
15681571 if self ._policy_gives_access (policy , source_arn , service_name ):
15691572 return
15701573 random_id = self ._random_id ()
15711574 dns_suffix = self .endpoint_dns_suffix_from_arn (source_arn )
1572- self ._client ('lambda' ).add_permission (
1573- Action = 'lambda:InvokeFunction' ,
1574- FunctionName = function_arn ,
1575- StatementId = random_id ,
1576- Principal = self .service_principal (service_name ,
1577- self .region_name ,
1578- dns_suffix ),
1579- SourceArn = source_arn ,
1580- )
1575+ kwargs = {
1576+ 'Action' : 'lambda:InvokeFunction' ,
1577+ 'FunctionName' : function_arn ,
1578+ 'StatementId' : random_id ,
1579+ 'Principal' : self .service_principal (service_name ,
1580+ self .region_name ,
1581+ dns_suffix ),
1582+ 'SourceArn' : source_arn ,
1583+ }
1584+ if source_account is not None :
1585+ kwargs ['SourceAccount' ] = source_account
1586+ self ._client ('lambda' ).add_permission (** kwargs )
15811587
15821588 def _policy_gives_access (self , policy , source_arn , service_name ):
15831589 # type: (Dict[str, Any], str, str) -> bool
@@ -1610,8 +1616,9 @@ def _policy_gives_access(self, policy, source_arn, service_name):
16101616 return True
16111617 return False
16121618
1613- def _statement_gives_arn_access (self , statement , source_arn , service_name ):
1614- # type: (Dict[str, Any], str, str) -> bool
1619+ def _statement_gives_arn_access (self , statement , source_arn ,
1620+ service_name , source_account = None ):
1621+ # type: (Dict[str, Any], str, str, Optional[str]) -> bool
16151622 dns_suffix = self .endpoint_dns_suffix_from_arn (source_arn )
16161623 principal = self .service_principal (service_name ,
16171624 self .region_name ,
@@ -1623,19 +1630,29 @@ def _statement_gives_arn_access(self, statement, source_arn, service_name):
16231630 return False
16241631 if statement .get ('Principal' , {}).get ('Service' , '' ) != principal :
16251632 return False
1633+ if source_account is not None :
1634+ if statement .get ('Condition' , {}).get ('StringEquals' , {}).get (
1635+ 'AWS:SourceAccount' , '' ) != source_account :
1636+ return False
16261637 # We're not checking the "Resource" key because we're assuming
16271638 # that lambda.get_policy() is returning the policy for the particular
16281639 # resource in question.
16291640 return True
16301641
16311642 def _remove_lambda_permission_if_needed (self , source_arn , function_arn ,
1632- service_name ):
1633- # type: (str, str, str) -> None
1643+ service_name , source_account = None ):
1644+ # type: (str, str, str, Optional[str] ) -> None
16341645 client = self ._client ('lambda' )
16351646 policy = self .get_function_policy (function_arn )
16361647 for statement in policy .get ('Statement' , []):
1637- if self ._statement_gives_arn_access (statement , source_arn ,
1638- service_name ):
1648+ kwargs = {
1649+ 'statement' : statement ,
1650+ 'source_arn' : source_arn ,
1651+ 'service_name' : service_name ,
1652+ }
1653+ if source_account is not None :
1654+ kwargs ['source_account' ] = source_account
1655+ if self ._statement_gives_arn_access (** kwargs ):
16391656 client .remove_permission (
16401657 FunctionName = function_arn ,
16411658 StatementId = statement ['Sid' ],
0 commit comments