Skip to content

Commit d10e62d

Browse files
author
Yalin Li
authored
[Tables] Add AAD sample (#33717)
* Add AAD sample * Update code snippet in README * Run black * Address comments * Remove SNIPPET annotations * Run black
1 parent 92f5634 commit d10e62d

File tree

3 files changed

+105
-43
lines changed

3 files changed

+105
-43
lines changed

sdk/tables/azure-data-tables/README.md

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ The `credential` parameter may be provided in a number of different forms, depen
5555
* Shared Key
5656
* Connection String
5757
* Shared Access Signature Token
58+
* TokenCredential(AAD)(Supported on Storage)
5859

5960
##### Creating the client from a shared key
6061
To use an account [shared key][azure_shared_key] (aka account key or access key), provide the key as a string. This can be found in your storage account in the [Azure Portal][azure_portal_account_url] under the "Access Keys" section or by running the following Azure CLI command:
@@ -64,13 +65,17 @@ az storage account keys list -g MyResourceGroup -n MyStorageAccount
6465
```
6566

6667
Use the key as the credential parameter to authenticate the client:
68+
6769
```python
68-
from azure.core.credentials import AzureNamedKeyCredential
6970
from azure.data.tables import TableServiceClient
71+
from azure.core.credentials import AzureNamedKeyCredential
7072

7173
credential = AzureNamedKeyCredential("my_account_name", "my_access_key")
72-
73-
service = TableServiceClient(endpoint="https://<my_account_name>.table.core.windows.net", credential=credential)
74+
with TableServiceClient(
75+
endpoint="https://<my_account_name>.table.core.windows.net", credential=credential
76+
) as table_service_client:
77+
properties = table_service_client.get_service_properties()
78+
print(f"{properties}")
7479
```
7580

7681
##### Creating the client from a connection string
@@ -92,8 +97,11 @@ Create a client from a connection string:
9297

9398
```python
9499
from azure.data.tables import TableServiceClient
100+
95101
connection_string = "AccountName=<my_account_name>;AccountKey=<my_account_key>;EndpointSuffix=<endpoint_suffix>"
96-
service = TableServiceClient.from_connection_string(conn_str=connection_string)
102+
with TableServiceClient.from_connection_string(conn_str=connection_string) as table_service_client:
103+
properties = table_service_client.get_service_properties()
104+
print(f"{properties}")
97105
```
98106

99107
##### Creating the client from a SAS token
@@ -105,16 +113,38 @@ from azure.data.tables import TableServiceClient, generate_account_sas, Resource
105113
from azure.core.credentials import AzureNamedKeyCredential, AzureSasCredential
106114

107115
credential = AzureNamedKeyCredential("my_account_name", "my_access_key")
116+
# Create a SAS token to use for authentication of a client
108117
sas_token = generate_account_sas(
109118
credential,
110119
resource_types=ResourceTypes(service=True),
111120
permission=AccountSasPermissions(read=True),
112121
expiry=datetime.utcnow() + timedelta(hours=1),
113122
)
114123

115-
table_service_client = TableServiceClient(endpoint="https://<my_account_name>.table.core.windows.net", credential=AzureSasCredential(sas_token))
124+
with TableServiceClient(
125+
endpoint="https://<my_account_name>.table.core.windows.net", credential=AzureSasCredential(sas_token)
126+
) as table_service_client:
127+
properties = table_service_client.get_service_properties()
128+
print(f"{properties}")
116129
```
117130

131+
##### Creating the client from a TokenCredential
132+
Azure Tables provides integration with Azure Active Directory(Azure AD) for identity-based authentication of requests to the Table service when targeting a Storage endpoint. With Azure AD, you can use role-based access control(RBAC) to grant access to your Azure Table resources to users, groups, or applications.
133+
134+
To access a table resource with a TokenCredential, the authenticated identity should have either the "Storage Table Data Contributor" or "Storage Table Data Reader" role.
135+
136+
With the `azure-identity` package, you can seamlessly authorize requests in both development and production environments. To learn more about Azure AD integration in Azure Storage, see the [azure-identity README](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/identity/azure-identity/README.md)
137+
138+
```python
139+
from azure.data.tables import TableServiceClient
140+
from azure.identity import DefaultAzureCredential
141+
142+
with TableServiceClient(
143+
endpoint="https://<my_account_name>.table.core.windows.net", credential=DefaultAzureCredential()
144+
) as table_service_client:
145+
properties = table_service_client.get_service_properties()
146+
print(f"{properties}")
147+
```
118148

119149
## Key concepts
120150
Common uses of the Table service included:
@@ -223,7 +253,7 @@ table_client = TableClient.from_connection_string(conn_str="<connection_string>"
223253
entities = table_client.query_entities(my_filter)
224254
for entity in entities:
225255
for key in entity.keys():
226-
print("Key: {}, Value: {}".format(key, entity[key]))
256+
print(f"Key: {key}, Value: {entity[key]}")
227257
```
228258

229259
## Optional Configuration
@@ -283,7 +313,7 @@ tc = service_client.create_table_if_not_exists(table_name)
283313
try:
284314
service_client.create_table(table_name)
285315
except HttpResponseError:
286-
print("Table with name {} already exists".format(table_name))
316+
print(f"Table with name {table_name} already exists")
287317
```
288318

289319
### Logging

sdk/tables/azure-data-tables/samples/async_samples/sample_authentication_async.py

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* shared access key
1616
* generating a sas token with which the returned signature can be used with
1717
the credential parameter of any TableServiceClient or TableClient
18+
* Azure Active Directory(AAD)
1819
1920
USAGE:
2021
python sample_authentication_async.py
@@ -23,9 +24,13 @@
2324
1) TABLES_STORAGE_ENDPOINT_SUFFIX - the Table service account URL suffix
2425
2) TABLES_STORAGE_ACCOUNT_NAME - the name of the storage account
2526
3) TABLES_PRIMARY_STORAGE_ACCOUNT_KEY - the storage account access key
27+
The following environment variables are required for using azure-identity's DefaultAzureCredential.
28+
For more information, please refer to https://aka.ms/azsdk/python/identity/docs#azure.identity.DefaultAzureCredential
29+
4) AZURE_TENANT_ID - the tenant ID in Azure Active Directory
30+
5) AZURE_CLIENT_ID - the application (client) ID registered in the AAD tenant
31+
6) AZURE_CLIENT_SECRET - the client secret for the registered application
2632
"""
2733

28-
from datetime import datetime, timedelta
2934
import os
3035
import asyncio
3136
from dotenv import find_dotenv, load_dotenv
@@ -41,38 +46,37 @@ def __init__(self):
4146
self.connection_string = f"DefaultEndpointsProtocol=https;AccountName={self.account_name};AccountKey={self.access_key};EndpointSuffix={self.endpoint_suffix}"
4247

4348
async def authentication_by_connection_string(self):
44-
# Instantiate a TableServiceClient using a connection string
49+
print("Instantiate a TableServiceClient using a connection string")
4550
# [START auth_from_connection_string]
4651
from azure.data.tables.aio import TableServiceClient
4752

48-
async with TableServiceClient.from_connection_string(conn_str=self.connection_string) as table_service:
49-
properties = await table_service.get_service_properties()
50-
print(f"Connection String: {properties}")
53+
async with TableServiceClient.from_connection_string(conn_str=self.connection_string) as table_service_client:
54+
properties = await table_service_client.get_service_properties()
55+
print(f"{properties}")
5156
# [END auth_from_connection_string]
5257

5358
async def authentication_by_shared_key(self):
54-
# Instantiate a TableServiceClient using a shared access key
59+
print("Instantiate a TableServiceClient using a shared access key")
5560
# [START auth_from_shared_key]
5661
from azure.data.tables.aio import TableServiceClient
5762
from azure.core.credentials import AzureNamedKeyCredential
5863

5964
credential = AzureNamedKeyCredential(self.account_name, self.access_key)
60-
async with TableServiceClient(endpoint=self.endpoint, credential=credential) as table_service:
61-
properties = await table_service.get_service_properties()
62-
print(f"Shared Key: {properties}")
65+
async with TableServiceClient(endpoint=self.endpoint, credential=credential) as table_service_client:
66+
properties = await table_service_client.get_service_properties()
67+
print(f"{properties}")
6368
# [END auth_from_shared_key]
6469

6570
async def authentication_by_shared_access_signature(self):
66-
# Instantiate a TableServiceClient using a connection string
71+
print("Instantiate a TableServiceClient using a connection string")
6772
# [START auth_by_sas]
73+
from datetime import datetime, timedelta
6874
from azure.data.tables.aio import TableServiceClient
69-
from azure.core.credentials import AzureNamedKeyCredential, AzureSasCredential
70-
71-
# Create a SAS token to use for authentication of a client
7275
from azure.data.tables import generate_account_sas, ResourceTypes, AccountSasPermissions
76+
from azure.core.credentials import AzureNamedKeyCredential, AzureSasCredential
7377

74-
print(f"Account name: {self.account_name}")
7578
credential = AzureNamedKeyCredential(self.account_name, self.access_key)
79+
# Create a SAS token to use for authentication of a client
7680
sas_token = generate_account_sas(
7781
credential,
7882
resource_types=ResourceTypes(service=True),
@@ -82,17 +86,31 @@ async def authentication_by_shared_access_signature(self):
8286

8387
async with TableServiceClient(
8488
endpoint=self.endpoint, credential=AzureSasCredential(sas_token)
85-
) as token_auth_table_service:
86-
properties = await token_auth_table_service.get_service_properties()
87-
print(f"Shared Access Signature: {properties}")
89+
) as table_service_client:
90+
properties = await table_service_client.get_service_properties()
91+
print(f"{properties}")
8892
# [END auth_by_sas]
8993

94+
async def authentication_by_AAD(self):
95+
print("Instantiate a TableServiceClient using a TokenCredential")
96+
# [START auth_from_aad]
97+
from azure.data.tables.aio import TableServiceClient
98+
from azure.identity.aio import DefaultAzureCredential
99+
100+
async with TableServiceClient(
101+
endpoint=self.endpoint, credential=DefaultAzureCredential()
102+
) as table_service_client:
103+
properties = await table_service_client.get_service_properties()
104+
print(f"{properties}")
105+
# [END auth_from_aad]
106+
90107

91108
async def main():
92109
sample = TableAuthSamples()
93110
await sample.authentication_by_connection_string()
94111
await sample.authentication_by_shared_key()
95112
await sample.authentication_by_shared_access_signature()
113+
await sample.authentication_by_AAD()
96114

97115

98116
if __name__ == "__main__":

sdk/tables/azure-data-tables/samples/sample_authentication.py

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* shared access key
1616
* generating a sas token with which the returned signature can be used with
1717
the credential parameter of any TableServiceClient or TableClient
18+
* Azure Active Directory(AAD)
1819
1920
USAGE:
2021
python sample_authentication.py
@@ -23,9 +24,13 @@
2324
1) TABLES_STORAGE_ENDPOINT_SUFFIX - the Table service account URL suffix
2425
2) TABLES_STORAGE_ACCOUNT_NAME - the name of the storage account
2526
3) TABLES_PRIMARY_STORAGE_ACCOUNT_KEY - the storage account access key
27+
The following environment variables are required for using azure-identity's DefaultAzureCredential.
28+
For more information, please refer to https://aka.ms/azsdk/python/identity/docs#azure.identity.DefaultAzureCredential
29+
4) AZURE_TENANT_ID - the tenant ID in Azure Active Directory
30+
5) AZURE_CLIENT_ID - the application (client) ID registered in the AAD tenant
31+
6) AZURE_CLIENT_SECRET - the client secret for the registered application
2632
"""
2733

