@@ -82,21 +82,18 @@ std::unordered_map<std::string, std::string> MergeProperties(
8282 return merged;
8383}
8484
85- // / SigV4 signer reproducing Java RESTSigV4AuthSession's
86- // / SignerChecksumParams(SHA256, X_AMZ_CONTENT_SHA256) output: canonical
87- // / headers carry Base64(SHA256(body)), canonical request trailer uses hex.
85+ // / Matches Java RESTSigV4AuthSession: canonical headers carry
86+ // / Base64(SHA256(body)), canonical request trailer uses hex.
8887class RestSigV4Signer : public Aws ::Client::AWSAuthV4Signer {
8988 public:
9089 RestSigV4Signer (const std::shared_ptr<Aws::Auth::AWSCredentialsProvider>& creds,
9190 const char * service_name, const Aws::String& region)
9291 : Aws::Client::AWSAuthV4Signer(creds, service_name, region,
9392 PayloadSigningPolicy::Always,
9493 /* urlEscapePath=*/ false ) {
95- // AWSAuthV4Signer normally overwrites x-amz-content-sha256 with the hex
96- // body hash right before canonicalization, which would clobber the Base64
97- // value the caller pre-sets. Clearing this flag skips that overwrite so
98- // canonical headers see the caller's Base64, while ComputePayloadHash
99- // still feeds hex into the canonical request trailer.
94+ // Skip the signer's hex overwrite of x-amz-content-sha256 so canonical
95+ // headers see the caller's Base64; ComputePayloadHash still feeds hex
96+ // into the canonical request trailer.
10097 m_includeSha256HashHeader = false ;
10198 }
10299};
@@ -118,41 +115,37 @@ SigV4AuthSession::SigV4AuthSession(
118115
119116SigV4AuthSession::~SigV4AuthSession () = default ;
120117
121- Status SigV4AuthSession::Authenticate (
122- std::unordered_map<std::string, std::string>& headers,
123- const HTTPRequestContext& request_context) {
124- ICEBERG_RETURN_UNEXPECTED (delegate_->Authenticate (headers, request_context));
125- auto original_headers = headers;
118+ Result<HTTPRequest> SigV4AuthSession::Authenticate (const HTTPRequest& request) {
119+ ICEBERG_ASSIGN_OR_RAISE (auto delegate_request, delegate_->Authenticate (request));
120+ const auto & original_headers = delegate_request.headers ;
126121
127122 // Relocate any delegate-set Authorization so SigV4 takes precedence.
128123 std::unordered_map<std::string, std::string> signing_headers;
129- for (const auto & [name, value] : headers ) {
124+ for (const auto & [name, value] : original_headers ) {
130125 if (StringUtils::EqualsIgnoreCase (name, " Authorization" )) {
131126 signing_headers[std::string (kRelocatedHeaderPrefix ) + name] = value;
132127 } else {
133128 signing_headers[name] = value;
134129 }
135130 }
136131
137- Aws::Http::URI aws_uri (request_context .url .c_str ());
132+ Aws::Http::URI aws_uri (delegate_request .url .c_str ());
138133 auto aws_request = std::make_shared<Aws::Http::Standard::StandardHttpRequest>(
139- aws_uri, ToAwsMethod (request_context .method ));
134+ aws_uri, ToAwsMethod (delegate_request .method ));
140135 for (const auto & [name, value] : signing_headers) {
141136 aws_request->SetHeaderValue (Aws::String (name.c_str ()), Aws::String (value.c_str ()));
142137 }
143138
144139 // Empty body uses hex EMPTY_BODY_SHA256 (Java workaround for the signer
145- // producing an invalid checksum for empty bodies); non-empty body uses
146- // Base64(SHA256(body)). See RestSigV4Signer doc for why this value survives
147- // signing to land in the canonical headers unchanged.
148- if (request_context.body .empty ()) {
140+ // producing an invalid checksum on empty bodies); non-empty uses Base64.
141+ if (delegate_request.body .empty ()) {
149142 aws_request->SetHeaderValue (" x-amz-content-sha256" , Aws::String (kEmptyBodySha256 ));
150143 } else {
151144 auto body_stream =
152- Aws::MakeShared<std::stringstream>(" SigV4Body" , request_context .body );
145+ Aws::MakeShared<std::stringstream>(" SigV4Body" , delegate_request .body );
153146 aws_request->AddContentBody (body_stream);
154147 auto sha256 = Aws::Utils::HashingUtils::CalculateSHA256 (
155- Aws::String (request_context .body .data (), request_context .body .size ()));
148+ Aws::String (delegate_request .body .data (), delegate_request .body .size ()));
156149 aws_request->SetHeaderValue (" x-amz-content-sha256" ,
157150 Aws::Utils::HashingUtils::Base64Encode (sha256));
158151 }
@@ -162,21 +155,25 @@ Status SigV4AuthSession::Authenticate(
162155 Error{ErrorKind::kAuthenticationFailed , " SigV4 signing failed" });
163156 }
164157
165- // Merge signed headers back; relocate any original value that conflicts.
166- headers.clear ();
158+ // Fill headers with the signed set, relocating any conflicting originals.
159+ HTTPRequest signed_request{.method = delegate_request.method ,
160+ .url = std::move (delegate_request.url ),
161+ .headers = {},
162+ .body = std::move (delegate_request.body )};
167163 for (const auto & [aws_name, aws_value] : aws_request->GetHeaders ()) {
168164 std::string name (aws_name.c_str (), aws_name.size ());
169165 std::string value (aws_value.c_str (), aws_value.size ());
170166 for (const auto & [orig_name, orig_value] : original_headers) {
171167 if (StringUtils::EqualsIgnoreCase (orig_name, name) && orig_value != value) {
172- headers[std::string (kRelocatedHeaderPrefix ) + orig_name] = orig_value;
168+ signed_request.headers [std::string (kRelocatedHeaderPrefix ) + orig_name] =
169+ orig_value;
173170 break ;
174171 }
175172 }
176- headers[std::move (name)] = std::move (value);
173+ signed_request. headers [std::move (name)] = std::move (value);
177174 }
178175
179- return {} ;
176+ return signed_request ;
180177}
181178
182179Status SigV4AuthSession::Close () { return delegate_->Close (); }
@@ -243,7 +240,6 @@ SigV4AuthManager::MakeCredentialsProvider(
243240 bool has_ak = access_key_it != properties.end () && !access_key_it->second .empty ();
244241 bool has_sk = secret_key_it != properties.end () && !secret_key_it->second .empty ();
245242
246- // Reject partial credentials — providing only one of AK/SK is a misconfiguration.
247243 ICEBERG_PRECHECK (
248244 has_ak == has_sk, " Both '{}' and '{}' must be set together, or neither" ,
249245 AuthProperties::kSigV4AccessKeyId , AuthProperties::kSigV4SecretAccessKey );
@@ -263,14 +259,10 @@ SigV4AuthManager::MakeCredentialsProvider(
263259
264260std::string SigV4AuthManager::ResolveSigningRegion (
265261 const std::unordered_map<std::string, std::string>& properties) {
266- auto it = properties.find (AuthProperties::kSigV4SigningRegion );
267- if ( it != properties.end () && !it->second .empty ()) {
262+ if ( auto it = properties.find (AuthProperties::kSigV4SigningRegion );
263+ it != properties.end () && !it->second .empty ()) {
268264 return it->second ;
269265 }
270- auto legacy_it = properties.find (AuthProperties::kSigV4Region );
271- if (legacy_it != properties.end () && !legacy_it->second .empty ()) {
272- return legacy_it->second ;
273- }
274266 if (const char * env = std::getenv (" AWS_REGION" )) {
275267 return std::string (env);
276268 }
@@ -282,14 +274,10 @@ std::string SigV4AuthManager::ResolveSigningRegion(
282274
283275std::string SigV4AuthManager::ResolveSigningName (
284276 const std::unordered_map<std::string, std::string>& properties) {
285- auto it = properties.find (AuthProperties::kSigV4SigningName );
286- if ( it != properties.end () && !it->second .empty ()) {
277+ if ( auto it = properties.find (AuthProperties::kSigV4SigningName );
278+ it != properties.end () && !it->second .empty ()) {
287279 return it->second ;
288280 }
289- auto legacy_it = properties.find (AuthProperties::kSigV4Service );
290- if (legacy_it != properties.end () && !legacy_it->second .empty ()) {
291- return legacy_it->second ;
292- }
293281 return AuthProperties::kSigV4SigningNameDefault ;
294282}
295283
0 commit comments