- Newest
- Most votes
- Most comments
aws:SourceArn, aws:SourceAccount, and the other aws:Source* condition keys only apply to requests with an AWS service principal as the calling principal. The CloudFormation stack normally gets executed using an AWS IAM mechanism called Forward Access Sessions (FAS) in the security context of an IAM role in your account instead, or alternatively, using a custom IAM service role that's been passed to the CloudFormation service. In both cases, the aws:Source* keys won't be present in the request context of API calls the stack makes.
You could try using this condition test in your Lambda's resource-based policy to identify that the call is coming through CloudFormation. Note the "ForAnyValue:" prefix to the comparison operator, required when evaluating multivalued condition keys:
"Condition": { "ForAnyValue:StringEquals": { "aws:CalledVia": "cloudformation.amazonaws.com" } }
This might also work, requiring further that the last service in the FAS chain is CloudFormation. Only one service can be the last one, so this key is single-valued and must be evaluated with a comparison operator without the "ForAnyValue:" prefix. However, I'm not 100% sure that some other service might not be in between in the case of your custom resource, so it's possible this variation won't work:
"Condition": { "StringEquals": { "aws:CalledViaLast": "cloudformation.amazonaws.com" } }

will the principal in this case be account:root? or role which cloudformation is using? Also its not possible to add these advanced conditions through console, right? Its not allowing me to do via cli also only possible options are SYNOPSIS
How to achieve this?
The principal is typically the IAM role under which you created the CloudFormation stack. If you explicitly specify a different role for the stack to use, it will be that IAM role. In both cases, it'll be one specific IAM role that you specify in the permissions, not requiring the entire account (via the :root principal).
I checked the API documentation (https://docs.aws.amazon.com/lambda/latest/api/API_AddPermission.html) and unfortunately you're right, regular IAM condition clauses can't be added to the resource-based policy of a Lambda function. The only option I can think of would be to use a Service Control Policy (SCP) in AWS Organizations with a condition to block access if the call isn't coming via CloudFormation. Deny statements in SCPs do support all global context keys.