Guide to Serverless Information Security

Featuring real-world examples

Chase Douglas

Information security & serverless applications

Information security (infosec) is a broad field. Its practitioners behave more like artists than engineers. After all, the mandate for security is not "do X", but instead "ensure no one can do X, Y, Z, ɑ, β, ɣ, etc.".

The array of possibilities leading to infosec failure are vast. It's like trying to prove a negative, thus making the task near impossible.

On one hand we have an impossible task, on the other we have the affordance of time. In one sense we have been practicing infosec since the invention of the​ Caesar Cipher​ in 50 BC.

Yes, software infosec is younger, but we benefit from decades of development in the field. Modern application designs are often developed with infosec in mind. For example, newer services have finer-grained access controls, stateless connections, and time-based authentication.

Cloud applications have three core infosec needs:

  • resource-level access controls
  • secrets management
  • fallbacks for network-level security (where necessary)

A look at some real-world examples

Resource-Level access controls

Modern applications are constructed via collections of managed services. (Aside: If you are operating off-the-shelf databases or similar services yourself, you are not really doing modern application development.)

Every interaction between managed services crosses a service boundary. These service boundaries are where we manage access controls. For example, if a ​Lambda Function​ wants to interact with a ​DynamoDB Table​ it needs to be granted access to the table.

Example

Let's look at an example:

`
  1. Add a Secrets resource
  2. Connect the right-side port of the Function to it
  3. Double-click on the Function resource to see the permissions granted to access secrets within the namespace of an environment

Often, a human identity uses write access to create or update a secret. And an application resource uses read-only access to retrieve the secret at runtime.

Sometimes even first-party cloud managed services require secrets. Relational databases like Aurora Serverless are an example of this. The most secure architecture for these solutions involves letting AWS manage the credentials, generating them cryptographically when creating databases, and then referencing credentials without ever accessing them when querying the database.

Secrets management example #2

  1. Connect the right-side port of the Function to the left-side port of the Database
  2. Double-click on the function resources to see the permissions granted to access both the database credentials and the data API service for the database

When the compute resource queries the database it does so by passing along the identifier of the credentials in AWS Secrets Manager without ever retrieving the credentials directly:

aws rds-data execute-statement \ --resource-arn "arn:aws:rds:us-east-1:123456789012:cluster:mydbcluster" \ --database "mydb" \ --secret-arn "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/dbcreds" \ --sql "select * from mytable"

This ensures the compute resource never stores the secret locally.

Considerations

When an application resource needs to use secrets, it should:

  • Store them in a secrets manager service that maintains access audit logs
  • Store them in namespaced regions to isolate environments (e.g. /dev/dbcreds vs /prod/dbcreds)
  • Grant application resources access to specific secrets or to secrets within the environment namespace
  • Use first-party secrets integration with managed services where available
  • Rotate credentials periodically

AWS Secrets Manager has built-in mechanisms to rotate credentials for many AWS managed databases. AWS Secrets Manager further enables custom rotation logic for other first-party and third-party services. Automated mechanisms enable frequent rotation, decreasing the chance that a leaked secret will be usable by a malicious third party.

Fallbacks for network-Level security (where necessary)

Sometimes the right architecture for an application involves managed services that predate modern infosec practices.

Relational databases

Relational databases are one example of such resources. While we may want to rid our applications of relational databases (for many reasons), there is too much value built up in existing application code and libraries to justify banishment of these database types. Instead, it's simpler to use alternative infosec mitigation strategies that can be just as effective (though a little more cumbersome to architect).

If you can build on or migrate to an Aurora Database Cluster with a managed Data API service, then you should try to use its vastly superior access controls.

If that's not an option, things get a bit trickier. Previous access models involve establishing stateful TCP connections to databases. These connections are authenticated using static username/password credentials. They are optionally configured to encrypt data in transit (but often are not configured to do so by default). Further, each stateful connection adds overhead and limits the scalability of databases. They present an opportunity for a DoS attack if a third party is able to locate a database service even if they don't have credentials to authenticate.

The best solution to ensure security in the face of these challenging conditions is to prevent access to databases from the public internet.

The easiest way to lock down access is to put the database into a virtual network, like AWS's Virtual Private Cloud service. Databases in these networks can be given private addresses that are not publicly reachable. But this also means compute resources that need to interact with the databases must be able to access the private network.

Example #1

  1. Add a Virtual Network resource and drag it around the Function and the Database
  2. Switch to the template view to see the additions to the SAM/CloudFormation template for the VPC
  3. Look again for the settings that connect the Function and Database to the VPC's subnets

One further complication results from using a virtual network. Private resources are by definition not accessible from the public internet, which can make it difficult to interact with them for development, testing, or debugging purposes.

We need a way to create a secure tunnel between ourselves and the private resources in the virtual network. There are multiple ways to create private tunnels, but one of the most cost-effective solutions is running an SSH Bastion Server.

Example #2

  1. Add a Bastion Server resource to the Virtual Network. This will create a virtual machine that can be tunneled through using SSH to reach the database server.
  2. Switch to the template view to look at the launch configuration for the Bastion Server, noting the addition of the Systems Manager agent.

Traditional SSH Bastion Servers also require static credentials, either username/password or public/private key authentication. The ideal authentication mechanism uses time-based credentials. Thankfully, AWS provides the Systems Manager Session Manager service for establishing SSH connections and tunnels to Bastion Servers. It can be used with tools like ssm-tool to authenticate and establish connections using single-use, temporary public/private keys.

Considerations

When an application resource requires stateful connections and/or static credentials, use the following techniques to securely provision and access them:

  • Connect the resource to a private virtual network without a public IP address
  • Connect compute resources that need to interact with the resource to the virtual network as well
  • Set up a tunneling mechanism using time-based authentication strategies to be able to interact with the resource from outside the virtual network for development and debugging purposes

Holistic solutions

While breaking down security solutions based on use cases and resource needs is an important step towards developing the right infosec application architecture, a holistic approach should also identify how humans working in teams collaborate to accurately reproduce these architectures across various projects. It's important to empower developers with the right tools that let them work at a human logic level rather than a machine logic level.

Conclusion

Stackery's platform enables teams to automate some infosec best practices. Get started today building well-architected applications.

Curious about Stackery and its capabilities?

Learn more