Azure Storage Table

Create and Manage Azure Storage Tables and Entities.

IT Services · Azure Storage Table

Details

IDAzure Storage Table
ProviderMicrosoft
CategoryIT Services
From Version6.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Azure Storage Table

Create and Manage Azure Storage Tables and Entities.
This integration was integrated and tested with version “2020-10-02” of Azure Storage Table

Configure Azure Storage Table in Cortex

Parameter Required
Storage account name True
Account SAS Token False
Use Azure Managed Identities False
Azure Managed Identities Client ID False
Use system proxy settings False
Trust any certificate (not secure) False

Shared Access Signatures (SAS) Permissions

In order to use the integration use-cases,
please make sure your SAS token contains the following permissions:

  1. ‘Table’ service.
  2. ‘Service’ and ‘Object’ resource types.
  3. ‘Read’, ‘Write’, ‘Delete’, ‘List’, ‘Create’, ‘Add’, ‘Update’ and ‘Immutable storage’ permissions.
  • Review and select “Generate”.

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

azure-storage-table-create


Creates a new table in a storage account.

Base Command

azure-storage-table-create

Input

Argument Name Description Required
table_name The name of the new table to create. Rules for naming tables can be found here: https://docs.microsoft.com/en-us/rest/api/storageservices/understanding-the-table-service-data-model. Required

Context Output

Path Type Description
AzureStorageTable.Table.name String Table name.

Command Example

!azure-storage-table-create table_name="xsoar"

Context Example

{
    "AzureStorageTable": {
        "Table": {
            "name": "xsoar"
        }
    }
}

Human Readable Output

Table xsoar successfully created.

azure-storage-table-delete


Delete the specified table and any data it contains.

Base Command

azure-storage-table-delete

Input

Argument Name Description Required
table_name The name of the table to delete. Required

Context Output

There is no context output for this command.

Command Example

!azure-storage-table-delete table_name="xsoar"

Human Readable Output

Table xsoar successfully deleted.

azure-storage-table-query


List tables under the specified account.

Base Command

azure-storage-table-query

Input

Argument Name Description Required
limit Number of Tables to retrieve. Default is 50. Default is 50. Optional
filter Filter Tables Query expression.
Information about Query expression structure can be found here: https://docs.microsoft.com/en-us/rest/api/storageservices/querying-tables-and-entities#constructing-filter-strings.
Optional
page Page Number. Default is 1. Default is 1. Optional

Context Output

Path Type Description
AzureStorageTable.Table.name String Table name.

Command Example

!azure-storage-table-query filter="TableName%20eq%20'xsoar'"

Context Example

{
    "AzureStorageTable": {
        "Table": {
            "name": "xsoar"
        }
    }
}

Human Readable Output

Tables List

Current page size: 50
Showing page 1 out others that may exist

Name
xsoar

azure-storage-table-entity-insert


Insert a new entity into a table.

Base Command

azure-storage-table-entity-insert

Input

Argument Name Description Required
table_name Table name. Required
partition_key Unique identifier for the partition within a given table. Required
row_key Unique identifier for an entity within a given partition. Required
entity_fields Entity fields in JSON format: { “Key1”: Value1, “Key2”: Value2}. Required

Context Output

Path Type Description
AzureStorageTable.Table.Entity.PartitionKey String Entity partition key.
AzureStorageTable.Table.Entity.RowKey String Entity row key.
AzureStorageTable.Table.Entity.Timestamp Date Entity last update UTC time.
AzureStorageTable.Table.name String Entity table name.

Command Example

!azure-storage-table-entity-insert table_name="xsoar" partition_key="xsoar-partition" row_key="xsoar-row" entity_fields=`{"Age":20}`

Context Example

{
    "AzureStorageTable": {
        "Table": {
            "Entity": [
                {
                    "Age": 20,
                    "PartitionKey": "xsoar-partition",
                    "RowKey": "xsoar-row",
                    "Timestamp": "2021-11-28T13:23:18"
                }
            ],
            "name": "xsoar"
        }
    }
}

Human Readable Output

Entity Fields for xsoar Table

Age Partition Key Row Key Timestamp
20 xsoar-partition xsoar-row 2021-11-28T13:23:18

azure-storage-table-entity-update


Update an existing entity in a table. The Update Entity command does not replace the existing entity.

Base Command

azure-storage-table-entity-update

Input

Argument Name Description Required
table_name Entity table name. Required
partition_key Unique identifier for the partition within a given table. Required
row_key Unique identifier for an entity within a given partition. Required
entity_fields Entity fields in JSON format: { “Key1”: Value1, “Key2”: Value2}. Required

Context Output

There is no context output for this command.

Command Example

!azure-storage-table-entity-update table_name="xsoar" partition_key="xsoar-partition" row_key="xsoar-row" entity_fields=`{"Address":"New York"}`

Human Readable Output

Entity in xsoar table successfully updated.

azure-storage-table-entity-replace


Replace an existing entity in a table. The Replace Entity command replace the entire entity and can be used to remove properties.

Base Command

azure-storage-table-entity-replace

Input

Argument Name Description Required
table_name Table name. Required
partition_key Unique identifier for the partition within a given table. Required
row_key Unique identifier for an entity within a given partition. Required
entity_fields Entity records in JSON format: { “Key1”: Value1, “Key2”: Value2}. Required

Context Output

There is no context output for this command.

Command Example

!azure-storage-table-entity-replace table_name="xsoar" partition_key="xsoar-partition" row_key="xsoar-row" entity_fields=`{"City": "TLV" }`

Human Readable Output

Entity in xsoar table successfully replaced.

azure-storage-table-entity-query


Query Entities in a table.

Base Command

azure-storage-table-entity-query

Input

Argument Name Description Required
table_name Entity table name. Required
partition_key Unique identifier for the partition within a given table. If specified, ‘row_key’ argument must also be specified. Optional
row_key Unique identifier for an entity within a given partition. If specified, ‘partition_key’ argument must also be specified. Optional
filter Filter Entities query expression.
Information about Query expression structure can be found here: https://docs.microsoft.com/en-us/rest/api/storageservices/querying-tables-and-entities#constructing-filter-strings.
Optional
select Comma-separated Entity properties to return. If not specified - all fields will be retrieved. Optional
limit Number of entities to retrieve. Default is 50.
This argument is will be ignored when ‘partition_key’ or ‘row_key’ arguments are provided. Default is 50.
Optional
page Page number. Default is 1.
This argument is will be ignored when ‘partition_key’ or ‘row_key’ arguments are provided. Default is 1.
Optional

Context Output

Path Type Description
AzureStorageTable.Table.name String Entity table Name.

Command Example

!azure-storage-table-entity-query table_name="xsoar"

Context Example

{
    "AzureStorageTable": {
        "Table": {
            "Entity": [
                {
                    "Address": "New York",
                    "City": "TLV",
                    "PartitionKey": "xsoar-partition",
                    "RowKey": "xsoar-row",
                    "Timestamp": "2021-11-28T13:23:27"
                }
            ],
            "name": "xsoar"
        }
    }
}

Human Readable Output

Entity Fields for xsoar table

Current page size: 50
Showing page 1 out others that may exist

Address City Partition Key Row Key Timestamp
New York TLV xsoar-partition xsoar-row 2021-11-28T13:23:27

azure-storage-table-entity-delete


Delete an existing entity in a table.

Base Command

azure-storage-table-entity-delete

Input

Argument Name Description Required
table_name Entity table name. Required
partition_key Unique identifier for the partition within a given table. Required
row_key Unique identifier for an entity within a given partition. Required

Context Output

There is no context output for this command.

Command Example

!azure-storage-table-entity-delete table_name="xsoar" partition_key="xsoar-partition" row_key="xsoar-row"

Human Readable Output

Entity in xsoar table successfully deleted.

Configuration parameters

  • credentials — Storage account name
  • use_managed_identities — Use Azure Managed Identities
  • managed_identities_client_id
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)

