Skip to content
Draft
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
5 changes: 0 additions & 5 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ on:
required: false
type: string
description: "Override the version of the dir Helm chart to install for the tests."
dirctl_image_tag:
required: false
type: string
description: "Override the tag of the dir-ctl Docker image to use in the tests."

permissions:
contents: write
Expand Down Expand Up @@ -90,7 +86,6 @@ jobs:
uses: ./.github/workflows/reusable-test-sdk.yaml
with:
dir_chart_version: ${{ inputs.dir_chart_version }}
dirctl_image_tag: ${{ inputs.dirctl_image_tag }}

release:
name: Release
Expand Down
7 changes: 0 additions & 7 deletions .github/workflows/reusable-test-sdk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ on:
required: false
type: string
description: "Override the version of the dir Helm chart to install for the tests."
dirctl_image_tag:
required: false
type: string
description: "Override the tag of the dir-ctl Docker image to use in the tests."
sdk_ref:
required: false
type: string
Expand Down Expand Up @@ -62,14 +58,11 @@ jobs:
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0

- name: Add dependencies for SDKs testing
env:
CLIENT_ID: "https://github.com/agntcy/dir-sdk-python/.github/workflows/reusable-test-sdk.yaml@${{ steps.sdk-ref.outputs.ref }}"
run: |
task deps:cicd:iodc-token-generation >> $GITHUB_ENV

- name: Test Python SDK
env:
DIR_CHART_VERSION: ${{ inputs.dir_chart_version }}
DIRCTL_IMAGE_TAG: ${{ inputs.dirctl_image_tag }}
run: |
task test
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ The Directory Python SDK provides comprehensive access to all Directory APIs wit
- **Network Management**: Unpublish records to remove them from network discovery

