Azure Blob Storage data fetch fails due to HTTPS Authentification MBed TLS

adrian-fratila
Posts: 6
Joined: Sat May 15, 2021 2:40 pm

Azure Blob Storage data fetch fails due to HTTPS Authentification MBed TLS

Postby adrian-fratila » Wed Sep 13, 2023 9:55 am

Hi everybody,

I try to fetch a binary file from an Azure Blob Storage, using esp_http_client, IDF v5.0.1. The fetch works in Postman or in a browser, which means the url path and the SAS token are correct.

The connection to the Azure server is established, but I get the error message: "Server failed to authenticate the request":
  1. I(15113) APP : Opened successfully the HTTP connection
  2. I(15273) HTTP_CLIENT : Body received in fetch header state, 0x3ffbb6da, 166
  3. I(15293) APP : Read data : ���< ? xml version = "1.0" encoding = "utf-8" ? >
  4. <Error><Code>AuthenticationFailed< / Code><Message>Server failed to authenticate the request.Make sure the value of Authorization header is formed correctly including the signature.
  5. RequestId : 01100f54 - 901e-0045 - 18cc - e3e32c000000

I have tried various combinations for the connection setting: the url with and without the SAS at the end, and setting the SAS in the http header "Authorization" field.

I suspect the problem comes from the way the connection data is set / arranged in the esp http client. This is the code that I have tested:

  1. esp_http_client_config_t config = {
  2.   //.url = "https://name.blob.core.windows.net/test/v0.0.2-fw.bin&sp=r&...0MtMgNI%3D",
  3.   .url = "https://name.blob.core.windows.net/test/v0.0.2-fw.bin",
  4.   .transport_type = HTTP_TRANSPORT_OVER_SSL,
  5.   .event_handler = http_event_handler,
  6.   .cert_pem = rootCaPem,
  7.   .cert_len = rootCaPemLen,
  8.   .timeout_ms = RECEIVE_TIMEOUT,
  9.   .keep_alive_enable = true,
  10.   .skip_cert_common_name_check = true,
  11.   //.use_global_ca_store = true
  12. };
  13.  
  14. esp_http_client_handle_t client = esp_http_client_init(&config);
  15.  
  16. if (client == NULL) {
  17.   ESP_LOGE(TAG, "Failed to initialise HTTP connection");
  18.   return;
  19. }
  20.  
  21. esp_http_client_set_header(client, "Authorization", "SharedAccessSignature sp=r&...0MtMgNI%3D");
  22. //esp_http_client_set_header(client, "ContentType", "application/octet-stream");
  23. esp_http_client_set_header(client, "Accept", "*/*"); // copied from Postman
  24. esp_http_client_set_header(client, "Accept-Encoding", "gzip, deflate, br"); // copied from Postman
  25. esp_http_client_set_header(client, "Host", "name.blob.core.windows.net");
  26. esp_http_client_set_method(client, HTTP_METHOD_GET);
  27.  
  28. err = esp_http_client_open(client, 0);
  29.  
  30. if (err != ESP_OK) {
  31.   ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
  32.   esp_http_client_cleanup(client);
  33.   return;
  34. }
  35. else {
  36.   ESP_LOGI(TAG, "Opened successfully the HTTP connection");
  37. }
  38.  
  39. esp_http_client_fetch_headers(client);

Any idea on why the Azure authorization fails?

Does anybody have an ESP http client example, for fetching data from an Azure Blob Storage?

I would really appreciate any help!

Thank you!

ESP_harshal
Posts: 24
Joined: Wed Jul 06, 2022 8:36 am

Re: Azure Blob Storage data fetch fails due to HTTPS Authentification MBed TLS

Postby ESP_harshal » Wed Sep 13, 2023 10:32 am

Hello @adrian-fratila,

