ansible-collections / azure

Development area for Azure Collections
https://galaxy.ansible.com/azure/azcollection
GNU General Public License v3.0
247 stars 330 forks source link

azure_rm_storageblob requires access to every single container even when directed to a single one #916

Open philipsd6 opened 2 years ago

philipsd6 commented 2 years ago
SUMMARY

When using the azure_rm_storageblob module to access content in a specified container I have access to, I receive an error because I do not have access to list all the containers of the storage account.

ISSUE TYPE
COMPONENT NAME

azure_rm_storageblob

ANSIBLE VERSION
ansible [core 2.14.0.dev0] (devel 185340e667) last updated 2022/05/18 12:11:56 (GMT -400)
  config file = /home/philipsd6/devel/e2e-automation/e2e-lz-gitops-automation/ansible.cfg
  configured module search path = ['/home/philipsd6/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/philipsd6/devel/ansible/lib/ansible
  ansible collection location = /home/philipsd6/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/philipsd6/.pyenv/versions/3.10.0/bin/ansible
  python version = 3.10.0 (default, Oct  8 2021, 16:24:19) [GCC 11.2.0] (/home/philipsd6/.pyenv/versions/3.10.0/bin/python3.10)
  jinja version = 3.0.3
  libyaml = True
COLLECTION VERSION
# /home/philipsd6/.ansible/collections/ansible_collections
Collection         Version
------------------ -------
azure.azcollection 1.13.0
CONFIGURATION
CONFIG_FILE() = /home/philipsd6/devel/testing/ansible.cfg
DEFAULT_HASH_BEHAVIOUR(/home/philipsd6/devel/testing/ansible.cfg) = merge
OS / ENVIRONMENT

n/a

STEPS TO REPRODUCE
  1. Grant access to a service principal (or user?) at the container level for a storageblob.
  2. Use the module as described below to download/upload a blob from a specific container
  3. Notice the error with the lack of authorization for storageAccounts/listKeys
  4. Grant the access at the storage account level and repeat
  5. Note that it works now.

Called the module like this (fake data of course)

- azure.azcollection.azure_rm_storageblob:
    tenant: d3944976-0156-11ed-9894-5f5a88ed670b
    subscription_id: e1612b82-0156-11ed-afd0-33464900d8b7
    client_id: ec756bbe-0156-11ed-92fd-17fa581ba74d
    secret: ZOtFQIH0IJhvynM1OKX7R920bXEw9Ift7FVZPMcik
    resource_group: my_rg
    storage_account_name: my_storage_account
    container: the_container
    blob: testing.json
    dest: /tmp/test.json  # or src: /tmp/test.json for uploading...
    force: true
EXPECTED RESULTS

I expect the testing.json blob to be downloaded to /tmp/test.json.

I expect to be able to work with the blobs in a specified container when access is granted to that specific container, even if I do not have full access to all containers in a storage account.

ACTUAL RESULTS

Received error:

Error getting keys for account my_storage_account - (AuthorizationFailed) The client
'9d6369b2-0157-11ed-9f9d-3ff64a62ec8c' with object id
'9d6369b2-0157-11ed-9f9d-3ff64a62ec8c' does not have authorization to perform action
'Microsoft.Storage/storageAccounts/listKeys/action' over scope
'/subscriptions/e1612b82-0156-11ed-afd0-33464900d8b7/resourceGroups/my_rg/providers/Microsoft.Storage/storageAccounts/my_storage_account'
or the scope is invalid.

This implies that even though I've specified "the_container" as my target container, the module still needs access to all containers in the storage account, which is broader permissions that necessary.

In order to resolve the issue, the service principal was required to have access granted at the Storage Account level instead of the Container level.

Fred-sun commented 2 years ago

@philipsd6 Can this problem be resolved if you change the storage account access permissions?

Fred-sun commented 2 years ago

kindly ping!

maartenvankessel commented 1 year ago

@Fred-sun : while I cannot answer for @philipsd6, my expectation would be that that would fix the issue. However, it is a really really bad idea to use the keys returned by listkeys for performing any actions as it completely nukes all security boundaries that might be applied in Azure. Is it possible to use the provided credentials via Ansible directly in the get_blob_service_client function?

In example: I want to download a blob from Azure, so the storage account owner grants me read rights. Should be sufficient right? However, this does not work due to the current get_blob_service_client routine that is hardcoded to request the storage account keys (see https://github.com/ansible-collections/azure/blob/ef944d9f715b5231cabf4e4caa1d930f8dc939ee/plugins/module_utils/azure_rm_common.py#L715 ). However, with that requested key I am able to modify every aspect of the storage account, and as such modify containers and blobs as a desire. Not exactly the read-only rights that I should have.

Same holds for another use case. A storage account owner grants a service principal read-write rights to a specific container, as he has different containers for different use cases. Uploading data without the listkeys access for the service principal will fail due to the same reason as in the previous example. With the listkeys access I can upload data to the target container perfectly fine, but due to the fact that a storage account key is used for authentication I can upload data to every other container as well! And for that reason the owner of the storage account will not grant me the listkeys action as it will allow me access way outside the intended scope.

DevopsMercenary commented 1 year ago

https://github.com/ansible-collections/azure/issues/1293