Modern Application Security Requires Defense in Depth
A zero-trust architecture requires a combination of coarse-grained and fine-grained access controls that work together to ensure application security.
Join the DZone community and get the full member experience.
Join For FreePerimeter security has been dying a slow death over the better part of a decade, as breaches of the corporate network have become commonplace. Most organizations now find it obvious that trusting devices and users merely for being "on the corpnet" is insufficient to maintain security in the face of evolving threats.
At the same time, the re-platforming of business applications to a SaaS model, coupled with a more mobile and distributed workforce, has made the need to "VPN into a corpnet" feel archaic and cumbersome. The pandemic created the perfect storm around these two long-term trends, accelerating this slow death into a fast one. Adopting a zero-trust architecture is no longer negotiable for any organization that wants to stay alive.
Zero Trust Means Defense in Depth
One of the most important principles of security (real-world and digital alike) is defense in depth: rather than relying on a single control into your world to maintain all security (or, “one lock on the front door"), you implement a set of measures that compose together to offer more security than each could in isolation.
This goes hand-in-hand with the principle of least privilege: every layer uses the information at its disposal to make access control decisions.
A Taxonomy for Doors and Locks
There are many places you could put in doors and locks that contribute to a zero-trust architecture. They fall under the general categories of coarse-grained and fine-grained access controls.
Over the last decade, most of the security industry’s attention has been focused on the former, but in the last two years, a wave of innovation has transformed the latter.
A defense-in-depth approach requires at least one solution (and possibly more) at each layer. Let’s dive into a few examples of each.
Coarse-Grained Access Controls
These types of locks know something about the user and device that is accessing a protected resource but don’t have the full context about the user, operation, and resource. Examples include access proxies, enterprise single sign-on/identity providers, and API gateways/routers.
1. Access Proxies
As Google popularized in its BeyondCorp technical notes, a modern Access Proxy is the first line of defense when it comes to users gaining access to corporate applications and resources. An admission control policy that can use attributes about the user, device, network, location, and even date/time can help ensure that only requests that are allowed by that policy are routed to the application. Large vendors such as Zscaler and Cisco cover this use case as a modern replacement for traditional VPNs.
2. Enterprise Single Sign-On/Identity Providers
Your identity provider (IDP) is used to authenticate every user as they sign in to the set of applications they can access. While this is not technically an authorization layer, the IDP can make coarse-grained decisions on whether a user has access to certain applications based on a set of attributes. For example, an IDP such as Okta can provision users in the sales department into Salesforce, and enforce that only salespeople can access this application.
The IDP is also critical to downstream access controls since it produces a signed access token (e.g. JWT), which other layers downstream of the IDP can use to determine the identity of the user on behalf of which the request is being made.
3. API Gateways/Routers
A modern service mesh provides the opportunity for an API request to be authorized by the API gateway before it is routed to the application. The Cloud Native Computing Foundation's Open Policy Agent (OPA) project has gained popularity as a general-purpose policy engine that can be used for request authorization. Vendors such as Styra make it easy to configure API gateways such as Kong and Envoy to evaluate an OPA policy that can allow or deny a request based on HTTP method, path, and even attributes in the access token (JWT).
With that said, API gateways don’t have sufficient context about users (beyond what is in the JWT), and can’t provide resource-specific access control, so this layer of defense is coarse-grained.
Fine-Grained Access Controls
These types of locks are built into the applications themselves or have an understanding of the resources that the application is accessing. Since they have all the context about the user that is attempting to perform an operation, the operation itself, and the resource to perform the operation on, we think of them as “fine-grained." Examples include application/API authorization, data filtering, and data proxies.
With coarse-grained solutions reaching maturity, much of the innovation has moved to fine-grained authorization. Most solutions that provide fine-grained authorization require some level of integration into an application, as opposed to intercepting requests at the network level.
1. Application/API Authorization Services
Almost every business application has roles and permissions, which allow differentiating the set of operations available to logged-in users based on their permission levels. A robust RBAC/ABAC solution allows an application to map attributes that come from an identity provider or directory into the application's roles and permissions so that the process of assigning roles and permissions can be as automatic as possible.
A modern application will have a microservice that is responsible for authorizing every application/API request, which will allow or deny the request based on an authorization policy that can be written in terms of user and resource attributes.
Open Policy Agent is also starting to gain momentum as a good solution at this layer, with vendors (including Aserto) adopting OPA as part of an end-to-end application authorization solution. SaaS application developers are starting to replace their home-grown authorization microservices with off-the-shelf solutions based on open source projects such as OPA.
2. Data Filtering Libraries
Some applications rely on data access layers to filter the "right" data based on which user is accessing that data. Traditionally this has been done either in the database ("row-level security") or in the application (the application developer constructs the queries "by hand" or through an ORM library).
New approaches to this problem include libraries that can be handed a schema that describes a subject (e.g., a user or a group), predicate (an action to perform), and object (a resource), as well as rules for which subjects can perform which actions on which resources. Those libraries will then help automatically construct the query restrictions on the data source and only return the "right" data, essentially providing an “authorization-aware ORM”.
Google's Zanzibar paper has given rise to a few vendors that are commercializing this approach.
3. Data Proxies
Last but not least, access to data sources can be restricted not only from the applications that rely on them but also at the network layer. Similar to an API gateway, a data proxy can intercept a request to a known data source, and make fine-grained access decisions based on the user as well as the fields that are being queried. Vendors like Cyral have adopted OPA as the underlying engine for enforcing these database access control rules.
Conclusion
With zero-trust architectures, security is no longer an all-or-nothing proposition: a defense-in-depth approach is far more effective at mitigating unauthorized access and data breach risks than the archaic perimeter-based security approaches of the past. Every organization should employ a mix of coarse-grained and fine-grained access control layers.
Using a combination of access proxies, modern identity providers, and API gateways provides coarse-grained access control for application, resource, and data access based on user and device identity. Creating applications that authorize every application request using a modern RBAC/ABAC-based authorization service ensures that fine-grained access control can be performed at the application layer, where there is the most context on who is allowed to do what on which resource.
Once an authorization service has allowed an operation, using a data filtering library or service can help restrict the data returned to only the data the user can access, reducing the need to code these queries “by hand”. Finally, a data proxy can be used to independently authorize queries to a data source based on fine-grained attributes about both the user and the fields that the application is accessing.
All of these approaches compose well and can be used together for greater security.
Published at DZone with permission of Omri Gazitt. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments