Monday, 19 November 2018

Implementing OAuth2 & JWT in a Micro Services Architecture with Spring Boot 2

The theme of loosely coupled independent software components underpins the rationale of the modern micro services architecture. Of course, this is nothing new: Encapsulation is one of the four principles of Object Oriented programming. Micro services seeks to extend this principle beyond the scope of code to the wider systems architecture. A Network of small, independent units of granular functionality, which adhere to common communication standards, are the natural progression from  classic n-tier software systems.

Key to this independence is statelessness, REST principles suggest that each and every request should be independent of the next: There is little point in implementing separated software components only to bind them together again to meet constraints of other technologies which might require session state or a shared back end resource. An example of this is authentication and authorization. Too often we go to great lengths to accomplish a clean and simple system only to shoe-horn in a legacy authentication mechanism which introduces tighter coupling between the network of independent components.

JSON Web Token, used with an OAuth 2 flow, is a solution to this. JWT is based on asymmetric encryption and allows us to guarantee the authenticity of requests across the micro service network without having to create tight coupling between these services with session state or a central token store. JWT can be configured to carry custom state within the access token, removing the need for any user information to be stored within each independent application. This has clear benefits for security compliance, testing and redundancy issues. It ensures that we only need to on-board and manage users in one place. It also provides the option of completely outsourcing the identity management to a 3rd party such as Okta, AuthO or Ping Identity.

In this example I will create my own OAuth 2 authorization server which can easily be enhanced to an enterprise scale identity management service using the rich features of Spring Security. A client application will provide the front end functionality which will be supported by a separate resource exposed as a REST API. Other than the private key, the resource server will be completely independent of the authorization server but will be able to make secure decisions for access control.

All of these components will be implemented with Spring Boot 2. This is ideally suited for a container based delivery into a micro service environment. Any number of resource services can be added to the network without the overhead of shared state or resource to manage authentication or authorization.

This exemplifies the principle of simple, clean, granular services which are easy to maintain and enhance to meet the rapidly changing demands from the business.

OAuth 2 Code Grant Flow

The goal of the OAuth Code Grant is to authorize a client application to access a resource on behalf of a resource owner without having to know the resource owner's security credentials. Although the process is not bound to any specific token implementation JWT compliments the Code Grant process to achieve a clean separation between the back end resources.

Before looking at the flow it's important to understand the four different actors in the authorization user-case.
  • Resource Owner - the user who makes requests to the client via HTTP, usually with a browser.
  • Authorization Server - The Identity Management service which hosts user identities and grants tokens to authenticated users to access other resources via a client
  • Client Application - In the Code Grant flow the client is a web application which consumes resources from the resource server. It is important to understand that this is a server side web app and NOT a Javascript app executing in the browser. The Code Grant flow requires that the Client can be trusted as it retains a Client Secret value which it uses to authenticate it's request with the Auth' Server
  • Resource Server - A REST API which produces and consumes representations of state from and to the client application. Multiple APIs may be implemented in a network micro services.   


  1. Resource Owner, (User), opens a browser and navigates to Client app
    • The client checks for a cookie
    • If none is present it redirects to the hosted login page on the Authorization Server
  2. User provides authentication credentials, username and password
    • Upon successful authentication returns a code, along with a state value, and redirects the browser back to the client app
  3. The Client app receives the code
    • Verifies the state to check for CSRF
    • Provides the code and secret to the Authorization server
    • The Authorization server receives the code, authenticates the client's request using the secret, creates a token using the private key and returns it to the Client
  4. The Client receives the token and uses it to make subsequent requests to the resource server
    • The Resource server receives requests, decrypts the token using the public key

Our Client application is assigned a scope, only those resources in scope are accessible by the resource. Individual users are granted authorities, most commonly implemented as roles. In Spring Security the Role Based Access Decision Manager interrogates the authenticated user's granted authorities. In JWT we can pass these through to the resource service in the claims and filter them as roles. We can also add anything from the domain model, such as organisation association, and maintain that information in the resource service by passing them through as custom claims in the token.

Spring Boot 2 Implementation


Now that we understand the OAuth process and the use-case we intend to solve, let's walk through a real example implemented with Spring Boot 2. All three independent services, can be found on Github -
Let's start by creating the Authorization Server. As always, we start with the build and bring in the Spring Boot dependencies into the pom.xml.

The main configuration annotation sets up everything we need for the Authorization server, the hosted login page, web service and all the request and response logic of the OAuth flow. 

For the purposes of this example the UserDetails are stored as in-memory attributes. This could easily be extended with a custom UserDetailsService backed by a store.

The same goes for the ClientDetails. For a real world implementation we would want to be able to manage the Clients via UI and as with the UserDetailsService Spring Security allows us to implement a custom ClientDetailsService and store details however we choose.

OAuth does not dictate any specific type, or management of, the token. Spring Security allows us to implement the token how we wish but provides extensions for JWT.

For simplicity we'll just set a static signing key, which will be used here and in the Resource Server to decode the token. In a real world implementation this would be an Asymmetric key and we'd generate the private part and export it to the resource service via a robust key management tool

As well as the converter, we need to create a token enhancer to add the custom claims to the access token. Here I'm just setting a static String value against the 'organization'. In reality our UserDetails are likely to be part of a relational schema which could also describe how the user relates to a wider organization account. This would be very important for access control of resources and this value could again come from the UserDetailsService.

Then add the converter and enhancer to the token store.


Client App

As with the authorization service, the Client application is configured purely from a single annotation

and the client settings are provided in the application properties

The Code Grant flow is best suited to server side web apps so this application uses Thymeleaf to render the values returned from the resource service on a secured page which is only accessible to an authenticated user. The rest of the configuration sets up the view controllers and resource handlers for the template html pages.

Resource Server

The resource server security is configured for the OAuth flow with another annotation.  

We add the JWT token store and a custom converter to decode the token with the key and access the custom claims

The resource service is a simple REST service created with the Spring Web framework. In order to access the authentication details and authenticated principal in the controller we can simply include them as arguments in the method. The converter we configured earlier then adds the custom claims from the token to the object and we can pull back the details in the logic. I've also set up method security annotations so we can annotate the controllers with the Spring Security annotations and restrict access based on SpEL expressions. In this case I'm securing the method both by restricting the scope and the authenticated user's granted authorities.

Running the System


All three services are set to run on different ports. Using the Maven Spring-Boot plugin run each one on localhost and navigate to the Client on http://localhost:8082

The browser doesn't yet have a cookie and so presents a page inviting the user to login. Clicking the login will redirect the browser to the Authorization Server's hosted login page on http://localhost:8080/auth/login. Enter the username and password defined in the example in memory configuration and sign in. 




The browser is now redirected back to the client app which will render the Secured Page. The resources for which are fetched from the resource server, running on http://localhost:8081 and substituted into the template.

Dangers of Stateless Authorization

The JWT's validity can only be ascertained by decryption with the private key. There is no way for the Authorization Server to revoke the key once issued. For this reason the key is only valid for a short period of time. Also, The attack surface of a system using JWT is large. If the private key is compromised all identities and resource servers are compromised.

Wednesday, 24 October 2018

White Listing S3 Bucket Access for AWS Resources


Limiting access to data with a white list is a security requirement of any serious data governance policy. In the Cloud the obvious storage choices, such as S3, might not seem like suitable solutions for hosting high risk data. However, the options available for securing data are very powerful. In this post I will show how to implement a robust white listing policy for an S3 bucket which limits access to resources with a given or assumed IAM role.

A common policy with high trust data, such as Personally Identifiable Information, is to only allow access via an application. No direct access to the file store hosting the secure data should be permitted. Of course, we want to avoid storing access credentials within the application itself, the container or machine image. The most risk adverse option to grant our resources, EC2, ECS, Lambda, with an IAM role. In an EC2 environment we can access those credentials from the Instance Profile, with Java we use the InstanceProfileCredentialsProvider  to enable the application to access the S3 resource.

The role is associated to the EC2 instance or, if we're a autoscaling a cluster, specified in the Launch Configuration and associated to an instance on launch.

The role associated to the instance grants the resource access to all operations in the S3 service. This does not limit access to the specific bucket or protect the resources within it in any way. Now we need to create a Bucket Policy which limits access only to authenticated principals with that role, or resources with the assumed role.

The policy is a 'Deny' with a White List of roles which are not subject to that effect. In many examples the 'NotPrinciple' statement is used to define the White List. This will work but requires us to name the instance Id, as well as the assumed role, as the principal is not subject to the 'Deny' effect. This causes us problems in an autoscaled EC2 group as we aren't able to add and remove specific instance Ids to the policy as and when they launch. We could implement some kind of elaborate callback as UserData and amend the policy but that would require us to grant access to manage IAM policies from the EC2 instance which would violate the Least Privilege principle.

