How to give lambda the least privilege access to OpenSearch domain with basic auth

0

Hi, we use TS CDK to create an OpenSearch domain and connect it from a lambda. Here is the code:

this.domain = new opensearch.Domain(scope, domainId, {...})
this.domainLambda = new nodejs.NodejsFunction(this, `${domainId}-domain`, {...})
this.domain.grantReadWrite(this.domainLambda)

This was working fine until we enable basic auth:

this.domain = new opensearch.Domain(scope, domainId, {
  fineGrainedAccessControl: {
    masterUserName: pass.secretValueFromJson('username').toString(),
    masterUserPassword: pass.secretValueFromJson('password'),
  },
  ...
})

// Lambda handler code:
new Client({
      node: `https://${domainEndpoint}`,
      auth: { username: '', password: '' },
    })

We properly pass the username and password when creating the Client and we can successfully connect to domain when we have this access policy:

this.domain.addAccessPolicies(
      new iam.PolicyStatement({
        actions: ['es:*'],
        effect: iam.Effect.ALLOW,
        principals: [new iam.AnyPrincipal()],
        resources: [`${this.domain.domainArn}`, `${this.domain.domainArn}/*`],
      })
    )

But this is not following the least privilege principle, we don't want to give the access to any principal. I wonder why the following policies don't work:

// Just lambda
this.domain.addAccessPolicies(
      new iam.PolicyStatement({
        actions: ['es:*'],
        effect: iam.Effect.ALLOW,
        principals: [this.domainLambda.grantPrincipal],
        resources: [`${this.domain.domainArn}`, `${this.domain.domainArn}/*`],
      })
    )

// This also doesn't work
this.domain.grantReadWrite(this.domainLambda)

// Even just lambda service doesn't work
this.domain.addAccessPolicies(
      new iam.PolicyStatement({
        actions: ['es:*'],
        effect: iam.Effect.ALLOW,
        principals: [new iam.ServicePrincipal('lambda.amazonaws.com')],
        resources: [`${this.domain.domainArn}`, `${this.domain.domainArn}/*`],
      })
    )

Whats the best way to give lambda to connect an OpenSearch domain and perform indexing actions with some cluster settings requests.

1 個回答
0

The lambda function itself doesn't directly interact with the OpenSearch domain; rather, it runs within an execution role that grants it permissions to perform certain actions. Therefore, you need to grant permissions to the execution role associated with your Lambda function.

  1. Ensure that the execution role associated with your Lambda function has the necessary permissions to access the OpenSearch domain. You can achieve this by adding appropriate permissions to the execution role.
const role = new iam.Role(this, 'LambdaExecutionRole', {
    assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});

// Attach permissions to the execution role
this.domain.grantReadWrite(role);
  1. Modify your Lambda function to assume this role when executing. You can achieve this by specifying the role property when creating the Lambda function.
this.domainLambda = new nodejs.NodejsFunction(this, `${domainId}-domain`, {
    // other properties
    role: role,
});

By doing this, you're ensuring that your Lambda function assumes a role with the necessary permissions to access the OpenSearch domain, rather than directly granting permissions to the Lambda function itself.

Remember to replace // other properties with the appropriate properties you've been using for your Lambda function.

AWS
已回答 2 個月前
profile picture
專家
已審閱 1 個月前
  • Hey, thanks for the answer. When using this.domain.grantReadWrite(this.domainLambda) it adds the following statement to the lambda execution role: {"Action": ["es:ESHttpDelete", "es:ESHttpGet", "es:ESHttpHead", "es:ESHttpPatch", "es:ESHttpPost", "es:ESHttpPut"], "Resource": ["arn:aws:es:us-east-1:123:domain/search/*", "arn:aws:es:us-east-1:123:domain/search/*/*"], "Effect": "Allow"}. So I guess it already sets the execution role properly.

您尚未登入。 登入 去張貼答案。

一個好的回答可以清楚地回答問題並提供建設性的意見回饋,同時有助於提問者的專業成長。

回答問題指南