Commands (8)

  • azure-storage-table-create

    Creates a new table in a storage account.

  • azure-storage-table-delete

    Delete the specified table and any data it contains.

  • azure-storage-table-entity-delete

    Delete an existing entity in a table.

  • azure-storage-table-entity-insert

    Insert a new entity into a table.

  • azure-storage-table-entity-query

    Query Entities in a table.

  • azure-storage-table-entity-replace

    Replace an existing entity in a table. The Replace Entity command replace the entire entity and can be used to remove properties.

  • azure-storage-table-entity-update

    Update an existing entity in a table. The Update Entity command does not replace the existing entity.

  • azure-storage-table-query

    List tables under the specified account.

import pytest
from CommonServerPython import *

ACCOUNT_NAME = "test"
BASE_URL = f"https://{ACCOUNT_NAME}.table.core.windows.net/"
SAS_TOKEN = "XXXX"
API_VERSION = "2020-10-02"


def load_mock_response(file_name: str) -> str:
    """
    Load mock file that simulates an API response.
    Args:
        file_name (str): Name of the mock response JSON file to return.
    Returns:
        str: Mock file content.
    """
    with open(f"test_data/{file_name}", encoding="utf-8") as mock_file:
        return mock_file.read()


def test_azure_storage_create_table_command(requests_mock):
    """
    Scenario: Create Table.
    Given:
     - User has provided valid credentials.
    When:
     - azure-storage-table-create called.
    Then:
     - Ensure number of items is correct.
     - Ensure outputs prefix is correct.
     - Ensure a sample value from the API matches what is generated in the context.
     - Ensure validation of the table name.
    """
    from AzureStorageTable import Client, create_table_command

    mock_response = json.loads(load_mock_response("create_table.json"))
    url = f"{BASE_URL}Tables?{SAS_TOKEN}"
    table_name = "test"

    requests_mock.post(url, json=mock_response)

    client = Client(
        server_url=BASE_URL,
        verify=False,
        proxy=False,
        account_sas_token=SAS_TOKEN,
        storage_account_name=ACCOUNT_NAME,
        api_version=API_VERSION,
    )

    result = create_table_command(client, {"table_name": table_name})

    assert len(result.outputs) == 1
    assert result.outputs_prefix == "AzureStorageTable.Table"
    assert result.outputs.get("name") == "xsoar"

    invalid_table_name = "test--1"

    with pytest.raises(Exception):
        create_table_command(client, {"table_name": invalid_table_name})


def test_azure_storage_delete_table_command(requests_mock):
    """
    Scenario: Delete Table.
    Given:
     - User has provided valid credentials.
    When:
     - azure-storage-table--delete called.
    Then:
     - Ensure that the output is empty (None).
     - Ensure readable output message content.
    """
    from AzureStorageTable import Client, delete_table_command

    table_name = "test"
    url = f"{BASE_URL}Tables('{table_name}')?{SAS_TOKEN}"

    requests_mock.delete(url, text="")

    client = Client(
        server_url=BASE_URL,
        verify=False,
        proxy=False,
        account_sas_token=SAS_TOKEN,
        storage_account_name=ACCOUNT_NAME,
        api_version=API_VERSION,
    )

    result = delete_table_command(client, {"table_name": table_name})

    assert result.outputs is None
    assert result.outputs_prefix is None
    assert result.readable_output == f"Table {table_name} successfully deleted."


def test_azure_storage_query_tables_command(requests_mock):
    """
    Scenario: Query Tables.
    Given:
     - User has provided valid credentials.
    When:
     - azure-storage-table-query called.
    Then:
     - Ensure number of items is correct.
     - Ensure outputs prefix is correct.
     - Ensure a sample value from the API matches what is generated in the context.
    """
    from AzureStorageTable import Client, query_tables_command

    mock_response = json.loads(load_mock_response("query_table.json"))
    url = f"{BASE_URL}Tables?{SAS_TOKEN}&$top=50"

    requests_mock.get(url, json=mock_response)

    client = Client(
        server_url=BASE_URL,
        verify=False,
        proxy=False,
        account_sas_token=SAS_TOKEN,
        storage_account_name=ACCOUNT_NAME,
        api_version=API_VERSION,
    )

    result = query_tables_command(client, {})

    assert len(result.outputs) == 2
    assert result.outputs_prefix == "AzureStorageTable.Table"
    assert result.outputs[0].get("name") == "xsoar1"
    assert result.outputs[1].get("name") == "xsoar2"