A more elegant solution is to use a 'Condition' clause, instead of the 'NotPrinciple' statement, and include a 'StringNotLike' attribute which defines the Role ID. This means we don't need to explicitly define instance ids in the White List.

Here's the Bucket Policy which will limit access to only those resources which are granted the role we created earlier.



Tuesday, 27 February 2018

Serverless Automated Lifecycle Management, For Free

Intro

As developers we should focus on implementation and delivery of business logic which solves the customer requirements. Everything else is ancillary to this. The customer doesn't care about our processes and so they should be slick and easy to manage as not to consume the time and money we have to focus on providing solutions. This isn't to say that the build and delivery processes aren't important. The continuous build process should ensure the integrity of the artifacts and the continuous delivery of those artifacts should be repeatable and error free. The entire process should be flexible, allowing us to delivery builds into different environments, with zero overhead, at any moment in time, managed directly from version control.

In this example I will show how to achieve this using tools which are provided as services, (or serverless as far as we are concerned), for free, to create a complete automated lifecycle process resulting in production deployment managed through the correct governance of version control.



Responsibilities and Governance

The governance of version control is paramount and each team member must understand their role and responsibility in its management. In an automated continuous integration environment the master branch, or trunk, represents the source code delivered to production and is owned by the Delivery Manager. Only the Delivery Manager role can authorize Pull Requests to the master, merge in branches and tag releases. It is these actions which will trigger a production build delivered to the production environment with zero downtime.

Developers branch or fork from the master. They do this for each piece of work, a bug fix or new feature requested by the business and raised as a documented issue. Many copies of the master maybe taken, branches or forks may be merged by the team to collate work. Continuous integration of these development branches and build of the source can happen at any time, the resulting artifact automatically deployed to another environment, staging, dev, test, etc... The important point is to ensure that we map a forked repository or branch to an environment and that the master copy remains secured by the Delivery Manager.

Example of a version control timeline

Application Architecture

The simplicity of the process and success of the development team to utilize it is underpinned by the gold standard of application architecture. To me this means statelessness and clean separation of concerns from top to bottom. A messy architecture will result in spaghetti code. Spaghetti code will result in build complexity and difficulty in testing. These problems will hinder the processes causing the team to spend time 'shoe horning' it to fit the configuration. The process will become bespoke and unrepeatable which ultimately will result in mistakes and errors in production deployment which wastes more time.

In this example I will use a Single Page App', written in Vue.js feeding from a Spring Boot REST API providing a gateway to read/write functionality of data in a relational database. This provides clean separation of concerns and statelessness to ensure scalability.

Token based authentication in an SPA architecture 

Storage and authentication of user identity is often the most difficult piece of state to remove from a system. Requests to a REST API should be completely independent from each other, there should be no user identity shared across server side machine instances. This is achieved through token based authentication and authorization, in this case OAuth, using JWT. The token provider in this example is Auth0. The token carries the identity and its granted authorities within the resources exposed through the API. The identity store and token provider are, in this case, completely separated from the resource server under development. Again, this is key to good architecture as it separates concerns and keeps the state away from the functionality. This ensures we don't need to customize the build for different environments by moving data around, obfuscating identities and fudging security credentials.

Dependency Management

I will focus on the build process of the REST  API and its underlying service and repository components. In this simple example all of those three tiers fall under one build. We could separate them out into different projects for added physical separation but so long as the architecture is stateless the cleanliness is maintained. In the event of separate build being required we must manage those build orders and dependencies within each project. There are two options for this: We can trigger build of dependencies prior to the build of the deliverable artifact or we can keep our dependent builds completely separate and store them in an artifact repository. In my opinion, the later option is more desirable as it adds another level of separation to the build process and therefore greater flexibility and more options for the team. In this case dependency management as a service, such as JitPack.io is a good choice as it integrates very easily with our other tool services, especially GitHub. I use Maven to build most of my backend Java projects and so its a simple case of associating my GitHub account to JitPack and importing the projects I want to store builds for. Additionally, I need to add the JitPack repository to build files and change their group Id.



Setting up the Environment

My target environment is Heroku. I prefer it to AWS because it is free, to a point, and its container based approach removes any requirement for managing any infrastructure, even as code. As my user identities are stored with a third party I don't need to concern myself with network segregation and complex firewall settings to protect highly secure data. I can just throw the application onto a container on a VM and run it.

