Fixing the if smell

From time to time we might end up with some huge ‘if’ statements in our codebase. Those statements have to be maintained and change the same code block over and over again. This is common also in cases where the ‘if’ statement checks if a variable belongs in a certain range of values.

Supposing you have an enum

public enum FoodType {

    FRUIT,
    VEGETABLES,
    RED_MEAT,
    WHITE_MEAT,
    FISH,
    DIARY,
    CERIAL
}

And you have a function making some recommendations

    public String recommend(FoodType foodType) {

        if(foodType==FoodType.FISH||foodType==FoodType.RED_MEAT||foodType==FoodType.WHITE_MEAT) {

            //execute a procedure
        } else if(foodType==FoodType.FRUIT||foodType==FoodType.VEGETABLES) {
            //execute a procedure
        } else {
            //execute a procedure
        }
    }

Now as you can see, a decision is made. The decision has to do with certain types of food which happen to belong under a specific group.
Fish, red meat and white meat are good for a user who prefers protein for his meal while fruit and vegetables are suited more for a fiber based diet.
In future cases this enum might be enhanced and more food types added to it.
The ‘if’ code block will have to be changed. Also in case, this complex ‘if’ statement is used in other files you will have to alter each file.
Not only you will have a huge if block but also a block which has to be maintained on each file and this might be error prone.

In order to avoid that you can change the contents of the if statement into a function.

package com.gkatzioura;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import static com.gkatzioura.FoodType.*;

public class DietFilter {

    private static final Set FOODS_WITH_PROTEIN = Collections.unmodifiableSet(new HashSet(Arrays.asList(
            FISH,
            RED_MEAT,
            WHITE_MEAT)));

    private static final Set FOODS_WITH_FIBER = Collections.unmodifiableSet(new HashSet(Arrays.asList(
            FRUIT,
            VEGETABLES)));

    public static boolean proteinBased(FoodType foodType) {
        return FOODS_WITH_PROTEIN.contains(foodType);
    }

    public static boolean fiberBased(FoodType foodType) {
        return FOODS_WITH_FIBER.contains(foodType);
    }

}

So instead of adding each single case of food type, inside an ‘if’ statement we created a function which checks if the argument given belongs to a specific group.

Therefore your ‘if’ statement will change into this.

    public String recommend(FoodType foodType) {

        if(DietFilter.proteinBased(foodType)) {

            //execute a procedure
        } else if(DietFilter.fiberBased(foodType)) {
            //execute a procedure
        } else {
            //execute a procedure
        }
    }

If more food types are added to the enum, the developer will only have to change the construction of the set and add the extra food type.
It will be much easier than changing multiple parts of the code and it is way more readable.

Spring Security with Spring Boot 2.0: Securing your endpoints

Up until now in our previous posts we had our endpoints and controllers secured using the default spring security configuration.
When Spring Security is on the classpath, the auto-configuration secures all endpoints by default.

When it comes to complex applications we need different security policies per endpoints. We need to configure which endpoints should be secured, what type of users should be able to access the endpoints and endpoints that should be public.

A great example would be an endpoint which will displays a welcome message to the user.

package com.gkatzioura.security.securityendpoints.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {

    @GetMapping(path = "welcome")
    public String getMessage() {

        return "Welcome to the application";
    }
}

Regarding the fact that your application is already secured you need to provide public access to that endpoint.

In order to do so, spring provides us with the HttpSecurity class. By extending the WebSecurityConfigurerAdapter we can configure the endpoints which should be secured and the endpoint which should be public.

So let’s create the WebSecurityConfigurerAdapter configuration.

package com.gkatzioura.security.securityendpoints.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/welcome").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .permitAll()
            .and()
            .logout()
            .permitAll();
    }
}

So let’s take it to parts by calling the authorizeRequests function. We get an http configurer and it’s possible to add the endpoints that we want public or secure.
By calling the function antMatchers we can pass an array of ant patterns. The function applied would create a rule for each endpoint specified in the antmatchers.
The next function is the anyRequest. The authenticated rule will be apply to any request received.

Last but not least spring comes with the default login form and the default logout endpoint. In order to make it feasible to login and logout we must allow access to these endpoints.

So the end result would be to have the welcome endpoint publicly accessible, a preconfigured form for login and the logout endpoint.

Spring Security with Spring Boot 2.0: Password Encoder

On a previous post we used the user details service in order to provide a way to load our data from a function based on a username given.

The implementation of the user details might be backed by an in-memory mechanism, a sql/no-sql database etc.
The options are unlimited.

What we have to pay attention when it comes to password storage is the password hashing.
For security reasons we want to store passwords in a hashed form.
Supposing someone gets unauthorised access to the table storing our user data. By storing the passwords clear text that person can retrieve the password of every user in the system.

So we want a way to hash our passwords before storing them to database.
Always be aware that your hashing has to be robust and up to date.
For example MD5 was very popular in the past but nowadays leads to poor security. Actually it is possible to crack MD5 passwords fairly easy if you use a gpu.

Spring Security provides us with out of the box functionality when it comes to encoding passwords.
Password encoder is an interface which is used through the authorisation process.


package org.springframework.security.crypto.password;


public interface PasswordEncoder {

	String encode(CharSequence rawPassword);

	boolean matches(CharSequence rawPassword, String encodedPassword);

}

The encode function shall be used to encode your password and the matches function will check if your raw password matches the encoded password. Once your user details service fetches the user information from the database then the password given to authorise shall be validated with the one fetched from the database. In this case spring will use the matches function.

Now spring provides us with various implementations of a password encoder.
Let’s try to create a password encoder bean.

package com.gkatzioura.security.passwordencoder.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class PasswordEncoderConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence rawPassword) {
                return rawPassword.toString();
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return rawPassword.toString().equals(encodedPassword);
            }
        };
    }
}

This bean is no different that the NoOpPasswordEncoder which comes with spring boot.
No we are going to do a small experiment and add a custom password encoder.
Our password encoder will compare the clear text password submitted by the user hash it and the compare it with an already hashed password from the equivalent user in our database.

