Pletratech is an AWS consulting partner specialized in develop application using AWS services. Security is an important factor for any serverless service using Lambda. In this article we are going to look into security and stability in Lambda.
Securing Permissions in Lambda
Serverless architecture introduces some new patterns that make it difficult to know what you should care about in terms of security. AWS handles many of the security concerns of your app with Lambda, so there are really only a couple of considerations. When Lambas execute, they assume an IAM role for permissions for use when accessing any resources other than themselves. These IAM roles should follow the principle of least privilege. The principle of least privilege says that a resource should only be given the permissions it absolutely needs and no more. In the case of Lambdas, this means that the permissions in a Lambdas role should only be what it needs. Amazon recommends that every Lambda function have its own unique role and that none should share. We car start with creating the role. We can do this from inside the Lambda we want to modify using Lambda dashboard. Select the function needs to deploy. The Permissions tab contains all the information about permissions. Add all permission as per need of the lambda fuinction. This Lambda we have created in previous blog already has a role, but we’re going to create a new one with restricted permissions. We will be creating a role for a Lambda function, so select Lambda here, and then click Next. AWS has already created a managed policy that is specifically designed for Lambdas that consume Kinesis streams. If you search for lambdakinesis, all one word, you’ll see the policy AWSLambdaKinesisExecutionRole, which gives access to write to CloudWatch logs and read from Kinesis streams. Next, search for lambdavpc, all one word, and select the AWSLambdaVPCAccessExecutionRole, which will allow our Lambda to interact with VPC network interfaces. Now our role has all the permissions our Lambda needs and no more. Now we’ll give the role of name that links it to the Lambda it’s used for. From here, go back to the Lambda function tab. Click the refresh button next to this drop‑down to update the list of available roles, and then select the role that we just created. Now, the processAction Lambda function has only the permissions it absolutely needs for what it’s doing, effectively locking it down.
Securing Credentials in Lambda
Besides permissions, another important security concern with Lambda is the storing of credentials and sensitive information. While IAM permissions are often enough to access most service’s in AWS, occasionally there are credentials you need to store for accessing things like databases or external services. There are a few different approaches to this, ranging from least secure to most. The first approach is to put the credentials in your application code. There are plenty of better ways, and this is the most insecure and hardest to update. A better approach is to store the credentials as environment variables in your Lambda. As you can see in the Lambda details for one of our functions, that’s what we’re doing in our demo application. This makes it easier to update and more secure. The environment variables are encrypted at rest by AWS, and using IAM permissions, you can lock down access to your Lambda configuration in the AWS console. The only step where these environment variables aren’t encrypted is in transit, such as when deploying to your Lambda. The best approach is to store these credentials in one of AWS’s secret solutions. One that has been available for a while is the EC2 Systems Manager Parameter Store. This gives you command‑line access to set and retrieve secrets, such as credentials. Your Lambda would then call the Parameter Store anytime it needs those credentials. This adds a little latency to your Lambdas that need those credentials, but greatly improved security. A newer service that follows the same model is AWS Secrets Manager. With a similar process, you store secrets and then retrieve them in your code with the SDK. What Secrets Manager adds is the ability to automatically connect to RDS databases and rotate credentials regularly. This means that your credentials for the database are ultra secure, rotated regularly and available anytime your Lambda needs them. Reducing the permissions of your Lambdas and securely storing credentials will ensure your serverless application is as secure as possible.
Stability with Lambda
AWS already handles many of the aspects of stability when executing your Lambda functions. They ensure your Lambda function is available, scaled out, and running on performant hardware. There’s not much else you have to think about except the stability of the code your Lambda is running. There are two things that I consider when thinking about Lambda stability. The first is monitoring the Lambda for states that are bad, such as errors, long execution time, et cetera. We will cover this in a later module on monitoring. The other thing is ensuring that events that come to the Lambda are processed for sure. There’s nothing worse than a Lambda receiving an event, but then dropping the ball. Imagine database records that should be written, but aren’t. The lack of stability in regards to event processing can affect your entire application. Monitoring can let you know when errors occur, but they won’t help you ensure whatever event caused those errors will eventually be processed. That’s where dead‑letter queues come in. As stated earlier, a dead‑letter queue is either an SNS topic or an SQS queue where your Lambda will send any events that were unable to be processed by the Lambda. For instance, if you’re code errors from an event, the Lambda infrastructure will then send that event to the dead‑letter queue, ensuring it isn’t lost. You can then retrieve any unprocessed events from the dead‑letter queue at a later time and run them back through the Lambda once you fix the underlying issue. If you look in the details of one of your Lambdas, you’ll see there’s an Asynchronous invocation section. Click Edit on this section, which contains information on function timeout and retry attempts. The DLQ, a.k.a. Dead‑letter queue, drop‑down is where you would configure the dead‑letter queue. You can select either SNS or SQS and then a resource from one of them. Once configured, you don’t need to do anything else. The Lambda infrastructure takes it from there. Processing these events at a later time is up to you, however, so you’d want to ensure there’s some sort of listener on the other end of these dead‑letter queues that is persisting the events somehow. Once the stability of your Lambda function processing is ensured with dead‑letter queues, you have a computing process that can handle basically any load you can throw at it. And speaking of that, let’s take a look at performance and concurrency in the next blog.