Azure / Azurite

A lightweight server clone of Azure Storage that simulates most of the commands supported by it with minimal dependencies
MIT License
1.82k stars 322 forks source link

Wrong errorCode returned, when malformed Etag is provided for table Update/Delete operations #2013

Open PrasantJillella opened 1 year ago

PrasantJillella commented 1 year ago

Which service(blob, file, queue, table) does this issue concern?

Table

Which version of the Azurite was used?

3.23.0

Where do you get Azurite? (npm, DockerHub, NuGet, Visual Studio Code Extension)

npm

What's the Node.js version?

v18.14.2

What problem was encountered?

When sending malformed Etag for table operations like Update, Delete. It is noticed that Exception is thrown with ErrorCode: InvalidOperation. But the actual expected ErrorCode: InvalidInput.

Steps to reproduce the issue?

namespace for TableClient class is 'Azure.Data.Tables' Etag value sent= "MalformedETag" Below is sample code snippet to describe change involved.

           TableClient tableClient = new TableClient()
            var row = tableClient .NewRecord(
                "ParitionKeyValue",
                "RowKeyValue");
            var result = await tableClient .AddRowAsync(
                row,
                this.context.CancellationToken);
            var result = await tableClient.AddRowAsync(
                row,
                this.context.CancellationToken);

            row.ETag = "MalformedETag";
            tableClient.UpdateEntityAsync(
                            row.ToTableEntity(),
                            ifMatch: new ETag(record.ETag),
                            mode: TableUpdateMode.Replace,
                            cancellationToken: cancellationToken)

If possible, please provide the debug log using the -d parameter, replacing \<pathtodebuglog> with an appropriate path for your OS, or review the instructions for docker containers:

`2023-07-21T05:37:15.047Z 6ad381e8-ef22-4347-9444-088b8243e56f info: TableStorageContextMiddleware: RequestMethod=DELETE RequestURL=http://127.0.0.1/devstoreaccount1/<TableName>(PartitionKey='c44fa781-8594-4f8a-a517-82aabaa77301',RowKey='75b854d8-469e-466f-bba4-e4bca7da492c')?$format=application%2Fjson%3Bodata%3Dminimalmetadata RequestHeaders:{"host":"127.0.0.1:10002","x-ms-version":"2020-12-06","dataserviceversion":"3.0","if-match":"MalformedETag","accept":"application/json;odata=minimalmetadata","x-ms-client-request-id":"a67ca882-7c0c-491c-8702-8eb353d7a1e8","x-ms-return-client-request-id":"true","user-agent":"azsdk-net-Data.Tables/12.7.1 (.NET 6.0.20; Microsoft Windows 10.0.19045)","x-ms-date":"Fri, 21 Jul 2023 05:37:15 GMT","authorization":"SharedKeyLite devstoreaccount1:zbskKoFmltOPS3ojOMDulpESIuuUfzVgd56VajlH3yM="} ClientIP=127.0.0.1 Protocol=http HTTPVersion=1.1
2023-07-21T05:37:15.047Z 6ad381e8-ef22-4347-9444-088b8243e56f debug: tableStorageContextMiddleware: Dispatch pattern string: /<TableName>(PartitionKey='PLACEHOLDER',RowKey='PLACEHOLDER')
2023-07-21T05:37:15.047Z 6ad381e8-ef22-4347-9444-088b8243e56f info: tableStorageContextMiddleware: Account=devstoreaccount1 tableName=<TableName>
2023-07-21T05:37:15.047Z 6ad381e8-ef22-4347-9444-088b8243e56f verbose: DispatchMiddleware: Dispatching request...
2023-07-21T05:37:15.047Z 6ad381e8-ef22-4347-9444-088b8243e56f info: DispatchMiddleware: Operation=Table_DeleteEntity
2023-07-21T05:37:15.047Z 6ad381e8-ef22-4347-9444-088b8243e56f verbose: AuthenticationMiddlewareFactory:createAuthenticationMiddleware() Validating authentications.
2023-07-21T05:37:15.047Z 6ad381e8-ef22-4347-9444-088b8243e56f info: TableSharedKeyLiteAuthenticator:validate() Start validation against account shared key authentication.
2023-07-21T05:37:15.047Z 6ad381e8-ef22-4347-9444-088b8243e56f info: TableSharedKeyLiteAuthenticator:validate() [STRING TO SIGN]:"Fri, 21 Jul 2023 05:37:15 GMT\n/devstoreaccount1/devstoreaccount1/<TableName>(PartitionKey='c44fa781-8594-4f8a-a517-82aabaa77301',RowKey='75b854d8-469e-466f-bba4-e4bca7da492c')"
2023-07-21T05:37:15.047Z 6ad381e8-ef22-4347-9444-088b8243e56f info: TableSharedKeyLiteAuthenticator:validate() Calculated authentication header based on key1: SharedKeyLite devstoreaccount1:zbskKoFmltOPS3ojOMDulpESIuuUfzVgd56VajlH3yM=
2023-07-21T05:37:15.047Z 6ad381e8-ef22-4347-9444-088b8243e56f info: TableSharedKeyLiteAuthenticator:validate() Signature 1 matched.
2023-07-21T05:37:15.047Z 6ad381e8-ef22-4347-9444-088b8243e56f verbose: DeserializerMiddleware: Start deserializing...
2023-07-21T05:37:15.048Z 6ad381e8-ef22-4347-9444-088b8243e56f info: HandlerMiddleware: DeserializedParameters={"options":{"queryOptions":{"format":"application/json;odata=minimalmetadata"},"requestId":"a67ca882-7c0c-491c-8702-8eb353d7a1e8","dataServiceVersion":"3.0"},"version":"2020-12-06","ifMatch":"MalformedETag"}
2023-07-21T05:37:15.048Z 6ad381e8-ef22-4347-9444-088b8243e56f error: ErrorMiddleware: Received a MiddlewareError, fill error information to HTTP response
2023-07-21T05:37:15.048Z 6ad381e8-ef22-4347-9444-088b8243e56f error: ErrorMiddleware: ErrorName=StorageError ErrorMessage=""  ErrorHTTPStatusCode=400 ErrorHTTPStatusMessage=undefined ErrorHTTPHeaders={"x-ms-error-code":"InvalidOperation","x-ms-request-id":"6ad381e8-ef22-4347-9444-088b8243e56f","x-ms-version":"2022-11-02"} ErrorHTTPBody="{\"odata.error\":{\"code\":\"InvalidOperation\",\"message\":{\"lang\":\"en-US\",\"value\":\"\\nRequestId:6ad381e8-ef22-4347-9444-088b8243e56f\\nTime:2023-07-21T05:37:15.048Z\"}}}" ErrorStack="\"StorageError\\n    at StorageErrorFactory.getInvalidOperation (<LocalPath>\\\\Azurite\\\\dist\\\\src\\\\table\\\\errors\\\\StorageErrorFactory.js:29:16)\\n    at TableHandler.deleteEntity (<LocalPath>\\\\Azurite\\\\dist\\\\src\\\\table\\\\handlers\\\\TableHandler.js:297:49)\\n    at <LocalPath>\\\\Azurite\\\\dist\\\\src\\\\table\\\\generated\\\\middleware\\\\HandlerMiddlewareFactory.js:58:18\\n    at <LocalPath>\\\\Azurite\\\\dist\\\\src\\\\table\\\\generated\\\\ExpressMiddlewareFactory.js:77:63\\n    at Layer.handle [as handle_request] (<LocalPath>\\\\Azurite\\\\node_modules\\\\express\\\\lib\\\\router\\\\layer.js:95:5)\\n    at trim_prefix (<LocalPath>\\\\Azurite\\\\node_modules\\\\express\\\\lib\\\\router\\\\index.js:328:13)\\n    at <LocalPath>\\\\Azurite\\\\node_modules\\\\express\\\\lib\\\\router\\\\index.js:286:9\\n    at Function.process_params (<LocalPath>\\\\Azurite\\\\node_modules\\\\express\\\\lib\\\\router\\\\index.js:346:12)\\n    at next (<LocalPath>\\\\Azurite\\\\node_modules\\\\express\\\\lib\\\\router\\\\index.js:280:10)\\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\""
2023-07-21T05:37:15.048Z 6ad381e8-ef22-4347-9444-088b8243e56f error: ErrorMiddleware: Set HTTP code: 400
2023-07-21T05:37:15.048Z 6ad381e8-ef22-4347-9444-088b8243e56f error: ErrorMiddleware: Set HTTP Header: x-ms-error-code=InvalidOperation
2023-07-21T05:37:15.048Z 6ad381e8-ef22-4347-9444-088b8243e56f error: ErrorMiddleware: Set HTTP Header: x-ms-request-id=6ad381e8-ef22-4347-9444-088b8243e56f
2023-07-21T05:37:15.048Z 6ad381e8-ef22-4347-9444-088b8243e56f error: ErrorMiddleware: Set HTTP Header: x-ms-version=2022-11-02
2023-07-21T05:37:15.048Z 6ad381e8-ef22-4347-9444-088b8243e56f error: ErrorMiddleware: Set content type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8
2023-07-21T05:37:15.048Z 6ad381e8-ef22-4347-9444-088b8243e56f error: ErrorMiddleware: Set HTTP body: "{\"odata.error\":{\"code\":\"InvalidOperation\",\"message\":{\"lang\":\"en-US\",\"value\":\"\\nRequestId:6ad381e8-ef22-4347-9444-088b8243e56f\\nTime:2023-07-21T05:37:15.048Z\"}}}"
2023-07-21T05:37:15.048Z 6ad381e8-ef22-4347-9444-088b8243e56f info: EndMiddleware: End response. TotalTimeInMS=1 StatusCode=400 StatusMessage=Bad Request Headers={"server":"Azurite-Table/3.23.0","x-ms-error-code":"InvalidOperation","x-ms-request-id":"6ad381e8-ef22-4347-9444-088b8243e56f","x-ms-version":"2022-11-02","content-type":"application/json;odata=minimalmetadata;streaming=true;charset=utf-8"}
2023-07-21T05:37:15.081Z 7da27640-f148-45f3-8a59-c1768fbb4772 info: TableStorageContextMiddleware: RequestMethod=POST RequestURL=http://127.0.0.1/devstoreaccount1/Tables?$format=application%2Fjson%3Bodata%3Dminimalmetadata RequestHeaders:{"host":"127.0.0.1:10002","x-ms-version":"2020-12-06","dataserviceversion":"3.0","prefer":"return-no-content","accept":"application/json;odata=minimalmetadata","x-ms-client-request-id":"9aa4b6dd-cfac-448d-ad3d-2ca53878d957","x-ms-return-client-request-id":"true","user-agent":"azsdk-net-Data.Tables/12.7.1 (.NET 6.0.20; Microsoft Windows 10.0.19045)","x-ms-date":"Fri, 21 Jul 2023 05:37:15 GMT","authorization":"SharedKeyLite devstoreaccount1:jZ4L8HrIJvYNh2RkOywG2sFROgbBCeNFpewVd0c4cCw=","content-type":"application/json;odata=nometadata","content-length":"35"} ClientIP=127.0.0.1 Protocol=http HTTPVersion=1.1
2023-07-21T05:37:15.082Z 7da27640-f148-45f3-8a59-c1768fbb4772 debug: tableStorageContextMiddleware: Dispatch pattern string: /Tables
2023-07-21T05:37:15.082Z 7da27640-f148-45f3-8a59-c1768fbb4772 info: tableStorageContextMiddleware: Account=devstoreaccount1 tableName=undefined
2023-07-21T05:37:15.082Z 7da27640-f148-45f3-8a59-c1768fbb4772 verbose: DispatchMiddleware: Dispatching request...`

Please be sure to remove any PII or sensitive information before sharing!
The debug log will log raw request headers and bodies, so that we can replay these against Azurite using REST and create tests to validate resolution.

Have you found a mitigation/solution?

No

blueww commented 1 year ago

@PrasantJillella Would you please share the Azurite debug log for this issue? For all kinds of table API that matters? We will need it to continue the investigation.

PrasantJillella commented 1 year ago

Hi

Sorry for delay, Updated the description with logs.

blueww commented 1 year ago

@PrasantJillella

Thanks for the update! The fix looks won't be too complex, might only need change the error kind when etag not match in related table request, from "getInvalidOperation" to "getInvalidInput". If you need the error message also be aligned besides error code, you might need to create a new kind of error.

Like in these line: Update Entity: https://github.com/Azure/Azurite/blob/800af6e9cd6639fa8a828c9b125c99f93707dc0e/src/table/handlers/TableHandler.ts#L397

Delete Entity:

https://github.com/Azure/Azurite/blob/800af6e9cd6639fa8a828c9b125c99f93707dc0e/src/table/handlers/TableHandler.ts#L547

Azurite welcome contribution! It would be great if you can raise a PR to fix it.