I think the http_request needs authentication data which is not included in the config. If you are trying to access the domain "https://name.blob.core.windows.net/test/v0.0.2-fw.bin" without any auth data then this should have been accessible using a browser publicly by me too. But when I try to access this domain, I get the same error message in the browser as the reported error "Server failed to authenticate the request. Make sure the value of the Authorization header is formed correctly including the signature."
I feel all you need is to add the authentication configs. You can refer to the basic auth example of esp_http_client: https://github.com/espressif/esp-idf/bl ... #L329-L355

MicroController
Posts: 1739
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Azure Blob Storage data fetch fails due to HTTPS Authentification MBed TLS

Postby MicroController » Wed Sep 13, 2023 8:43 pm

AFAICT, the SAS token goes into the URI of the request. And apparently, a "date" or "x-ms-date" header is mandatory for all authenticated accesses; see e.g. examples here.

Edit:

Code: Select all

//.url = "https://name.blob.core.windows.net/test/v0.0.2-fw.bin&sp=r&...0MtMgNI%3D"
looks almost right. Just the resource-path 'test/v0.0.2-fw.bin' needs to be separated from the query parameters by a ? instead of an &!
Try

Code: Select all

.url = "https://name.blob.core.windows.net/test/v0.0.2-fw.bin?sp=r&...0MtMgNI%3D"

adrian-fratila
Posts: 6
Joined: Sat May 15, 2021 2:40 pm

Re: Azure Blob Storage data fetch fails due to HTTPS Authentification MBed TLS

Postby adrian-fratila » Thu Sep 14, 2023 8:27 am

Hi guys,

Thank you for your input. I should have stated in my previous post that the URL and SAS were dummy. For completeness I have created a new Azure blob and uploaded two .txt files (3kB & 12KB).

The strange thing is that the small one (test.txt) is somehow loaded, even there is an error from the HTTP_CLIENT. In this error the beginning of the text file appears in the Error log:

I (12172) OTA: Opened successfully the HTTP connection
I (12252) HTTP_CLIENT: Body received in fetch header state, 0x3ffbad7a, 486
E (12252) HTTP_CLIENT: This is a test file.
This example demonstrates common operations the OTA tool:
- reading, writing and erasing OTA partitions,
- switching boot partitions, and
- switching to factory partition.

Users taking a look at this example should focus on the contents of the Python script [otatool_example.py](otatool_example.py) or shell script [otatool_example.sh](otatool_example.sh). The scripts contain
programmatic invocation of the tool's functions via the Python API and command-l�?!

I (12302) OTA: Fetching the Image file of length 2840 bytes
I (12302) OTA: Incremented length 1024
I (12312) OTA: Incremented length 2048
I (12312) OTA: Incremented length 2840
I (12322) OTA: Connection closed
I (12322) OTA: Total received data length: 2840
I (12332) HTTP_CLIENT: HTTP_EVENT_DISCONNECTED


The second file: test_long.txt doesn't load at all, and throws this error:

I (14202) OTA: Opened successfully the HTTP connection
E (14282) esp-tls-mbedtls: read error :-0x7100:
E (14282) transport_base: esp_tls_conn_read error, errno=Connection already in progress
E (14292) OTA: HTTP client fetch headers failed

I (14292) HTTP_CLIENT: HTTP_EVENT_DISCONNECTED


