Amazon S3 signed urls accessible from outside world - java

So we have a use case where we need to be able to download the S3 files from the outside world on the internet. For this we are creating s3 pre signed url as below. My doubt is how can we access this on the internet? Are these urls accessible by default on the internet. Or do we need to create a proxy.
https://<bucket-name>.s3.amazonaws.com/<filename><some other parameters>

The URL you are showing is not a Pre-signed URL. A Pre-signed URL look like this:
https://bucketxxxxxx.s3.amazonaws.com/note.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20230117T153509Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3599&X-Amz-Credential=AKIA33JWY3BX2TYWxxxxxxxxxxx%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=e55142af548e46fc2870bb03331d0e9aa9ffbd21xxxxxxxxxxxxxxxxxx
Once you generate a valid Pre-signed URL, you do not need a proxy. A user can download the object in the given time window - which you define when you create GetObjectPresignRequest .
GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder()
.signatureDuration(Duration.ofMinutes(60))
.getObjectRequest(getObjectRequest)
.build();
You can see the proper way to create a pre-signed URL using AWS SDK for Java v2 in the AWS Code Github here:
https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/GetObjectPresignedUrl.java
TO read more about using the AWS SDK for Java v2 to create them, see this topic in the AWS Java V2 Developer Guide.
Working with Amazon S3 presigned URLs

Related

How to explicitly provide AWS credentials for Amazon Athena Service Client object

The Amazon documentation says to use:
AwsBasicCredentials awsCreds = AwsBasicCredentials.create(
"your_access_key_id",
"your_secret_access_key");
S3Client s3 = S3Client.builder()
.credentialsProvider(StaticCredentialsProvider.create(awsCreds))
.build();
But that's for the S3Client, when I try to use the same structure for my AthenaClient my app won't even run and it fails to initialize.
For my application I'm grabbing the credentials from a repo with a configuration file for this app.
static #Value("${AWS_ACCESS_KEY_ID}") String amazonAccessId;
static #Value("${AWS_SECRET_ACCESS_KEY}") String amazonSecretKey;
AwsBasicCredentials awsCreds = AwsBasicCredentials.create(
"your_access_key_id",
"your_secret_access_key");
AthenaClient athenaClient = AthenaClient.builder()
.region(Region.US_WEST_2)
.credentialsProvider(StaticCredentialsProvider.create(awsCreds))
.build();
I want to provide the credentials this way so that when I push the code from my local machine the code still functions, instead of relying on my environment variables. Please tell me what I'm doing wrong, because the documentation does not.
Understand how credentials work when using the AWS SDK for Java V2 SDK. You can read about them in the AWS Java V2 Developer Guide here:
Using credentials
Specifically, read about the Credential retrieval order in that doc topic.
As far as what service you are using, it does not matter. An S3 Service Client works the same way as other Java Service clients in terms of handling creds.
The topic linked about describes this way to handle creds. As described in this topic, you can use the shared credentials and config files:
The SDK uses the ProfileCredentialsProvider to load credentials from the [default] credentials profile in the shared credentials and config files.
You can create a file named credentials - as shown here:
In that file - specify your keys:
[default]
aws_access_key_id=Axxxxxxxxxxxxxxxxxxxxxxxxxxx
aws_secret_access_key=Kxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Then you can use this code to create a service client:
AthenaClient athenaClient = AthenaClient.builder()
.region(Region.US_WEST_2)
.credentialsProvider(ProfileCredentialsProvider.create())
.build();
And also - ensure you are using the correct POM in your Java project that uses Amazon Athena. See:
https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/athena

How to set Policy conditions in Java AWS S3 SDK presigned url

I use Java AWS S3 SDK to presign my requests. I have the following code:
var request = new GeneratePresignedUrlRequest(bucketName, filename)
.withMethod(method)
.withExpiration(expiration());
// do something with request
return s3Client.generatePresignedUrl(request);
What I need to write in place of comment to add custom conditions like content-length-range?
For browser-based POST uploads to S3, the AWS Java SDK doesn't provide a way to generate pre-signed URLs with conditions. There's an open feature request to add this to the v2 SDK. Note that the PHP, Node.js, and Python SDKs do all provide this feature.
For regular HTTP PUT pre-signed URLs, you can't apply content length restrictions to pre-signed URLs. You can place conditions using a custom policy but that only supports:
DateLessThan
DateGreaterThan
IpAddress
If you need to deal with objects outside of a given size range then you could potentially do that in AWS Lambda, after the object has been uploaded.

Calling Google Cloud KMS from AWS Lambda

I'm new to Google's Cloud services and to Java, but I'm trying to set up a Java function on AWS Lambda that makes a call to Google Cloud KMS. I have working Java code locally, but from what I can tell the only way to authenticate the Google client is to set an environment variable with the path to a JSON file containing your credentials. I can do that easily locally when triggering my Java function - I just set the environment variable pointing to a file on my computer when running the code. Can anyone give me any pointers for how to do that in Lambda where all I seem to be able to do is upload a single .jar file?
You will probably want to store the JSON file in AWS Secret Manager and then retrieve the JSON file at function boot by authenticating to the AWS Secret Manager. Then you should configure the Google client library to use that credential contents.
Alternatively (more complex but also more secure) would be to configure GCP as an OIDC provider for AWS and then create an AWS role with permission to call GCP KMS directly - no credential file required.

S3 operations with V4 authentication using Query parameter as Authentication method using AWS JAVA SDK

I am trying to perform some S3 operations (like create bucket, get bucket, put object, list object etc) with V4 authentication using Query parameter as Authentication method.
I want to perform the operation using AWS JAVA SDKs
Question-
1. Does AWS JAVA SDK support Query parameter as Authentication method?If yes which package needs to be imported.
2. Any example of how to do that using AWS JAVA SDK will be greatly appreciated
You can generate pre-signed URL requests to access s3 resources using query parameter authentication. Here's how to do it with the Java SDK:
URL url = s3Client.generatePresignedUrl(bucketName, key, expirationDate);
I've only used it successfully with GET requests.

Amazon S3 and Cloudfront with Java API

I am currently using S3 with the Java API to get objects and their content. I've created a Cloudfront distribution using the AWS console and I set my S3 bucket with my objects as the Bucket-origin. But I didn't notice any improvement in the download performance, and I noticed in the console window the url refers to s3:
INFO: Sending Request: GET https://mybucket.s3.amazonaws.com /picture.jpg Headers: (Range: bytes=5001-1049479, Content-Type: application/x-www-form-urlencoded; charset=utf-8, )
whereas in the Getting Started guide for Cloudfront, the url should be:
http://(domain name)/picture.jpg
where (domain name) is specific to the Cloudfront distribution. So the Java API still is getting the file from S3 and not through cloudfront
Is there anyway using the Java API for S3 to download files via Cloudfront? If not, what's the best approach I should use to get objects via cloudfront in my java program? I am still kinda new to this stuff, any help greatly appreciated!
JAVA API for S3 can not be used for interacting with Cloudfront.
If you want to download the content through cloud front distribution, you have to write your own HTTP code (which should be simple). You can also just use http://(cloud front domain name)/picture.jpg in browser and check the download speed first.
URL url = new URL(your_cloudfront_url);
InputStream in = url.openStream();
But, you should know that it can take 24 hours or more for changes in S3 to be active.
If you cannot open the stream, the other way is to use getObject(bucketName, key) method.

Categories