TRY
S3관련 서비스를 구축하면서 겪었던 문제들이다.
Spring boot 3을 사용하면서 다양한 이슈들을 겪었는데 (jakarta등 라이브러리 호환..) 처음 사용했던 Spring-cloud-aws 2버전대가 boot3와 이슈가 있다는 걸 지나가다 보았다.
SQS를 이제 곧 사용하게 될텐데 이부분에서 이슈가 있다는 글들이었다.
해당 글들을 확인하고 spring-cloud-aws의 git을 확인하였다.
이왕이면 호환도 되고 DynamoDB도 추가된 aws sdk v2를 사용하기 위해(또 최신버전이면 좋으니까..) Spring-cloud-aws 3으로 변경하는 작업을 진행했다.
변경하며 v1과 다른 점들을 느꼈는데 특히 PresignedUrl을 발급할때 v1에선 AmazonS3
의 generatePresignedUrl
을 이용해 발급했었는데 v2로 넘어오며 Client는 S3Client
로 변경되었고 PresignedURL은 S3Preginer
를 통해 발급받았다.
뭔가 이유가 있겠지만 더 복잡하게 만들 필요가 있나 싶었다.
또 BucketName 과 Key등을 파라미터로 넣고 만들 수 있었지만 v2에선 각 Request 객체를 만들고 이를 파라미터로 사용하여 요청하였다.
이부분은 마음에 들었다.
이외에 다양한 차이점들이 있다.
이렇게 변경 작업을 완료하고 이제 기존 테스트를 수정하여 테스트 하려 했다.
이때부터 문제가 생기기 시작한다.
CATCH
-
PresignedURL을 생성하는데 400 bad reqeust가 발생하기 시작한다.
정상적으로 동작하던 간단한 테스트가 400을 뱉기 시작했다.
이유를 보니 요청하는 파라미터가 안맞는다는 것 이었는데 보니까 @TestConfiguration에 설정해두었던 S3Client의 endpoint가 적용되고 있지않았다.
계속 이유를 찾아보다가 놓친 부분을 발견했다.
맞다. 위에서 말했던S3Presigner
를 통해 PresignedURL을 발급하고 있었다.
S3Client의 endpoint는 적용해뒀지만 S3Presigner에서도 endpoint 및 다른 설정들이 필요했다.
이를 변경하여 400 bad request를 해결하였다.
이제 되겠지. 다시 테스트를 돌려보자. -
SigV4만 사용가능하다는 에러가 발생하였다.
이상하다. 분명 V2는 SigV4를 사용하고 있다고 들었고 디폴트 설정인줄 알았는데..
계속 삽질하다가 기존에 Test에서 AmazonS3의 설정으로 사용하던 credential을 보았다.
설마.. 하고AnonymousAWSCredentials
을 변경하였다.
그랬더니 정상동작하였다..
AnonymousAWSCredentials
가 내부적으로 Signature version를 다른걸 쓰고 있는건지 찾아봐야 할 것 같다.
사실 Signature와 credential 부분의 공부가 필요 할 것 같다.
이부분은 좀 더 조사가 필요하고 아마 다른 방법도 있었을 것이다.
다만 저부분은 사용하지않고 테스트에서만 이용하고 있었으며 실제 @Configuration에선 다른 걸 사용하고 있고 정상동작 하고있었다.
그래서 변경하였다.
이것외에도 몇가지 있었다.
추가 (signature v4)
‘AnonymousAwsCredentials’을 테스트에서 사용했을때 다음과 같은 에러가 났었다.
Only SigV4 presigners are supported at this time, but the configured presigner (software.amazon.awssdk.auth.signer.AwsS3V4Signer@32d3bc83) did not seem to generate a SigV4 signature.
그리고 사이트를 참고 해서 Signature Version 4 요소들을 확인 할 수 있었다.
AnonymousAWSCredentials
가 안됐던 이유를 예상하기론
Authentication information
Each request that you send must include the following information. AWS uses this information to ensure the validity and authenticity of the request.
Algorithm – Use AWS4-HMAC-SHA256 to specify Signature Version 4 with the HMAC-SHA256 hash algorithm.
Credential – A string that consists of your access key ID, the date in YYYYMMDD format, the Region code, the service code, and the aws4_request termination string, separated by slashes (/). The Region code, service code, and termination string must use lowercase characters.
AKIAIOSFODNN7EXAMPLE/YYYYMMDD/region/service/aws4_request Signed headers – The HTTP headers to include in the signature, separated by semicolons (;). For example, host;x-amz-date.
Signature – A hexadecimal-encoded string that represents the calculated signature. You must calculate the signature using the algorithm that you specified in the Algorithm parameter.
여기서 아마 이부분
Credential – A string that consists of your access key ID ~~~
일 것 같다.
Signature를 생성해서 presignedURL을 발급하는데 AnonymousAWSCredentials
는 계정정보등이 없기에 signature version 4를 생성할 수 없었던게 아닌가 싶다.
FINALLY
이같은 문제들을 겪으며 나는 처음에 S3Mock의 문제라고 생각하고 접근했었다.
하지만 나의 문제였던 것이다.
앞으로도 항상 나를 의심하며 공식 Docs를 뒤져보아야 겠다.
또 V2는 많이 사용하지 않는지 레퍼런스가 생각보다 너무 없었다..
뭔가 새로 시작할땐 조사를 철저히 해야겠다.
그리고 Spring-cloud-aws-s3를 사용하며 쓰는건 S3Template밖에 없었다.
그것도 PresignedURL을 발급하기위해..
어차피 S3Presigner를 Bean으로 생성하여 설정하고 관리하는데 굳이 Spring-cloud-aws-s3를 써야겠다는 생각이 들지않았다.
또 아직 초기버전이라 개발중인 단계라고 생각했다.
그래서 그냥 이슈를 피하기위해 Spring-cloud-aws를 걷어내고 Aws sdk v2만 사용하게되었다.
나중에 버전업이되고 기술적인 부분이 필요하게되면 다시 도입할 예정이다.
또 시간을 들여 Credential쪽을 한번 보려고 한다.
항상 머릿글을 뭘로 잡을까 고민한다. 그래서 그냥 try, catch, finally로 해보려한다.
끝