Security Pattern Assurance through Round-trip Engineering
The process of designing and analyzing software architectures is complex. Architectural design is a minimally constrained search through a vast multi-dimensional space of possibilities. The end result is that architects are seldom confident that they have done the job optimally, or even satisfactorily. Over the past two decades, practitioners and researchers have used architectural patterns to expedite sound software design. Architectural patterns are prepackaged chunks of design that provide proven structural solutions for achieving particular software system quality attributes, such as scalability or modifiability. While use of patterns has simplified the architectural design process somewhat, key challenges remain. This blog explores these challenges and our solutions for achieving system security qualities through use of patterns.
One common approach for realizing system security is through authentication and authorization. The question for the architect is "How do I design them into the software? What do I have to build in to achieve them?" To resolve this dilemma, the developer might choose to use a pattern. By way of analogy, a building architect might decide to make a truss to support a roof and so choose one of the standard available designs for trusses. The architect is starting with a pre-packaged piece of design. A pattern in software architecture is a piece of design, just like a truss in a physical building.
It is commonplace, however, for developers to implement architectural patterns incorrectly. Due to such factors as ambiguity in specifications or miscommunication during the development process, the transition from design to code often does not go smoothly. Translating patterns into code involves the risk for error that is inherent in any translation process. Moreover, there are interpretation issues regarding how any pattern should be implemented; different programmers often implement the same pattern differently.
Patterns also degrade over time, due to changes made during maintenance. Programmers often insert seemingly innocuous changes to the code without realizing that they're actually undermining the intent of the pattern. For example, let's say that you're designing a system where A should never call B directly, for various reasons, e.g., because you don't want them too tightly coupled or because they're in different security domains. To resolve this you insert C, an intermediary (sometimes called the Mediator pattern). But later a programmer comes along and looks at the code and thinks, "Well it looks to me like A can just call B," and changes the code, without understanding the design intent. The programmer can't see the grand plan from looking at the minutiae. In this way, even good designs typically are undermined--they erode and degrade over time. For some system qualities, such as modifiability, this is bothersome. For security, it is potentially fatal.
I along with my colleagues--Jungwoo Ryoo of Pennsylvania State University and Amnon Eden of the University of Essex, U.K--developed an approach to address these challenges. Our approach comprises two major components: the design guide and the Two-Tier Programming (TTP) Toolkit, described below.
In the design guide, we first provide natural language descriptions of approaches for achieving design intent. If your purpose is to achieve security, for example, your design intent might involve detecting, resisting, or recovering from attacks on your system. To help you realize your intent, the guide presents a hierarchy of tactics for building in security. Tactics form the building blocks of patterns. To continue a previous analogy, if a pattern is a roof truss, a tactic is a component of that truss: a chord, web, or plate. Tactics involve a more fine-grained level of design than do patterns.
Hierarchy of Security Tactics Presented in the Design Guide
In the figure above, you'll notice that Limit Exposure is categorized as a tactic for resisting attack. The Limit Exposure tactic minimizes the "attack surface" of a system; it typically is realized by having the least possible number of access points for resources, data, or services and by reducing the number of connectors that may provide unanticipated exposure. This tactic focuses on reducing the probability of and minimizing the effects of damage caused by a hostile action.
The Limit Exposure tactic is associated with patterns that build in security, such as the Check Point pattern. This pattern monitors incoming messages, to determine whether they are consistent with a given security policy, and triggers countermeasures if necessary.
After you have chosen the pattern and its associated tactics for achieving your design intent, these must be converted into code. As mentioned above, whenever you undertake such a translation step, you have the possibility of producing an inaccurate translation.
To solve this challenge, our approach requires that you express your chosen pattern by creating (or, even better, reusing) code charts. Code charts are formal specifications that model and visually depict a program's structure and organization. The figure below shows the Check Point pattern as expressed through a code chart.
The Check Point Pattern as Represented by a Code Chart
You create the code charts through the Two-Tier ProgrammingToolkit, the second element of our approach.
Two-tier programming integrates the representations of both design and implementation. Frequently, when a system undergoes redesign, the changes between the design and the code that implements it may not be coordinated, causing the design to deteriorate. To maintain design quality, programmers must keep these two tiers coordinated through the software's lifecycle.
Our TTP toolkit is a round-trip engineering tool; it maintains design and implementation as separate representations, while facilitating the propagation of changes between them. It supports round-trip engineering in that it has facilities for forward engineering (planning a new design and ensuring that this design is faithfully implemented by the code) and reverse engineering (determining what structures already exist in the code, and modeling those).
The TTP Toolkit was created by a team of colleagues at the University of Essex whom I joined in developing this tool. The program visualizations are reverse engineered from Java source code, and visual specification of object-oriented design is represented in a visual language (based on the formal specification language, LePUS3).
When you have created the code charts via the TTP toolkit, you will need to associate each pattern with the source code that implements it. To do this you simply need to associate (or bind) each variable in the pattern to a specific programming language construct. For example, the Check Point pattern makes use of a security policy, represented as "Policy" in the code chart. The Check Point monitors if messages are consistent with the Policy; if they are not, a counter-measure, represented as "Countermeasure" in the code chart, may be triggered.
Variables and Constants of the Check Point Pattern
Finally, the TTP Toolkit can check that your design is implemented correctly. The toolkit automates the verification process so that you can easily determine whether the code conforms to a tactic or pattern specification. The tool lets you recheck the design at the click of a button any time you make changes to the code, to assure conformance as the system evolves. This verification mitigates the problem of programmers' unwittingly undermining patterns during maintenance.
Successful Verification through the TTP Toolkit
Round-trip engineering tools usually support reverse engineering by generating visualizations from analyzed source code. If the output of the reverse engineering tool (in this case, code charts) can feed directly into the forward engineering tool, and vice versa, then the engineering cycle can be said to be closed--hence round-trip engineering. Closing the engineering cycle can ensure that anytime a gap between design and implementation is generated, it can quickly be detected and remedied.
In summary, our approach involves these steps for achieving system security:
- Identify your security requirements to determine your design intent. Using the design guide, find security tactics to compose security patterns, creating a library.
- Through the TTP toolkit, convert this library of security patterns to code charts.
- Use the TTP toolkit to automatically ensure conformance of implementations to design specifications.
Wrapping Up and Looking Ahead
The design guide provides a natural language description of the architectural approach, guiding the architect from a statement of design intents to one or more tactics, which in turn lead to one or more patterns. We have already specified a large number of security patterns in the guide and the toolkit, and are adding more. While many patterns catalogs have emerged over the past two decades, what sets this work apart is that the toolkit adds rigor to the specification of a pattern and adds conformance checking to ensure that the design and implementation always stay synchronized.
This synchrony is essential. If developers don't maintain this coordination, then the software's design will certainly degrade over time, a condition referred to as "software entropy." Every designer and project manager should be aware of this risk and concerned about reducing it.
It's useful, by the way, to note that the TTP toolkit has limitations and cannot check every property. For example, it can't tell you that A is going to happen after B, or is going to happen immediately after B, because those are temporal specifications, involving timing and ordering. The toolkit can only confirm structural properties, such as A calls B or A inherits from B. In other words, it can check static properties and relationships as opposed to dynamic properties and relationships.
We hope that our approach will enable practitioners to improve their design process and the software it produces. As with the introduction of any new technology, we expect to encounter some resistance to learning a new tool and a new formalism and concern about adoption risks. We also want practitioners to realize that this technology won't solve all of their design problems. It will solve some important ones, however.
If successful, the design guide and TTP toolkit will make it easier to maintain conformance and reduce the cost of doing so. Adopting our approach should result in higher quality design and implementation, in turn resulting in more secure implementations of designs. Please let us know your thoughts about the utility of this techniques in the comments section below.
To read the book Software Architecture in Practice, which I co-authored with Len Bass and Paul Clements, please visit
To read the paper Using Security Patterns to Model and Analyze Security Requirements by Sascha Konrad, Betty H.C.Cheng, Laura A. Campbell, and Ronald Wassermann, please visit
To read the paper A Pattern Language for Security Models by Eduardo B. Fernandez and Rouyi Pan, please visit
To read the paper In Search of Architectural Patters for Software Security by Jungwoo Ryoo, Phil Laplante, and Rick Kazman please visit https://dl.acm.org/citation.cfm?id=1591991
To read the paper Security Engineering with Patterns by Markus Schumacher and Utz Roedig, please visit
To read the paper, Architectural Patterns for Enabling Application Security by Joseph Yoder and Jeffrey Baraclo, please visit
More By The Author
More In Software Architecture
Six Acquisition Pathways for Large-Scale, Complex Systems
This post has been shared 0 times.
Get updates on our latest work.
Sign up to have the latest post sent to your inbox weekly.