def test_azure_storage_insert_entity_command(requests_mock):
    """
    Scenario: Insert Entity.
    Given:
     - User has provided valid credentials.
    When:
     - azure-storage-table-entity-insert called.
    Then:
     - Ensure number of items is correct.
     - Ensure outputs prefix is correct.
     - Ensure a sample value from the API matches what is generated in the context.
    """
    from AzureStorageTable import Client, insert_entity_command

    mock_response = json.loads(load_mock_response("insert_entity.json"))
    table_name = "test"
    url = f"{BASE_URL}{table_name}?{SAS_TOKEN}"

    requests_mock.post(url, json=mock_response)

    client = Client(
        server_url=BASE_URL,
        verify=False,
        proxy=False,
        account_sas_token=SAS_TOKEN,
        storage_account_name=ACCOUNT_NAME,
        api_version=API_VERSION,
    )

    command_arguments = {
        "entity_fields": '{"Age":20}',
        "partition_key": "xsoar-partition",
        "row_key": "xsoar-row",
        "table_name": table_name,
    }
    result = insert_entity_command(client, command_arguments)

    assert len(result.outputs) == 2
    assert result.outputs_prefix == "AzureStorageTable.Table"
    assert len(result.outputs.get("Entity")) == 1
    assert len(result.outputs.get("Entity")[0]) == 4
    assert result.outputs.get("Entity")[0].get("PartitionKey") == "xsoar-partition"
    assert result.outputs.get("Entity")[0].get("RowKey") == "xsoar-row"
    assert result.outputs.get("name") == table_name


#
def test_azure_storage_update_entity_command(requests_mock):
    """
    Scenario: Update Entity.
    Given:
     - User has provided valid credentials.
    When:
     - azure-storage-table-entity-update called.
    Then:
     - Ensure that the output is empty (None).
     - Ensure readable output message content.
    """
    from AzureStorageTable import Client, update_entity_command

    table_name = "test"
    partition_key = "xsoar-partition"
    row_key = "xsoar-row"
    url = f"{BASE_URL}{table_name}(PartitionKey='{partition_key}',RowKey='{row_key}')?{SAS_TOKEN}"

    requests_mock.register_uri("MERGE", url, text="")

    client = Client(
        server_url=BASE_URL,
        verify=False,
        proxy=False,
        account_sas_token=SAS_TOKEN,
        storage_account_name=ACCOUNT_NAME,
        api_version=API_VERSION,
    )

    command_arguments = {
        "entity_fields": '{"Address":"New York"}',
        "partition_key": partition_key,
        "row_key": row_key,
        "table_name": table_name,
    }
    result = update_entity_command(client, command_arguments)

    assert result.outputs is None
    assert result.outputs_prefix is None
    assert result.readable_output == f"Entity in {table_name} table successfully updated."


def test_azure_storage_replace_entity_command(requests_mock):
    """
    Scenario: Replace Entity.
    Given:
     - User has provided valid credentials.
    When:
     - azure-storage-table-entity-replace called.
    Then:
     - Ensure that the output is empty (None).
     - Ensure readable output message content.
    """
    from AzureStorageTable import Client, replace_entity_command

    table_name = "test"
    partition_key = "xsoar-partition"
    row_key = "xsoar-row"
    url = f"{BASE_URL}{table_name}(PartitionKey='{partition_key}',RowKey='{row_key}')?{SAS_TOKEN}"

    requests_mock.put(url, text="")

    client = Client(
        server_url=BASE_URL,
        verify=False,
        proxy=False,
        account_sas_token=SAS_TOKEN,
        storage_account_name=ACCOUNT_NAME,
        api_version=API_VERSION,
    )

    command_arguments = {
        "entity_fields": '{"Address":"New York"}',
        "partition_key": partition_key,
        "row_key": row_key,
        "table_name": table_name,
    }
    result = replace_entity_command(client, command_arguments)

    assert result.outputs is None
    assert result.outputs_prefix is None
    assert result.readable_output == f"Entity in {table_name} table successfully replaced."


