1#include <userver/s3api/authenticators/signature_v4.hpp>
3#include <userver/http/common_headers.hpp>
4#include <userver/s3api/models/request.hpp>
5#include <userver/utils/mock_now.hpp>
7#include <userver/utest/utest.hpp>
17constexpr std::string_view kAccessKey =
"AKIAIOSFODNN7EXAMPLE";
18constexpr std::string_view kSecretKey =
"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY";
19constexpr std::string_view kRegion =
"us-east-1";
20constexpr std::string_view kBucket =
"examplebucket";
21constexpr std::string_view kVirtualHost =
"examplebucket.s3.amazonaws.com";
23constexpr std::string_view kEmptyPayloadHash =
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
26constexpr time_t kMockedNowEpoch = 1369353600;
29 return SignatureV4{std::string{kAccessKey}, Secret{std::string{kSecretKey}}, std::string{kRegion}};
36 request.method = method;
37 request.bucket = kBucket;
38 request.req = std::move(req);
39 request.headers
[USERVER_NAMESPACE::http::
headers::kHost
] = std::string{kVirtualHost};
45TEST(S3ApiSignatureV4, AuthGetObject) {
46 auto request = MakeRequest(clients::http::
HttpMethod::kGet,
"test.txt");
47 request.headers
[USERVER_NAMESPACE::http::
headers::
kRange] =
"bytes=0-9";
49 const auto headers = MakeAuthenticator().Auth(request);
51 EXPECT_EQ(headers.at(
"X-Amz-Date"),
"20130524T000000Z");
52 EXPECT_EQ(headers.at(
"X-Amz-Content-Sha256"), kEmptyPayloadHash);
54 headers.at(
"Authorization"),
55 "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, "
56 "SignedHeaders=host;range;x-amz-content-sha256;x-amz-date, "
57 "Signature=f0e8bdb87c964420e857bd35b5d6ed310bd44f0170aba48dd91039c6036bdb41"
61TEST(S3ApiSignatureV4, AuthPutObject) {
62 auto request = MakeRequest(clients::http::
HttpMethod::kPut,
"test$file.text");
63 request.body =
"Welcome to Amazon S3.";
64 request.headers
[USERVER_NAMESPACE::http::
headers::kDate
] =
"Fri, 24 May 2013 00:00:00 GMT";
65 request.headers
[std::string_view{
"x-amz-storage-class"}
] =
"REDUCED_REDUNDANCY";
67 const auto headers = MakeAuthenticator().Auth(request);
69 EXPECT_EQ(headers.at(
"X-Amz-Content-Sha256"),
"44ce7dd67c959e0d3524ffac1771dfbba87d2b6b4b4e99e42034a8b803f8b072");
71 headers.at(
"Authorization"),
72 "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, "
73 "SignedHeaders=date;host;x-amz-content-sha256;x-amz-date;x-amz-storage-class, "
74 "Signature=98ad721746da40c64f1a55b78f14c238d841ea1380cd77a1b5971af0ece108bd"
78TEST(S3ApiSignatureV4, AuthQueryParameterWithoutValue) {
79 const auto request = MakeRequest(clients::http::
HttpMethod::kGet,
"?lifecycle");
81 const auto headers = MakeAuthenticator().Auth(request);
84 headers.at(
"Authorization"),
85 "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, "
86 "SignedHeaders=host;x-amz-content-sha256;x-amz-date, "
87 "Signature=fea454ca298b7da1c68078a5d1bdbfbbe0d65c699e0f91ac7a200a0136783543"
91TEST(S3ApiSignatureV4, AuthQueryParametersSorted) {
92 const auto request = MakeRequest(clients::http::
HttpMethod::kGet,
"?prefix=J&max-keys=2");
94 const auto headers = MakeAuthenticator().Auth(request);
97 headers.at(
"Authorization"),
98 "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, "
99 "SignedHeaders=host;x-amz-content-sha256;x-amz-date, "
100 "Signature=34b48302e7b5fa45bde8084f4b7868a86f0a534bc59db6670ed5711ef69dc6f7"
104TEST(S3ApiSignatureV4, AuthPathStyleAddressing) {
105 auto request = MakeRequest(clients::http::
HttpMethod::kGet,
"test.txt");
107 request.headers
[USERVER_NAMESPACE::http::
headers::kHost
] =
"s3.amazonaws.com";
109 const auto headers = MakeAuthenticator().Auth(request);
112 headers.at(
"Authorization"),
113 "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, "
114 "SignedHeaders=host;x-amz-content-sha256;x-amz-date, "
115 "Signature=0fcb291c4b47980ad34dd9a29532ceae67b48e45de3d6054873b430740567ec2"
119TEST(S3ApiSignatureV4, AuthEncodedPathAndQuery) {
121 const auto request = MakeRequest(clients::http::
HttpMethod::kGet,
"my%20folder/my%20file.txt?versionId=abc%20123");
123 const auto headers = MakeAuthenticator().Auth(request);
126 headers.at(
"Authorization"),
127 "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, "
128 "SignedHeaders=host;x-amz-content-sha256;x-amz-date, "
129 "Signature=d6e900c34937a984ac3eeff28c985f58b4cbfa4ecfdb216af808afdef4145933"
133TEST(S3ApiSignatureV4, AuthRequiresHostHeader) {
137 request.method = clients::http::
HttpMethod::kGet;
138 request.bucket = kBucket;
139 request.req =
"test.txt";
141 EXPECT_THROW(MakeAuthenticator().Auth(request), std::runtime_error);
142 EXPECT_THROW(MakeAuthenticator()
.Sign(request
, kMockedNowEpoch + 60
), std::runtime_error);
145TEST(S3ApiSignatureV4, SignPresignedUrl) {
146 const auto request = MakeRequest(clients::http::
HttpMethod::kGet,
"test.txt");
148 const auto params = MakeAuthenticator()
.Sign(request
, kMockedNowEpoch + 86400
);
150 EXPECT_EQ(params.at(
"X-Amz-Algorithm"),
"AWS4-HMAC-SHA256");
151 EXPECT_EQ(params.at(
"X-Amz-Credential"),
"AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request");
152 EXPECT_EQ(params.at(
"X-Amz-Date"),
"20130524T000000Z");
153 EXPECT_EQ(params.at(
"X-Amz-Expires"),
"86400");
154 EXPECT_EQ(params.at(
"X-Amz-SignedHeaders"),
"host");
155 EXPECT_EQ(params.at(
"X-Amz-Signature"),
"aeeed9bbccd4d02ee5c0109b86d86835f995330da4c265957d157751f604d404");