To do the hashing we will user bcrypt.

    @Bean
    public PasswordEncoder customPasswordEncoder() {

        return new PasswordEncoder() {

            @Override
            public String encode(CharSequence rawPassword) {

                return BCrypt.hashpw(rawPassword.toString(), BCrypt.gensalt(4));
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {

                return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
            }
        };
    }

To test this we will set up our security by using the environmental variables as we’ve seen on a previous post.

First we need to have our password encoded. Our system will not have the password stored in any clear text form.

System.out.println(BCrypt.hashpw("user-password",BCrypt.gensalt(4)));
$2a$04$i4UWtMw6surai4dQMhoKSeLddi1XlAh2sSyG58K3ZvBHqVkhz8Y3y

So what we are gonna do next is to set our environmental variables before running our spring boot application.

SPRING_SECURITY_USER_NAME=test-user
SPRING_SECURITY_USER_PASSWORD=$2a$04$i4UWtMw6surai4dQMhoKSeLddi1XlAh2sSyG58K3ZvBHqVkhz8Y3y

Next step is to go to your login screen and give the credentials user-name and user-password.
As you can see you have just been authenticated.
Behind the scenes spring hashed the password you submitted and compared to the one existing through the environmental varialbles.

Secure a docker registry using ssl

As mentioned on a previous article having a registry with a username and password is not secure if the registry is not ssl configured.

DockerImage

So we are going to add the ssl certificates to our registry. To make things easier we will use let’s encrypt which is free.

Once we have generated the credentials we have to add them to the registry. We will create a directory called certificates which will contain the certificate pem file and the key pem file. Then we will move the generated certificates on the certificates directory with the names crt.pem and key.crt.

We will follow exactly the same steps we followed in the previous article to generate the password.

docker run --entrypoint htpasswd registry:2 -Bbn {your-user} {your-password} > auth/password-file

Now we are ready to create our registry by also specifying the certificates. To do so we will mount the certificates directory to our docker container. The we will specify where the registry is going to find the credentials on the containers filesystem

docker run -d -p 5000:5000 --restart=always --name registry -v `pwd`/auth:/auth -v `pwd`/certificates:/certificates -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/password-file -e REGISTRY_HTTP_TLS_CERTIFICATE=/certificates/crt.pem -e REGISTRY_HTTP_TLS_KEY=/certificates/key.pem registry:2

So your registry will pickup the credentials specified and will also use the certificates created.
Next step is to do the dns mapping and add a dns entry which directs your subdomain to your registry’s ip.

However if you just wan’t to test it, you can run your registry locally and just change your /etc/hosts and add this entry.

127.0.0.1 registry.{your certificate's domain }

Once you navigate through your browser to https://registry.{your certificate’s domain }:5000
you will get a 200 status code and your browser will identify your connection as secure.

Docker basics: Docker Registry

By default when using docker you pull the images from the Dockerhub docker registry. Most probably you have your own docker images for you application and you want to distribute them and do so in a secure way. One way to do so is to go with the already set options such as a paid plan from Dockerhub or the registries provided by cloud providers like amazon, azure etc.

The other option is setting up your own docker registry.
In any case since you use docker you need to have a registry to distribute your images so that they can make it into production.
There are many benefits on managing your own registry but be aware that it requires effort on your side on provisioning and maintaining it.
Therefore we will create our docker registry

docker run -d -p 5000:5000 --restart=always --name registry registry:2

So we have a docker registry running on port 5000 and the registry will always restart.

Now let’s test our registry and push an image.
First I will build a simple image with no specific purpose.

FROM ubuntu
ENTRYPOINT top

It is just a dummy image printing top.

so we are gonna build it

docker build --tag top-ubuntu:1.0 .

The key is to tag your image based on the domain under which your registry runs.
Currently our registry runs on the localhost therefore by tagging we also specify the location of the registry.

docker tag top-ubuntu:1.0 localhost:5000/top-ubuntu:1.0

And no we push our image

docker push localhost:5000/top-ubuntu:1.0

Now let’s remove our images and see if our image will be downloaded from our running registry

docker rmi top-ubuntu:1.0
docker rmi localhost:5000/top-ubuntu:1.0

And let’s pull

docker pull localhost:5000/top-ubuntu:1.0

As you can see our image has been downloaded from our local registry and is ready to be used.

So far so good. The next step is securing our registry with a username and password.

Let’s start by setting the username and password

First let’s create a directory which shall contain our credentials

mkdir auth

The we shall creae

docker run --entrypoint htpasswd registry:2 -Bbn {your-user} {your-password} > auth/password-file

The file shall contain your username and password information. The password shall be hashed.

Now let’s run our secured registry

 docker run -d -p 5000:5000 --restart=always --name registry -v `pwd`/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/password-file registry:2

As you can see we mounted the credentials file to the docker container and we specified the location of the password-file.

Let’s try to push our image

docker push localhost:5000/top-ubuntu:1.0
.
.
.

059ad60bcacf: Preparing 
8db5f072feec: Preparing 
67885e448177: Preparing 
ec75999a0cb1: Preparing 
65bdd50ee76a: Preparing 
no basic auth credentials

It’s time to login to our registry

docker login localhost:5000

Once your have provided your credentials you will be able to push the image to your local repository.

docker push localhost:5000/top-ubuntu:1.0

Be aware that our registry is not secure. Having your registry secured with credentials does not make it secure since you need to have ssl encryption.

On the next tutorial we will secure a docker registry with ssl.

 

Docker basics: Containers

So we have just created a docker image and now it’s time for us to run a container and interact with it.

docker run nginx

This will run an nginx image and as we can see due to running the container in an interactive mode the terminal we issued the command is no longer available.

We will press ctrl-c. By doing so the docker process exists and our container is no longer running. Our container lifecycle is bound to the main process. If the process exits the container stops.

So let’s run our container in the detached mode and interact with it

docker run -d nginx 

The minus -d option makes the container to run in a detached mode.

Now let’s have a look on our running containers

docker ps

Only one container is listed. The ps command by default show only the running containers. The ps command gives us various information such as when the container was created, the status of the container and the image which was created.
If we want to see our previously stopped container all we have to do is to execute ps with the -a option

docker ps -a

We can remove a container either after stopping the container or we can specify the container to get removed automatically once the container is stopped.

docker run --rm -d nginx 

Otherwise in order to remove a container we just have to issue the rm command

docker rm {container-id|container-name}

Be aware that in order to delete a container, the container must be stopped. Otherwise you must use the -f argument which forces the container to stop and gets deleted.

In order to stop the container issue

docker stop {container-id|container-name}

As we can see we can remove a container by specifying it’s name. In the previous examples we did not any names so let’s do it now.

We can set a name by either renaming a running container

docker rename 53552a9f0a95 my-nginx

Or we can specify the name of the container while we create it.

docker run --name='my-nginx' -d nginx 

Now that we have only one container the ps command serves us well, however in cases where we run multiple containers we need to apply the filter argument which comes along with the ps command.

You can filter by the id, name, label, status etc.
Also you can use filter with substrings in case of name.

docker ps --filter=name="nginx"

So everything is set for us. As we have seen running a container in a detached state does not display any logs in the console. To get the logs we can use the logs command.

docker logs my-nginx

If we want to follow the logs we can also follow the output

docker logs -f my-nginx

The next step is to get into interactive mode with our container while it is running

docker run --rm --name='my-nginx' -it nginx /bin/bash

with this command our container is running and we are logged in to the containers bash console. Be aware that in cases where an entrypoint has been specified you need to override it.

docker run -it --entrypoint "/bin/bash" {image}

However still we might need some extra commands to be run. One way to do this is to use
the docker exec command

docker exec my-nginx echo 'hello wolrd'

As you see we specified the container name and the bash command to execute.

So most of the thing to get us covered has been mentioned. The last tip has to do with exposing the port of our docker container.
Our container is accessible through the ip it has been assigned while creating it however there are cases where we want to map the container’s listening port to our host.

To do so we will use the -p command

docker run -d -p 8080:80 --name my-nginx nginx 

In the above example 8080 is the port of our host and 80 is the port of our docker container.

Last but not least you can create an image by a running container by committing it

docker commit e2e222e22e2e dockerimage:version1

So that was a quick reference on the docker commands which you might use on a daily basis.

Docker basics: Images

So what is a docker image? A docker image is read-only layer consisting of binaries libraries and the software which the container shall execute.

A docker image can have as a base another docker image. Actually they are a read only template.
Once created they are stored in your file system.

To view the docker images currently installed on your system you can issue

docker images

Let’s download an image

docker pull ubuntu

By default your images are downloaded through DockerHub. Also you can upload your images to DockerHub too, if you want to share them.
In cases you want to share your images privately then you have to check the private option on image hosting on dockerhub or other providers such as Google, Amazon, Azure etc.

Since we have just downloaded an image, we will list again our images. Now we will go a bit further and issue

docker images -a

What you can see is that some images don’t have any name on them. Those images are called intermediate images. Behind the scenes the image that you use consists of many other images. Actually it is a parent-child relation. An intermediate image might be contained in two different images due to common dependencies and binaries.
So next time you download an image the intermediate files and your image will be downloaded.

Now let’s filter some of our images.
Current filters supported are
dangling, label, before, since, reference.

Most probably the reference is the one you are gonna use the most.

docker images --filter=reference='*ubuntu*'

What you actually do with the reference filter is filtering based on the image reference and the pattern you specified.

Now let’s build an image. To build an image you need to create a Dockerfile. The dockerfile will specify the image which you will inherit from and any extra action you need to do.

Here’s the content of the Dockerfile

FROM ubuntu
ARG username
ENV USERNAME $username
ENTRYPOINT echo $USERNAME

An argument is passed and the default command that will be executed when the container is running would be to echo the USERNAME environmental variable which is set based on the argument.

So let’s build the image

docker build --build-arg username=john .

As you can see you have your intermediate images printed and the segment images. Try building it again and the same steps and ids will fill your screen, changes and new intermediates will happen only if you change your Dockerfile.

Next step is to check all our images.

docker images

Seems like our image is different that the others. The others have name and tags whilst ours has the autogenerated image id.

Let’s add one

docker tag d88ef0502ecf ubuntu-hello:1.0

Also we can do the tagging while we build the image

docker build --build-arg username=john --tag ubuntu-hello:1.0 .

As you can see I have put a version on the image. For your application most probably you are going to have more than one images created therefore you can tag your images in order to keep track of the versions.

Now time to clean up.

docker rmi ubuntu-hello:1.0

This one will not be successful if you have already run the image. You can force it’s deletion by using the -f argument but is not graceful so don’t do it. Instead delete the containers created from this image and then delete the images.

Also be aware that when you issue rmi using tags, if your image has been tagged with more multiple tags then your tags get removed from the image until the image remains with one tag. If your image has only one tag left then the image gets removed as well.

Docker basics: An introduction

On this blog docker is mentioned many times, and many tutorials utilize docker. It is always good to have a go on docker basics and provide a fast reference, in our workday the more we get absorbed with certain problems the easier it gets to forget.

So with docker you can achieve containerization. You can achieve a special runtime for your process to get executed isolated without affecting any other resources of your system.

Instead of spawning a new virtual machine for your applications and consume extra resources, which a vm needs to simulate a machine and the operating system, you can use docker.

So here are some of the benefits on using docker.

  • Isolation
  • Portability
  • Safety

Isolation

If your application needs some certain binaries installed on your os, instead of installing them to your os you can have them installed on your docker image. This way you application does not affect your host system installation.

Portability

You application and it’s dependencies are stored in the form of an image. This image can be shipped, distributed and run on any docker installation without the need of taking any extra action such as installing dependencies.

Safety

The software that comes packaged with your image is used by the container only. It is not installed or used by your os. If there is anything untrusted on that It will be run only by your containers process. Your container is isolated, it cannot interact with other parts of your system.

The main parts which we will discuss are the

In the meantime the best way to start is just by running a hello-world application on docker.

 docker run hello-world 

The best thing with the above image is that we have a step by step documentation on the process of running a docker image.

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

Create a wildcard certificate using let’s encrypt manually

Let’s encrypt has become the number one choice on certificates since it is free and although it is short lived, there is an abundance of tools out there making sure that your certificate will be updated on time.
This post will go through creating a wildcard let’s encrypt certificate using the dns challenge.
All you need is a domain name registered and you being able to add a txt dns record.

I assume you have the latest version of certbot installed.

First step is to issue

certbot certonly --server https://acme-v02.api.letsencrypt.org/directory --work-dir ./work-dir/ --config-dir ./config-dir --logs-dir ./logs-dir/ --manual --preferred-challenges dns -d *.{your domain name}

You will have some questions on the command prompt which you should answer.
Once done you will end up with a screen asking you to take action and add a DNS txt record.

Please deploy a DNS TXT record under the name
_acme-challenge.{your domain} with the following value:

Once you put the entry to your dns record you need to wait until your txt record gets propagated

One of the ways to check if it is ready, is to use the nslookup method on another terminal.

nslookup -type=TXT _acme-challenge.{your domain}

This might take a while so feel free to use the watch command

watch -n 1 nslookup -type=TXT _acme-challenge.{your domain}

Once done you can press enter and your let’s encrypt certificates shall be generated and this would be the result on your screen.

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   {path}/fullchain.pem
   Your key file has been saved at:
   {path}privkey.pem
   Your cert will expire on 2018-08-28. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Now that you have your chain certificate and your private key and your are ready to use them to your applications.

Dockerize your Scala application

Dockerizing a Scala application is pretty easy.

The first concern is creating a fat jar. Now we all come from different backgrounds including maven/gradle and different plugins that handle this issue.
If you use sbt the way to go is to use the sbt-assembly plugin.

To use it we should add it to our project/plugins.sbt file. If the file does not exist create it.

logLevel := Level.Warn

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.6")

So by executing

sbt clean assembly

We will end up with a fat jar located at the target/scala-**/**.jar path.

Now the easy part is putting our application inside docker, thus a Dockerfile is needed.

We will use the openjdk alpine as a base image.

FROM openjdk:8-jre-alpine

ADD target/scala-**/your-fat-jar app.jar

ENTRYPOINT ["java","-jar","/app.jar"]

The above approach works ok and gives the control needed to customize your build process.
For a more bootstraping experience you can use the sbt native packager.

All you need to do is to add the plugin to project/plugins.sbt file.

logLevel := Level.Warn

addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.4")

Then we specify the main class of our application and enable the Java and Docker plugins from the native packager at the build.sbt file.

mainClass in Compile := Some("your.package.MainClass")

enablePlugins(JavaAppPackaging)
enablePlugins(DockerPlugin)

The next step is to issue the sbt command.

sbt docker:publishLocal

This command will build your application, include the binaries needed to the jar, containerize your application and publish it to your local maven repo.