We have a mobile app with sign-up functionality (think of it as an AWS lambda), which is publicly accessible.
During development, we deploy to a sandbox AWS account. We want the dev system to prohibit public sign-up, but still allow the developer to sign up through a specifically configured (i.e. with necessary secret keys) front-end.
The reasoning for this is that we don't want malicious actors to be able to talk to our dev systems! Since we are doing serverless it is hard to apply network level isolation, so all security must come from authentication. We also want to keep most authentication and authorization work to IAM because unauthorized calls to lambdas don't incur a cost.
My current solution is:
In production, attach a resource-based policy to the sign-up Lambda function, explicitly allowing public invocation (Principal: "*")
for lambda:InvokeFunction
.
In development, attach a Deny
statement to Lambda functions tagged with dev_protect = true
. This deny rule blocks invocation if the caller does not have a principal tag developer = true
. Add this tag to developer roles, which the front-end uses for sign-up.
Here is the example of the policies:
Production (Public Access to sign-up
):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPublicInvokeForSignUp",
"Effect": "Allow",
"Principal": "*",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:sign-up"
}
]
}
Development (Deny Access to dev_protect
Functions Without developer
Tag):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyNonDeveloperAccessToDevProtected",
"Effect": "Deny",
"Principal": "*",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/dev_protect": "true"
},
"ForAnyValue:StringNotEqualsIfExists": {
"aws:PrincipalTag/developer": "true"
}
}
}
]
}
Is this a good approach or there are better ones for my problem?
The best approach is to use API Gateway, and sit the lambdas behind specific routes (I’m guessing you’re using the direct lambda invoke urls at the moment?). Allow the lambda to be invoked by the API Gateway (not the caller) IAM credentials.
Then you can neatly put an access policy in front of the various routes. So prod routes all have allow all, and dev routes you can allow by IP, header value, etc. As the block happens in front of APIG you won’t get charged https://stackoverflow.com/a/74674307/5746996