def test_azure_storage_query_entity_command(requests_mock):
    """
    Scenario: Query Entity.
    Given:
     - User has provided valid credentials.
    When:
     - azure-storage-table-entity-query called.
    Then:
     - Ensure number of items is correct.
     - Ensure outputs prefix is correct.
     - Ensure a sample value from the API matches what is generated in the context.
    """
    from AzureStorageTable import Client, query_entity_command

    mock_response = json.loads(load_mock_response("query_entity.json"))
    table_name = "test"
    url = f"{BASE_URL}{table_name}()?{SAS_TOKEN}&$top=1"

    requests_mock.get(url, json=mock_response)

    client = Client(
        server_url=BASE_URL,
        verify=False,
        proxy=False,
        account_sas_token=SAS_TOKEN,
        storage_account_name=ACCOUNT_NAME,
        api_version=API_VERSION,
    )

    result = query_entity_command(client, {"table_name": table_name, "limit": "1"})

    assert len(result.outputs) == 2
    assert len(result.outputs.get("Entity")) == 1
    assert len(result.outputs.get("Entity")[0]) == 4
    assert result.outputs_prefix == "AzureStorageTable.Table"
    assert result.outputs.get("Entity")[0].get("PartitionKey") == "xsoar-partition"
    assert result.outputs.get("Entity")[0].get("RowKey") == "xsoar-row"
    assert result.outputs.get("Entity")[0].get("Address") == "New York"
    assert result.outputs.get("name") == table_name


def test_azure_storage_delete_entity_command(requests_mock):
    """
    Scenario: Delete Entity.
    Given:
     - User has provided valid credentials.
    When:
     - azure-storage-table-entity-delete called.
    Then:
     - Ensure that the output is empty (None).
     - Ensure readable output message content.
    """
    from AzureStorageTable import Client, delete_entity_command

    table_name = "test"
    partition_key = "xsoar-partition"
    row_key = "xsoar-row"
    url = f"{BASE_URL}{table_name}(PartitionKey='{partition_key}',RowKey='{row_key}')?{SAS_TOKEN}"

    requests_mock.delete(url, text="")

    client = Client(
        server_url=BASE_URL,
        verify=False,
        proxy=False,
        account_sas_token=SAS_TOKEN,
        storage_account_name=ACCOUNT_NAME,
        api_version=API_VERSION,
    )

    command_arguments = {"partition_key": partition_key, "row_key": row_key, "table_name": table_name}

    result = delete_entity_command(client, command_arguments)

    assert result.outputs is None
    assert result.outputs_prefix is None
    assert result.readable_output == f"Entity in {table_name} table successfully deleted."


@pytest.mark.parametrize(argnames="client_id", argvalues=["test_client_id", None])
def test_test_module_command_with_managed_identities(mocker, requests_mock, client_id):
    """
    Given:
        - Managed Identities client id for authentication.
    When:
        - Calling test_module.
    Then:
        - Ensure the output are as expected.
    """

    import re

    import AzureStorageTable
    import demistomock as demisto
    from AzureStorageTable import MANAGED_IDENTITIES_TOKEN_URL, main

    mock_token = {"access_token": "test_token", "expires_in": "86400"}
    get_mock = requests_mock.get(MANAGED_IDENTITIES_TOKEN_URL, json=mock_token)
    requests_mock.get(re.compile(".table.core.windows.net/.*"))

    params = {
        "managed_identities_client_id": {"password": client_id},
        "use_managed_identities": "True",
        "credentials": {"identifier": "test_storage_account_name"},
    }
    mocker.patch.object(demisto, "params", return_value=params)
    mocker.patch.object(demisto, "command", return_value="test-module")
    mocker.patch.object(AzureStorageTable, "return_results", return_value=params)

    main()

    assert "ok" in AzureStorageTable.return_results.call_args[0][0]
    qs = get_mock.last_request.qs
    assert (client_id and qs["client_id"] == [client_id]) or "client_id" not in qs