Domain-driven design for secure code
With the ever growing software ecosystem, the attributes of a successful product are performance, security, maintainability, and usability. When it comes to delivering a product, the priorities are quality assurance, time to market and on budget. Security-related tasks in the backlog are getting less and less priority compared to business functionality. After all, time is running out and it doesn’t matter if the system is secure if the features that users need are not there.
With the traditional approach, the security review identifies vulnerabilities that are serious and need to be addressed before deployment to production. This delays your project for a few weeks or even months, possibly resulting in lost income. To create secure software efficiently and effortlessly, it is important to focus more on design rather than security after the fact.
When writing code, special attention is paid to the representation of business logic, which is the functionality that makes the product unique, creates code in a way that is explicit and easy to maintain. When modeling our domain of activity, considerable time is spent evolving and refining the domain model and how it will be represented in the code. For example, consider aspects like readability or performance, depending on preferences, decide how we are going to write the code in this statement. Based on experience and knowledge to actively make choices appropriate to the software being built. These choices are part of what determines the design of the software.
Design is the guiding principle in building a system and is applicable at all levels, from code to architecture. Activities that involve conscious decision making in software development are an integral part of the design process. This means that domain models, software modules, APIs, and design models are just as important to software design as field declarations, if statements, hash tables, and method declarations. All of these contribute to the stability of the design.
The recommended design approach for building complex software is Domain-Driven Design (DDD). This is an approach that centers development on programming a domain model that has a deep understanding of the processes and rules of a domain, such as the payment functionality of e-commerce. The focus is on the domain, which is a way of dividing the application into smaller areas based on their business rules.
Building Blocks for DDD define a number of high-level concepts that can be used in conjunction with each other to create and modify domain models.
- Entity: Entities are objects that are supposed to be unique in the domain and are obtained by using one or more properties to identify a given entity. It is crucial to identify information in a consistent manner to coordinate and control behaviors in order to maintain security in the application.
- Valuable objects: Unlike entities, they have no identity, so only their properties can be used to distinguish two instances. In DDD, the value object is an immutable and conceptual whole. It ensures centralized validation of information, thus reducing security bugs in the application.
- Data events: object used to record a discrete event related to the activity of the model within the system. While all system events can be tracked, a domain event is only created for the types of events that domain experts care about and ensure data integrity.
- Aggregates: A DDD aggregate is a cluster of domain objects that can be treated as a single unit. An example can be an order and its line items, they will be separate objects, but it is useful to treat the order (with its line items) as a single aggregate. It protects the modification of information in true invariants within the confidence limit.
- Deposits: This is an authorization service that uses a global interface to provide access to all the entities and valuables that are in a particular aggregated collection.
Key design principles
- Immutability: Security issues involving data integrity and availability could have a negative effect on overall business. When designing valuables, you need to decide whether they should be mutable or immutable. It will keep data consistent throughout its lifecycle and ensure that data can be obtained at the level of performance expected in a system.
- Quick failure: Security issues involving illegal entries and states can be minimized with proper prerequisites and design-by-contract software design practices. A contract specifies the prerequisites required for the method to work as expected, and it specifies the posterior conditions for how the object will have changed after the method is completed. Design by contract avoids many of these vulnerabilities. Secure processing to complete the job as soon as it becomes clear that the prerequisites are not met.
- Validation: A major security issue is not validating user input. Make sure that validation is implemented on both client and server side, as well as during database data. The list presented here also suggests a good order in which to perform the different types of validation. The order ranges from the fastest filters, the least expensive in terms of performance, to the more complicated control.
Types of validation:
- Origin: does the data come from a legitimate sender?
- Size: is it within the expected limit?
- Lexical content: does it contain the right characters and the right encoding?
- Syntax: is it in the correct format?
- Semantics – Does the data make sense?
THE ADVANTAGES OF THE DESIGN APPROACH
With design-driven software development, security can become a natural part of the development process instead of being seen as a forced requirement.
- Software design is the core interest and skill of most developers, which makes secure design concepts easy to adapt.
- By focusing on design, business and security concerns are given equal priority in the eyes of business experts and developers.
- By choosing good design constructs, non-security experts are able to write secure code.
- By focusing on the domain, many security bugs are fixed implicitly.