Estoy tratando de realizar una solicitud de envío al almacenamiento de Azure, básicamente cambiando las propiedades de almacenamiento. Si bien puedo hacer que la solicitud GET funcione siguiendo el tutorial aquí https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key#Subheading2 pero no veo uno adecuado para construir un PONER la solicitud allí.

Entonces, mientras buscaba, obtuve esto pero con el get, no se puede conectar a la API REST del servicio de archivos azure por Python pero esto es nuevamente con una solicitud GET. para la solicitud PUT siempre obtengo HTTP 403, no estoy seguro de dónde falla. aquí está el código modificado del enlace para representar lo que estoy haciendo en mi código.

import requests
import datetime
import hmac
import hashlib
import base64

storage_account_name = 'strtest'
storage_account_key = 'key'
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': '',
    'Content-MD5': '',
    'Content-Type': 'application/xml',
    'Date': '',
    'If-Modified-Since': '',
    'If-Match': '',
    'If-None-Match': '',
    'If-Unmodified-Since': '',
    'Range': '',
    'CanonicalizedHeaders': 'x-ms-date:' + request_time + '\nx-ms-version:' + api_version + '\n',
    'CanonicalizedResource': '/' + storage_account_name + '/\ncomp:properties\nrestype:service'
}

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()

headers = {
    'x-ms-date' : request_time,
    'x-ms-version' : api_version,
    'Authorization' : ('SharedKey ' + storage_account_name + ':' + signed_string)
}

url = ('https://' + storage_account_name + '.blob.core.windows.net/?restype=service&comp=properties')

data = """<StorageServiceProperties></StorageServiceProperties>"""

r = requests.put(url, headers = headers, data = data)

print(r.content)

El contenido que intento enviar está en formato XML. Mientras el código funciona en la solicitud GET, PUT no lo está.

4
threeleggedrabbit 16 oct. 2018 a las 19:10

2 respuestas

La mejor respuesta

Además de Content-Type, para una solicitud de venta, también debe completar Content-Length en string_params, ya que sdk configura el encabezado correspondiente automáticamente.

2
Jerry Liu 17 oct. 2018 a las 03:14

Aquí está el código de trabajo.

import requests
import datetime
import hmac
import hashlib
import base64

storage_account_name = 'acc_name'
storage_account_key = 'ac_key'
api_version = '2018-03-28'
request_time = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
data = "<StorageServiceProperties></StorageServiceProperties>"
content_len = str(len(data))

string_params = {
    'verb': 'PUT',
    'Content-Encoding': '',
    'Content-Language': '',
    'Content-Length': content_len,
    'Content-MD5': '',
    'Content-Type': 'application/xml',
    'Date': '',
    'If-Modified-Since': '',
    'If-Match': '',
    'If-None-Match': '',
    'If-Unmodified-Since': '',
    'Range': '',
    'CanonicalizedHeaders': 'x-ms-date:' + request_time + '\nx-ms-version:' + api_version + '\n',
    'CanonicalizedResource': '/' + storage_account_name + '/\ncomp:properties\nrestype:service'
}

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()

headers = {
    'x-ms-date' : request_time,
    'x-ms-version' : api_version,
    'Content-Type': 'application/xml',
    'Content-Length': content_len,
    'Authorization' : ('SharedKey ' + storage_account_name + ':' + signed_string)
}

url = ('https://' + storage_account_name + '.blob.core.windows.net/?restype=service&comp=properties')

data = "<StorageServiceProperties></StorageServiceProperties>"

r = requests.put(url, headers = headers, data=data)

print(r.content)
1
codebot 17 oct. 2018 a las 10:16