Before I can deploy my application to Heroku from my CI tool I need to set up the container and the apps I need. The backend relational database, Spring Boot API and the from end files will all deploy to different Heroku apps. I won't go into the detail of setting up the MySQL backend, I use ClearDB and just go through the basic setup to get an end point from where I can create a database and let Hibernate create the schema from the JPA mappings on my domain model in my Spring Boot API application with the following setting


The application is a web app and so I've chosen to run it on a web container. This prepares the app to receive web traffic, HTTP requests from the front end, and provides some default options for execution. I need to tell the container how to run the Spring Boot app and how to connect to the database. Heroku will automatically detect that my app is Java and built with Maven and provides the default command


to start the app when the container is fired up. In Spring Boot all the configuration, such as database connection URLs and credentials, are consolidated into an application.properties. I can override that by creating all the properties I need for this environment as environment variables within the container and this is a straight forward task of setting the properties and values in the Config Vars settings. Obviously, these can be varied for production, test, pre-prod or whatever environment we want the version control we will link it to to reflect.

Now the container is configured I need to link it to the build as a deployment target. This is secured through an API key which I must set in the project settings for the CI tool.

Build and Deployment 

The build is triggered automatically by a push to a branch. This is achieved through the association of  the GitHub and build server account, CircleCI, another free container based tool which integrates seamlessly with Git. Before importing the project we need to add a file to the source to tell CircleCI what to do above the default of just detecting and runing the Maven build. Its a simple case of adding the a circle.yml file to the project root. There are many options here for managing test reports, runing custom script and deploying the build to an environment. I'm using CircleCI 1.0, which has built in Heroku support. This makes life much easier than using v2.0, which requires some customization to deploy to a Heroku Dyno. The deployment configuration section of the file tells CircleCI where to deploy the resulting artifact when triggered from specific locations in Git.



In the above configuration I have two deployment scenarios. The first tells CircleCI to deploy to a staging environment, a Heroku app named rest-api-stage, whenever there's a commit to the staging branch. The release configuration is a little different. This time CircleCI will only deploy to the production Heroku app, named rest-api, when the repository is tagged with a label matching the regex, e.g. v1.0, v1.1, v1.2.1 ...etc. the important control here is that only the owner of the repository, that's me as the Delivery Manager, can trigger the build. We could add multiple usernames of people added to the project repo as collaborators.

Heroku uses git to deploy code onto the containers. Under the hood, the above configuration is adding the build artifacts to a local git repository on the build container, connecting to the remote repository on the Heroku container and pushing the files.


A successful build and deploy to Heroku. See the full detail - https://circleci.com/gh/johnhunsley/returns/33

Now we've connected all the dots and implemented a complete end-to-end process for managing the life cycle of the app. If I need a new environment I simply create the new heroku app, branch or fork the repository and edit the circle.yml and add the app name as the deployment target. The Delivery Manager just needs to ensure that s/he doesn't merge that file and sets the correct production target on the master branch. All part of the their responsibility for managing the production delivery.

Unit and Integration Testing

Going slightly off track here but it's worth noting the power of Spring Boot's testing capability. We have two types of tests: Unit and Integration. Both are written as unit tests and exist in the test dir of the application. Unit tests isolate the individual classes we want to test using Mockito, or which ever flavour of mocking framework you usually use. I've configured my Maven build file to only execute anything named *IntegrationTest when the integration-test goal is executed. CircleCI will execute this goal as part of the default maven build process. Integration tests usually rely on external resources, such as a real database, to achieve their goals. In the case of this example I am testing the read/write functions of my repository types. However, I still don't want to have a build dependency on an external database, such as an instance of MySQL. Spring allows me to test that functionality against an in-memory HSQLDB instance which is initialized with the test and torn down at the end. It's a simple case of including the HSQLDB dependency in the test scope.



Caveats

Of course, we all like things for free. In this example the processes implemented with the tools I have used cost nothing. Just like a free beer, the barman isn't going to give you more than one for nothing! If you want to scale up, increase the number of users, number of developers in the team, number of build process you want to run concurrently and of course the hits on your application then you're going to have to expect to pay. However, I'd challenge anyone to find it lower cost solution than the tools outlined in this example which give you absolute control of your end to end lifecycle process. From setting up a dev' team right through to production delivery and support, it really can be very simple and cost effective to achieve.


