How to work with Azure Blobs when only Azure CLI installed

To avoid Azure Storage account keys usage and give to user the just enough access that is recommended to use Azure AD authentication and RBAC.

To download or read the blob from Storage Account with Private container, user needs at least “Storage Blob Data Reader” role (even if he is an owner of Storage Account resource)

Azure CLI script example:

subscription_id="00000-0000-0000-0000-00000000"
storage_account_name="<storage-account-name>"
container_name="<container-name>"
blob_path="<blob-name>"
output_file_path="<local-file-name>"

az login
az account set -s $subscription_id
az storage blob download  --account-name "$storage_account_name" \
                          --container-name "$container_name" \
                          --name "$blob_path" \
                          --file "$output_file_path" \
                          --auth-mode login

In Linux you have also Python by default and Python is included with Azure CLI installation (with all Azure, Azure AD, Azure Storage Python modules), following Python script can be used to get the similar to Azure CLI result with Device Login:

import adal

from azure.storage.blob import (
    BlockBlobService, 
    PublicAccess
)
from azure.storage.common import (
    TokenCredential
)

storage_account_name  = "<storage-account-name>"
container_name        = "<container-name>"
blob_path             = "<blob-name>"
output_file_path      = "<local-file-path>"


def get_device_login_token():
    # only for example Azure CLI Application ID
    client_id     = '04b07795-8ddb-461a-bbee-02f9e1bf7b46'
    # Your organisation's Tenant ID which used for RBAC for Storage
    tenant_id     = '<tenant-id>'
    authority_uri = ('https://login.microsoftonline.com/' + tenant_id + '/')
    resource_uri  = 'https://storage.azure.com'

    context = adal.AuthenticationContext(authority_uri, api_version=None)
    code = context.acquire_user_code(resource_uri, client_id)
    print(code['message'])
    mgmt_token = context.acquire_token_with_device_code(resource_uri, code, client_id)

    return TokenCredential(mgmt_token['accessToken'])

block_blob_service = BlockBlobService(
        account_name  = storage_account_name, 
        token_credential  = get_device_login_token()
    )

block_blob_service.get_blob_to_path(container_name, blob_path, output_file_path)

If you use your custom application as Python code then service principal must be registered in the tenant of your organisation. Multi-tenant application ID of Azure CLI is used here as an example, in this case we will see the logins from Python script as from Azure CLI. How to create and register multi-tenant application is explained here: https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-convert-app-to-be-multi-tenant

Python 3.5 Essentials – 1. Output

When you are trying to learn a new language it is always better if you will see a practical real life result. Let’s try to learn Python from zero and develop a chess game.

The first topic to onboard is Output, because it is the only one way for human to get a result of program execution. For our first programs we will use a text output on screen to console (terminal).

For this series of articles I am using Ubuntu 16.04 where Python 2.7.12 and Python 3.5.2 are preinstalled.  I will write an article to make an instructions for using examples on Windows.

To print some text on the screen we should use print() function in Python. You can create chess0.py text file with following code:

print(" abcdefgh ")
print("8RNBQKBNR8")
print("7PPPPPPPP7")
print("6        6")
print("5        5")
print("4        4")
print("3        3")
print("2PPPPPPPP2")
print("1RNBQKBNR1")
print(" abcdefgh ")

To run this code, open console and type following command:

python3 chess0.py

Now, Python 3.5 will interpret your code and print the chessboard on the screen:

 abcdefgh 
8RNBQKBNR8
7PPPPPPPP7
6        6
5        5
4        4
3        3
2PPPPPPPP2
1RNBQKBNR1
 abcdefgh

Usually any console is using monospaced fixed-width fonts, so, all characters should be well aligned.  But i=even if we can understand the figures it does not looks like a chessboard. To make it more realistic we can use escape sequences. Now you can modify your code to add right background colors for chessboard cells:

print("  abcdefgh  ")
print("8 \x1b[38;5;232m\x1b[48;5;231mR\x1b[0m\x1b[38;5;231m\x1b[48;5;232mN\x1b[0m\x1b[38;5;232m\x1b[48;5;231mB\x1b[0m\x1b[38;5;231m\x1b[48;5;232mQ\x1b[0m\x1b[38;5;232m\x1b[48;5;231mK\x1b[0m\x1b[38;5;231m\x1b[48;5;232mB\x1b[0m\x1b[38;5;232m\x1b[48;5;231mN\x1b[0m\x1b[38;5;231m\x1b[48;5;232mR\x1b[0m 8")
print("7 \x1b[38;5;231m\x1b[48;5;232mP\x1b[0m\x1b[38;5;232m\x1b[48;5;231mP\x1b[0m\x1b[38;5;231m\x1b[48;5;232mP\x1b[0m\x1b[38;5;232m\x1b[48;5;231mP\x1b[0m\x1b[38;5;231m\x1b[48;5;232mP\x1b[0m\x1b[38;5;232m\x1b[48;5;231mP\x1b[0m\x1b[38;5;231m\x1b[48;5;232mP\x1b[0m\x1b[38;5;232m\x1b[48;5;231mP\x1b[0m 7")
print("6 \x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m 6")
print("5 \x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m 5")
print("4 \x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m 4")
print("3 \x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m\x1b[38;5;231m\x1b[48;5;232m \x1b[0m\x1b[38;5;232m\x1b[48;5;231m \x1b[0m 3")
print("2 \x1b[38;5;232m\x1b[48;5;231mP\x1b[0m\x1b[38;5;231m\x1b[48;5;232mP\x1b[0m\x1b[38;5;232m\x1b[48;5;231mP\x1b[0m\x1b[38;5;231m\x1b[48;5;232mP\x1b[0m\x1b[38;5;232m\x1b[48;5;231mP\x1b[0m\x1b[38;5;231m\x1b[48;5;232mP\x1b[0m\x1b[38;5;232m\x1b[48;5;231mP\x1b[0m\x1b[38;5;231m\x1b[48;5;232mP\x1b[0m 2")
print("1 \x1b[38;5;231m\x1b[48;5;232mR\x1b[0m\x1b[38;5;232m\x1b[48;5;231mN\x1b[0m\x1b[38;5;231m\x1b[48;5;232mB\x1b[0m\x1b[38;5;232m\x1b[48;5;231mQ\x1b[0m\x1b[38;5;231m\x1b[48;5;232mK\x1b[0m\x1b[38;5;232m\x1b[48;5;231mB\x1b[0m\x1b[38;5;231m\x1b[48;5;232mN\x1b[0m\x1b[38;5;232m\x1b[48;5;231mR\x1b[0m 1")
print("  abcdefgh  ")

Run python3 again:

chess1

Now, it looks nicer but our code became unreadable. How to make it better with help of variables we will cover in the next article.

Congratulations with your first program on Python 3.5!