I am using below code to create new file in azure file storage

url = 'https://%s.file.core.windows.net/%s/%s/%s' % (
    acc_name, share_name, dir_name, new_file)
string = 'PUT\n\n0\n\n\n\n\n\n\n\nx-ms-date:%s\nx-ms-version:%s\nx-ms-type:file\nx-ms-content-length:2024\n/%s/%s/%s/%s' % (
    ms_date, ms_version, acc_name, share_name, dir_name, new_file)
signature = generate_sign(string)
headers = {
    'x-ms-version': ms_version,
    'x-ms-date': ms_date,
    'x-ms-type': 'file',
    'x-ms-content-length': 2024,
    'Authorization': 'SharedKey %s:%s' % (acc_name, signature)
}
result = requests.put(url, headers=headers)

But after execution getting error like signature not corrent.

The MAC signature found in the HTTP request 'xslgK6ohXHCAnk2PaJt+RupQZwT/y9fPl8RTFA807fw='
 is not the same as any computed signature. Server used following string to sign
: 'PUT


0








x-ms-content-length:2024
x-ms-date:Tue, 09 Jun 2015 07:39:24 GMT
x-ms-type:file
x-ms-version:2014-02-14
/filetest/test1/testdir/createtestfile'.</AuthenticationErrorDetail></Error>
2

There are 2 answers

6
Martijn Pieters On

You need to carefully verify that your string for the signature is correct. It appears there is an extra newline between the PUT and the 0, for example (you insert two, the error message uses three). Tripplecheck your string against the documentation and the error message.

It may be easier to pull some of those signature values out of the prepared request, for example:

session = requests.Session()
request = requests.Request('PUT', url, data=file_data_to_send, headers=headers)
prepared = request.prepare()
canon_headers = '\n'.join(sorted(['{}:{}'.format(h.lower(), v) for h, v in request.headers.iteritems() if h.lower().startswith('x-ms-')]))
canon_resource = '{}\n{}'.format(
    prepared.path_url)  # TODO: add query parameters

signature_string = (
    '{verb}\n{encoding}\n{language}\n{length}\n{md5}\n'
    '{type}\n{date}\n{if_modified}\n{match}\n{none_match}\n'
    '{if_unmodified}\n{range}\n{canon_headers}\n{canon_resource}'
).format(
    verb=prepared.method,
    encoding=prepared.headers.get('Content-Encoding', ''),
    language=prepared.headers.get('Content-Language', ''),
    length=prepared.headers.get('Content-Length', 0),
    md5=prepared.headers.get('Content-MD5', ''),
    type=prepared.headers.get('Content-Type', ''),
    date=prepared.headers.get('Date', ''),
    if_modified=prepared.headers.get('If-Modified-Since', ''),
    match=prepared.headers.get('If-Match', ''),
    none_match=prepared.headers.get('If-None-Match', ''),
    if_unmodified=prepared.headers.get('If-Unmodified-Since', ''),
    range=prepared.headers.get('Range', ''),
    canon_headers=canon_headers,
    canon_resource=canon_resource
)
prepared.headers['Authorization'] = 'SharedKey {}:{}'.format(
    acc_name, generate_sign(signature_string))
response = session.send(prepared)

I ignored the query parameters; that's easier done without the encoded URL.

0
Ming Xu - MSFT On

I have performed a quick test on my side, it looks like your ‘string’ which used for generating MessageSignature missed some items. Based on the documentation: https://msdn.microsoft.com/en-us/library/azure/dd179428.aspx it is needed to use 12 properties (besides CanonicalizedHeaders and CanonicalizedResource) to build up a StringToSign.

Thus, please try to use below string to replace yours to see if it works fine:

string = 'PUT\n\n\n0\n\n\n\n\n\n\n\n\nx-ms-date:%s\nx-ms-version:%s\nx-ms-type:file\nx-ms-content-length:2024\n/%s/%s/%s/%s' % ( ms_date, ms_version, acc_name, share_name, dir_name, new_file)

In addition, please ensure other variables’ formats are correct as well. Here is my working string for your reference:

"PUT\n\n\n0\n\n\n\n\n\n\n\n\nx-ms-content-length:1024\nx-ms-date:Tue, 09 Jun 2015 20:08:19 GMT\nx-ms-type:file\nx-ms-version:2014-02-14\n/mingxufiletest/mingxusharefile/testdir/filename"

Feel free to let us know if you have any further concerns. For going further, you may want to check the remarks section:

To create a new file, first initialize the file by calling Create File and specify its maximum size, up to 1 TB. When performing this operation, do not include content in the request body. Once the file has been created, call Put Range to add content to the file or to modify it.

You can change the size of the file by calling Set File Properties. If the share or parent directory does not exist, then the operation fails with status code 412 (Precondition Failed).

Note that the file properties cache-control, content-type, content-md5, content-encoding and content-language are discrete from the file system properties available to SMB clients. SMB clients are not able to read, write or modify these property values.