**Update**

Just as I have published this post I've received an update from CircleCI saying that they're not going to support v1.0 builds anymore after August 2018 and that everyone must migrate to v2.0. I dont mind that so much, v2.0 gives us much granular control of the build process but it is lacking the simple Heroku support from v1.0. I'm currently looking into deploying to Heroku from a v2.0 build and will certainly post a blog about it when I figure it out!

Monday, 12 December 2016

Jackson Type ID Mapping

Mapping JSON to a Domain Model

Mapping class types directly to a JSON schema with annotations is always a preferable solution for (de)serialization as it's so straight forward. Jackson makes this even simpler and happens automatically without the need to annotate simple domain types, the parser simply uses class, method and field names to generate some suitable JSON. Where we don't wish to bind the JSON schema directly to concrete classes, or where some legacy code or schema must be mapped to a new domain structure we are forced to customize the mapping. This can be done in many ways and we could override the toString method of our domain classes and hard code the JSON schema. Separating the JSON schema away from concrete domain objects has obvious benefits, especially when using UI frameworks such as Angular which heavily depend on JSON from the server side. Mapping becomes difficult in this situation because we need to tell the parser what type of object to map to when it receives some data. Unless we include the class type name within the data, which would again bind our data to the model, we must tell Jackson how to find a suitable type to use.

In this example a REST controller consumes and produces JSON which represents a user. The user is defined as an interface which is implemented in different domain model packages. This separates the controller from the underlying implementation and has clear advantages. However, Jackson must still know which concrete domain model object it is mapping the JSON to and this should be configurable so that the controller is not bound in any way to the model.

Defining the User interface is straight forward but we must annotate it to tell the parser where to find the identifier within the data structure and what functionality to use to determine the mapping.

Now we need to define the functionality to tell the Jackson parser how to resolve the class type. A possible solution would be to hard code the mapping somewhere within the domain model package or within the concrete type itself. But, what if we have multiple implementations of the model and wish to configure which type is mapped at runtime? Jackson provides the com.fasterxml.jackson.databind.jsontype.TypeIdResolver stereotype, and its abstract sub type TypeIdResolverBase specifically for this use case. In our case the UserTypeIdResolver extends the TypeIdResolverBase. There are two functions which must be implemented to allow Jackson to map the ID within the data to a specific class type.

Serialization

The TypeIdResolver enforces a function to generate the JSON ID property from the underlying concrete domain model type. The JSON property @type contains this value, as defined by the property attribute in the JsonTypeInfo annotation. The obvious format for this value would be the class name. However, this could be defined by some legacy schema or be something generic which doesn't relate to the Java domain model. In this example let's assume the property value is just 'User' and we'll formulate that value by trimming of the package name and any suffix from concrete class name assuming the usual class naming convention. In this example the User interface is implemented by com.johnhunsley.user.jpa.UserJpaImpl

The package name and class name suffix - 'JpaImpl' is predefined and injected into the resolver using the usual Spring property placeholder. Currently the Resolver is not a managed bean, it is instantiated by Jackson at runtime when the parser is invoked. Therefore, we must annotate the class with the @Configuration to tell Spring that instances of this class should be managed within the default context to allow configuration to be injected from the properties file.

The function to generate the ID value from the domain model class name boils down to simple String manipulation with some sanity checking to ensure the class name format fits the usual naming convention

Deserialization

The reverse operation is again enforced by the TypeIdResolver and is again a simple matter of String manipulation. In this case we construct a class name from the injected package name, suffix and ID value from the JSON property.


Configuration

Spring Boot automatically provides a Property Placeholder Configurator which uses the default application.properties file from the class path. Therefore, configuration of the TypeIdResolver is a case of adding the domain package and suffix properties to this file. 

So long as the com.johnhunsley.user.jpa.UserJpaImpl concrete domain type is on the class path Jackson will (de)serialize it from/to JSON which contains the @type:User value. There's no need to add any specific Jackson annotations or explicit mapping for this class

A complete example which uses this function for abstracting the mapping between an interface and concrete implementation can be found within the following repositories -

simple-user-account  - Defines the User model interfaces
simple-user-account-jpa - Contains the concrete implementations of the model specifially for Jpa
simple-user-account-api - Defines the REST Controller and configuration for the application

Friday, 25 November 2016

Spring Data JPA with a Hash & Range Key DynamoDB Table

