Hi, I’m Forrest Brazeal at Trek10, and this is ‘Think FaaS’, where we learn about the world of serverless computing in less time than it takes to run a Lambda function. So put five minutes on the clock - it’s time to ‘Think FaaS’.
We’re continuing with our miniseries this week on serverless best practices. Last week Jared walked us through some wisdom about project layout, and this week we’ll be tackling security.
There are a lot of startups in the serverless security space right now, all with their own products, and to be honest whether intentionally or not they’ve created a bit of FUD around serverless as something that has all these scary new security holes. I’m not here to be snarky about those startups or their offerings. If they work for you, great, give them a try. But the first best practice is to remember that serverless as a concept actually has huge strengths in the area of security, and you can get a long way by capitalizing on those.
So how do you write a secure serverless function?
Serverless functions have a huge advantage over traditional servers in that they only run for short amounts of time, which gives an attacker less room to cryptomine or scan your network or whatever. So use the bare minimum of time for your functions. Don’t just crank your Lambda limits to five minutes just because you can. Come to think of it, I guess that makes this five-minute podcast bad practice, but we won’t dwell too much on that.
Another security win you can get with serverless is least privilege. You’re building these tiny microservices that only do small amounts of work. The big best practice here is, even though some of the frameworks out there make it easy, be really careful about using global IAM roles that span all the functions in your project. It’s much better to define least-privilege roles for each function.
You’ll hear folks talk about insecure dependencies, like npm packages that may be zipped up with your Lambda code. Obviously you could have this same problem on a server as well. I think an easy best practice to remember here is not to commit library code to your own source control. I don’t think many of us would admit to doing this, but probably most of us have, because Lambda package management can be a rough time, especially for native dependencies, so you compile your .so files once on an EC2 instance and then you just want to put them in source control and forget about them. That’s easy until suddenly the dependency patches a zero-day and now you’re not building your package against the latest code. So if at all possible, try to build a workflow that fetches those dependencies fresh each time you build.
Of course, if you leave a function out there for a year and don’t update it, the dependencies could go bad and you’d have no idea. There’s a startup called Snyk — S-N-Y-K — that does a nice job of scanning dependencies in your environment and alerting you to problems. So if that’s a big concern for you, you could definitely check them out.
Attack surface is a common concern you hear in the serverless world. Functions cost nothing if they’re not being run, so it’s certainly easy to leave old functions lying around that have IAM permissions, or even VPC access, that they don’t really need. Obviously the best practice here is to enforce least privilege by terminating with prejudice any unused functions, but you can’t get rid of them if you’re not aware of them. I’ve seen a couple of startups recently offering services to detect and destroy unused functions. I haven’t used them so can’t recommend them, but one thing you can do on your own is simply check out the IAM access advisor in the AWS console. It will tell you when a role was last used, what permissions it’s used, and may lead you to functions that aren’t doing anything.
Getting back to strengths, you have the advantage with serverless of using a managed service for your secrets. OK fine, that’s not exclusive to serverless. But here you are in the cloud! You have KMS right there. You have Secrets Manager and SSM Parameter Store. They are free or at least cheap to use, certainly cheaper than leaking your database credentials. Use them, I beg of you. And in what I think is becoming the unofficial motto of this podcast, don’t put plaintext secrets in freakin’ Lambda environment variables!
I know, deep breath, Forrest. Calm down. I understand that hitting a service to decrypt credentials creates annoyances, like how do you manage caching. That’s one of those areas where the best practice is “use one of the little libraries on Github or write some boilerplate code” for now. The more of us that write this code, the sooner AWS will release an update to Lambda that makes it all obsolete, so let’s make this happen.
Finally, I want to address what I think is the most important topic in serverless security. It sounds cliche, and it’s not even a technical thing, but make sure your infrastructure is defined as code and passes code review before it gets deployed. How many of us have manually given something ‘star’ permissions in the IAM console real quick because we just needed to get something working, and then forgot to change it back? If you get eyes on your CloudFormation templates and your Serverless Framework templates before you deploy, you’ll catch problems and frankly you’ll write more secure code and config to begin with. That’s just human nature.
In the meantime, if you’re ready to take the next step with best practices for your serverless environment, Trek10 would be glad to help. You can find us on Twitter @Trek10inc, or hit me up @forrestbrazeal, and I’ll see you on the next episode of Think FaaS.