Access Denied to amazon AWS SQS through CLI or API - node.js

I am getting access denied when I try to access the Amazon SQS through CLI or API. This is the node.js code:
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'eu-west-1'});
var credentials = new AWS.SharedIniFileCredentials({profile: 'default'});
AWS.config.credentials = credentials;
// Create the SQS service object
var sqs = new AWS.SQS({apiVersion: 'latest'});
var params = {
MaxResults: 10
};
sqs.listQueues(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});
The sqs policy is the following:
{
"Version": "2012-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__owner_statement",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::437568002678:root",
"arn:aws:iam::ACCOUNTID:role/MyRole",
"arn:aws:iam::ACCOUNTID:user/username"
]
},
"Action": [
"sqs:GetQueueAttributes",
"sqs:SendMessage",
"sqs:ListQueues"
],
"Resource": "arn:aws:sqs:eu-west-1:ACCOUNTID:NAME"
}
]
}
The complete error is:
Error AccessDenied: Access to the resource https://sqs.eu-west-1.amazonaws.com/ is denied.
The credentials file is set at /home/user/.aws/credentials.
I am using one account for AWS services.

To reproduce your situation I did the following:
Created an IAM User with no permissions
Configured the AWS CLI to use credentials associated with the new IAM User
Created a standard (non-FIFO) Amazon SQS queue
Attached your policy to the queue, but with an updated Resource and Principal
Used the AWS CLI to send a message to the SQS queue:
aws sqs send-message --queue-url https://sqs.ap-southeast-2.amazonaws.com/123456789012/queuename --message-body foo
The message was successfully sent to the queue. This means that the Access Policy on the SQS queue was sufficient to grant permission to send the message, without requiring any additional permissions on the IAM User.
Therefore, either your AWS CLI is not using the IAM User referenced in your Access Policy or there are some permissions on the IAM User or Account SCP that is specifically denying the ability to use SendMessage().

Related

How sendMessage from an AWS Lambda to an AWS SQS in a different AWS account?

I have a use case to send a message from an AWS Lambda function, let's say from Account A,To an AWS SQS in Account B,
In Account A, I have written a Lambda function that uses aws-sdk library in NodeJs to use the sendMessage method to send a message to the Queue URL in Account B,
The Lambda function has a role with permission to sendMessage to the SQS service
In Account B, I have created an SQS, which has permission to allow the ARN of the IAM role of the Lambda function in Account A as a Principal, and the SQS as the Resource
Lambda code -
import { SQSClient, SendMessageCommand } from "#aws-sdk/client-sqs";
const sqsClient = new SQSClient({ region: "ap-southeast-1" });
export const handler = async (event) => {
let response;
const params = {
MessageGroupId: "test",
MessageBody: "some message here",
QueueUrl: "https://sqs.ap-southeast-1.amazonaws.com/AWS_ACCOUNT_B_NUMBER/TEST.fifo"
};
try {
const data = await sqsClient.send(new SendMessageCommand(params));
if (data) {
console.log("Success, message sent. MessageID:", data.MessageId);
const bodyMessage = 'Message Sent, MessageId: ' +data.MessageId;
response = {
statusCode: 200,
body: JSON.stringify(bodyMessage),
};
}else{
response = {
statusCode: 500,
body: JSON.stringify('Some error occured !!')
};
}
return response;
}
catch (err) {
console.log("Error", err);
}
};
SQS Permission Statement -
{
"Sid": "Stmt1676274704834",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::AWS_ACCOUNT_A_NUMBER:role/test-ap-southeast-1-lambdaRole"
},
"Action": "sqs:SendMessage",
"Resource": "*"
}
I am getting the following error -
The specified queue does not exist or you do not have access to it.
There are 2 ways to do this :-
Use Access Policy for Sqs queues to allow different account access queue. Typically in the policy you will add lambda role arn to allow access.
Setup role in sqs account which will be assumed by lambda. Give Lambda the assume role permissions to assume role created in sqs account and then lambda will assume and get temporary credentials to perform the operation .

Access denied when trying to delete S3 Object from node js

