Skip to content

Commit f6c685b

Browse files
authored
[Confidential Ledger] [DP] Update Readme and sample related to tags (#41672)
* [Confidential Ledger] [DP] Update Readme and sample related to tags
1 parent bea2830 commit f6c685b

File tree

2 files changed

+216
-0
lines changed

2 files changed

+216
-0
lines changed

sdk/confidentialledger/azure-confidentialledger/README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ While most use cases involve just one collection per Confidential Ledger, we pro
9292

9393
Ledger entries are retrieved by their `collectionId`. The Confidential Ledger will always assume a constant, service-determined `collectionId` for entries written without a `collectionId` specified.
9494

95+
### Tags
96+
SDK versions based on `2024-12-09-preview` or newer support tags.
97+
They allow for improved management of data within a collection by acting as secondary keys to a collection of data. Tags are limited to 64 character strings.
98+
9599
### Users
96100
Users are managed directly with the Confidential Ledger instead of through Azure. Users may be AAD-based, identified by their AAD object id, or certificate-based, identified by their PEM certificate fingerprint.
97101

@@ -303,6 +307,54 @@ ranged_result = ledger_client.list_ledger_entries(
303307
for entry in ranged_result:
304308
print(f'Contents at {entry["transactionId"]}: {entry["contents"]}')
305309
```
310+
### Using Collections and Tags
311+
312+
In order to specify a collection ID, the user has to specify the collectionID parameter during write request.
313+
314+
```python
315+
sample_entry = {"contents": "Secret recipe ingredients...!"}
316+
append_result = ledger_client.create_ledger_entry(entry=sample_entry, collection_id="icecream-flavors")
317+
```
318+
The transaction can then be retrieved by specifying the `collection ID` and the `transaction ID` during a read operation or by specifying just the collection ID in `list` operations.
319+
320+
```python
321+
# Get the latest transaction in a collection
322+
get_result = ledger_client.get_ledger_entry(collection_id="icecream-flavors")
323+
```
324+
```python
325+
# Get a specific entry in a collection
326+
list_result = ledger_client.get_ledger_entry(transaction_id=2.68, collection_id="icecream-flavors")
327+
```
328+
```python
329+
# Get all entries in a collection
330+
list_result = ledger_client.list_ledger_entries(collection_id="icecream-flavors")
331+
for entry in list_result:
332+
print(f"Transaction ID: {entry['transactionId']}")
333+
print(f"Contents: {entry['contents']}")
334+
```
335+
336+
It's also possible to get a list of entries within a collection by specifying both the collection ID and a range of Transaction ID parameters.
337+
338+
```python
339+
list_result = ledger_client.list_ledger_entries(from_transaction_id=2.1, to_transaction_id=2.50, collection_id="icecream-flavors")
340+
```
341+
342+
343+
In order to use tags inside a collection, tags parameter needs to be specified.
344+
345+
```python
346+
# multiple tags can be specified using commas.
347+
append_result = ledger_client.create_ledger_entry(entry=sample_entry, collection_id="icecream-flavors", tags="chocolate,vanilla")
348+
```
349+
350+
Retrieving entries can be done as before:
351+
```python
352+
# Get all entries in a collection which has a specified tag. Only one tag is supported per query during a Read operation. Only list/ranged operations are supported with tags.
353+
list_result = ledger_client.list_ledger_entries(collection_id="icecream-flavors", tag="chocolate")
354+
for entry in list_result:
355+
print(f"Transaction ID: {entry['transactionId']}")
356+
print(f"Contents: {entry['contents']}")
357+
```
306358

307359
### Managing users
308360
Users with `Administrator` privileges can manage users of the Confidential Ledger directly with the Confidential Ledger itself. Available roles are `Reader` (read-only), `Contributor` (read and write), and `Administrator` (read, write, and add or remove users).
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# -------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License. See License.txt in the project root for
4+
# license information.
5+
# --------------------------------------------------------------------------
6+
7+
"""
8+
FILE: use_tags.py
9+
DESCRIPTION:
10+
This sample demonstrates how to use tags inside a Confidential Ledger. In this sample, we write
11+
ledger entries to a collection using different tags. Tags may be used to group semantically or
12+
logically related ledger entries within a collection.
13+
USAGE:
14+
python use_tags.py
15+
Set the environment variables with your own values before running the sample:
16+
1) CONFIDENTIALLEDGER_ENDPOINT - the endpoint of the Confidential Ledger.
17+
"""
18+
19+
import logging
20+
import os
21+
import sys
22+
import tempfile
23+
from typing import Any, Dict
24+
25+
from azure.confidentialledger import ConfidentialLedgerClient
26+
from azure.confidentialledger.certificate import (
27+
ConfidentialLedgerCertificateClient,
28+
)
29+
from azure.identity import DefaultAzureCredential
30+
31+
32+
logging.basicConfig(level=logging.ERROR)
33+
LOG = logging.getLogger()
34+
35+
36+
def main():
37+
# Set the values of the client ID, tenant ID, and client secret of the AAD application as
38+
# environment variables:
39+
# AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET, CONFIDENTIALLEDGER_ENDPOINT
40+
try:
41+
ledger_endpoint = os.environ["CONFIDENTIALLEDGER_ENDPOINT"]
42+
except KeyError:
43+
LOG.error(
44+
"Missing environment variable 'CONFIDENTIALLEDGER_ENDPOINT' - "
45+
"please set it before running the example"
46+
)
47+
sys.exit(1)
48+
49+
# Under the current URI format, the ledger id is the first part of the ledger endpoint.
50+
# i.e. https://<ledger id>.confidential-ledger.azure.com
51+
ledger_id = ledger_endpoint.replace("https://", "").split(".")[0]
52+
53+
identity_service_client = ConfidentialLedgerCertificateClient() # type: ignore[call-arg]
54+
ledger_certificate = identity_service_client.get_ledger_identity(ledger_id)
55+
56+
# The Confidential Ledger's TLS certificate must be written to a file to be used by the
57+
# ConfidentialLedgerClient. Here, we write it to a temporary file so that is is cleaned up
58+
# automatically when the program exits.
59+
with tempfile.TemporaryDirectory() as tempdir:
60+
ledger_cert_file = os.path.join(tempdir, f"{ledger_id}.pem")
61+
with open(ledger_cert_file, "w") as outfile:
62+
outfile.write(ledger_certificate["ledgerTlsCertificate"])
63+
64+
print(
65+
f"Ledger certificate has been written to {ledger_cert_file}. "
66+
"It will be deleted when the script completes."
67+
)
68+
69+
# Build a client through AAD
70+
ledger_client = ConfidentialLedgerClient(
71+
ledger_endpoint,
72+
credential=DefaultAzureCredential(),
73+
ledger_certificate_path=ledger_cert_file,
74+
)
75+
76+
print("This Confidential Ledger will contain messages from different senders.")
77+
print(
78+
"We will group ledger entries by the sender of the message. For all client methods "
79+
"that take an optional 'collection_id' parameter, if none is provided, a "
80+
"service-assigned, default collection id will be assigned."
81+
)
82+
83+
# Lets write some entries with tags and collections.
84+
# We will write entries into "messages" collection and add tags to each entry.
85+
86+
transactions = [
87+
{"contents": "Hello from Alice!"},
88+
{"contents": "Hi from Bob!"},
89+
{"contents": "Bye from Alice!"},
90+
{"contents": "Bye from Bob!"}
91+
]
92+
93+
print("Here are the entries being written to the 'messages' collection:")
94+
write_result = ledger_client.create_ledger_entry(collection_id="messages", entry=transactions[0], tags="alice,greeting")
95+
print(f"Transaction ID for Alice's greeting: {write_result['transactionId']}")
96+
write_result = ledger_client.create_ledger_entry(collection_id="messages", entry=transactions[1], tags="bob,greeting")
97+
print(f"Transaction ID for Bob's greeting: {write_result['transactionId']}")
98+
write_result = ledger_client.create_ledger_entry(collection_id="messages", entry=transactions[2], tags="alice,goodbye")
99+
print(f"Transaction ID for Alice's goodbye: {write_result['transactionId']}")
100+
write_result = ledger_client.create_ledger_entry(collection_id="messages", entry=transactions[3], tags="bob,goodbye")
101+
print(f"Transaction ID for Bob's goodbye: {write_result['transactionId']}")
102+
103+
# Lets retrieve all the entries in the collection
104+
list_result = ledger_client.list_ledger_entries(
105+
collection_id="messages"
106+
)
107+
print("Here are the entries in the 'messages' collection:")
108+
for entry in list_result:
109+
print(f"Transaction ID: {entry['transactionId']}")
110+
print(f"Contents: {entry['contents']}")
111+
if 'tags' in entry:
112+
print(f"Tags: {entry['tags']}")
113+
print("-" * 30)
114+
115+
# Now lets retrieve all the entries in the collection that are a "greeting"
116+
list_result = ledger_client.list_ledger_entries(
117+
collection_id="messages", tag="greeting"
118+
)
119+
print("Here are the entries in the 'messages' collection with tag 'greeting':")
120+
for entry in list_result:
121+
print(f"Transaction ID: {entry['transactionId']}")
122+
print(f"Contents: {entry['contents']}")
123+
if 'tags' in entry:
124+
print(f"Tags: {entry['tags']}")
125+
print("-" * 30)
126+
127+
# Let's retrieve all the goodbyes
128+
list_result = ledger_client.list_ledger_entries(
129+
collection_id="messages", tag="goodbye"
130+
)
131+
print("Here are the entries in the 'messages' collection with tag 'goodbye':")
132+
for entry in list_result:
133+
print(f"Transaction ID: {entry['transactionId']}")
134+
print(f"Contents: {entry['contents']}")
135+
if 'tags' in entry:
136+
print(f"Tags: {entry['tags']}")
137+
print("-" * 30)
138+
139+
# Lets retrieve all the entries in the collection that are from Alice
140+
list_result = ledger_client.list_ledger_entries(
141+
collection_id="messages", tag="alice"
142+
)
143+
print("Here are the entries in the 'messages' collection with tag 'alice':")
144+
for entry in list_result:
145+
print(f"Transaction ID: {entry['transactionId']}")
146+
print(f"Contents: {entry['contents']}")
147+
if 'tags' in entry:
148+
print(f"Tags: {entry['tags']}")
149+
print("-" * 30)
150+
151+
# Lets retrieve all the entries in the collection that are from Bob
152+
list_result = ledger_client.list_ledger_entries(
153+
collection_id="messages", tag="bob"
154+
)
155+
print("Here are the entries in the 'messages' collection with tag 'bob':")
156+
for entry in list_result:
157+
print(f"Transaction ID: {entry['transactionId']}")
158+
print(f"Contents: {entry['contents']}")
159+
if 'tags' in entry:
160+
print(f"Tags: {entry['tags']}")
161+
print("-" * 30)
162+
163+
if __name__ == "__main__":
164+
main()

0 commit comments

Comments
 (0)