Integrating SpringBoot Apps on a secured Amazon OpenSearch application

Angel Conde
7 min readSep 2, 2022

--

Introduction

On our previous post, we have seen how to secure Amazon OpenSearch service with Amazon Cognito providing Fine Access Grained Controls (FGAC) for accessing Amazon OpenSearch Dashboards.

You can see the documentation for this on this link.

The next step is to integrate Amazon OpenSearch with a custom REST API that can connect to this OpenSearch instance. For this, in this post we will employ Spring Boot. As the website says: Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”.

Note: Right now (September 2022) this code uses the recommended ElasticSearch libraries in combination with spring-data-elasticsearch. A version of spring-data-opensearch is in the works and this post and code will be updated. Until then, please enable the compatibility mode when you create the Domain.

Compatibility mode on Domain creation

Please remember that this demo deletes and instantiates a new index called “Customer” each time, please use it in an isolated Amazon OpenSearch instance to avoid loosing data.

Application

Do you want to explore the source code for this post’s Spring Boot service or deploy it to AWS Fargate or Kubernetes before reading the full article? The source code, Docker image, and Fargate task definition are open-source and are available on GitHub. You can clone the repo on your local machine:

git clone https://github.com/aws-samples/opensearch-bootful

A Docker image for the application is also available on Docker Hub. We will use the Docker hub image for running the application via Fargate.

Docker Hub image for the Spring Boot application

Project Setup

We are going to use Spring Initializr in order to bootstrap our project. An example of the project setup using this tool can be seen below. You can skip this step and copy the full pom.xml pasted on the next step.

Remember to check:

  • Project: Maven project
  • Language: Java
  • Spring Boot: 2.6.11
  • Dependencies: Spring Data ElasticSearch, Spring Web, Thymeleaf ( this will be customized on the next step).
Project setup using Spring Initializr

We will add more custom libraries in the next step.

Maven

This post uses Maven to develop, test, build, package, and deploy the SpringBoot service. Based on the packages selected in the new project setup shown above, the Spring Initializr will generate a pom.xml file along a project structure for a Java Project using Maven. We are going to personalize the dependencies adding packages, such as Lombok, Micrometer, and Rest Assured.

Note: for having a supported version of SpringBoot along the recommended AWS libraries we need to exclude the ElasticSearch libraries version. This will change as soon as spring-data-opensearchis released.

Maven pom.xml — Dependency list

Amazon Corretto

The Spring boot service is developed for and compiled with the most recent version of Amazon Corretto 17. Amazon Corretto is a no-cost, multiplatform, production-ready distribution of the Open Java Development Kit (OpenJDK). Corretto comes with long-term support that includes performance enhancements and security fixes. Corretto is certified as compatible with the Java SE standard and is used internally at Amazon for many production services.

Development environment (IDE)

For this post you can use JetBrains IntelliJ IDEA 2022, Apache Netbeans or Visual Studio Code as Java editors. In my case I used IntelliJ but all of them provide a good experience on Maven projects.

Application Implementation

The application is a standard Spring-Boot application, the idea here is that we will configure the ElasticSearch client library to sign the HTTP calls with AWS Sigv4 in order to authenticate the calls. This is configured on theOpenSearchRestClientConfigclass.

In order to obtain the credentials from the inherited AWS role the AWS Credential Provider is customized. This can be seen on the AWSCredentialsConfigclass.

The application uses two ways to communicate with OpenSearch:

  • One is with the Spring-Data abstraction mechanism where all the benefits of this can of abstraction with repositories can be fully utilized. This can be seen on the CustomerServiceclass.
  • Another is with the High Level client where custom calls can be used in order to gain access to more advanced functionality. This can be seen on the CustomerSearchServiceclass.

Remember that on a production scenario the CORS filter should be adapted for security purposes.

AWS IAM: Authentication and Authorization

For the Spring Boot service to interact with Amazon OpenSearch, AWS Glue, and Amazon S3, you need to establish an AWS IAM Role that will be used in order to obtain the different Cognito Roles that you have previously defined on the previous post which the service assumes once authenticated. The Role must be associated with an attached IAM Policy containing the requisite Athena, Glue, and S3 permissions. For development, the service uses a policy similar to the one shown below. Please note this policy is broader than recommended for Production; it does not represent the security best practice of least privilege. In particular, the use of the overly-broad * for Resources should be strictly avoided when creating policies.

We are using the IAMMaster role that we created following the instructions on the last post, however we will restrict the resource of the policy for only allow access to our demo OpenSearch domain.

You need to change your IAM Policy attached to that role to restrict the resource as show below.

"Resource": "domain-arn/*"

In production, depending the logged user in the REST API, we can leverage STS functionality to scope down the permissions depending on the logged user. Remember that in this demo, the REST API is not secured in any way ( although it could be integrated with Cognito like Amazon OpenSearch).

Deploying the APP on Fargate

We are going to deploy our demo app on Fargate. For that we will put the app on a container and serve it via an Application Load Balancer. We won’t go into much detail here as there a a lot of documentation on how to achieve this. However you can use these links as a guide:

The task definition can be seen below (you can see that starts on port 8080 by default and the rest of the parameters). Remember that you will need to change:

  • Task execution IAM role.
  • Task execution role.
  • Environment variables of the container, specifically:
    - aws.iam.role: the ARN of the OpenSearch “master” role
    - aws.os.endpoint: the endpoint of the OpenSearch domain
    - aws.os.region: the AWS region where you are deploying

Moreover, if you generate a custom ECR image you can customize that too. Remember that by default you are using the one I created.

The JSON as reference can be found below.

ECS Task definition

We want later on to deploy our demo app into a Fargate container. In order to the container be able to be capable of assuming our “IAMMaster” role we need to made a trust link between the role and the ECS Service.

We will go to our IAM Master role inside the IAM console, click on Trust relationships and edit the Trust policy and add a statement for trusting the ECSTaskExecutionRole of our Fargate task.

{
"Sid": "StatementTrust",
"Effect": "Allow",
"Principal": {
"AWS": "yourECStaskExecutionRole-arn"
},
"Action": "sts:AssumeRole"
}

Remember that on a production environment apart from securing the API you would put your REST API on HTTPS mode or use the Application Load Balancer to make the HTTPS to HTTP redirection.

Web Interface

The Rest API have a nice web interface to that can be accessed on your Fargate URL via “search” endpoint.

http://application-load-balancer-url/search

Here, you can start typing and searching suggestions will be available. You can also click on search whenever you want to see the customer names that match your query. The search uses “fuzziness” and therefore it can autocorrect small spelling errors.

Swagger UI

The OpenAPI definition can be seen using Swagger. The Open API definition can be seen in this URL:

http://application-load-balancer-url/swagger-ui/index.html
OpenAPI Definition via swagger

With this URL you can also interact with the different REST API endpoints present on the demo.

Interacting with the REST API via Swagger UI

You could use Postman or other kind of tools such as the famous curl to interact with the REST API too.

Conclusion

This post taught us how to create a Spring Boot RESTful Web Service, allowing end-user applications to securely interact with data stored in Amazon OpenSearch service.

The source code will be updated when the spring-data-opensearch library is released.

Remember to delete all the resources we have created after they are not longer needed.

Happy searching!!

This blog represents my own viewpoints and not of my employer, Amazon Web Services (AWS). All product names, logos, and brands are the property of their respective owners. All diagrams and illustrations are property of the author unless otherwise noted.

--

--