The same error appears for any large size file. I have inlined the code below, which contains valid URLs and SAS tokens with the expiration at the end of October, so plenty of time left for testing.
  1.       esp_http_client_config_t config = {
  2.             .url = "https://dumstorage.blob.core.windows.net/test/test.txt?sp=r&st=2023-09-13T16:10:57Z&se=2023-10-31T01:10:57Z&spr=https&sv=2022-11-02&sr=b&sig=5WjKp2Mp7uJWVJNLr2sdYt17YWuhYpVoJSwhmmBBgAo%3D",
  3.             //.url = "https://dumstorage.blob.core.windows.net/test/test_long.txt?sp=r&st=2023-09-13T14:51:07Z&se=2023-10-30T23:51:07Z&spr=https&sv=2022-11-02&sr=b&sig=lK88A5l41ysl%2BxEgwhvOsYZaia3CdJzFchDHnLlGaNE%3D",
  4.                 .transport_type = HTTP_TRANSPORT_OVER_SSL,
  5.             .event_handler = http_event_handler,
  6.                 .cert_pem = rootCaPem,
  7.             .cert_len = rootCaPemLen,
  8.                 .timeout_ms = 5000,
  9.                 //.auth_type = HTTP_AUTH_TYPE_BASIC,
  10.                 .keep_alive_enable = true,
  11.                 .skip_cert_common_name_check = true,
  12.             //.use_global_ca_store = true
  13.         };
  14.  
  15.         esp_http_client_handle_t client = esp_http_client_init(&config);
  16.         if (client == NULL) {
  17.            ESP_LOGE(TAG, "Failed to initialise HTTP connection");
  18.            return;
  19.         }
  20.  
  21.         //esp_http_client_set_header(client, "Authorization", "");
  22.         //esp_http_client_set_header(client, "ContentType", "application/octet-stream");
  23.         //esp_http_client_set_header(client, "Accept", "*/*");
  24.         esp_http_client_set_method(client, HTTP_METHOD_GET);
  25.  
  26.  
  27.         err = esp_http_client_open(client, 0);
  28.         if (err != ESP_OK) {
  29.           ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
  30.           esp_http_client_cleanup(client);
  31.           return;
  32.         }else{
  33.             ESP_LOGI(TAG, "Opened successfully the HTTP connection");
  34.         }
  35.  
  36.         content_length = esp_http_client_fetch_headers(client);
  37.  
  38.         if (content_length <0){
  39.             ESP_LOGE(TAG, "HTTP client fetch headers failed");
  40.             esp_http_client_cleanup(client);
  41.             return;
  42.         }else{
  43.             ESP_LOGI(TAG, "Fetching the Image file of length %d bytes", content_length);
  44.         }
  45.  
  46.         int binary_file_length = 0;
  47.  
  48.         while (1) {
  49.             int data_read = esp_http_client_read_response(client, ota_write_data, BUFFSIZE);
  50.  
  51.             if (data_read < 0) {
  52.                 ESP_LOGE(TAG, "Error: SSL data read error");
  53.                 esp_http_client_cleanup(client);
  54.                 return;
  55.             } else if (data_read > 0) {
  56.                   //ESP_LOGI(TAG, "Read data: %s", ota_write_data);
  57.                 binary_file_length += data_read;
  58.                 ESP_LOGI(TAG, "Incremented length %d", binary_file_length);
  59.             } else if (data_read == 0) {
  60.                 if (errno == ECONNRESET || errno == ENOTCONN) {
  61.                     ESP_LOGE(TAG, "Connection closed, errno = %d", errno);
  62.                     break;
  63.                 }
  64.                 if (esp_http_client_is_complete_data_received(client) == true) {
  65.                     ESP_LOGI(TAG, "Connection closed");
  66.                     break;
  67.                 }
  68.             }
  69.         }
  70.         ESP_LOGI(TAG, "Total received data length: %d", binary_file_length);
  71.         if (esp_http_client_is_complete_data_received(client) != true) {
  72.             ESP_LOGE(TAG, "Error in receiving complete file");
  73.             http_cleanup(client);
  74.             return;
  75.         }
  76.  
  77.         esp_http_client_cleanup(client);
Following @ESP_harshal suggestion, I have also set .auth_type = HTTP_AUTH_TYPE_BASIC in config, but that doesn't change the outcome.

I believe there must be some ESP HTTP CLIENT config settings which are missing, in order to get the data from an Azure blob storage. The links in the code above work in a browser or Postman.

Any help will be highly appreciated!

crodriguez
Posts: 2
Joined: Mon Jul 08, 2024 7:02 am

Re: Azure Blob Storage data fetch fails due to HTTPS Authentification MBed TLS

Postby crodriguez » Mon Jul 08, 2024 7:06 am

Hello Adrian,

Did you manage to solve it? I am facing the same issue...

Thanks in advance

Who is online

Users browsing this forum: Bing [Bot], Majestic-12 [Bot] and 107 guests