How to delete an s3 object from a lambda function using aws-sdk

I am trying to delete an object from an s3 bucket, but no matter what I do the delete request always ends up timing out. I'm thinking I've either configured the permissions incorrectly or I'm using the aws-sdk incorrectly.

Here is my lambda function creation, defined in aws-cdk:

this.appsyncS3LambdaResolver = new NodejsFunction(
      this,
      "appsyncS3LambdaResolver",
      {
        memorySize: 1024,
        handler: "handler",
        runtime: lambda.Runtime.NODEJS_14_X,
        timeout: cdk.Duration.seconds(5),
        entry: __dirname + "/../../lambda-fns/AppsyncS3LambdaResolver/index.ts",
        environment: {
          SECRET_NAME: props.rdsSecretName || "",
          SECRET_VALUE: props.rdsSecretValue || "",
          S3_BUCKET_NAME: props.s3bucket.bucketName,
          S3_BUCKET_URL: props.s3bucket.bucketWebsiteUrl,
        },
        bundling: {
          externalModules: ["aws-sdk"],
          nodeModules: ["pg"],
        },
        vpc: props.vpc,
        vpcSubnets: { subnetType: ec2.SubnetType.ISOLATED },
        securityGroups: [props.lambdaAccessToRDSSecurityGroup],
      }
    );

    // Give appsyncS3LambdaResolver access to put to S3 bucket (which enables it to make presigned urls)
    // and delete
    props.s3bucket.grantPut(this.appsyncS3LambdaResolver);
    props.s3bucket.grantDelete(this.appsyncS3LambdaResolver);

And here is my s3 bucket creation:

this.s3bucket = new s3.Bucket(this, "s3-bucket", {
      // bucketName: 'my-bucket',
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
      versioned: false,
      publicReadAccess: false,
      encryption: s3.BucketEncryption.S3_MANAGED,
      cors: [
        {
          allowedMethods: [s3.HttpMethods.GET, s3.HttpMethods.PUT],
          allowedOrigins: props.isProd
            ? [] // tbd
            : ["http://localhost:3000", "http://localhost:3000/*"],
          allowedHeaders: ["*"],
        },
      ],
      lifecycleRules: [
        {
          abortIncompleteMultipartUploadAfter: cdk.Duration.days(90),
          expiration: cdk.Duration.days(365),
          transitions: [
            {
              storageClass: s3.StorageClass.INFREQUENT_ACCESS,
              transitionAfter: cdk.Duration.days(30),
            },
          ],
        },
      ],
    });

    this.s3bucket.addToResourcePolicy(
      new iam.PolicyStatement({
        sid: "allow deleting objects from s3 bucket /public/*",
        effect: iam.Effect.ALLOW,
        principals: [new iam.AnyPrincipal()],
        actions: ["s3:DeleteObject"],
        resources: [this.s3bucket.bucketArn + "/public/*"],
      })
    );

And the actual lambda function code which isn't deleting:

for (let i = 0; i < result.rows[0].num_media; i++) {
        const params = {
          Bucket: process.env.S3_BUCKET_NAME,
          Key: `public/reviewmedia/${reviewId}/${i}`,
        };

        console.log("params:", params);

        const res = await s3.deleteObject(params).promise();
        console.log(res);
      }

I have the two permissions to grant my lambda function access to delete from the s3 bucket (s3bucket.grantDelete() and the policy on the s3 bucket) but neither of them seem to work. Here I have given my policy the equivalent of principals: "*" but that didn't fix it either. I'm not sure what's wrong with my configuration... I would really appreciate some advice.


Solution 1:

Usually timeout errors are related to connectivity issues.

In case of lambda running in VPC, make sure the associated SG allows outbound traffic and also check the lambda subnets has a route to connect to S3 (via IGW for public subnets, Nat Gateway/Nat Instance for private subnets or S3 VPC Endpoint to connect to S3 privately without requiring options mentioned before).