Getting Identity and Authz Right in Kubernetes

Curity
8 min readFeb 13, 2024

--

The article was written by Curity’s Gary Archer and originally published on The New Stack

Start by capturing business requirements, then add an architectural design that puts security in the hands of engineers who understand the domain logic.

Most people involved in digital solutions will have heard the term “zero trust” from technology vendors concerning backend security. Proposed solutions typically involve Kubernetes clusters that run service meshes with modern techniques for enabling transparent mutual Transport layer Security (TLS) between backend components.

Yet, these architectures often put solutions before requirements and are, therefore, insufficient. Let’s explore why security for digital solutions is a business problem. The best solutions start by capturing business requirements, then continue by producing a solid architectural design that puts security in the hands of engineers with a strong understanding of the domain logic.

The main requirement is to protect data, such as the organization’s intellectual property; personal data belonging to citizens, end users or employees; or sensitive data from business partners. User-facing applications access this data over the internet using APIs. Therefore, securing APIs is the primary focus when protecting data. It requires three main building blocks of authorization, user identity and workload identity, and each of them has an important role:

Many APIs today are inadequately secured, and API security breaches are widespread. This can cause reputational damage to an organization, inconvenience for customers and major fines in some cases. The Open Worldwide Application Security Project (OWASP) has identified broken object-level authorization as the world’s №1 API vulnerability:

“Attackers can exploit API endpoints that are vulnerable to broken object-level authorization by manipulating the ID of an object that is sent within the request. Object IDs can be anything from sequential integers, unique user IDs or generic strings. Regardless of the data type, they are easy to identify in the request target (path or query string parameters), request headers or even as part of the request payload.”

Identify Business Rules

To design API security, you must understand end-to-end usage in terms of the business or problem domain. Consider a fictional medical system that handles highly sensitive patient data. The following example shows a particular use case where various medical worker roles access patient information.

The primary security concern is the rules defining how and when to reveal data. Domain experts design those access rules, which might need to comply with industry-specific regulations. Some possible examples are listed here:

  • Doctors must be only able to view appointments for their own department.
  • Doctors can only create appointments for themselves.
  • A doctor in the cardiology department must only be able to access cardiology-related patient data.
  • Doctors must only be able to access data for hospitals where they work.
  • Doctors must only be able to access appointment data in the appointments app.

To enforce these authorization rules, the API must receive the values needed to enforce them, including the doctor’s identity. This information is often sent over multiple connections before reaching a specific API. The security architecture must protect the integrity of identity and authorization values to prevent a man in the middle from changing them. It can do so by providing secure values in an unforgeable API message credential.

Implement API Authorization

The OAuth 2.0 authorization framework provides a security architecture for digital services, with the API message credential at the center. This article does not cover any OAuth technical details and instead only explains the behaviors the framework enables.

The heart of OAuth is the access token, which is designed to give each client least-privilege access to APIs. It is cryptographically verifiable so the integrity of its data is protected. This delivers the values needed for authorization. APIs validate the access token and then conveniently use its values to enforce business rules using a pattern called claims-based authorization. This design scales to many APIs and clients without a linear increase in code complexity.

Next, consider where to implement the authorization. In Kubernetes, some service mesh extensions enable APIs to implement at least some API security work using a sidecar component, reducing the code developers need to write.

Yet this approach has some problems. The deepest of these is that your organization’s domain-specific security rules should be tested frequently as part of the secure development process. Therefore, instead, use a “shift left” approach to API security so that API security tests run frequently on the workstation of every API developer.

✔ A malformed access token results in a 401 API response.
✔ An expired access token results in a 401 API response.
✔ An access token with insufficient scope results in a 403 API response.
✔ Doctors in the appointments app cannot access medical records.
✔ Doctors can view appointments for colleagues in the same department.
✔ Doctors can only edit their own appointments.

All engineers can follow this type of approach when testing APIs without impeding development. Our article, “Testing Zero Trust APIs,” describes a system that provides a productive way for engineers to use mocking methods to test all scenarios. Developers can even make test results available to non-technical domain experts for review.

