Månadsarkiv: mars 2016

Security through domain modeling

Detta inlägg finns även att läsa på HRM Softwares teknikblogg!

At the time of writing this I am sitting on the train home after attending the jDays 2016, a two-day conference packed with talks about Java and related technologies. Me and two of my fellow colleagues had a really nice time there and right now I feel quite stuffed with information that will need some time to sink in. One of the keynote speakers actually pointed out that sleeping and resting are important ingredients for accommodating what you are trying to learn, and fortunately those ingredients are perfectly in line with what my mind is signaling right now.

But prior to resting there is one thing that I need to put down in words right away. Being a fan of Domain-Driven Design (DDD) for quite some years now I am glad that I attended a talk about the concept of Domain-Driven Security (DDS) with the irresistible name ”Arm yourself with Domain Driven Security. It’s time to slay some security trolls…” by Daniel Deogun and Dan Bergh Johnsson. In the next couple of paragraphs I will attempt to pass on my understanding of the concept. If the notion of DDD is new to you then I warmly recommend you to read up on it. For me I found DDD to be an eye opener to say the least.

Now, the overall idea behind DDS is that we can use DDD as a way tackle various security challenges that we all have to deal with in some way or another, for example input validation, cross-site scripting or SQL injections. And the really nice part of this is that there is no technical wizardry or mysterious frameworks here – it all comes down to modeling the domain properly. Let me describe this with an injection attack example inspired from the talk I refereed to earlier. Here we go.

In a simple on-line registration page for a cat owner community there is an input field where you are asked to fill in the name of your favorite cat. Everything works fine and the community site is coming along nicely with an ever-growing user base, but then one day a terrible thing happened. Someone had injected JavaScript code in the cat name input field which made the browser redirect to a dog owner community page whenever the cat name was supposed to be displayed on the screen. Under the hood, the value in the cat name input field had been persisted as is, and when retrieved from the database to be displayed the JavaScript code executed, redirecting the browser.

The cat owner community was not pleased.

If the cat owner community instead had designed the application according to DDS they would most probably not have ended up in this situation. A cat name is a domain concept in its own that clearly differ from a string in that it cannot contain weird characters such as ”<” or ”>”. And if you think about it, does the concept of a ”string” really have any meaning in the domain of cat owners? Probably not. Moreover, numbers are probably not be something that the should allow in a cat name. With such business rules in place, we can define a class – for instance CatName – within the domain model that enforces all of these rules in its constructor.

We now repeat the injection attack described above with our new domain model construct CatName in place. The attacker enters the terrible script into the input field and submits the form. The string containing the JavaScript code, including the ”<” and ”>” characters, are passed on down towards the domain model, eventually to be mapped to the domain model concept CatName. Depending on how the cat naming rule is enforced, an exception could be thrown or any characters that aren’t letters are filtered away from the string. In any case, we can be sure that a CatName instance will never, ever contain malicious JavaScript code.

What I just tried to explain is just one example of security challenges that DDS aims to tackle. And the great thing is that much of DDS really comes for free if you just do DDD properly. Just think about the example above – the injection attack was avoided as a consequence of thorough domain modeling work a la DDD. The restrictions and rules enforced by the domain model saved the day for many cat owners.

For me, the talk about DDS was yet another piece of evidence that DDD is worth the extra modeling work up front. Through exploiting the ideas in DDD we can take a proactive stance to fight security challenges by simply doing our domain modeling work properly.

If you want to have a look at this particular talk it will be available on the jDays 2016 site in a couple of weeks. I strongly recommend watching it!

Preconditions in Google Guava

Detta inlägg finns även att läsa på HRM Softwares teknikblogg!

While the Guava project from Google comes packed with goodies for Java developers there is one thing in particular that I tend to use over, over and over again. Actually there used to be two of those, but since Java 8 comes with their own implementation of Optional I have shifted over towards that implementation instead. Anyway, the topic of this short text is Preconditions in Google Guava.