DynamoDB is an attractive option for a quick and simple NoSql database for storing non-relational items consistently and safely without the need for setting up hardware, software and configuration for clustering. DynamoDB will scale up perfectly well to cope with large volumes of data. It is extremely quick and easy to set up a table and read write items from other AWS components.

Spring Data for DynamoDB


From an application point of view the obvious choice for access is to use the AWS SDK. For CRUD operations, from some front end gateway such as a REST API, we would want to abstract the boiler plate code of mapping a POJO to a table which is the perfect use case for JPA. I was unaware of any JPA framework which had built in extensions for DynamoDB until I looked at Spring's implementation - Spring Data. There's a nice framework on GITHub, forked from Michael La'Velles original work, which provides a DynamoDB extension with all the annotations for mapping Java domain classes I'd expect.

Mapping Items to the Java Domain Model


As with all database design the first step is to define a unique key with which to uniquely identify each item in the table.  In DynamoDB this is known as the Partition or Hash Key. Often, the items we are dealing with have no unique natural identifier and we need to specify a second identifier, the Sort or Range Key, which, when coupled together with the Partition Key, is unique within the table.

When annotating a domain type we are expected to mark a field as an ID. With Spring Data we only have the option of using the org.springframework.data.annotation.Id annotation. This must be at field level and only one field can be annotated. Therefore, with our compound key model, we are forced to create an identifier class which is embedded into the domain type. This is a common pattern with JPA and relational data models. However, it has knock-on effects with the DynamoDB persistence model and how the domain object is serialized from a JSON document.

In this example I will map a Widget domain type with both Partition and Sort keys. In order to ensure uniqueness by compound key I will create a WidgetId class which is embedded into Widget. However, I don't want this persisted into the store as an object. The keys should be defined as simple number and String types within the JSON schema. The JSON schema I will map is shown below.

Rather than map other domain model attributes I simply want the Widget class to contain a String of JSON data which is dumped directly into single DynamoDB attribute. In reality I would probably map each attribute and tightly constrain the Java model to the JSON schema. But, this approach gives increased flexibility to store whatever data I want. Even so, the lack of constraint increases the risk of persisting bad or invalid data. When persisted into DynamoDB a Widget item looks like this



I need to tell the underlying Jackson mapper to treat the data String as raw JSON rather than deserialize it as a String. Here's the Widget and WidgetId classes annotated with everything Spring Data and Jackson need to serialize and persist single instances.

The annotations on the get/set Hash and Range key values essentially act as proxies to the encapsulated WidgetId instance which is ignored by both DynamoDB and the Jackson serializer. The @Id annotation ensures JPA still uses this class as the embedded identifier allowing us to utilize the compound key.

CRUD Repository


I need to set up the configuration to access the DynamoDB Widgets table. Access control is via IAM so I can either add a key pair of my IAM account to the application or grant the required role to the EC2 instance I'm running this app from. In this example I'm going to give it the access and secret key which, being a Spring Boot application, I add as properties to the application.properties file on my class path along with the end point URL to the DynamoDB service.

Now to define a repository to handle the CRUD operations. The Spring Data framework provides all the functionality needed straight out the box to such an extent that no further code is required. In this example I want to read all the Widgets with a given Partition key value, there may be multiple items because that key alone isn't unique. The interface which extends the Spring Data org.springframework.data.repository.CrudRepository simply needs another method defining. Spring Data will interpret this from it's name, parameters and return type and formulate the query at runtime.


Use MVC to Create a REST API


It's pretty straight forward to add the dependency for Spring MVC and create a simple REST Controller to implement GET and PUT, read & write, methods.

Securing the End Points


As with any web application I need to secure the REST end points. I'll do this with Basic authantication, a simple base64 encoded user and pass on the Authorization header of the request. This is again very simple to achieve with Spring Security and the convention over configuration of Spring Boot. Simply extend the WebSecurityConfigurerAdapter class, override the configure method and set the required authority for the specific paths. In my case I just want to force any request to either method exposed by the controller to be authenticated. Spring Security will create a default user/pass and print it out to the system log on boot up. I can override this by adding the credentials into the application.properties file. In a production system I'd add my own UserDetailsService and load those credentials from store of some kind.

End-to-End Testing

Postman is my favourite tool for testing basic REST APIs, here's an example running the GET to return the data I wrote into the widgets table ealier



Complete code for the widget example can be forked from this repository

Monday, 4 April 2016