Design Security Components

A well-considered setup with sound technical choices is also a key ingredient in your security architecture. This will ensure the correct separation of responsibilities and should scale well as an organization’s software components grow and additional people are employed. Study the following recommended setup for Kubernetes:

API clients have their own best practices. Business partners often connect to APIs using mutual TLS and proof of possession tokens. Web clients should use the strongest secure cookies to limit the impact of cross-site scripting (XSS) exploits. Use an API gateway and gateway plugins to manage these differences. For example, in Kubernetes, the ingress controller provides a sophisticated API gateway that can be extended in this manner. APIs then use claims-based authorization for all clients.

The authorization server is responsible for managing the complexities of user authentication and allowing clients to choose from many types of user authentication flows. Regardless of how users authenticate, the authorization server consistently captures their identity.

The authorization server also issues tokens to clients, which they then send to APIs. To protect data correctly, the authorization server must issue the right claims and the required identity data to the access token. APIs then implement zero trust in terms of the business data they protect, using the data in the access token. The security values in access tokens remain verifiable and auditable as APIs call each other using token-sharing approaches.

Access tokens should be used for both external and internal API requests to reduce threats, such as from a malicious employee or component that attempts to call API endpoints. To successfully call APIs, an attacker must first get a valid access token. Only the authorization server can issue one since only it has access to the cryptographic key material.

Use Workload Identities

Some additional data security requirements remain once OAuth is integrated. API requests inside the cluster should be kept confidential. String passwords used by APIs for database connections, or for OAuth client secrets, could potentially be exploited. If an access token is somehow leaked, such as by capturing it in a network trace, it might be replayed maliciously.

To manage these concerns, Kubernetes environments provide some leading-edge infrastructure security. Service meshes provide an internal public key infrastructure (PKI) to enable the confidentiality of API requests. The service mesh deals with challenging areas like certificates and key renewals. APIs then call each other using plain HTTP URLs, and sidecars transparently upgrade connections to use mutual TLS.

The Secure Production Identity Framework for Everyone (SPIFFE) specification enables solutions where workloads are issued with identity documents, such as X509 client certificates, that serve as client credentials. SPIFFE can be configured as the service mesh’s PKI issuer and assigned a root certificate trust bundle. This enables workload-to-workload authentication to be managed securely across clusters when required. Each API or database component can then restrict its allowed callers to specific client workload identities.

Some database servers can be configured to require mutual TLS to strengthen data access. The database server must also receive and audit the calling database user identity. In the past, this has often proved impractical due to the administrative burden of deploying and renewing keys and certificates across multiple components. SPIFFE achieves this type of solution without much work since the platform components perform the difficult tasks. Application components simply need to use a helper sidecar that downloads certificates and keys to a shared volume. APIs then make secure connections to databases, such as using JDBC (Java Database Connectivity):

Combining the best features of OAuth and workload identities is an emerging trend. In the future, this should enable stronger OAuth client credentials to replace client secrets. It could also allow bearer tokens to be upgraded to proof-of-possession tokens as soon as they enter a Kubernetes cluster. This would ensure that if an access token somehow leaks inside the cluster, it is not replayable against external API endpoints.

Conclusion

For organizations providing digital solutions, regardless of the business domain, zero trust starts and ends with your data. Authorizing access correctly should be the foremost concern when designing API security. With the right security components, you also have a future-facing architecture that can keep up with the latest security innovations.

Also, aim to make security testing part of the base setup for API developers and testers. OAuth is an authorization framework, and its key principles are easy for people to learn. This should result in security tests running frequently as part of a secure development life cycle.

At Curity, it’s part of our mission to explain modern API security designs. For further information on protecting your business data using OAuth and zero trust, see these online resources:

--

--

Curity

Curity is the leading supplier of API-driven identity management, providing unified security for digital services. Visit curity.io or contact info@curity.io