i am using S3 bucket for uploading and getting image from S3 server. image is uploading and fetching fine but whenever i try to delete the object it says Access denied, i am unable to find which permission i am not giving in permission roles
here is my node js code which i am running local on my machine.
import S3 from 'aws-sdk/clients/s3';
const bucketName = process.env.AWS_BUCKET_NAME;
const region = process.env.AWS_BUCKET_REGION;
const accessKeyId = process.env.AWS_ACCESS_KEY;
const secretAccessKey = process.env.AWS_SECRET_KEY;
const s3 = new S3({
region,
accessKeyId,
secretAccessKey
});
const deleteFile = (filekey) => {
try {
const deleteParams = {
Bucket: bucketName,
Key: filekey
};
return s3.deleteObject(deleteParams).promise();
} catch (error) {
return error;
}
};
export default deleteFile;
here is the response
I think you have a little mis understanding when it comes to roles.Roles are used when you want one aws service to talk to another aws service, so basically by roles you are giving permission to one service to talk to another service.
by in your case you are not using aws service, so roles are not the problem.THe problem is with bucket policies.In order to do operations in your bucket, you need to give permission for the particular bucket
check this sample policy -> this example, you want to grant an IAM user in your AWS account access to one of your buckets, awsexamplebucket1, and allow the user to add, update, and delete objects.
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Action": "s3:ListAllMyBuckets",
"Resource":"arn:aws:s3:::*"
},
{
"Effect":"Allow",
"Action":["s3:ListBucket","s3:GetBucketLocation"],
"Resource":"arn:aws:s3:::awsexamplebucket1"
},
{
"Effect":"Allow",
"Action":[
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject"
],
"Resource":"arn:aws:s3:::awsexamplebucket1/*"
}
]
}
for more check https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html
Deleting an object in Amazon S3 requires s3:DeleteObject permission on the appropriate bucket (or all buckets).

s3 check if file exist by getting metadata

I am trying to check if file exists in s3 bucket using AWS javascript sdk.
I have defined my policy to Allow HeadBucket for my s3 bucket.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "s3:HeadBucket",
"Resource": "*"
}
]
}
I have attached the above policy to a user and I am using that user in setting up the config for the s3 as follows:
aws-config.json
{
"user1": {
"bucket": "my-bucket",
"region": "us-east-2",
"accessKey": "********",
"secretKey": "*********"
}
}
In my node.js code, I am trying to use headObject to get the meta data for the object as follows:
var AWS = require('aws-sdk');
var s3Config = require("../data/aws-config.json").user1;
AWS.config.update(s3Config);
var s3 = new AWS.S3;
var params = {
Bucket: "my-bucket",
Key: "mykey.PNG"
};
s3.headObject(params, function (err, metadata) {
console.log(err);
});
This is giving me 403 Forbidden error. I have tried everything from changing AWS policy to allow all s3 operations to allow access to all resources, nothing seems to work.
EDIT:
I checked the AWS.config.credentials and it is loading some random accessKey and secretKey and not from my config file. I am not sure why this is happening.
You are trying to HEAD object. There's no HEAD bucket operation which is what your IAM policy grants.
To do HEAD operation on an object, you need s3:GetObject permission.
See docs for more information.

Programmatic file upload to AWS S3 bucket

