简体   繁体   中英

AWS Lambda and MongoDB Atlas Connectivity Issue

I want to create a connection to MongoDB Atlas from an AWS Lambda function. The AWS Lambda function I created is not able to connect to MongoDB Atlas using an IAM connection.

The following Java exception is thrown after attempting to connect to MongoDB Atlas.

com.mongodb.MongoSocketOpenException: Exception opening socket
    at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:73) ~[mongodb-driver-core-4.8.1.jar:?]
    at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:183) ~[mongodb-driver-core-4.8.1.jar:?]
    at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.lookupServerDescription(DefaultServerMonitor.java:198) [mongodb-driver-core-4.8.1.jar:?]
    at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:158) [mongodb-driver-core-4.8.1.jar:?]
    at java.lang.Thread.run(Unknown Source) [?:?]
Caused by: java.net.SocketTimeoutException: connect timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method) ~[?:?]
    at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) ~[?:?]
    at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) ~[?:?]
    at java.net.AbstractPlainSocketImpl.connect(Unknown Source) ~[?:?]
    at java.net.SocksSocketImpl.connect(Unknown Source) ~[?:?]
    at java.net.Socket.connect(Unknown Source) ~[?:?]
    at sun.security.ssl.SSLSocketImpl.connect(Unknown Source) ~[?:?]
    at com.mongodb.internal.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:107) ~[mongodb-driver-core-4.8.1.jar:?]
    at com.mongodb.internal.connection.SocketStream.initializeSocket(SocketStream.java:82) ~[mongodb-driver-core-4.8.1.jar:?]
    at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:68) ~[mongodb-driver-core-4.8.1.jar:?]
    ... 4 more

Here's my Java code that I currently use to establish a connection to MongoDB Atlas


    final String accessKeyId = System.getenv("AWS_ACCESS_KEY_ID");
    final String secretAccessKey = System.getenv("AWS_SECRET_ACCESS_KEY");
    final Regions region = Regions.US_EAST_1;
    final BasicAWSCredentials credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey);

    final AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard()
      .withCredentials(new AWSStaticCredentialsProvider(credentials))
      .withRegion(region)
      .build();

    final AssumeRoleRequest roleRequest = new AssumeRoleRequest()
      .withRoleArn("<Role ARN>")
      .withRoleSessionName("my-session");
    final AssumeRoleResult roleResponse = stsClient.assumeRole(roleRequest);
    final Credentials sessionCredentials = roleResponse.getCredentials();
    final ConnectionString connectionString
      = new ConnectionString("mongodb+srv://" + accessKeyId + ":" + secretAccessKey
      + "@cluster.e.mongodb.net/?authSource=%24external&authMechanism=MONGODB-AWS&retryWrites=true&w=majority&authMechanismProperties=AWS_SESSION_TOKEN:"
      + stsClient.getSessionToken().getCredentials().getSessionToken());
    final MongoClientSettings settings = MongoClientSettings.builder()
      .applyConnectionString(connectionString)
      .serverApi(ServerApi.builder()
        .version(ServerApiVersion.V1)
        .build())
      .build();
    return MongoClients.create(settings);

Here's the IAM policy that is being used:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sts:*",
                "logs:CreateLogGroup"
            ],
            "Resource": [
                "arn:aws:logs:***:kuungana-fn-api-log:*",
                "arn:aws:iam::***:role/KuunganaApiRole",
                "arn:aws:iam::***:user/user1"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:***:log-group:/aws/lambda/events_get:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "sts:GetSessionToken",
                "sts:DecodeAuthorizationMessage",
                "sts:GetAccessKeyInfo",
                "sts:GetCallerIdentity",
                "sts:GetServiceBearerToken",
                "sts:GetSessionToken"
            ],
            "Resource": "*"
        }
    ]
}

Here's the trust relationships for KuunganaApiRole:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::***:user/user1"
            },
            "Action": "sts:AssumeRole"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:sts::***:assumed-role/KuunganaApiRole/events_create"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

This is likely not a permission issue but more of a.network access issue.

  1. If your Lambda is within a VPC then ensure it is allowed access to the MongoDB Atlas, su.nets and ACL's should permit access.
  2. If Lambda is not within a VPC, then ensure your cluster has access to the public inte.net 0.0.0.0/0

https://www.mongodb.com/docs/atlas/manage-connections-aws-lambda/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM