From ea3293be75c86b5e6c9ca4158b5ebe2a3224f76f Mon Sep 17 00:00:00 2001 From: David Steele Date: Sun, 27 Sep 2026 11:01:39 +0300 Subject: [PATCH] Set the Azure version header for SAS authentication. The version header was not set for SAS since a SAS specifies a version in the sv parameter. That is sufficient for normal requests but batch requires the version to be set explicitly and rejects the entire batch with 400 InvalidInput when it is missing. Azure reports the rejection as a single response part with no content-id, so it appeared that one sub-request had failed rather than that none had run. That part was retried individually and the remaining files in the batch were silently not deleted, leaving expired backups and WAL in the repository while expire reported success. --- doc/xml/release/2020s/2026/2.59.2.xml | 13 +++++++++++++ doc/xml/release/contributor.xml | 5 +++++ src/storage/azure/storage.c | 7 ++++--- test/src/module/storage/azureTest.c | 10 ++++++---- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/doc/xml/release/2020s/2026/2.59.2.xml b/doc/xml/release/2020s/2026/2.59.2.xml index 71d4a15ff..3647b5fec 100644 --- a/doc/xml/release/2020s/2026/2.59.2.xml +++ b/doc/xml/release/2020s/2026/2.59.2.xml @@ -27,6 +27,19 @@

Disable read retry when filters are passed to the driver.

+ + + + + + + + + + +

Set the Azure version header for SAS authentication.

+
+ diff --git a/doc/xml/release/contributor.xml b/doc/xml/release/contributor.xml index aee1fa716..0368b6900 100644 --- a/doc/xml/release/contributor.xml +++ b/doc/xml/release/contributor.xml @@ -433,6 +433,11 @@ fatihmtekin + + Florian Helmberger + fhelmberger + + Francisco Miguel Biete Banon fmbiete diff --git a/src/storage/azure/storage.c b/src/storage/azure/storage.c index 24abc6529..aa10c1daa 100644 --- a/src/storage/azure/storage.c +++ b/src/storage/azure/storage.c @@ -153,9 +153,10 @@ storageAzureAuth( if (this->keyType == storageAzureKeyTypeShared) httpHeaderPut(httpHeader, HTTP_HEADER_DATE_STR, dateTime); - // Set version header (required for shared key and auto auth types, not for SAS) but never on batch sub-requests, - // which inherit the version from the top-level batch request - if (this->keyType != storageAzureKeyTypeSas && !subRequest) + // Set version header but never on batch sub-requests, which inherit the version from the top-level batch request. SAS + // specifies a version in the sv parameter, but that is not sufficient for batch, which rejects the request when the version + // is not set explicitly. + if (!subRequest) httpHeaderPut(httpHeader, AZURE_HEADER_VERSION_STR, AZURE_HEADER_VERSION_VALUE_STR); // Shared key authentication diff --git a/test/src/module/storage/azureTest.c b/test/src/module/storage/azureTest.c index 5bcb4ddcc..243df75b8 100644 --- a/test/src/module/storage/azureTest.c +++ b/test/src/module/storage/azureTest.c @@ -117,8 +117,7 @@ testRequest(IoWrite *write, const char *verb, const char *path, TestRequestParam strCatFmt(request, "x-ms-tags:%s\r\n", param.tag); // Add version - if (driver->sharedKey != NULL || driver->credHttpClient != NULL) - strCatZ(request, "x-ms-version:2024-08-04\r\n"); + strCatZ(request, "x-ms-version:2024-08-04\r\n"); // Complete headers strCatZ(request, "\r\n"); @@ -474,7 +473,9 @@ testRun(void) TEST_RESULT_VOID( storageAzureAuth(storage, HTTP_VERB_GET_STR, STRDEF("/path/file"), query, dateTime, header, false), "auth"); TEST_RESULT_VOID(FUNCTION_LOG_OBJECT_FORMAT(header, httpHeaderToLog, logBuf, sizeof(logBuf)), "httpHeaderToLog"); - TEST_RESULT_Z(logBuf, "{content-length: '66', host: 'account.blob.core.usgovcloudapi.net'}", "check headers"); + TEST_RESULT_Z( + logBuf, "{content-length: '66', host: 'account.blob.core.usgovcloudapi.net', x-ms-version: '2024-08-04'}", + "check headers"); TEST_RESULT_STR_Z(httpQueryRenderP(query), "a=b&sig=key", "check query"); } @@ -1133,7 +1134,8 @@ testRun(void) "GET /account/container?comp=list&restype=container&sig=\n" "*** Request Headers ***:\n" "content-length: 0\n" - "host: %s", + "host: %s\n" + "x-ms-version: 2024-08-04", strZ(hrnServerHost())); // -----------------------------------------------------------------------------------------------------------------