Micro Services - Spring Boot, Eureka and Feign - Part 2

In the last post I set up a very basic 'Hello World' Spring Boot REST service running on an EC2 instance. One of the corner stones of Micro Services and Spring Boot is auto discovery of services from a client. In this post I will demonstrate the use of Eureka and Feign to register the Hello Service and automatically discover and call it from a client. Eureka, created by Netflix, runs in the same environment as the micro services. You are likely to want multiple environments - Dev, Test, Production, each with a different set of the services and end points. In a cloud environment, those services and their end points are transient. You may well be spinning up and tearing down instances many times a day in Dev. In production, you may well be autoscaling services across multiple availability zones. The importance of self registering services and auto discovery is evident.

  1. The Spring Boot Hello Service is modified to register itself with another Spring Boot application configured as a Eureka server.
  2. Another Spring Boot app, which implements the Feign client to call the Hello Service, queries the Eureka server asking for the end point of the Hello Service. 
  3. Eureka returns the details of the Hello Service to the client.
  4. The client makes requests to the Hello Service without any prior knowledge as to its whereabouts.

Create the Eureka Server


First of all we'll create and launch the Eureka server in the same environment our Hello Service is running. In a Dev environment we'll probably just want one single Eureka instance but in Production we will want some kind resilience. Eureka handles this with the ability to replicate the service across availability zones. For the purposes of simplicity I won't be covering that in this blog and will just set up a single Eureka instance in a single availability zone.

Eureka is itself run as a simple Spring Boot application. Again, we'll start with the pom.xml and import into an IDE. As with the Hello Service; the key is the parent. This gives us everything we need. This time, I will also pull in the Spring Cloud pom which is a parent of the Eureka server I will implement within the application.

Import this into the IDE, set up a simple package structure and create a class with a main method. This is pretty much exactly the same as our Application class from the Hello service although this time we add the EnableEurekaServer annotation.

As with our previous Spring Boot example I can add an application.properties file to the classpath which contains any custom configuration I require. By default the Eureka server will attempt to register itself as a service. It's a simple case to turn that off. I've also added some logging configuration to quiet things down a bit and specified a point through which services and clients will 'talk' to the Eureka service.
And that is it!!!!! Spin up another micro instance, deploy the build and execute it as before. One thing to note is that you'll need to ensure your security groups and VPC subnet configuration allows the Hello Service and Eureka instances to communicate. Obviously, there are many ways to set this up and you'll probably have your own security configuration. As this is just a Dev example, I launched my instances into the same subnet and opened up 8761 to any other instance with the same security group association.

Register the Hello Service with Eureka


Now we'll edit the Hello Service from the previous article and make it register itself with Eureka so that clients can discover its location. To do this we must enable the application as a Eureka Discovery Client with another annotation. Currently, our Hello Service app only has a dependency on Spring Boot. We need to reimport the build file and add a dependency on Spring Cloud and Eureka.

We can add the annotation to the Hello Service Application class telling it to register with Eureka.

By default, the Eureka client will attempt to locate Eureka on localhost. We need to tell it to find Eureka on the instance we are running it on. Depending on your AWS set up you may add the private ip, Elastic ip or domain as a property to the application.properties file in the Hello Service classpath.
As you can see, there's an additional configuration to tell Eureka to register the Hello Service by IP address. By default, Eureka will register the machine name. On AWS that's the instance ID. We could force Eureka to register the service with a configured value such as a load balancer or Route 53 domain. As this is only a basic example and the service, client and Eureka server are all in the same subnet, the private IP address of the Hello Service will do.

Start the Eureka and then redeploy and reboot the Hello Service. Watch the logs, you'll see the Hello Service start and after a few seconds it will report a successful registration with Eureka. We can now open a browser and point it at Eureka. This will present us with the management UI and show our Hello Service as the only registered service along with the IP address where the end point can be found.

Eureka UI showing the Hello Service with registered IP address (blurred)

Create a Hello Service Client 

Now the Hello Service is registered with Eureka we can create a client which will call the Hello Service without having any prior knowledge of its whereabouts. To do this we will again use Spring Boot, Spring Cloud and also Feign which will discover the Hello Service end point from Eureka. Once again we'll create a simple Spring Boot project starting with the pom.xml below

Once imported created another Application class, annotated as a SpringBootApplication. We also annotate this class to tell Spring it's a Eureka and Feign client.

