Search code examples
amazon-web-servicesaws-lambdaamazon-sqsrolespolicies

I have a lambda with a role that has full access to SQS but I still can't send messages to SQS


Please help, I've been defeated by AWS...

I have a lambda with the following permissions.

enter image description here

Neither sqs resource-based policy nor the service role has any Deny statements. The lambda should send a message to another SQS queue but it can't, instead I just get this error

{
    "code": "AccessDenied",
    "time": "2021-06-03T20:50:09.722Z",
    "requestId": "62e15127-9f9b-527f-b1a8-0814dd5a5c9a",
    "statusCode": 403,
    "retryable": false,
    "retryDelay": 47.17774745450638,
    "level": "error",
    "message": "Access to the resource https://sqs.eu-west-1.amazonaws.com/ is denied.",
    "timestamp": "2021-06-03T20:50:09.723Z"
}

The lambda code that should do this (this code is normally on multiple files)

import { SQSEvent } from 'aws-lambda';
import { isLeft } from 'fp-ts/lib/Either';
import { first } from 'lodash';
import reporter from 'io-ts-reporters';
import ExitWithSuccess from 'Entities/ExitWithSuccess';
import { error } from '@mvf/logger';
import { SQS } from 'aws-sdk';
import Event from './Event';

const sqsClient = new SQS({
  region: 'eu-west-1',
});

const delayed = {
  client: sqsClient,
  url: 'https://sqs.eu-west-1.amazonaws.com/<account>/event_dispatcher_delayed_messages',
};

type ISqsClient = typeof delayed;
interface SqsOperations {
  sendMessage(body: Record<string, unknown>): Promise<unknown>;
}

const sqs = {
  instance: ({ client, url }: ISqsClient): SqsOperations => ({
    sendMessage: (body: Record<string, unknown>) =>
      client
        .sendMessage({ QueueUrl: url, MessageBody: JSON.stringify(body) })
        .promise(),
  }),
  delayed,
};

const lambda = async (event: SQSEvent): Promise<void> => {
  const record = first(event.Records);
  if (!record) {
    throw new ExitWithSuccess(error, 'lambda was invoked without any records');
  }

  const maybeEvent = Event.decode(JSON.parse(record.body));
  if (isLeft(maybeEvent)) {
    throw new ExitWithSuccess(error, 'invalid record body', {
      typeErrors: reporter.report(maybeEvent),
    });
  }

  await sqs.instance(delayed).sendMessage(maybeEvent.right);
};

export default lambda;

I've now spent 3 days on this, has anyone encountered a similar issue? How is it possible to have full access to resources and still not be able to interact with it?

Any tips, suggestions or ideas as to what is going on here is greatly appreciated.


Solution

  • Does the SQS queue have its resource-based policy that explicitly denies access?

    Is the SQS queue in the same account where the Lambda function is? otherwise, you need to allow cross-account access too.

    https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-examples-of-sqs-policies.html