Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Python和托管标识/SAS凭据从VM访问Azure存储帐户_Python_Azure_Powershell_Authentication - Fatal编程技术网

如何使用Python和托管标识/SAS凭据从VM访问Azure存储帐户

如何使用Python和托管标识/SAS凭据从VM访问Azure存储帐户,python,azure,powershell,authentication,Python,Azure,Powershell,Authentication,目标我使用系统分配的托管身份设置了Azure VM。我希望能够: 允许用户使用VM访问存储帐户内的Blob 确保用户无法访问VM外部的Blob 使用Python—我们的大多数用户都是Python用户,但不懂Powershell 设置详细信息: 存储帐户:sa030802util容器:testutilsBlob:hello3.txt 托管标识和角色。VM具有系统为sa030802util分配的托管标识和参与者、存储帐户参与者、存储blob数据参与者角色 方法 我试过四种方法来解决这个问题 部分成功

目标我使用系统分配的托管身份设置了Azure VM。我希望能够:

  • 允许用户使用VM访问存储帐户内的Blob

  • 确保用户无法访问VM外部的Blob

  • 使用Python—我们的大多数用户都是Python用户,但不懂Powershell

  • 设置详细信息: 存储帐户:sa030802util容器:testutilsBlob:hello3.txt 托管标识和角色。VM具有系统为sa030802util分配的托管标识和参与者、存储帐户参与者、存储blob数据参与者角色

    方法 我试过四种方法来解决这个问题

    部分成功的方法1:Python。在Python中,我能够使用以下代码访问sa030802util存储帐户,这些代码派生自和。问题在于,这会使用存储帐户和密钥,而不仅仅依赖于VM的托管标识。我担心的是,这会让用户有可能提取存储密钥并访问VM之外的Blob

    优点:在Python中Con:不使用托管标识进行身份验证。BlockBlobService还不能使用MSI进行身份验证

    部分成功的方法2:Powershell。在Powershell中,我找到了两种使用托管标识访问blob的方法。挑战在于,两者都不能创建一个我可以轻松替换为Python的凭证,如下所述。第一种方法来自于Microsoft教授的关于为Microsoft Azure资源()实现托管标识的Pluralsight课程()。它使用Az模块

    优点:使用托管身份,相对简单缺点:不在Python中。不会生成可在Python中使用的凭据

    部分成功的方法3:Powershell。此方法来自。它使用VM管理的标识生成SAS凭据并访问Azure存储

    优点:使用托管标识并生成SAS凭据,这可能很有价值,因为Python中的BlockBlobService可以接受SAS令牌缺点:不在Python中。上述方法2给出的Powershell本身的Overkill以更少的努力实现了同样的效果。我试用了它,因为我想看看是否可以提取SAS凭据以在Python中使用

    方法4失败:Python和Powershell。我想我可能能够使用方法3在Powershell中生成SAS令牌,然后将令牌插入方法1的BlockBlobService代码中。我的东西坏了。我怀疑原因是SAS凭据是为testutils容器创建的,Python BlockBlobbService需要sa030802util存储帐户的SAS凭据

    Pro:将允许我依靠虚拟机的托管身份访问Azure存储Con:不起作用

    问题 我的问题是:

  • 如果我想确保用户只能访问VM内部的存储帐户,那么我认为依赖VM管理的标识和/或SAS凭据比依赖帐户密钥更好吗

  • 有没有办法拼凑代码,让我使用Python访问数据?方法4是有希望的还是浪费时间

  • 代码

    方法1:Python

    from azure.mgmt.storage import StorageManagementClient
    from azure.mgmt.storage.models import StorageAccountCreateParameters
    from msrestazure.azure_active_directory import MSIAuthentication
    from azure.mgmt.resource import SubscriptionClient
    from azure.storage.blob import BlockBlobService
    
    # find credentials and subscription id
    credentials = MSIAuthentication()
    subscription_client = SubscriptionClient(credentials)
    subscription = next(subscription_client.subscriptions.list())
    subscription_id = subscription.subscription_id
    
    # find storage keys
    storage_client = StorageManagementClient(credentials, subscription_id)
    storage_account = storage_client.storage_accounts.get_properties("<resourcegroup>", "sa030802util")
    storage_keys = storage_client.storage_accounts.list_keys("<resourcegroup>", "sa030802util")
    storage_keys = {v.key_name: v.value for v in storage_keys.keys}
    
    # create BlockBlobService and for e.g. print blobs in container
    account_name = "sa030802util"
    account_key = storage_keys["key1"]
    container_name = "testutils"
    block_blob_service = BlockBlobService(account_name = account_name, account_key = account_key)
    
    print("List blobs in container")
    generator = block_blob_service.list_blobs(container_name)
    for blob in generator:
        print("Blob name: " + blob.name)
    
    方法2:Powershell

    Connect-AzAccount -MSI -Subscription <subscriptionid>
    $context = New-AzStorageContext -StorageAccountName sa030802util
    Get-AzStorageBlob -Name testutils -Context $context
    
    # to get an access token using the VM's identity and use it to call Azure Resource Manager
    $response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' -Method GET -Headers @{Metadata="true"}
    $ content = $response.Content | ConvertFrom-Json
    #ArmToken = $content.access_token
    
    # to get SAS credential from Azure Resource Manager to make storage calls
    ## convert parameters to JSON
    $params = @{canonicalizedResource="/blob/sa030802util/testutils"; signedResource="c"; signedPermission="rcwl"; signedProtocol="https"; signedExpiry="2019-08-30T00:00:00Z"}
    $jsonParams = $params | ConvertTo-Json
    
    ## call storage listServiceSas endpoint to create SAS credential
    $sasResponse = Invoke-WebRequest -Uri https://management.azure.com/subscriptions/<subscription_id>/resourceGroups/<resourceGroup>/providers/Microsoft.Storage/storageAccounts/sa030802util/listServiceSas/?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F -Method POST -Body $jsonParams -Headers @{Authorization = "Bearer $ArmToken"} -UseBasicParsing
    
    ## extract SAS credential from response
    $sasContent = $sasResponse.Content | ConvertFrom-Json
    $sasCred = $sasContent.serviceSasToken
    
    # as example, list contents of container
    $context = New-AzStorageContext -StorageAccountName sa030802util -SasToken $sasCred
    Get-AzStorageBlob -Name testutils -Context $context
    
    方法3:Powershell

    Connect-AzAccount -MSI -Subscription <subscriptionid>
    $context = New-AzStorageContext -StorageAccountName sa030802util
    Get-AzStorageBlob -Name testutils -Context $context
    
    # to get an access token using the VM's identity and use it to call Azure Resource Manager
    $response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' -Method GET -Headers @{Metadata="true"}
    $ content = $response.Content | ConvertFrom-Json
    #ArmToken = $content.access_token
    
    # to get SAS credential from Azure Resource Manager to make storage calls
    ## convert parameters to JSON
    $params = @{canonicalizedResource="/blob/sa030802util/testutils"; signedResource="c"; signedPermission="rcwl"; signedProtocol="https"; signedExpiry="2019-08-30T00:00:00Z"}
    $jsonParams = $params | ConvertTo-Json
    
    ## call storage listServiceSas endpoint to create SAS credential
    $sasResponse = Invoke-WebRequest -Uri https://management.azure.com/subscriptions/<subscription_id>/resourceGroups/<resourceGroup>/providers/Microsoft.Storage/storageAccounts/sa030802util/listServiceSas/?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F -Method POST -Body $jsonParams -Headers @{Authorization = "Bearer $ArmToken"} -UseBasicParsing
    
    ## extract SAS credential from response
    $sasContent = $sasResponse.Content | ConvertFrom-Json
    $sasCred = $sasContent.serviceSasToken
    
    # as example, list contents of container
    $context = New-AzStorageContext -StorageAccountName sa030802util -SasToken $sasCred
    Get-AzStorageBlob -Name testutils -Context $context
    
    Python代码返回以下错误:

    AzureHttpError: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. ErrorCode: AuthenticationFailed
    <?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
    RequestId:<subscriptionid>
    Time:2019-08-05T05:33:40.0175771Z</Message><AuthenticationErrorDetail>Signature did not match. String to sign used was rcwl
    
    2019-08-30T00:00:00.0000000Z
    /blob/sa030802util/testutils
    
    
    https
    2018-03-28
    
    
    
    
    </AuthenticationErrorDetail></Error>
    

    非常有趣的帖子,不幸的是我不是Python专家,但这可能会有所帮助:

    如果我想确保用户只能访问VM内的存储帐户

    您可以在没有MSI的情况下实现这一点:

    MSI确实提供了一个额外的安全层,它还简化了管理,因为您不需要管理密钥/SAS令牌,但这不是绝对的要求,您可以在没有它的情况下构建安全设计


    祝你好运

    非常有趣的帖子,不幸的是我不是Python专家,但这可能会有所帮助:

    如果我想确保用户只能访问VM内的存储帐户

    您可以在没有MSI的情况下实现这一点:

    MSI确实提供了一个额外的安全层,它还简化了管理,因为您不需要管理密钥/SAS令牌,但这不是绝对的要求,您可以在没有它的情况下构建安全设计


    祝你好运

    在Azure SDK for Python中,创建一个类,然后使用其
    get\u blob\u client
    方法检索类。然后在该客户端上使用
    download\u blob
    获取blob内容


    BlobServiceClient
    接受一个
    credentials
    参数,您可以在Azure SDK for Python中向该参数传递
    MSIAuthentication()
    ,创建一个类,然后使用其
    get\u blob\u client
    方法检索类。然后在该客户端上使用
    download\u blob
    获取blob内容


    BlobServiceClient
    接受一个
    credentials
    参数,您可以向该参数传递
    MSIAuthentication()

    非常感谢您的回复。Python链接很有用,但不幸的是,根据我的研究,Python对MSI的使用似乎有点有限。在通过MSI进行身份验证后,可以使用Python删除/创建/列出存储帐户。不幸的是,当你想列出/上传/下载blob时,你需要使用BaseBlobService/BlockBlobService,而这两个类只接受SAS凭据或访问密钥——它们似乎无法依赖MSI。我将执行您第二个链接中的网络安全建议,再次感谢!Th
    from azure.storage.blob import BlockBlobService, PublicAccess
    import os
    
    # import SAS credential
    with open("cred.txt") as f:
        line = f.readline()
    
    # create BlockBlobService
    block_blob_service = BlockBlobService(account_name = "sa030802util", sas_token=line)
    
    # print content of testutils container
    generator = block_blob_service.list_blobs("testutils")
    for blob in generator:
        print(blob.name)
    
    AzureHttpError: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. ErrorCode: AuthenticationFailed
    <?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
    RequestId:<subscriptionid>
    Time:2019-08-05T05:33:40.0175771Z</Message><AuthenticationErrorDetail>Signature did not match. String to sign used was rcwl
    
    2019-08-30T00:00:00.0000000Z
    /blob/sa030802util/testutils
    
    
    https
    2018-03-28
    
    
    
    
    </AuthenticationErrorDetail></Error>