DEV Community

Ed Legaspi
Ed Legaspi

Posted on • Edited on

Use AWS Parameter Store Values for Quarkus Lambda Datasource Credential

1. Introduction

In this example, we are running a Quarkus application as a microservice on top of an AWS Lambda function. If you are wondering how to do that, you can follow this article https://www.czetsuyatech.com/2022/06/quarkus-deploy-a-resteasy-microservice-as-a-lambda-function.html.

A microservice would often need to access the database. Still, the problem with AWS Lambda is that there is no way to fetch the username/password credentials directly from the AWS Parameter Store (this is not an issue when using a container in ECS).

2. Parameter Store

Make sure to create the following keys:
/dev/ct-quarkus-service/DB_USERNAME
/dev/ct-quarkus-service/DB_PASSWORD

3. Code Review

3.1 Add a dependency to AWS SSM.

<dependency>
  <groupId>io.quarkiverse.amazonservices</groupId>
  <artifactId>quarkus-amazon-ssm</artifactId>
  <version>${quarkus-amazon-ssm.version}</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

3.2 Create the SSM Client.

public class SsmProvider {

  public Map<String, String> getSecretParams(List<String> paramsNames) {

    final SsmClient ssmClient = SsmClient.builder()
        .credentialsProvider(AwsCredentialsProviderChain
            .of(EnvironmentVariableCredentialsProvider.create()))
        .region(new SystemSettingsRegionProvider().getRegion())
        .build();

    GetParametersResponse parametersResponse = ssmClient.getParameters(
        GetParametersRequest.builder()
            .names(paramsNames)
            .withDecryption(true)
            .build());

    ssmClient.close();

    return parametersResponse.parameters().stream()
        .collect(toMap(Parameter::name, Parameter::value));
  }
}
Enter fullscreen mode Exit fullscreen mode

3.3 Implement the CredentialsProvider.

@ApplicationScoped
@Unremovable
@Named("ssm-credentials-provider")
@Slf4j
public class SsmCredentialsProvider implements CredentialsProvider {

  @ConfigProperty(name = "ct.datasource.username")
  String username;

  @ConfigProperty(name = "ct.datasource.password")
  String password;

  @Override
  public Map <String, String> getCredentials(String credentialsProviderName) {
    SsmProvider ssmProvider = new SsmProvider();
    Map <String, String> properties = new HashMap<>();

    List <String> ssmParamsNames = List.of(username, password);
    Map <String, String> secretParams = ssmProvider.getSecretParams(ssmParamsNames);

    properties.put(USER_PROPERTY_NAME, secretParams.get(username));
    properties.put(PASSWORD_PROPERTY_NAME, secretParams.get(password));

    return properties;
  }
}
Enter fullscreen mode Exit fullscreen mode

3.4 Update the application.yml.

quarkus:
  application:
    name: ct-quarkus-service
  datasource:
    credentials-provider: custom
    credentials-provider-name: ssm-credentials-provider
    db-kind: mysql
    jdbc:
      url: xxx
ct:
  datasource:
    username: ${DB_USERNAME:/dev/ct-quarkus-service/DB_USERNAME}
    password: ${DB_PASSWORD:/dev/ct-quarkus-service/DB_PASSWORD}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)