{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Azure Blob Service Functions\n", "\n", "MSTICpy versions > 0.8.9\n", "\n", "### Description\n", "\n", "This Notebook provides an example of using the Azure Blob Storage features of MSTICpy in order interact with an Azure Blob Storage account.\n", "\n", "You must have msticpy installed to run this notebook:\n", "```\n", "%pip install --upgrade msticpy[azure]\n", "```\n", "\n", "### Installation and imports" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "from msticpy.data.storage import AzureBlobStorage\n", "from msticpy.data import data_obfus as mask" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first step is to initalize the AzureBlobStorage client. Each client is specific to a seperate Azure Blob Storage account and you must pass it the account name when initalizing the client. " ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "abs = AzureBlobStorage(abs_name=\"abscontainer\")\n", "abs.connect()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first step when working with Azure Blob Storage is identifying the container to store blobs in, we can enumerate all the containers in the account with `.containers()`. Note that only containers you have permissons to access will be shown, the Azure Blob Storage features of MSTICpy use the same authentication methods as other Azure service elements and you can specific `auth_methods` when calling `.connect` to select the required authentication method." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Attempting to sign-in with environment variable credentials...\n", "obfuscating columns:\n", "name, etag, \n", "done\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
namelast_modifiedetagpublic_accesshas_immutability_policydeletedversionhas_legal_holdmetadata
0bikjdaerb2020-11-06 21:53:33+00:00rbjkmanljijmqpqmpjcNoneFalseNoneNoneFalseNone
1epfdkmlmqkmqb2020-11-19 15:22:38+00:00ooidklonjqooimbjkpbNoneFalseNoneNoneFalseNone
\n", "
" ], "text/plain": [ " name last_modified etag public_access \\\n", "0 bikjdaerb 2020-11-06 21:53:33+00:00 rbjkmanljijmqpqmpjc None \n", "1 epfdkmlmqkmqb 2020-11-19 15:22:38+00:00 ooidklonjqooimbjkpb None \n", "\n", " has_immutability_policy deleted version has_legal_hold metadata \n", "0 False None None False None \n", "1 False None None False None " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "containers = abs.containers()\n", "display(containers.mp_obf.obfuscate(column_map={\"etag\": \"str\", \"name\":\"str\"}))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also create new containers with `.create_container()`" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
namelast_modifiedetagpublic_accesshas_immutability_policydeletedversionhas_legal_hold
0documenationcontainer2020-11-24 17:40:53+00:00\"0x8D890A0179F6EAA\"NoneFalseNoneNoneFalse
\n", "
" ], "text/plain": [ " name last_modified etag \\\n", "0 documenationcontainer 2020-11-24 17:40:53+00:00 \"0x8D890A0179F6EAA\" \n", "\n", " public_access has_immutability_policy deleted version has_legal_hold \n", "0 None False None None False " ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "abs.create_container(container_name=\"documenationcontainer\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once we have a container we can write blobs to the container. Blob objects can be of any type but here we are passing a simple string." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Upload complete\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "abs.upload_to_blob(blob=\"Here is some test data\", container_name=\"documenationcontainer\", blob_name=\"test-blob\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can list blobs within a container in the same way we listed containers, here you can see the blob we just created." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
namecontainersnapshotversion_idis_current_versionblob_typeencrypted_metadatalast_modifiedetagsize...remaining_retention_dayscreation_timearchive_statusencryption_key_sha256encryption_scoperequest_server_encryptedobject_replication_source_propertiesobject_replication_destination_policytag_counttags
0test-blobdocumenationcontainerNoneNoneNoneBlobType.BlockBlobNone2020-11-24 17:47:41+00:000x8D890A10A6DC6A322...None2020-11-24 17:47:41+00:00NoneNoneNoneNone[]NoneNoneNone
\n", "

1 rows × 34 columns

\n", "
" ], "text/plain": [ " name container snapshot version_id is_current_version \\\n", "0 test-blob documenationcontainer None None None \n", "\n", " blob_type encrypted_metadata last_modified \\\n", "0 BlobType.BlockBlob None 2020-11-24 17:47:41+00:00 \n", "\n", " etag size ... remaining_retention_days \\\n", "0 0x8D890A10A6DC6A3 22 ... None \n", "\n", " creation_time archive_status encryption_key_sha256 \\\n", "0 2020-11-24 17:47:41+00:00 None None \n", "\n", " encryption_scope request_server_encrypted \\\n", "0 None None \n", "\n", " object_replication_source_properties object_replication_destination_policy \\\n", "0 [] None \n", "\n", " tag_count tags \n", "0 None None \n", "\n", "[1 rows x 34 columns]" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "abs.blobs(container_name=\"documenationcontainer\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also return the contents of a blob like so:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "b'Here is some test data'" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "abs.get_blob(container_name=\"documenationcontainer\", blob_name=\"test-blob\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When sharing blobs its often necessary to access a SAS token that allow a user to access a specific blob for a specific amount of time, without having to have explicity permissions on the Azure Blob Storage account.\n", "In the example below we obsfucate the retruned SAS token but it will take the form of a full URL to the blob, with the required SAS token appeneded. By default tokens generated allow access for 7 days but this can be adjusted." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'irrjnoieonelkirmqkerfibemcjbclillbjcncpiooqjklelmqebrambdkjaaqpqirrjnoieonelkirmqkerfibemcjbclillbjcncpiooqjklelmqebrambdkjaaqpqirrjnoieonelkirmqkerfibemcjbclillbjcncpiooqjklelmqebrambdkjaaqpqirrjnoieonelkirmqkerfibemcjbclillbjcncpiooqjklelmqebrambdkjaaqpqirrjnoieonelkirmqkerfibemcjbclillbjcncpiooqjklelmqebrambdkjaaqpq'" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sast = abs.get_sas_token(container_name=\"documenationcontainer\", blob_name=\"test-blob\")\n", "mask.hash_string(sast)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally we can delete a blob, below we delete the blob we just created and then list all blobs in the container, which returns nothing as it is now empty:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "abs.delete_blob(container_name=\"documenationcontainer\", blob_name=\"test-blob\")" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "abs.blobs(container_name=\"documenationcontainer\")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.9" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }