How to connect spring boot application to aws document db

228 views Asked by At

I'm not able to connect my spring boot application to aws document db. Please tell me where am I going wrong.

pom.xml

 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven- 
4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.0</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>

<groupId>com.mercedes-benz.xdrs</groupId>
<artifactId>xdrs_data_service_api</artifactId>
<version>1.0.0.0</version>
<name>xdrs_data_service_api</name>
<description>xdrs data service api</description>
<packaging>jar</packaging>

<properties>
    <java.version>11</java.version>
    <spring-cloud.version>2021.0.2</spring-cloud.version>
    <log4j2.version>2.19.0</log4j2.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
        <version>1.3.1</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>3.0.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.13</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-ui</artifactId>
        <version>1.2.9</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>

    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>3.12.10</version> <!-- Use the latest version -->
    </dependency>

    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongodb-driver-sync</artifactId>
        <version>4.4.1</version> <!-- Use the latest version -->
    </dependency>

    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk</artifactId>
        <version>1.11.986</version> <!-- Use the latest version -->
    </dependency>


    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-jdk8</artifactId>
        <version>1.3.0.Beta2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongodb-driver-core</artifactId>
        <version>3.11.2</version>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
    <finalName>xdrs-data-service-api</finalName>
</build>

DocumentDBConf.java

package com.mercedesBenz.xdrs.dataService.config;

import java.io.File;
import java.security.Security;

import javax.net.ssl.SSLContext;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;

import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;


@Configuration
public class DocumentDBConf {


@Value("${documentdb.connectionString}")
private String connectionString;

@Value("${documentdb.pemFile}")
private String pemFile;

@Bean
public MongoClient mongoClient() throws Exception {
    // Load the .pem certificate file
    File pemCertificate = new File(pemFile);

    // Enable AWS DocumentDB TLS
    System.setProperty("javax.net.ssl.trustStore", pemCertificate.getAbsolutePath());
    System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); // The default trust store password
    System.setProperty("javax.net.debug", "ssl");
    
    // Enable strong cryptography
    // Security.setProperty("crypto.policy", "unlimited");

    ConnectionString connString = new ConnectionString(connectionString);
    MongoClientSettings settings = MongoClientSettings.builder()
            .applyToSslSettings(sslSettingsBuilder -> {
                try {
                    sslSettingsBuilder.enabled(true)
                            .context(SSLContext.getDefault()); // Use the default SSLContext
                } catch (Exception e) {
                    throw new RuntimeException("Error creating SSL context", e);
                }
            })
            .applyConnectionString(connString)
            .build();

    return MongoClients.create(settings);
}

@Bean
public MongoTemplate mongoTemplate(MongoClient mongoClient) {
    return new MongoTemplate(mongoClient, "test"); // Replace 'your_database_name' with your actual database name
}

}

application.properties

documentdb.connectionString=mongodb://user:pwd@xdrs-int-docdb- 
cluster-identifier.cluster-c6wywertyiq6.eu-central-1.docdb.amazonaws.com:27017/test?tls=true
documentdb.pemFile=/xdrs_data_service_api/src/main/resources/global-bundle.pem
#documentdb.pemFile=classpath:docdb.cert
#documentdb.pemFile=classpath:rds-truststore.jks
management.metrics.mongo.command.enabled=false 
management.metrics.mongo.connectionpool.enabled=false

XdrsDataServiceApplication.java

package com.mercedesBenz.xdrs.dataService;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;


@SpringBootApplication(exclude = {MongoAutoConfiguration.class, 
MongoDataAutoConfiguration.class})
public class XdrsDataServiceApplication {

public static void main(String[] args) {
    SpringApplication.run(XdrsDataServiceApplication.class, args);
}

}

Image of where my pem file is stored enter image description here

In local I am getting following error

enter image description here

When I deploy the same code in AWS ECS Fargate, I see the following logs

enter image description here

1

There are 1 answers

0
Emmanuel Jones On

There are two issues here:

  • First, when connecting locally, you can't connect directly - you need to connect through an SSH tunnel instead. See Connecting to an Amazon DocumentDB Cluster from Outside an Amazon VPC for details on how to do this.
  • Second, the .pem certificate file isn't directly usable as a Java trust store. Instead, it contains the certificates which should be imported into a Java trust store (using the keytool Java utility), so that your program can then reference that trust store (via the javax.net.ssl.trustStore system property) in verifying the identity of the DocumentDB server.
    • Context: The sun.security.* packages (referenced in the Fargate logs you posted) verify the DocumentDB server's identity by attempting to build a valid PKIX certification path from the root CA certificates found in the Java trust store to the certificate presented by the particular DocumentDB server you are targeting. If the Java trust store found at javax.net.ssl.trustStore is either invalid (e.g., because it's a .pem file instead of a valid .jks file), or if it doesn't contain the necessary certificates (e.g., because the root CA certificates found in global-bundle.pem were never imported using the Java keytool utility), PKIX path building fails, meaning the identity of the DocumentDB server cannot be established. See Connecting with TLS Enabled for more details (and be sure to select the "Java" tab to see Java-specific instructions.)