I have multiple images within a private S3 bucket and I would like an instance of Tableau to be able to access those images. Is there a URL or some way to access those images while still keeping the S3 bucket private?
Access Private Bucket through Tableau
You can setup a IAM user with access permission to S3 and allow Tableau access.
Check the article on Connect to your S3 data with the Amazon Athena connector in Tableau 10.3 for more details.
Note: You need to configure Amazon Athena for Querying the S3 content.
Custom Generated S3 Urls to Access Private Bucket
Yes. You can generate a Signed URL from your backend using AWS SDK. This can be done directly using S3 or through AWS CloudFront.
Using S3 Signed Urls. e.g, Signed Url for GET Object.
var params = {Bucket: 'bucket', Key: 'key'};
var url = s3.getSignedUrl('getObject', params);
console.log('The URL is', url);
Using CloudFront Signed Urls. e.g, Signed Url for GET in CloudFront.
var cfsign = require('aws-cloudfront-sign');
var signingParams = {
keypairId: process.env.PUBLIC_KEY,
privateKeyString: process.env.PRIVATE_KEY,
// Optional - this can be used as an alternative to privateKeyString
privateKeyPath: '/path/to/private/key',
expireTime: 1426625464599
}
// Generating a signed URL
var signedUrl = cfsign.getSignedUrl(
'http://example.cloudfront.net/path/to/s3/object',
signingParams
);
Note: Generating the Url needs to be done in your backend. You can setup a serverless solution for this by using AWS API Gateway and Lambda to provide an endpoint for authenticated users to access.
In addition you can also use AWS Cognito UserPools with Identity Pool to get direct access to S3 Private Content without the above steps. For this you need to use the Cognito UserPools or a federated identity as the identity provider which is connected with Cognito Identity Pools.
Related
I'm trying to generate a presigned upload URL to AWS S3, and this is the URL that I receive:
iex(3)> ExAws.S3.presigned_url(ExAws.Config.new(:s3), :put, "myapp-staging", "picture.png")
{:ok, "https://s3.us-east-1.amazonaws.com/myapp-staging/picture.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=MY-KEY-IS-HERE%2F20191215%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20191215T220120Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=df6a289130d12e3e8175457b5f8e21a8840f9b5713134ac83c91368332b84eed"}
Notice MY-KEY-IS-HERE - the AWS access key id is part of the url generated.
Is it safe for this API key to be publicly visible to anyone online asking for a presigned upload URL?
ACCESS_KEY_ID is ok but SECRET ACCESS Key will be cause the security issue.
Following is what I'm doing. I'm generating a pre-signed URL using a custom domain for my s3 bucket resources which are not public.
https://files.customdomain.com/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX
Also to add the certificate I've created a cloudfront distribution for the bucket having following origin settings
Origin Domain Name: bucket-name.s3.amazonaws.com
Origin Id : s3.bucket-name
Restrict Bucket Access: No
Yet I'm unable to access my resources. Throws access denied error. Any help would be appreciated.
There are two cases:
If your bucket has regular name.
In this case you should use CloudFront to access your bucket.
And like mentioned above URL looks like in this answer:
https://cloudfront-url/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX
If your bucket has s3 static website name.
In this case your bucket name looks like files.customdomain.com and you can generate pre-signed url for this bucket:
https://files.customdomain.com/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX
In your DNS you will have CNAME files.customdomain.com points to files.customdomain.com.s3.[bucket-region].amazonaws.com.
NOTICE
When I generate pre-signed URL via aws-cli:
aws s3 presign s3://files.customdomain.com/file123 --endpoint-url https://files.customdomain.com
I get URL with duplicate bucket name in the path:
https://files.customdomain.com/files.customdomain.com/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX
instead of:
https://files.customdomain.com/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX
I don't know if it has the same behavior via SDK.
Have you tried initializing S3 with the custom url var S3 = new AWS.S3({endpoint: 'media.domain.com', s3BucketEndpoint: true});
More info https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html
Also, make sure signature is correct as well https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingAWSSDK.html#specify-signature-version
Ref : https://github.com/aws/aws-sdk-js/issues/891
When using S3 with CloudFront, you don't want an S3 signed URL... you want a CloudFront signed URL.
Read Configuring Security and Limiting Access to Content in the CloudFront developer guide.
I found a solution for this question. The signed url needs to be generated for cloudfront url endpoint from s3 bucket. Therefore instead of
https://files.customdomain.com/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX
it needs to be
https://cloudfront-url/file123?AWSAccessKeyId=XXX&Expires=1541220685&Signature=XXXX
and DNS records had to resolve custom domain to cloudfront url.
I am using aws-amplify and aws-sdk in Angular JS/Typescript.
I can successfully access my AWS DynamoDB as an authenticated user.
I am also trying to add guest user access for a certain table in Dynamo, but I am struggling to understand how I would get a reference to the DynamoDB without any credentials.
My code looks like this at the moment
getDocumentClient() {
return Auth.currentCredentials()
.then(credentials => new AWS.DynamoDB.DocumentClient({ credentials: credentials }))
.catch(err => logger.debug('error getting document client', err));
How would I do something similar to get access to the DynamoDB as an unauthenticated guest user?
Cheers
Lee
Try makeUnauthenticatedRequest.
Here's an example with S3 - I've shown this because I know you can make requests to S3 from the AWS SDK as an unauthenticated user. I'm assuming that this will also work for DynamoDB but have not tested it.
var s3 = new AWS.S3();
var params = {
Bucket: 'mybucket'
};
s3.makeUnauthenticatedRequest('listObjects', params, callback);
The more strategic approach would be Amazon Cognito Identity Pools which support unauthenticated/guest identities. Cognito vends an identity and AWS credentials, and you can configure an IAM role allowing DynamoDB read access for unauthenticated identity types.
I think you can refer to what is mentioned in the blog post below.
https://aws.amazon.com/blogs/compute/using-amazon-api-gateway-as-a-proxy-for-dynamodb/
The basic idea is to use API Gateway as a proxy for DynamoDB API. Permission to access DynamoDB is granted to API Gateway via execution role, and API Gateway is configured to open to public. In doing so, the flow will be as follows:
Web Browser <----- HTTPS -----> API Gateway <----- AWS Service Proxy integration -----> DynamoDB
i am trying to access cloudfront to s3 bucket object response "AccessDenied".
xxxxxxxxxxxxx.cloudfront.net/bucket_name/35.jpg
inside bucket i can access url this is "public" url.
https://s3.ap-south-1.amazonaws.com/bucket_name/35.jpg
I am also try another bucket with another cloudfront ID with signed URL result is same. Please view code here =>
amazon cloudfront Error "AccessDenied"
You should:
Configure your CloudFront distribution with an Origin to point to your S3 bucket
Access the content via: xxxx.cloudfront.net/35.jpg
See:
Using Amazon S3 Origins and Custom Origins for Web Distributions
Using CloudFront with Amazon S3
Task List for Creating a Web Distribution
I am trying to use Signed URL for images and once I was able to do it. But then, I deleted it and trying to do it once again and I am not able to do it.
Here is what I have done so far:
Created a Cloudfront Key Pair in IAM Management Console. Downloaded
the private and public key and also noted the Access Key ID =
XXXXXXXXXXXXXXXXXXXX.
Created a S3 bucket. No custom configuration
Created a Cloudfront distribution with the following settings
Origin domain name: my bucket
Restrict bucket access: Yes
Created a new Origin Access Identity
Grant read permissions on Bucket: Selected Yes
Restrict Viewer Access (Use Signed URLs or Signed Cookies) = Yes
Trusted Signers = Self
And then inside my laravel code, I have the following inside my controller:
$keyPairId = 'XXXXXXXXXXXXXXXXXXXX';
$privateKey = config_path('pk-XXXXXXXXXXXXXXXXXXXX.pem');
$url = "http://xxxxxxxxxxxxxx.cloudfront.net/image.jpg";
$cf = new UrlSigner($keyPairId, $privateKey);
$imgSrc = $cf->getSignedUrl($url, time());
echo "<img src='{$imgSrc}' />";
But every time I am getting the same error:
<Error>
<Code>MissingKey</Code>
<Message>Missing Key-Pair-Id query parameter or cookie value</Message>
</Error>
Need help.
You have to use CloudFront specific key pairs and add those to $cf. More information on how to download or upload your own public key:
http://docs.aws.amazon.com/AWSSecurityCredentials/1.0/AboutAWSCredentials.html#KeyPairs
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html#private-content-creating-cloudfront-key-pairs