You’re a security professional, or at least someone who cares enough about security to be reading this article. So you’re familiar with the principle of least privilege. The renowned computer science pioneer Jerome Saltzer stated it as:
Every program and every privileged user of the system should operate using the least amount of privilege necessary to complete the job.
— Jerome Saltzer, Communications of the ACM
This idea is so fundamental to our security thinking that it is probably almost instinct to all of you. It’s also one that is rarely achieved. There are several reasons for this.
Serverless takes these difficulties to the next level, primarily because the number of resources that can act and be acted upon can grow by one or two orders of magnitude. Suddenly you need to consider the policies governing the interaction between hundreds of resources, with hundreds of possible permissions in each direction.
Additionally, AWS doesn’t make your life easier by allowing permissions to live in several possible places. Even the AWS Documentation for Lambda leaves you scratching your head with statements like:
Instead of using a Lambda function policy, you can create another IAM role that grants the event sources (for example, Amazon S3 or DynamoDB) permissions to invoke your Lambda function. However, you might find that resource policies are easier to set up and they make it easier for you to track which event sources have permissions to invoke your Lambda function.
One more complicating factor, is that we’re constantly encouraged to not reinvent the wheel. Reuse is king these days and there’s no problem for which a solution can’t be imported or required. AWS recently went one step further, announcing their upcoming Serverless Application Repository, making it a matter of a few clicks to bring someone else’s solution into your application.
All this 70’s era sharing makes deploying new features a breeze. But it also means you may be using code and configurations you’ve never even looked over. We’ll talk about using third-party libraries in a future post, but for now let’s focus on policies and privilege. GitHub hosts over 5,500 projects that are designed for AWS Lambda. Let’s take a look at the permissions given to your lambda function if you use a popular project called awslabs/serverless-photo-recognition. As the name alludes, this project actually comes from AWS itself.
The deployment script for this project creates functions with a very wide set of privileges:
These functions can do anything in ElasticSearch, Rekognition, CloudWatch, and S3. That means an attacker that finds a way to exploit any of these functions, can exfiltrate, encrypt, or destroy your entire data store. All you wanted was to reuse some photo analysis code.
All hope is not lost. First, the upside of serverless designs are that if you have been convinced to spend the time crafting minimal roles for each of your functions, these functions are often simple enough that this is not an impossible task. Reviewing the code and configuration of each function, it may be possible to enumerate all the possible actions taken by your code, and craft a suitable role for the function. Rinse and repeat.
Of course, that can be a painful, and error prone process. So your second ray of light is an emerging set of technologies that can help craft these policies for you, decreasing both your workload and you anxiety levels. Some tools, such as a nifty plugin for the Serverless.com framework, can try and figure out the permissions your function needs without your help. If you use the Chalice framework, it too tries to infer the permissions your function needs. Unfortunately, each is only useful if you already use their respective frameworks, and both are far too prone to false positives and negatives to really be used automatically.
Our own Protego Serverless Security Platform takes a different approach, continuously analyzing your functions as they change and detecting and helping you remedy any policy promiscuity that makes its way into your environments. As we’re not limited in scope to acting only during deployment, we have the unfair advantage of monitoring the function’s behavior as it’s being used, and fine tuning our understanding of the function as time goes on. This means our recommendations can be significantly more accurate. It also has the advantage of being framework agnostic, so you can avoid the common contention between security decisions and software engineering decisions.
It’s not all roses, but it’s not all thorns either. Serverless applications can present an almost endless set of opportunities to get permissions configured incorrectly, and there are a lot of forces pulling your application in that direction. But serverless applications are also built in a way that makes the secure configuration possible, especially if you leverage the right tools to keep you ahead of the game.