Skip to content

Commit 379c79c

Browse files
feat(dir-sdk-python): migrate latest changes (#8)
Signed-off-by: Bendegúz Csirmaz <csirmazbendeguz@gmail.com>
1 parent 2d2ec9d commit 379c79c

12 files changed

Lines changed: 1279 additions & 54 deletions

File tree

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.13
1+
3.14

README.md

Lines changed: 160 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,60 @@
11
# Directory Python SDK
22

3-
[![Release](https://img.shields.io/github/v/release/agntcy/dir-sdk-python)](CHANGELOG.md)
3+
## Overview
44

5-
## About The Project
6-
7-
The Directory Python SDK provides a simple way to interact with the Directory API.
5+
Dir Python SDK provides a simple way to interact with the Directory API.
86
It allows developers to integrate and use Directory functionality from their Python applications with ease.
97

10-
## Getting Started
8+
## Features
119

12-
To get a local copy up and running follow these simple steps.
10+
The Directory Python SDK provides comprehensive access to all Directory APIs with a simple, intuitive interface:
1311

14-
### Prerequisites
12+
### **Store API**
13+
- **Record Management**: Push records to the store and pull them by reference
14+
- **Metadata Operations**: Look up record metadata without downloading full content
15+
- **Data Lifecycle**: Delete records permanently from the store
16+
- **Referrer Support**: Push and pull artifacts for existing records
17+
- **Sync Management**: Manage storage synchronization policies between Directory servers
1518

16-
- Python 3.10 or higher
17-
- Directory server instance
18-
- [dirctl](https://github.com/agntcy/dir/releases) - Directory CLI binary
19+
### **Search API**
20+
- **Flexible Search**: Search stored records using text, semantic, and structured queries
21+
- **Advanced Filtering**: Filter results by metadata, content type, and other criteria
1922

20-
### Installation
23+
### **Routing API**
24+
- **Network Publishing**: Publish records to make them discoverable across the network
25+
- **Content Discovery**: List and query published records across the network
26+
- **Network Management**: Unpublish records to remove them from network discovery
2127

22-
```sh
23-
uv add agntcy-dir --index https://buf.build/gen/python
28+
### **Signing and Verification**
29+
- **Local Signing**: Sign records locally using private keys or OIDC-based authentication.
30+
Requires [dirctl](https://github.com/agntcy/dir/releases) binary to perform signing.
31+
- **Remote Verification**: Verify record signatures using the Directory gRPC API
32+
33+
### **Developer Experience**
34+
- **Type Safety**: Full type hints for better IDE support and fewer runtime errors
35+
- **Async Support**: Non-blocking operations with streaming responses for large datasets
36+
- **Error Handling**: Comprehensive gRPC error handling with detailed error messages
37+
- **Configuration**: Flexible configuration via environment variables or direct instantiation
38+
39+
## Installation
40+
41+
Install the SDK using [uv](https://github.com/astral-sh/uv)
42+
43+
1. Initialize the project:
44+
```bash
45+
uv init
2446
```
2547

26-
## Usage
48+
2. Add the SDK to your project:
49+
```bash
50+
uv add agntcy-dir --index https://buf.build/gen/python
51+
```
2752

28-
### Configuration
53+
## Configuration
2954

30-
The SDK can be configured either via environment variables:
55+
The SDK can be configured via environment variables or direct instantiation:
3156

32-
```sh
57+
```python
3358
# Environment variables (insecure mode, default)
3459
export DIRECTORY_CLIENT_SERVER_ADDRESS="localhost:8888"
3560
export DIRCTL_PATH="/path/to/dirctl"
@@ -44,11 +69,8 @@ export DIRECTORY_CLIENT_SERVER_ADDRESS="localhost:8888"
4469
export DIRECTORY_CLIENT_AUTH_MODE="jwt"
4570
export DIRECTORY_CLIENT_SPIFFE_SOCKET_PATH="/tmp/agent.sock"
4671
export DIRECTORY_CLIENT_JWT_AUDIENCE="spiffe://example.org/dir-server"
47-
```
48-
49-
Or via a `Config` object:
5072

51-
```python
73+
# Or configure directly
5274
from agntcy.dir_sdk.client import Config, Client
5375

5476
# Insecure mode (default, for development only)
@@ -78,13 +100,92 @@ jwt_config = Config(
78100
jwt_client = Client(jwt_config)
79101
```
80102

81-
### Error Handling
103+
### OAuth 2.0 for Directory Bearer Auth
104+
105+
The Python SDK currently supports these OIDC/OAuth flows for Directory bearer auth:
106+
107+
- Interactive login via Authorization Code + PKCE with a loopback callback
108+
- Pre-issued access token via `DIRECTORY_CLIENT_AUTH_TOKEN`
109+
110+
Interactive PKCE sessions are cached in the same location as the Go client:
111+
`$XDG_CONFIG_HOME/dirctl/auth-token.json` or `~/.config/dirctl/auth-token.json`.
112+
Explicit pre-issued tokens are used directly and are not cached.
113+
114+
Use this mode when your deployment expects a **Bearer access token** on gRPC (for example via a gateway that validates OIDC tokens). Register your IdP application with a **redirect URI** that matches `oidc_redirect_uri` exactly (for example `http://localhost:8484/callback`). The SDK starts a short-lived HTTP server on loopback to receive the authorization redirect.
115+
116+
Some IdPs use **public clients** with PKCE; Authlib may still expect a `client_secret` value in configuration. In that case, use a **random placeholder** from environment variables, not a real secret in source code.
117+
118+
**Important:** The default in-repo Envoy authz stack validates **GitHub** tokens. OIDC access tokens from your IdP provider only work if your environment’s gateway or auth service is configured to accept them.
119+
120+
```bash
121+
export DIRECTORY_CLIENT_AUTH_MODE="oidc"
122+
export DIRECTORY_CLIENT_SERVER_ADDRESS="directory.example.com:443"
123+
export DIRECTORY_CLIENT_OIDC_ISSUER="https://your-idp-provider.example.com"
124+
export DIRECTORY_CLIENT_OIDC_CLIENT_ID="your-app-client-id"
125+
# Optional placeholder for public clients:
126+
export DIRECTORY_CLIENT_OIDC_CLIENT_SECRET="random-non-secret-string"
127+
export DIRECTORY_CLIENT_OIDC_REDIRECT_URI="http://localhost:8484/callback"
128+
# Optional: comma-separated scopes
129+
export DIRECTORY_CLIENT_OIDC_SCOPES="openid,profile,email"
130+
# Optional: override gRPC TLS server name / authority
131+
export DIRECTORY_CLIENT_TLS_SERVER_NAME="directory.example.com"
132+
# Optional: non-interactive use (CI) after obtaining a token elsewhere
133+
export DIRECTORY_CLIENT_AUTH_TOKEN="your-access-token"
134+
# Optional: skip TLS certificate verification for IdP HTTPS only (development; avoid in production)
135+
export DIRECTORY_CLIENT_TLS_SKIP_VERIFY="false"
136+
```
137+
138+
```python
139+
from agntcy.dir_sdk.client import Client, Config, OAuthPkceError
140+
141+
config = Config(
142+
server_address="directory.example.com:443",
143+
auth_mode="oidc",
144+
oidc_issuer="https://your-idp-provider.example.com",
145+
oidc_client_id="your-app-client-id",
146+
oidc_client_secret="random-placeholder-if-required",
147+
oidc_redirect_uri="http://localhost:8484/callback",
148+
oidc_callback_port=8484,
149+
oidc_auth_timeout=300.0,
150+
)
151+
client = Client(config)
152+
# Client construction does not start browser login automatically.
153+
# Opens the system browser and completes PKCE on loopback:
154+
try:
155+
client.authenticate_oauth_pkce()
156+
except OAuthPkceError as e:
157+
print(f"Login failed: {e}")
158+
```
159+
160+
gRPC transport to the Directory still uses **TLS with system trust anchors** (or `tls_ca_file` if set). `TLS_SKIP_VERIFY` applies to **HTTPS calls to the OIDC issuer** (discovery and token endpoint), not to relaxing gRPC TLS to the Directory.
161+
162+
If you need to force the TLS server name / authority used by gRPC, set
163+
`DIRECTORY_CLIENT_TLS_SERVER_NAME`.
164+
165+
For non-interactive callers that already have an access token, skip PKCE entirely:
166+
167+
```python
168+
from agntcy.dir_sdk.client import Client, Config
169+
170+
config = Config(
171+
server_address="directory.example.com:443",
172+
auth_mode="oidc",
173+
auth_token="your-access-token",
174+
)
175+
client = Client(config)
176+
```
177+
178+
If no explicit `auth_token` is provided, the SDK will also try to reuse a valid
179+
cached interactive token from the shared `dirctl` cache path before you need to
180+
run `client.authenticate_oauth_pkce()`.
181+
182+
## Error Handling
82183

83184
The SDK primarily raises `grpc.RpcError` exceptions for gRPC communication issues and `RuntimeError` for configuration problems:
84185

85186
```python
86187
import grpc
87-
from agntcy.dir_sdk.client import Client
188+
from agntcy.dir_sdk.client import Client, OAuthPkceError
88189

89190
try:
90191
client = Client()
@@ -100,6 +201,9 @@ except grpc.RpcError as e:
100201
except RuntimeError as e:
101202
# Handle configuration or subprocess errors
102203
print(f"Runtime error: {e}")
204+
except OAuthPkceError as e:
205+
# Browser / loopback OAuth PKCE flow failed
206+
print(f"OAuth error: {e}")
103207
```
104208

105209
Common gRPC status codes:
@@ -109,27 +213,44 @@ Common gRPC status codes:
109213
- `PERMISSION_DENIED`: Authentication/authorization failure
110214
- `INVALID_ARGUMENT`: Invalid request parameters
111215

112-
_For more examples, please refer to the [Documentation](https://docs.agntcy.org/dir/directory-sdk/#python-sdk) or
113-
the [Wiki](https://github.com/agntcy/dir-sdk-python/wiki)_
114216

115-
## Roadmap
217+
## Getting Started
218+
219+
### Prerequisites
220+
221+
- Python 3.10 or higher
222+
- [uv](https://github.com/astral-sh/uv) - Package manager
223+
- [dirctl](https://github.com/agntcy/dir/releases) - Directory CLI binary
224+
- Directory server instance (see setup below)
225+
226+
### 1. Server Setup
116227

117-
See the [open issues](https://github.com/agntcy/dir-sdk-python/issues) for a list
118-
of proposed features (and known issues).
228+
**Option A: Local Development Server**
119229

120-
## Contributing
230+
```bash
231+
# Clone the repository and start the server using Taskfile
232+
task server:start
233+
```
121234

122-
Contributions are what make the open source community such an amazing place to
123-
learn, inspire, and create. Any contributions you make are **greatly
124-
appreciated**. For detailed contributing guidelines, please see
125-
[CONTRIBUTING.md](CONTRIBUTING.md)
235+
**Option B: Custom Server**
126236

127-
## License
237+
```bash
238+
# Set your Directory server address
239+
export DIRECTORY_CLIENT_SERVER_ADDRESS="your-server:8888"
240+
```
128241

129-
Distributed under the Apache 2.0 License. See [LICENSE](LICENSE) for more
130-
information.
242+
### 2. SDK Installation
131243

132-
## Contact
244+
```bash
245+
# Add the Directory SDK
246+
uv add agntcy-dir --index https://buf.build/gen/python
247+
```
133248

134-
Project Link:
135-
[https://github.com/agntcy/dir-sdk-python](https://github.com/agntcy/dir-sdk-python)
249+
### Usage Examples
250+
251+
See the [Example Python Project](../examples/example-py/) for a complete working example that demonstrates all SDK features.
252+
253+
```bash
254+
uv sync
255+
uv run example.py
256+
```

Taskfile.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ tasks:
3939
4040
sdk:build:python:
4141
desc: Build python client SDK package
42-
dir: ./dir-sdk-python
4342
deps:
4443
- task: sdk:deps:python
4544
cmds:
@@ -60,7 +59,6 @@ tasks:
6059

6160
sdk:test:python:
6261
desc: Test python client SDK package
63-
dir: ./dir-sdk-python
6462
deps:
6563
- task: sdk:deps:python
6664
cmds:
@@ -80,7 +78,6 @@ tasks:
8078
8179
sdk:deps:python:
8280
desc: Install deps for python SDK package
83-
dir: ./dir-sdk-python
8481
deps:
8582
- task: deps:uv
8683
- task: deps:cosign
@@ -91,7 +88,7 @@ tasks:
9188
sdk:deps:python:example:
9289
desc: Install deps for Python SDK example package
9390
internal: true
94-
dir: ./sdk/examples/example-py
91+
dir: ./examples
9592
deps:
9693
- task: deps:uv
9794
cmds:
@@ -105,7 +102,6 @@ tasks:
105102

106103
sdk:release:python:
107104
desc: Release python client SDK package
108-
dir: ./dir-sdk-python
109105
env:
110106
UV_PUBLISH_TOKEN: "{{ .UV_PUBLISH_TOKEN }}"
111107
deps:
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Copyright AGNTCY Contributors (https://github.com/agntcy)
22
# SPDX-License-Identifier: Apache-2.0
33

4-
from .client import Client
5-
from .config import Config
4+
from agntcy.dir_sdk.client.client import Client
5+
from agntcy.dir_sdk.client.config import Config
6+
from agntcy.dir_sdk.client.oauth_pkce import OAuthPkceError as OAuthPkceError

0 commit comments

Comments
 (0)