Microsoft Azure REST API

Hello all,

I have been recently using Azure Blob Storage to store and access data in an Ignition project. I have had success using a GET request to access the stored data. The issue I am having however is using a PUT request to upload data from Ignition. I believe I am having difficulty in constructing the authorization header, but I am not completely sure. I am currently receiving a 403 HTTP response code (meaning Client authorization is not acceptable I believe). Has anyone been able to successfully accomplish something similar?

Thanks

What Ignition version are you using? Can you share any of your script so far?
For a variety of reasons, I highly recommend system.net.httpClient() for interacting with REST/web APIs.

The system.net.httpClient() is definitely something I have been using. The PUT request has been providing a 403 HTTP error as well as a compiling error that states ā€˜Content-Lengthā€™ is a restricted header (when included). The exact code I am using is included below:

import datetime
import hmac
import hashlib
import base64

storage_account_name = '...'
storage_account_key = '...'
container_name='...'
api_version = '2016-05-31'
request_time = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')

string_params = {
    'verb': 'PUT',
    'Content-Encoding': '',
    'Content-Language': '',
    'Content-Length': '11',
    'Content-MD5': '',
    'Content-Type': 'text/plain; charset=UTF-8',
    'Date': '',
    'If-Modified-Since': '',
    'If-Match': '',
    'If-None-Match': '',
    'If-Unmodified-Since': '',
    'Range': '',
    'CanonicalizedHeaders': 'x-ms-blob-type:BlockBlob' + '\nx-ms-date:' + request_time + '\nx-ms-version:' + api_version + '\n',
    'CanonicalizedResource': '/' + storage_account_name +'/'+container_name+ '/' +'fname'
}

string_to_sign = (string_params['verb'] + '\n' 
                  + string_params['Content-Encoding'] + '\n'
                  + string_params['Content-Language'] + '\n'
                  + string_params['Content-Length'] + '\n'
                  + string_params['Content-MD5'] + '\n' 
                  + string_params['Content-Type'] + '\n' 
                  + string_params['Date'] + '\n' 
                  + string_params['If-Modified-Since'] + '\n'
                  + string_params['If-Match'] + '\n'
                  + string_params['If-None-Match'] + '\n'
                  + string_params['If-Unmodified-Since'] + '\n'
                  + string_params['Range'] + '\n'
                  + string_params['CanonicalizedHeaders']
                  + string_params['CanonicalizedResource'])

signed_string = base64.b64encode(hmac.new(base64.b64decode(storage_account_key), msg=string_to_sign.encode('utf-8'), digestmod=hashlib.sha256).digest()).decode()

headerVals = {
    'x-ms-version' : api_version,
    'x-ms-date' : request_time,
    'x-ms-blob-type': 'BlockBlob',
    'Content-Type': "text/plain; charset=UTF-8",
    'Authorization' : ('SharedKey ' + storage_account_name + ':' + signed_string),
    'Content-Length': '11'
}

urlCurr = ('https://' + storage_account_name + '.blob.core.windows.net/'+container_name+'/fname')

putData = 'hello world'

# Create the JythonHttpClient
client = system.net.httpClient()

response = client.put(url=urlCurr, data=putData, headers=headerVals)
1 Like

BUMP

I noticed that about a week ago a nightly fix was uploaded to the HTTP client POST function. The fix was aimed at resolving corruption when posting binary data. As seen in this post, I am using a PUT request and still seem to observe some data corruption on the byte arrays that I have been using (ie Content-Length is still incorrect). Has anybody been able to find a functional work-around or have any insight into how to resolve this problem? Also, is it possible that the bug identified in the POST function exists in the PUT function as well?

I wonder if Microsoftā€™s Python library for Azure blobs is compatible with ignition (always a question of whether it is a C-based library)

https://docs.microsoft.com/en-us/python/api/overview/azure/storage-blob-readme?view=azure-python

That would certainly help. Itā€™s also a bummer that this thread went dead. Iā€™m looking for answers on this as well.

1 Like

So I was actually able to get the API call to work. The C-based library compatibility presented itself as an issue when trying to use the Microsoft provided functions. The API call however uses generic libraries/functions, provided by ignition, for HTTP requests. A solution that worked for me was using the PUT BLOB call of the Azure Cloud Storage. The file intended for upload needed to be split up into smaller chunks and uploaded independently. After that I was able to upload and download to the Azure Cloud.

Here is some documentation on how to do this: Put Blob (REST API) - Azure Storage | Microsoft Docs

3 Likes

Worth mentioning for future readers that Postman is a phenomenal tool for testing APIs. See https://www.postman.com/. Using a tool like this will help you clarify whether the request itself is set up right.

2 Likes

I just wanted to thank you for posting this. It was very helpful in quick-starting Azure Blob Storage interaction. I had to remove ā€˜Content-Lengthā€™ from headerVals, but otherwise it worked perfectly!

1 Like

Hi everybody,

At our company we are moving our ERP-system from onprem to the Azure cloud. We are planning to connect with Busines Central (BC) through webservices (APIā€™s). At the moment we use almost standard queryā€™s for everything.

But I have only limited knowledge regarding connecting to the cloud. I have been told BC will use OAuth2.0 authentication. In Postman I was able to connect to the test cloud environment. But is there somewhere I can get information on how to perform this trick in Ignition?

Thanks in advance!

KR,
Steven

I am unsure of the exact solution you would need, as I have never worked with BC before. I suspect that you could build out a template for API connections and use Ignitions scripting functions to establish that connection. The template would look something like the code posted above, but it would include only the information provided by the MS documentation. I have included one of the more general landing pages for such documentation that I briefly looked through.

Business Central API Overview - Microsoft Graph | Microsoft Docs

Jonas, thank you for the quick response.
We do have an external partner for implementing the BC ERP-system. They have knowledge regarding the available APIā€™s for BC.

Iā€™ll try with modifying the code above you are referring to.

KR
Steven

So the code pasted above is specifically for a Put Blob request into Azure. It may help guide you in replacing some of your standard queries you mentioned. In regards to establishing a simple connection, nearly all of the overall structure and library imports can be disregarded. Iā€™m not all that familiar with 0Auth2.0 authentication, so it may be worth reading about its relationship to the services you need.

If I am correct 0Auth2 is implied from Q1 2022, so like ā€œas we speakā€. I donā€™t know much about it either. I was able to create an GET request to it in Postman. But now I need to translate this to Ignition.

Iā€™ll keep you posted if it ever worked :slightly_smiling_face:

1 Like

Hi, I am currently running into the same issue. Was this resolved in Business Central / ERP? Or is there a workaround within Ignition?

I know it's been quite some time but... Thank You!! I was able to get this working in a fraction of the time it would take to sort it by myself from scratch.

Thanks for the comment. I was using the code above and was running into the same issue with Content-Length key in the headerVals