How to: check if a container exists without account level List permission

In a storage account, you can create a SAS scoped to a specific container, however, that SAS does not have permission to execute BlobClient.exists() as this requires at least list privileges on the parent object (e.g. the account), and when you try to perform the check, you’ll get this error:

azure.core.exceptions.HttpResponseError: This request is not authorized to perform this operation.

Note that this is an HttpResponseError, not a ClientAuthenticationError (which is actually a more specific error which extends HttpResponseError), so you need to interrogate the specific response code, although note that if the container client does not exist, you might also get a ClientAuthenticationError with this message:

Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:a52b0bdf-401e-0030-755f-fc3a0f000000\nTime:2024-09-01T11:09:19.0123125Z\nErrorCode:AuthenticationFailed\nauthenticationerrordetail:Signature did not match. String to sign used was rwl\n2022-01-01T00:00:00.0000000Z\n2030-01-01T00:00:00.0000000Z\n/blob/<account>/<container>\n\n\nhttps\n2015-04-05\nmax-age=5\ninline\ndeflate\n\napplication/json

As a workaround, you can instead try to read from or write to (depending on the privilege level you want to test for) the container. For example, you might do something like this:

def test_if_container_exists(container_client: ContainerClient) -> bool:
  """check if a container exists first by calling the .exists() method, even if the SAS scope is restricted to the specific container"""
  # first use the .exists() method to check if the container exists
  try:
    container_client.exists()
    return True
  except ClientAuthenticationError:
    # we dont know if this is because the SAS token doesnt have access or the container doesnt exist
    pass
  except HttpResponseError as e:
    if e.status_code == 404:
      return False
    elif e.status_code == 403:
      pass  # could be a SAS token scope restriction
  except ResourceNotFoundError:
    return False
  except Exception as e:
    # if we got any other exception, raise it
    raise
  # if we got ClientAuthenticationError, try to write a small blob to check if the SAS token is valid
  try:
    blob_client = container_client.get_blob_client("test_blob")
    blob_client.upload_blob(b"Test content", overwrite=True)
    return True
  except ClientAuthenticationError or ResourceNotFoundError:
    return False
  except Exception as e:
    # if we got any other exception, raise it
    raise

Leave a Reply

Your email address will not be published. Required fields are marked *