I’m continuing my series on providing basic tips for developers. For those who are new, I’ve written on a few topics to make it easier to start on security for developers until they have a dedicated security hire.
In today’s newsletter, I’m going to discuss access control. Access control is a broad topic, and different pieces of it, such as customer access, are complex and can be multiple newsletters. However, I’m going to focus on employee access and how to maintain good access hygiene.
Guiding principles
Before describing some suggestions for access control, it’s important to have some guiding principles to frame how things should work.
First, let’s discuss the threat model. Specifically, what are we protecting against? Especially, early on, it’s important to trust employees. Early employees tend to need a lot of access to machines, and having too restrictive of an access policy because you assume employees are malicious will slow down development. As a corollary, it’s fair to assume anything “suspicious” an employee does is either unintentional or potentially a compromised account.
Next, we want to follow the principle of least privilege. This means that you have the minimum set of permissions to do your job. A lot of times at a startup, it’s easy to give people admin access so that it covers all particular cases rather than worrying about whether someone has the proper access or not. It’s a tricky balance between time and security. A way to combat this is to do just-in-time access, which allows the person to only have access when he/she needs access and only for a set period of time. This is the alternative to having persistent access, which just means you grant access and the employee keeps it in perpetuity. Ideally, we have both, but just-in-time access mitigates much of the risk of not having the least privilege.
Where do I start?
To start, the two main places to focus on access are SaaS applications and infrastructure. There’s some overlap, but they are slightly different techniques. For example, it’s likely your company uses a cloud provider and much of the access to certain features for a product like AWS is similar to providing SaaS applications.
For SaaS applications, especially for high-risk applications that contain substantial data, the best practice is to ensure MFA is enabled, and there’s a smooth way to grant and revoke privileges as well as onboard and offboard employees. The easiest way it to have a corporate identity tool with single sign-on that allows for SAML integrations. Common tools here are Okta, Google, and Microsoft. These might be expensive but totally worth it in terms of reduced operational burden. There are some open-source ones like Keycloak. These tools make it easy to have a standardized policy, such as MFA, for logging into sites. It also makes it easy to grant and revoke privileges based on groups.
SaaS applications
Each SaaS application will be a bit different, but a good start is to have an admin role and a regular user role. Try to reduce the number of admin roles people have. Every important account should have a service account so that if a person leaves the company, others will still be able to access the application. Many times, an application will have a notion of an “account owner.” This should definitely be a service account with credentials stored somewhere secure like 1Password. The reason is that many times, this account is meant as a “break glass” or root account that can bypass SSO in case Okta isn’t working. It’s important to ensure MFA is enabled for this account.
Okta has some features to allow self-service granting and revoking. Okta doesn’t allow for time-based constraints, but other platforms can do this by connecting to Okta’s API. It’s also possible to build this yourself.
Cloud infrastructure
This article assumes the use of cloud infrastructure. Some of these ideas are applicable to on-premises, but the focus here is on the main cloud providers. I will be using AWS as an example, but they are generally applicable.
For AWS, you should connect it to your SAML provider, e.g. Okta, and enable SCIM. This allows for easy onboarding and offboarding. You can also create Okta groups and map them to AWS roles. AWS has set roles, such as Admin, PowerUser, ReadOnly, etc. It’s easiest to use these, and there’s a long tail of more specific preset roles.
My recommendation is to start with the Admin, PowerUser, and ReadOnly roles. The Admin role has access to everything. The PowerUser can do everything except IAM-based actions, such as adding and removing permissions. The ReadOnly allows for observation. Sometimes, it’s necessary to temporarily escalate to the PowerUser role, but typically, this should work for most normal engineering teams. Of course, as the team grows, there are more dedicated roles, such as Billing, etc.
All key infrastructure that your application’s users don’t directly need to access, e.g. database, s3 buckets, etc. should be in their own private network and not exposed to the public internet.
So how do you access AWS and database instances behind your private network? Traditionally, people have used VPNs. The main issue with VPNs is that they don’t provide fine-grained access control. Once they access the private network, they have access to various assets. New products like Tailscale have more fine-grained access control for VPNs, but they are hard to use.
Another approach is to set up a bastion host, which has access to the public network, and have engineers tunnel through that. This way, you can do some access control in the bastion host by limiting what the bastion host can connect to and only providing access. In this case, people tend to share an SSH key, and many people have access to the bastion host. It will likely be hard to manage. Also, it’s hard to manage access control to something like a database because it complicates the way IAM authentication would work.
Solutions like Teleport and StrongDM provide access controls to infrastructure in a more user-friendly way and provide fine-grained access control. If you don’t want to spend any money, Teleport has an open-source version you can deploy and manage. Initially, it might be useful to provide a simple way to access databases without creating individual users. You can use the IAM auth feature and have people log in through a couple of set database users, such as read-only and admin users.
Conclusion
This newsletter provides some basic tips on how to think about access controls as a developer. It’s easier to start with good hygiene and layer on. It might be a bit annoying at first, but it definitely helps reduce debt and makes it easier to have more sophisticated controls in the future.