Skip to content
This repository was archived by the owner on Sep 26, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions README.md

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also at ## Examples tab we can add example referencing to 11_azure_blob_quickstart.py file.

Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,9 @@ pip install chuk-artifacts

**Optional:**
- `redis` - For Redis session provider
- `boto3` - For S3 storage backend
- `ibm-cos-sdk` - For IBM Cloud Object Storage
- `boto3` - For S3 storage backend (automatically installed)
- `ibm-cos-sdk` - For IBM Cloud Object Storage (automatically installed)
- `azure-storage-blob` - For Azure Blob Storage (automatically installed)

---

Expand Down Expand Up @@ -522,6 +523,7 @@ We provide **9 comprehensive examples** covering all features:
7. **[06_session_isolation.py](examples/06_session_isolation.py)** - Session isolation and scoping
8. **[07_large_files_streaming.py](examples/07_large_files_streaming.py)** - Large file handling
9. **[08_batch_operations.py](examples/08_batch_operations.py)** - Batch operations
10. **[11_azure_blob_quickstart.py](examples/11_azure_blob_quickstart.py)** - Azure Blob quickstart

Run any example:

Expand Down Expand Up @@ -716,6 +718,28 @@ export ARTIFACT_PROVIDER=vfs-s3
export AWS_ACCESS_KEY_ID=your_key
export AWS_SECRET_ACCESS_KEY=your_secret
export AWS_DEFAULT_REGION=us-east-1

# Azure Blob Storage (persistent cloud storage)
export ARTIFACT_PROVIDER=azure_blob

# Option 1: Connection String
export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net"

# Option 2: Account Name + Key
export AZURE_STORAGE_ACCOUNT_NAME=your_account
export AZURE_STORAGE_ACCOUNT_KEY=your_key

# Option 3: Azure AD (Recommended for production)
export AZURE_STORAGE_ACCOUNT_NAME=your_account
export AZURE_USE_AD=true
# For service principal (for apps/CICD):
export AZURE_CLIENT_ID=your-client-id
export AZURE_CLIENT_SECRET=your-client-secret
export AZURE_TENANT_ID=your-tenant-id
# Or use Managed Identity (if on Azure VM/AKS/Functions)
# Or use Azure CLI: az login (for local dev)