28-
from datetime import datetime, timedelta
2934
import os
3035
from dotenv import find_dotenv, load_dotenv
3136

@@ -40,39 +45,36 @@ def __init__(self):
4045
self.connection_string = f"DefaultEndpointsProtocol=https;AccountName={self.account_name};AccountKey={self.access_key};EndpointSuffix={self.endpoint_suffix}"
4146

4247
def authentication_by_connection_string(self):
43-
# Instantiate a TableServiceClient using a connection string
48+
print("Instantiate a TableServiceClient using a connection string")
4449
# [START auth_from_connection_string]
4550
from azure.data.tables import TableServiceClient
4651

47-
with TableServiceClient.from_connection_string(conn_str=self.connection_string) as table_service:
48-
properties = table_service.get_service_properties()
49-
print(f"Connection String: {properties}")
52+
with TableServiceClient.from_connection_string(conn_str=self.connection_string) as table_service_client:
53+
properties = table_service_client.get_service_properties()
54+
print(f"{properties}")
5055
# [END auth_from_connection_string]
5156

5257
def authentication_by_shared_key(self):
53-
# Instantiate a TableServiceClient using a shared access key
58+
print("Instantiate a TableServiceClient using a shared access key")
5459
# [START auth_from_shared_key]
5560
from azure.data.tables import TableServiceClient
5661
from azure.core.credentials import AzureNamedKeyCredential
5762

