AWS Secret Manager Service as application properties with Spring boot

Secrets Manager enables us to supersede hardcoded credentials in our code, including passwords, with an API call to Secrets Manager to retrieve the secret programmatically. This avails ascertain the secret can't be compromised by someone examining our code, because the secret no longer subsists in the code. Withal, we can configure Secrets Manager to automatically rotate the secret for us according to a designated schedule. This enables us to supersede long-term secrets with short-term ones, significantly abbreviating the peril of compromise.

Overview


1. The admin creates a new secret in AWS Secrets Manager
2. A Spring Boot application uses the secret name to access the secrets stored in AWS Secrets Manager

Step 1: Create & Store secrets in AWS Secret Manager.

Use the AWS Console to create and store a new secret in AWS Secrets Manager. Link

Step 2: Add the below dependency to the pom.xml file.

<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-secretsmanager</artifactId>
<version>1.11.942</version>
</dependency>

Step 3: Create an application listener class to retrieve secrets from the Java side.

package com.knf.aws.secretmanager.demo.listner;

import java.io.IOException;
import java.util.Properties;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertiesPropertySource;
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
import com.amazonaws.services.secretsmanager.model.DecryptionFailureException;
import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest;
import com.amazonaws.services.secretsmanager.model.GetSecretValueResult;
import com.amazonaws.services.secretsmanager.model.InternalServiceErrorException;
import com.amazonaws.services.secretsmanager.model.InvalidParameterException;
import com.amazonaws.services.secretsmanager.model.InvalidRequestException;
import com.amazonaws.services.secretsmanager.model.ResourceNotFoundException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class PropertiesListener implements
ApplicationListener<ApplicationPreparedEvent> {

private ObjectMapper mapper = new ObjectMapper();
private static final String AWS_SECRET_NAME = "<AWS_SECRET_NAME>";
private static final String AWS_REGION = "<AWS_REGION>";
private static final String USERNAME = "username";
private static final String PASSWORD = "password";

@Override
public void onApplicationEvent(ApplicationPreparedEvent event) {
String secretJson = getSecret();
String database = getString(secretJson, USERNAME);
String uri = getString(secretJson, PASSWORD);
ConfigurableEnvironment environment = event.
getApplicationContext().getEnvironment();
Properties props = new Properties();
props.put(USERNAME, database);
props.put(PASSWORD, uri);
environment.getPropertySources().addFirst
(new PropertiesPropertySource("aws.secret.manager", props));
}

private String getSecret() {
AWSSecretsManager client = AWSSecretsManagerClientBuilder.
standard().withRegion(AWS_REGION).build();
String secret = null;
GetSecretValueRequest getSecretValueRequest = new
GetSecretValueRequest().withSecretId(AWS_SECRET_NAME);
GetSecretValueResult getSecretValueResult = null;
try {
getSecretValueResult = client.getSecretValue(getSecretValueRequest);
if (getSecretValueResult != null && getSecretValueResult.
getSecretString() != null) {
secret = getSecretValueResult.getSecretString();
}
} catch (DecryptionFailureException | InternalServiceErrorException
| InvalidParameterException
| InvalidRequestException | ResourceNotFoundException e) {

return null;
}
return secret;
}

private String getString(String json, String path) {
try {
JsonNode root = mapper.readTree(json);
return root.path(path).asText();
} catch (IOException e) {

return null;
}
}
}

Step 4: Create a spring.factories

We will also need to add the new application listener to the spring. factories file in the folder src/main/resources/META-INF/spring.factories:
org.springframework.context.ApplicationListener=com.knf.aws.secretmanager.demo.
                               listner.PropertiesListener

More...



Popular posts from this blog

Spring boot video streaming example-HTML5

DataTable-Pagination example with Spring boot, jQuery and ajax

10 Best Job Posting Sites 2021-2022

Spring boot web project free download:User Registration System

Spring Boot + JPA/Hibernate One to Many mapping example

5 Hardest Puzzle,100% fail answers

Java security AES,SHA256,SHA512,MD5-Spring Boot Project Free Download

Spring Boot-AngularJS-Bootstrap-JPA-CRUD

ReactJS - Bootstrap - Buttons

Spring Boot file upload/download example