You can think of preconditions in Guava (as the word suggests) as a way to express and enforce preconditions that must be true in order for the execution to continue. A natural fit for these would be at the beginning of a method or a constructor, acting as guard statements of sorts that throw exceptions when violated.

To make things a bit more concrete we turn to code. First off we take a look at the ”normal” way to achieve precondition-like functionality without relying on Guava:

public class SomeClass {  
   private final String aString;  
   private final String anotherString;  
   private final int anInteger;  

   public SomeClass(String aString, String anotherString, int anInteger) {  
     if (aString == null) {  
       throw new NullPointerException("aString was null");  
     }  
     if (anotherString == null) {  
       throw new NullPointerException("anotherString was null");  
     }  
     if (anInteger <= 0) {  
       throw new IllegalArgumentException(  
           String.format("Expected anInteger to be > 0, got %s", anInteger));  
     }  
     this.aString = aString;  
     this.anotherString = anotherString;  
     this.anInteger = anInteger;  
   }  
   // more code here..  
 }  

In the SomeClass constructor we want to a) enforce that the strings passed as arguments are not null and that the integer argument is greater than zero and b) assign the arguments to their respective class member variable. Throughout the 16 lines of code in the constructor body we spend 12 lines of code just enforcing the correctness of the supplied arguments. One word that comes to my mind is verbose.

Another thing to note is that in each of the if-statements we check if the argument has a value that we do not accept. In plain english we can say ”if aString is null, then throw an exception” or ”if anInteger is equal to or lower than zero, throw an exception”.

We now turn to preconditions in Guava. An implementation of the constructor with the same functionality would then look as follows:

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

public class SomeClass {  
   private final String aString;  
   private final String anotherString;  
   private final int anInteger;  

   public SomeClass(String aString, String anotherString, int anInteger) {  
     checkArgument(anInteger > 0, "Expected anInteger to be > 0, got %s", anInteger);  
     this.anInteger = anInteger;  
     this.aString = checkNotNull(aString);  
     this.anotherString = checkNotNull(anotherString);  
   }  
   // more code here..  
 }  

In this version of the class constructor we make use of two static methods in the Preconditions class, namely checkArgument and checkNotNull. In order to make the code more readable these two methods have been statically imported, as seen above the class definition. Let’s walk through the lines in the constructor one by one.

The first line calls the checkArgument precondition to check that anInteger is greater than zero, otherwise an IllegalArgumentException will be thrown. A second and third argument can be supplied to the method – this is optional as the method is overloaded – that provides the exact same functionality as the String.format method used in the former version of the constructor. The most important thing to note on this line is that we check if the argument has a value that we accept. This is the complete opposite to what we did in the former version of the constructor, where we checked if the argument had a value we did not accept. In plain english we can now say ”anInteger must be greater than 0 or an exception will be thrown”.

The second line in the constructor is just an assignment, nothing more to say about that. The fourth and the fifth lines are however much more interesting. Here we use a precondition on each line to check that the string is not null, otherwise a NullPointerException will be thrown. If the precondition is enforced successfully, the argument supplied to the checkNotNull method is assigned to its member variable. In plain english we can now say ”aString cannot be null or an exception will be thrown”. Again, the way we express this is completely inverted from the former version of the constructor, where we say ”if aString is null, then throw an exception”.

Aside from making the code more compact – we have now effectively reduced the code from 16 lines down to 5 – it is also in my strong opinion that the latter version of our constructor is easier to understand. With preconditions in Guava we have the ability to state how things must be rather than how things must not be in order to proceed with the execution. This might seem like a trivial improvement to code readability, but with each small improvement to readability we add to our code base we also make it more maintainable.

After all, code is a form of communication, and code that communicates well is easier to understand and maintain.

P.S. An alternative to the Preconditions.checkNotNull method is the Objects.requireNonNull method available in Java 7.