5863
credential = AzureNamedKeyCredential(self.account_name, self.access_key)
59-
with TableServiceClient(endpoint=self.endpoint, credential=credential) as table_service:
60-
properties = table_service.get_service_properties()
61-
print(f"Shared Key: {properties}")
64+
with TableServiceClient(endpoint=self.endpoint, credential=credential) as table_service_client:
65+
properties = table_service_client.get_service_properties()
66+
print(f"{properties}")
6267
# [END auth_from_shared_key]
6368

6469
def authentication_by_shared_access_signature(self):
65-
# Instantiate a TableServiceClient using a shared access signature
66-
70+
print("Instantiate a TableServiceClient using a shared access signature")
6771
# [START auth_from_sas]
68-
from azure.data.tables import TableServiceClient
72+
from datetime import datetime, timedelta
73+
from azure.data.tables import TableServiceClient, generate_account_sas, ResourceTypes, AccountSasPermissions
6974
from azure.core.credentials import AzureNamedKeyCredential, AzureSasCredential
7075

71-
# Create a SAS token to use for authentication of a client
72-
from azure.data.tables import generate_account_sas, ResourceTypes, AccountSasPermissions
73-
74-
print(f"Account name: {self.account_name}")
7576
credential = AzureNamedKeyCredential(self.account_name, self.access_key)
77+
# Create a SAS token to use for authentication of a client
7678
sas_token = generate_account_sas(
7779
credential,
7880
resource_types=ResourceTypes(service=True),
@@ -82,14 +84,26 @@ def authentication_by_shared_access_signature(self):
8284

8385
with TableServiceClient(
8486
endpoint=self.endpoint, credential=AzureSasCredential(sas_token)
85-
) as token_auth_table_service:
86-
properties = token_auth_table_service.get_service_properties()
87-
print(f"Shared Access Signature: {properties}")
87+
) as table_service_client:
88+
properties = table_service_client.get_service_properties()
89+
print(f"{properties}")
8890
# [END auth_from_sas]
8991

92+
def authentication_by_AAD(self):
93+
print("Instantiate a TableServiceClient using a TokenCredential")
94+
# [START auth_from_aad]
95+
from azure.data.tables import TableServiceClient
96+
from azure.identity import DefaultAzureCredential
97+
98+
with TableServiceClient(endpoint=self.endpoint, credential=DefaultAzureCredential()) as table_service_client:
99+
properties = table_service_client.get_service_properties()
100+
print(f"{properties}")
101+
# [END auth_from_aad]
102+
90103

91104
if __name__ == "__main__":
92105
sample = TableAuthSamples()
93106
sample.authentication_by_connection_string()
94107
sample.authentication_by_shared_key()
95108
sample.authentication_by_shared_access_signature()
109+
sample.authentication_by_AAD()

0 commit comments

Comments
 (0)