I want to provision an AWS S3 bucket and an IAM user (with programmatic access only) so I can facilitate file upload privilege for that user only. The user will receive the AWS access key ID and secret access key, to use in a simple Node.js or Python console application. What are the minimal steps required to achieve this?
Create an IAM user (with programmatic access), with no permissions - DONE
Create a S3 bucket and block all public access - DONE
Add a bucket policy that looks like this:
{
"Version": "2012-10-17",
"Id": "Policy1234567",
"Statement": [
{
"Sid": "Stmt1234567",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::1234567890:user/someuser"
},
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::some-bucket-name/*"
}
]
}
I have a simple node.js application that will upload a given file to the bucket:
const fs = require('fs');
const zlib = require('zlib');
const AWS = require('aws-sdk');
const s3 = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
});
const bucketName = 'some-bucket-name';
const fileName = 'alargefile.iso';
var body = fs.createReadStream(fileName)
.pipe(zlib.createGzip());
// Upload the stream
var s3obj = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
params: {
Bucket: bucketName,
Key: fileName
}
});
s3obj.upload({
Body: body
}, function(err, data) {
if (err) {
console.log("An error occurred", err);
}
else {
console.log("Uploaded the file at", data.Location);
}
});
Since the user does not have any permissions, do I still need to create a custom policy to apply as a permission for the user? The OOTB policies are either too generous (AmazonS3FullAccess) or too restrictive (AmazonS3ReadOnlyAccess). Another bit of confusion is that I have set a bucket policy that regulates access to the bucket for a specific user, so would that not be sufficient?
You can create custom policy for IAM user as well, where you only allow PUTObject to specific bucket.
example:
{
"Version": "2012-10-17",
"Id": "Policy1234567",
"Statement": [
{
"Sid": "Stmt1234567",
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::some-bucket-name/*"
}
]
}
If the bucket and IAM user are in the same account, you don't need bucket policy if IAM user has the above policy.
You definitely need Identity policy based on below link:
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html

Access denied when making api calls to s3 bucket with Node.js

Using Node.js, I'm making an api that makes calls to my s3 bucket on AWS. When I try to make use putObject method, i receive this error:
message: 'Access Denied',
code: 'AccessDenied',
region: null,
time: 2018-07-27T17:08:29.555Z,
... etc
}
I have a config and credentials file in C:/User/{User}/.aws/ directory
config file:
[default]
region=us-east-2
output=json
credentials file:
[default]
aws_access_key_id=xxxxxxxxxxxxxxx
aws_secret_access_key=xxxxxxxxxxx
I created policies for both IAM user and Bucket. Here's my IAM user inline policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:PutObject",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
And my bucket policy:
{
"Version": "2012-10-17",
"Id": "Policy1488494182833",
"Statement": [
{
"Sid": "Stmt1488493308547",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::134100338998:user/Test-User"
},
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:GetBucketLocation",
"s3:Get*",
"s3:Put*"
],
"Resource": "arn:aws:s3:::admin-blog-assets"
}
]
}
And finally, my api
var fs = require('fs'),
AWS = require('aws-sdk'),
s3 = new AWS.S3('admin-blog-assets');
...
var params = {
Bucket: 'admin-blog-assets',
Key: file.filename,
Body: fileData,
ACL:'public-read'
};
s3.putObject(params, function (perr, pres) {
if (perr) {
console.log("Error uploading image: ", perr);
} else {
console.log("uploading image successfully");
}
});
I've been banging my head on this for hours, can anyone help?
I believe the source of the problem is related to how you are defining the s3 object, as s3 = new AWS.S3('admin-blog-assets');
If you look at the example used here, it has this line:
var bucketPromise = new AWS.S3({apiVersion: '2006-03-01'}).createBucket({Bucket: bucketName}).promise();
Where the argument passed to AWS.S3 is an object containing that apiVersion field. But you are passing a string value.
The S3 specific documentation overview section has more information:
Sending a Request Using S3 var s3 = new AWS.S3();
s3.abortMultipartUpload(params, function (err, data) { if (err)
console.log(err, err.stack); // an error occurred else
console.log(data); // successful response }); Locking the
API Version In order to ensure that the S3 object uses this specific
API, you can construct the object by passing the apiVersion option to
the constructor:
var s3 = new AWS.S3({apiVersion: '2006-03-01'}); You can also set the
API version globally in AWS.config.apiVersions using the s3 service
identifier:
AWS.config.apiVersions = { s3: '2006-03-01', // other service API
versions };
var s3 = new AWS.S3();
Some of the permissions you were granting were bucket permissions and others were object permissions. There are actions matching s3:Get* and s3:Put* that apply to both buckets and objects.
"Resource": "arn:aws:s3:::example-bucket" is only the bucket itself, not the objects inside it.
"Resource": "arn:aws:s3:::example-bucket/*" is only the objects in the bucket, and not the bucket itself.
You can write two policy statements, or you can combine the resources, like this:
"Resource": [
"arn:aws:s3:::example-bucket",
"arn:aws:s3:::example-bucket/*"
]
Important Security Consideration: By using s3:Put* with both the bucket and object ARNs, your policy likely violates the principle of least privilege, because you have implicitly granted this user s3:PutBucketPolicy which allows these credentials to change the bucket policy. There may be other, similar concerns. You probably do not want to give these credentials that much control.
Credit to #PatNeedham for noticing a second issue that I overlooked, the AWS.S3() constructor expects an object as its first argument, not a string.

Resources