Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic s3 signed URL implementation #620

Merged
merged 16 commits into from
Jan 23, 2023

Conversation

Belair34
Copy link
Contributor

@Belair34 Belair34 commented Jan 11, 2023

馃摙 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

馃摐 Description

Added two methods to S3Operations and thus S3Template that simplify creating signed urls for getting/putting objects in S3.

馃挕 Motivation and Context

It simplifies the creation of signed URLs for S3 into one function call each.

#318

馃挌 How did you test it?

So far I've manually tested it by doing ./mvnw install and then importing 3.0.0-SNAPSHOT from my local repository in a fresh spring project.

馃摑 Checklist

  • I reviewed submitted code
  • I added tests to verify changes
  • I updated reference documentation to reflect the change
  • All tests passing
  • No breaking changes

馃敭 Next steps

I'm not 100% sure this is what the issue was requesting, so please let me know! I also don't think the way I have the S3 presigner is ideal, but I'm unsure how I should set it up. I imagine it should be configured like the S3Client, but I was unable to figure out how that works exactly and could use some advice. If any of this seems promising, I will go ahead and add tests and what not.

@github-actions github-actions bot added the component: s3 S3 integration related issue label Jan 11, 2023
Copy link
Contributor

@maciejwalkowiak maciejwalkowiak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot @Belair34! I left few comments. Make sure to add integration tests for that. I think Localstack supports signed urls with S3.

@Belair34 Belair34 marked this pull request as ready for review January 12, 2023 20:26
@Belair34
Copy link
Contributor Author

@maciejwalkowiak I updated everything based on your comments! I do have one concern: I can't get all of the tests to pass even when I'm on the up-to-date main branch. It always fails at ParameterStoreConfigDataLoaderIntegrationTests.whenKeysAreNotSpecifiedFailsWithHumanReadableFailureMessage. I'm on Windows 10 using Java 17 for the record.
Also, about docs: do I need to add anything besides the javadocs in S3Operations.java?

Copy link
Contributor

@maciejwalkowiak maciejwalkowiak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for an update. I fixed the compilation issue. There are few more things needed - if you find it unclear please let me know!

HttpResponse response = httpClient.execute(httpPut);
httpClient.close();

HeadObjectResponse headObjectResponse = client.headObject(HeadObjectRequest.builder()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Genuine question - shouldn't we upload something in this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it technically isn't uploading a local file, but it is adding a new file "file.txt" to the bucket with the request body as its contents and then checking to make sure it is there at the end. Personally, I think knowing this works is enough to be confident that the signed URL itself works. The difference is just about how you use it. That's just my interpretation, though. I'm open to other opinions!

@maciejwalkowiak
Copy link
Contributor

Regarding ParameterStoreConfigDataLoaderIntegrationTests - make sure you are up to date with main branch and just in case run ./mvnw clean - this test used to be flaky but should not be any longer.

@Belair34
Copy link
Contributor Author

Everything should be ready for review again! By the way, I found out the tests were failing for me because of lines like this:

assertThat(output.getOut())
.contains("Description:\n" + "\n" + "Could not import properties from AWS Parameter Store");
}

Since I'm on Windows all my new lines were '\r\n' instead of '\n' so the assertions were failing. I temporarily replaced these '\n' with System.lineSeparator() and all of my tests passed.

Copy link
Contributor

@maciejwalkowiak maciejwalkowiak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for an update @Belair34. I left few comments we also need to update the reference docs (look s3.adoc). If you have any questions let me know!

@github-actions github-actions bot added the type: documentation Documentation or Samples related issue label Jan 16, 2023
@Belair34
Copy link
Contributor Author

@maciejwalkowiak I tried to make ConfiguredS3Presigner, and based on my evaluation of their internals it seemed like I didn't really need to change anything besides names. It worked perfectly for the first test I added regarding endpoints, but my second test gets null for the common aws properties. I'm really not sure why this is. Any ideas? I could also use some recommendations on which properties to test if this seems like the path forward.

@maciejwalkowiak
Copy link
Contributor

@Belair34 I fixed the test and did some final polishing.

@maciejwalkowiak
Copy link
Contributor

@MatejNedic if you have time please review.

Copy link
Member

@MatejNedic MatejNedic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a few questions regarding what should be returned but otherwise looks good!

* @param duration - duration that the URL will work
* @return a {@link URL} representing the signed URL
*/
URL createSignedGetURL(String bucketName, String key, Duration duration);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we return signedHeaders, SignedPayload, and isBrowserExecutable as well here?

Since in AWS docs for signedHeaders -> Returns the subset of headers that were signed, and MUST be included in the presigned request to prevent the request from failing.

Copy link
Contributor

@maciejwalkowiak maciejwalkowiak Jan 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I am quite confident we need an end to end test for that. createsWorkingSignedPutURL tests the whole flow.

* @param duration - duration that the URL will work
* @return a {@link URL} representing the signed URL
*/
URL createSignedPutURL(String bucketName, String key, Duration duration, @Nullable ObjectMetadata metadata,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we return signedHeaders, SignedPayload, and isBrowserExecutable as well here?

@maciejwalkowiak maciejwalkowiak merged commit 77a7080 into awspring:main Jan 23, 2023
@maciejwalkowiak maciejwalkowiak added this to the 3.0.0 RC1 milestone Jan 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: s3 S3 integration related issue type: documentation Documentation or Samples related issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants