Event-Driven Architectures & the Security Implications
This article explores event-driven architecture (EDA) with a detailed definition and explains how EDA offers many essential benefits to developers. It concludes with an outline of some best practices for mitigating security concerns.
In an era of rapid digitisation, growth can come so quickly and massively that you cannot react fast enough. In a bid to keep up, the software industry developed new design paradigms and operational methodologies—like distributed systems, cloud computing, and Agile methodology.
These new ways of doing things had one principle in common: Crush the rock into gravel, and you can do more with it. So, from the crushed rock of monolithic system design came event-driven architecture.
The result has been improved efficiency, nearly endless scalability, and rapid deployment. However, the security of this architecture has remained an area of understandable concern.
What is event-driven architecture?
Event-driven architecture (EDA) is a software design approach where activities (known as events) that occur naturally in a designed system are predefined and used to orchestrate how the independent modules in a microservice application function collectively. These events could be discrete actions (like the click of a button) or a stream of actions that cause a significant change in a system state or business process.
EDA is an increasingly prevalent method of connecting microservices and managing how applications perform tasks in response to events that originate in other systems. Typically, an event-driven system comprises:
- A producer—also known as the event generator—a channel or event router that collects and queues these events in a stream for transmission
- A consumer that subscribes to the events and acts on them
Just as a notification can lead you to a message, events are not the actions themselves; they are records of the activity. An event contains information about the action that triggered it, the intended consumer, and its read state. This data goes to the respective consumers, who respond by executing the necessary tasks. Events can be:
- User-generated (like clicking a “Favourite” button in a music streaming application)
- System-generated (like a series of programmed database maintenance activities)
- Derived from an external source (like the data generated by the sensor of an IoT device)
Security implications of event-driven architecture
EDA offers astounding benefits once implemented. Because it does not require point-to-point integration, you can rapidly develop and deploy multiple instances of any module for seamless scaling. It also boasts minimal latency and redundancy, and its isolated modules promote unmatched flexibility. However, it is important to carefully consider the intricacies and security risks of the migration process and the established EDA.
Challenges of migrating to an event-driven architecture
It’s never easy to crush a rock, but it is far from impossible. Taking an existing application from traditional architecture to EDA requires extensive resources and development time. Also, while building something new can be exciting, reworking the old may be unstimulating, especially when it still seems functional. This can sometimes result in postponing such a drastic transition. However, this transformation can be quite enlightening—both from a technical and an operational viewpoint.
Developers perceive EDA to be inherently complex, especially for businesses with intricate processes. There is the concern that EDA does not effectively capture critical aspects of a company and that monitoring and debugging the system is more challenging because of the lack of a centralised structure. However, this complexity does not simply disappear by opting for a different architecture.
Monitoring and debugging are easier with suitable tracing tools that are tailor-made for distributed systems, proper encapsulation of individual services, and an in-depth understanding of the functions of individual services and the events that should trigger them. Using complex event processing, you can even set up alerts to call your attention to suspicious activities. Overall, EDA rewards your effort with a system that you can more easily control and maintain.
Moreover, the process of creating an EDA is so granular that it compels you to take a rare, close-up view of your solution and business processes. By taking your business apart, piece by piece, you can rebuild it into something more efficient, relevant, and future-proof. However, this means little if your implementation plan does not adequately factor in security.
Fortunately, even these challenges can be mitigated with proper design and implementation. With a thoughtful approach, you can enact strict rules about how services interact with each other and identify potential points of failure to make them fail-safe.
While the overarching security concern about EDA is that its architectural model creates more potential weak points for attack vectors, such security issues become apparent in the migration process.
Every producer or consumer added to the system creates a new potential vulnerability. In practice, this singularity of services can also bring security benefits. Designing microservices with EDA as their spine can isolate individual services and components effectively.
With EDA’s system of democratised communication, components seem to have increased access to data generated in the system compared to a point-to-point model. From a security standpoint, this is not good news. Every access point is an opportunity for a data leak or compromise, especially if there aren’t sufficient restrictions. As the complexity of the EDA grows and necessitates adding new components, this concern only multiplies.
Fortunately, it is possible to manage access to data and interactivity between components in an EDA. You must be diligent in your design and implementation plan. You must enact strict rules about how services interact with each other and events. Using strategic encryption protocols, you should also ensure that you protect sensitive data in transit or at rest, and only decrypt the data with the service designated to consume that event.
Best practices for mitigating security risks in event-driven architecture
Most likely, your application handles information you must keep protected, like personally identifiable information or private messages. For a small application, you can avoid storing sensitive data on a disk since data is usually in transit. You can get away with ensuring that your data isn’t persistent anywhere and connections are through HTTPS and TLS. However, storing this information can be unavoidable to minimise latency and build-in fault tolerance when it’s time to scale. In this case, you must secure this data, both when it is at rest and when it is in transit.
You could encrypt the message on the client side before sending it to the event router or message broker. The event producer encrypts the data while only the intended consumers possess the private key needed to decrypt the information. A framework or library like NServiceBus can help here. This way, you protect the data stored in local storage or logs from prying eyes.
Alternatively, if your event router (Amazon SQS) supports server-side encryption, you can leave the task of encrypting sensitive data to it. The router can encrypt the data as soon as it receives it and decrypt it just before passing it on to the designated consumer. This ensures encrypted data when it is at rest.
If classic point-to-point integrated microservices were an apartment building with independent but conjoined apartments, EDA would be a housing estate with several blocks of houses. Each housing unit is functionally independent of the other, but that doesn’t mean there won’t be shared facilities like roads, the post office, or the sewer system. While close neighbours interact more and with fewer restrictions, other neighbours can reach out should the need arise.
Similarly, in an event-driven microservice system, you create a decentralised system where each component is fundamentally independent but still within reach of other components. While this gives you something you need—a more resilient and scale-ready application—it can also be a daunting task and a source of multiple points of weakness.
Thankfully, we can mitigate these challenges with a thoughtful and efficient design and implementation strategy.