### **Signing and Verification**
- **Local Signing**: Sign records locally using private keys or OIDC-based authentication.
Requires [dirctl](https://github.com/agntcy/dir/releases) binary to perform signing.
- **Remote Verification**: Verify record signatures using the Directory gRPC API
- **Local Signing**: Sign records locally using private keys or OIDC-based authentication via native Sigstore support
- **Local Verification**: Verify record signatures locally or using the Directory gRPC API

### **Developer Experience**
- **Type Safety**: Full type hints for better IDE support and fewer runtime errors
Expand Down Expand Up @@ -59,7 +58,6 @@ The SDK can be configured via environment variables or direct instantiation:
```python
# Environment variables (insecure mode, default)
export DIRECTORY_CLIENT_SERVER_ADDRESS="localhost:8888"
export DIRCTL_PATH="/path/to/dirctl"

# Environment variables (X.509 authentication)
export DIRECTORY_CLIENT_SERVER_ADDRESS="localhost:8888"
Expand All @@ -78,14 +76,12 @@ from agntcy.dir_sdk.client import Config, Client
# Insecure mode (default, for development only)
config = Config(
server_address="localhost:8888",
dirctl_path="/usr/local/bin/dirctl"
)
client = Client(config)

# X.509 authentication with SPIRE
x509_config = Config(
server_address="localhost:8888",
dirctl_path="/usr/local/bin/dirctl",
spiffe_socket_path="/tmp/agent.sock",
auth_mode="x509"
)
Expand All @@ -94,7 +90,6 @@ x509_client = Client(x509_config)
# JWT authentication with SPIRE
jwt_config = Config(
server_address="localhost:8888",
dirctl_path="/usr/local/bin/dirctl",
spiffe_socket_path="/tmp/agent.sock",
auth_mode="jwt",
jwt_audience="spiffe://example.org/dir-server"
Expand Down Expand Up @@ -223,7 +218,6 @@ Common gRPC status codes:

- Python 3.10 or higher
- [uv](https://github.com/astral-sh/uv) - Package manager
- [dirctl](https://github.com/agntcy/dir/releases) - Directory CLI binary
- Directory server instance (see setup below)

### 1. Server Setup
Expand Down
19 changes: 1 addition & 18 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ version: "3"

vars:
DIR_CHART_VERSION: '{{ .DIR_CHART_VERSION | default "v1.5.0" }}'
DIRCTL_IMAGE_TAG: '{{ .DIRCTL_IMAGE_TAG | default "v1.5.0" }}'

# renovate: datasource=github-releases depName=renovatebot/renovate versioning=semver
RENOVATE_VERSION: "43.227.1"

Expand Down Expand Up @@ -68,7 +66,6 @@ tasks:
- defer: { task: test-env:delete }
- task: test-env:create
- |
export DIRCTL_IMAGE_TAG="{{ .DIRCTL_IMAGE_TAG }}"
export COSIGN_PATH="$(printf "%s" "${COSIGN_PATH:-{{ .COSIGN_BIN }}}")"

# Run SDK tests
Expand All @@ -84,7 +81,6 @@ tasks:
deps:
- task: deps:uv
- task: deps:cosign
- task: deps:dir-ctl
cmds:
- "{{.UV_BIN}} sync --all-packages"

Expand Down Expand Up @@ -381,17 +377,6 @@ tasks:
status:
- test -x {{.COSIGN_BIN}}

deps:dir-ctl:
desc: Install dir-ctl
internal: true
run: once
vars:
DIRCTL_IMAGE_TAG: "{{ .DIRCTL_IMAGE_TAG }}"
preconditions:
- which docker
cmds:
- docker image pull ghcr.io/agntcy/dir-ctl:{{ .DIRCTL_IMAGE_TAG }}

deps:renovate:
desc: Install Renovate
internal: true
Expand Down Expand Up @@ -422,8 +407,6 @@ tasks:

deps:cicd:iodc-token-generation:
desc: Get Fulcio OIDC token for CICD
requires:
vars: [CLIENT_ID]
cmds:
- |
OIDC_TOKEN=$(curl -s -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
Expand All @@ -433,5 +416,5 @@ tasks:
PROVIDER_URL="https://token.actions.githubusercontent.com"

echo "OIDC_PROVIDER_URL=${PROVIDER_URL}"
echo "CLIENT_ID=${CLIENT_ID}"
echo "OIDC_CLIENT_ID=sigstore"
echo "OIDC_TOKEN=${OIDC_TOKEN}"
2 changes: 1 addition & 1 deletion dir-sdk-python/agntcy/dir_sdk/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def __init__(self, config: Config | None = None) -> None:
self.routing_service = RoutingService(self.routing_client, logger)
self.publication_service = PublicationService(self.publication_client, logger)
self.search_service = SearchService(self.search_client, logger)
self.sign_service = SignService(self.config, self.sign_client, logger)
self.sign_service = SignService(self.store_service, self.sign_client, logger)
self.sync_service = SyncService(self.sync_client, logger)
self.event_service = EventService(self.event_client, logger)
self.naming_service = NamingService(self.naming_client, logger)
Expand Down
89 changes: 0 additions & 89 deletions dir-sdk-python/agntcy/dir_sdk/client/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,69 +30,8 @@ def _parse_comma_scopes(value: str | list[str] | None, default: list[str]) -> li
return [s.strip() for s in value.split(",") if s.strip()]


class DockerConfig:
"""
A class for using dirctl via the Docker image.
"""

DEFAULT_DIRCTL_IMAGE = "ghcr.io/agntcy/dir-ctl"
DEFAULT_DIRCTL_IMAGE_TAG = "latest"

def __init__(
self,
dirctl_image: str = DEFAULT_DIRCTL_IMAGE,
dirctl_image_tag: str = DEFAULT_DIRCTL_IMAGE_TAG,
envs: dict[str, str] | None = None,
mounts: list[str] | None = None,
user: str | None = None,
) -> None:
if envs is None:
envs = {}
if mounts is None:
mounts = []

self.dirctl_image = dirctl_image
self.dirctl_image_tag = dirctl_image_tag
self.envs: dict[str, str] = envs
self.mounts: list[str] = mounts
self.user = user

def get_commands(self) -> list[str]:
self.prune_mounts()
commands = [
"docker",
"container",
"run",
"--name=dir-ctl",
"--rm",
"--network",
"host",
]
if self.user:
commands.extend(["--user", self.user])
for key, val in self.envs.items():
commands.append("--env")
commands.append(f"{key}={val}")
for mount in self.mounts:
commands.append("--mount")
commands.append(mount)
commands.append(f"{self.dirctl_image}:{self.dirctl_image_tag}")
return commands

def prune_mounts(self) -> None:
mounts = []
for mount in self.mounts:
if mount.startswith("type=bind"):
type, src, dst = mount.split(",")
_, src = src.split("=")
if os.path.isfile(src):
mounts.append(mount)
self.mounts = mounts


class Config:
DEFAULT_SERVER_ADDRESS = "127.0.0.1:8888"
DEFAULT_DIRCTL_PATH = "dirctl"
DEFAULT_SPIFFE_SOCKET_PATH = ""
DEFAULT_AUTH_MODE = ""
DEFAULT_AUTH_TOKEN: str = ""
Expand All @@ -114,7 +53,6 @@ class Config:
def __init__(
self,
server_address: str = DEFAULT_SERVER_ADDRESS,
dirctl_path: str | None = DEFAULT_DIRCTL_PATH,
spiffe_socket_path: str = DEFAULT_SPIFFE_SOCKET_PATH,
auth_mode: str = DEFAULT_AUTH_MODE,
auth_token: str = DEFAULT_AUTH_TOKEN,
Expand All @@ -132,10 +70,8 @@ def __init__(
oidc_auth_timeout: float = DEFAULT_OIDC_AUTH_TIMEOUT,
oidc_scopes: list[str] | None = None,
oidc_access_token: str | None = None,
docker_config: DockerConfig | None = None,
) -> None:
self.server_address = server_address
self.dirctl_path = dirctl_path
self.spiffe_socket_path = spiffe_socket_path
resolved_auth_token = auth_token or oidc_access_token or ""
self.auth_token = resolved_auth_token
Expand All @@ -159,33 +95,10 @@ def __init__(
if oidc_scopes is not None
else list(Config.DEFAULT_OIDC_SCOPES)
)
self.docker_config = docker_config
if dirctl_path and docker_config:
raise ValueError("You cannot specify both dirctl_path and docker_config.")

def get_dirctl(self) -> list[str]:
if self.dirctl_path:
return [self.dirctl_path]
if self.docker_config is None:
msg = "Either dirctl_path or docker_config must be configured"
raise ValueError(msg)
return self.docker_config.get_commands()

@staticmethod
def load_from_env(env_prefix: str = "DIRECTORY_CLIENT_") -> "Config":
"""Load configuration from environment variables."""
dirctl_path = os.environ.get("DIRCTL_PATH")
dirctl_image = os.environ.get("DIRCTL_IMAGE")
dirctl_image_tag = os.environ.get("DIRCTL_IMAGE_TAG")

docker_config = None
if dirctl_image or dirctl_image_tag:
docker_config = DockerConfig(
dirctl_image or DockerConfig.DEFAULT_DIRCTL_IMAGE,
dirctl_image_tag or DockerConfig.DEFAULT_DIRCTL_IMAGE_TAG,
user="0:0",
)

server_address = os.environ.get(
f"{env_prefix}SERVER_ADDRESS",
Config.DEFAULT_SERVER_ADDRESS,
Expand Down Expand Up @@ -257,7 +170,6 @@ def load_from_env(env_prefix: str = "DIRECTORY_CLIENT_") -> "Config":

return Config(
server_address=server_address,
dirctl_path=dirctl_path,
spiffe_socket_path=spiffe_socket_path,
auth_mode=auth_mode,
auth_token=auth_token,
Expand All @@ -274,5 +186,4 @@ def load_from_env(env_prefix: str = "DIRECTORY_CLIENT_") -> "Config":
oidc_callback_port=oidc_callback_port,
oidc_auth_timeout=oidc_auth_timeout,
oidc_scopes=oidc_scopes,
docker_config=docker_config,
)
9 changes: 0 additions & 9 deletions dir-sdk-python/agntcy/dir_sdk/client/dirctl/__init__.py

This file was deleted.

74 changes: 0 additions & 74 deletions dir-sdk-python/agntcy/dir_sdk/client/dirctl/runner.py

This file was deleted.

Loading
Loading