export ARTIFACT_BUCKET=your-container
```

### Session Providers
Expand Down Expand Up @@ -792,6 +816,17 @@ CHUK Artifacts is designed for high performance:
- Parallel uploads for large files
- Battle-tested at scale

**Azure Blob Storage Provider:**
- Native async Azure SDK
- Multiple authentication methods:
- Account key (connection string or name+key)
- Azure AD (Service Principal, Managed Identity, Azure CLI)
- Compatible with all Azure storage tiers
- Presigned URL support:
- Account Key SAS (requires "Allow Blob public access" setting)
- User Delegation SAS with Azure AD (works without public access setting)
- Production-ready with RBAC and identity-based access

**SQLite Provider:**
- Fast for small to medium workspaces
- Queryable storage with indexes
Expand Down
182 changes: 182 additions & 0 deletions examples/11_azure_blob_quickstart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Azure Blob Storage Quickstart Example

Demonstrates using Azure Blob Storage as the artifact backend.
"""

import asyncio
import os


async def azure_blob_example():
"""Example using Azure Blob Storage provider."""
from chuk_artifacts import ArtifactStore

# Configure Azure Blob Storage
# Credentials should be set in your environment before running this script:
# Option 1: Connection String (recommended)
# export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net"
# Option 2: Account Name + Key
# export AZURE_STORAGE_ACCOUNT_NAME="your_account"
# export AZURE_STORAGE_ACCOUNT_KEY="your_key"

os.environ["ARTIFACT_PROVIDER"] = "azure_blob"
os.environ["ARTIFACT_BUCKET"] = "my-artifacts-container"
os.environ["SESSION_PROVIDER"] = "memory"

# Create store
store = ArtifactStore(
storage_provider="azure_blob",
session_provider="memory",
bucket="my-artifacts-container",
)

print("✓ Connected to Azure Blob Storage")

# Store an artifact
artifact_id = await store.store(
data=b"Hello from Azure!",
mime="text/plain",
summary="Test artifact",
session_id="demo-session",
)
print(f"✓ Stored artifact: {artifact_id}")

# Retrieve it
data = await store.retrieve(artifact_id)
print(f"✓ Retrieved: {data.decode('utf-8')}")

# List files
files = await store.list_files(session_id="demo-session")
print(f"✓ Found {len(files)} file(s) in session")

# Delete
await store.delete(artifact_id)
print("✓ Deleted artifact")

print("\n✅ Azure Blob Storage example complete!")


async def azure_with_programmatic_config():
"""Example using programmatic configuration."""
from chuk_artifacts import ArtifactStore

# Programmatic configuration (no environment variables needed)
_ = ArtifactStore(
storage_provider="azure_blob",
session_provider="memory",
bucket="my-container",
# Azure credentials can be passed via environment or connection string
)

print("✓ Created store with programmatic config")


async def azure_with_azure_ad():
"""Example using Azure AD authentication."""
from chuk_artifacts import ArtifactStore

# Azure AD configuration (no account key needed!)
os.environ["ARTIFACT_PROVIDER"] = "azure_blob"
os.environ["AZURE_STORAGE_ACCOUNT_NAME"] = "your_account"
os.environ["AZURE_USE_AD"] = "true"

# Option 1: Service Principal (for applications)
# os.environ["AZURE_CLIENT_ID"] = "your-client-id"
# os.environ["AZURE_CLIENT_SECRET"] = "your-client-secret"
# os.environ["AZURE_TENANT_ID"] = "your-tenant-id"

# Option 2: Managed Identity (if running on Azure VM/AKS/Functions)
# No credentials needed - identity is automatic!

# Option 3: Azure CLI (for local development)
# Just run: az login

os.environ["ARTIFACT_BUCKET"] = "my-artifacts-container"
os.environ["SESSION_PROVIDER"] = "memory"

store = ArtifactStore(
storage_provider="azure_blob",
session_provider="memory",
bucket="my-artifacts-container",
)

print("✓ Connected to Azure Blob Storage with Azure AD")

# Store an artifact
artifact_id = await store.store(
data=b"Hello from Azure AD!",
mime="text/plain",
summary="Test artifact",
session_id="demo-session",
)
print(f"✓ Stored artifact: {artifact_id}")

# Generate presigned URL (User Delegation SAS)
# Works WITHOUT "Allow Blob public access" enabled!
presigned = await store.presign(artifact_id, expires=3600)
print(f"✓ Presigned URL generated: {presigned[:80]}...")
print(" (This works without 'Allow Blob public access' setting!)")

# Cleanup
await store.delete(artifact_id)
print("✓ Deleted artifact")

print("\n✅ Azure AD authentication example complete!")


async def main():
"""Run examples."""
print("Azure Blob Storage Examples")
print("=" * 50)

# Check if Azure AD is configured
azure_ad_configured = os.getenv("AZURE_USE_AD", "").lower() == "true"

# Check if account key credentials are set
account_key_configured = bool(
os.getenv("AZURE_STORAGE_CONNECTION_STRING")
or (
os.getenv("AZURE_STORAGE_ACCOUNT_NAME")
and os.getenv("AZURE_STORAGE_ACCOUNT_KEY")
)
)

if not (azure_ad_configured or account_key_configured):
print("\n⚠️ Azure credentials not configured")
print("\nOption 1: Account Key Authentication")
print(" Set AZURE_STORAGE_CONNECTION_STRING or")
print(" AZURE_STORAGE_ACCOUNT_NAME + AZURE_STORAGE_ACCOUNT_KEY")
print("\nOption 2: Azure AD Authentication")
print(" Set AZURE_STORAGE_ACCOUNT_NAME")
print(" Set AZURE_USE_AD=true")
print(" Plus: AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID")
print(" Or: az login (for Azure CLI authentication)")
print("\nTo run this example:")
print(' export AZURE_STORAGE_CONNECTION_STRING="..."')
print(" python examples/11_azure_blob_quickstart.py")
return

try:
if azure_ad_configured:
print("\n🔐 Using Azure AD Authentication\n")
await azure_with_azure_ad()
else:
print("\n🔑 Using Account Key Authentication\n")
await azure_blob_example()
except Exception as e:
print(f"\n❌ Error: {e}")
print("\nMake sure:")
print("1. Azure credentials are correct")
print("2. Container exists or you have permission to create it")
print("3. azure-storage-blob and azure-identity packages are installed")
if azure_ad_configured:
print("4. Azure AD identity has proper RBAC roles:")
print(" - Storage Blob Data Contributor")
print(" - Storage Blob Delegator (for presigned URLs)")


if __name__ == "__main__":
asyncio.run(main())
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ dependencies = [
"chuk-virtual-fs>=0.5.1",
"dotenv>=0.9.9",
"asyncio>=3.4.3",
"azure-storage-blob>=12.19.0",
"azure-identity>=1.15.0",
]

[project.optional-dependencies]
Expand Down
Loading
Loading