We now need to create two more Java types to enable the application to make a call to the Hello Service. First of all, create an interface annotated as a FeignClient. This interface has one method for each service end point or operation, annotated with a RequestMapping bind. This might not seem so obvious because a RequestMapping annotation might more commonly be found on a controller. The presence of this annotation might make you think it is serving the mapping but it simply binds it to the method. Feign understands this and knows to route calls to the method to the remote Hello Service, at the end point discovered from Eureka with the path and mapping described in the annotation. The FeignClient annotation has a value of the name of the service we want to call. Our Hello Service application is named hello-service and we can see the name in the Eureka registry. using this name, Feign will contact Eureka and discover the end point IP address.

We now need a runnable class, Spring Boot supplies the CommandLineRunner stereotype which enforces implementation of a run method. This is called following successful initialization of the Spring Boot application. Our CommandLineRunner implementation simply calls the HelloClient method so that, in this example, the web service call to HelloService is made once on boot up.

Lastly, we just need to the application.properties on the classpath. The only configuration we need is to tell the application the location of Eureka server which the EnableEurekaClient annotation will pick up and use.

Nice and simple! If you like, you can build and deploy this and run it in the same way as the other two Spring Boot apps or just run the main method from your IDE. You should see the Client application boot up, contact Eureka, discover the Hello Service end point and call it, which will return the Hello World message. All accomplished without any pre configured address information of the Hello Service itself.

Micro Services - Spring Boot, Eureka and Feign - Part 1

Micro Services


The term 'Micro Service' is the current flavour of the month within software circles. However, this approach to architecture; splitting up applications into small units of functionality is nothing new. As developers and architects we always look to decouple our systems into single, simple units of functionality. This is a basic principle of OO. The philosophy of Micro Services is to decouple units of functionality entirely. Each unit should effectively standalone in its own environment with as little, or no, dependency on others. Again, this isn't a new approach. Since the advent of web services, inparticular REST, we have decoupled our systems into simple, stateless, independently scalable applications. The advantages of this are clear but as our systems grow into transient environments it becomes difficult for each application to keep track on service end points of other systems. The big win of the Micro Service approach is automatic discovery which helps DevOps solve the headache of configuration across the ecosystem.

In part 1 of this blog I will use Spring Boot to set up a Micro Service very quickly and easily and run it in the cloud. In part 2 I will configure this service to register itself for auto discovery and create a client which has no configuration dependency on the service. This is accomplished with Spring Cloud, Netflix Eureka and Feign; three important frameworks which make up the basis of Spring's Micro Service implementation.

Creating a Micro Service with Spring Boot


Spring Boot allows us to create a deployable application at the drop of a hat. There's no need for a external web server or servlet container, Spring Boot takes care of all that and allows us to just execute a jar file to run a web service. Spring Boot employs the common Spring philosophy of convention over configuration, often to the extreme. This results in an annotation rich framework with little, or no, xml or properties to configure.

To demonstrate this we'll start with a simple REST service which will return a 'hello world' string to a GET request. As with all applications, start with the Maven build file - pom.xml and import into your favorite IDE.

The key here is the parent - spring-boot-starter-parent. This brings in all the dependencies and environment configuration you need to run a Spring Boot app. The only additional dependencies I've added are the web and test packages because this application will be a web app for which I want to write some unit tests. Once imported, create a package structure and add a class name 'Application' with a main method.

By default, the SpringBootApplication annotation enables component scan for its own and sub packages. Therefore, it is convention to add our other components to packages below this one. Create a web and service package for our MVC controller and service layer classes.




The MVC controller and service are both very simple as you'd imagine. Amongst other things, Spring Boot includes automatic configuration of Spring MVC, which is again enabled by the SpringBootApplication annotation. This means its a simple case of just annotating the controller as a RestController and adding the mappings. The HelloService simply returns a string saying hello

That pretty much concludes the service. The only other addition is a properties file. By default, Spring Boot will look for a file named application.properties on the root classpath. This file will hold any other configurations which are required in subsequent parts of this blog. For now, we just add a name for the service, like so.
To run the application as a web service we need an environment hosting the JDK 1.8. No application server is required as Spring Boot has an embedded pre-configured tomcat. If you have an AWS account, spin up a micro instance, ensure you are running Java 1.8 and add the following line as user data to run the HelloService
Open a browser and navigate to the instance on the default 8080 tomcat port. The browser, by default, will issue a GET request and return the message from the service.