Skip to content

Repository files navigation

Directory CLI

Command-line client for the IB1 Directory member API. Built to make the API easy to exercise as it grows, and to be drivable by scripts and code agents (machine-readable output, real exit codes, no prompts).

Authenticate either by logging in (browser, authorization-code + PKCE, token cached in the OS keyring) or by pasting a token (--token / DIRECTORY_TOKEN) for short runs and CI.

Install

pip install ib1-directory-cli

For local development from a clone:

pip install -e ".[dev]"   # or: uv sync --extra dev

This installs a directory command.

Configuration

Option Env var Default
--api-url DIRECTORY_API_URL https://directory.core.sandbox.trust.ib1.org
--token DIRECTORY_TOKEN (none)
--organization DIRECTORY_ORGANIZATION (none)
--json pretty-printed

The default API is the sandbox. Point --api-url or DIRECTORY_API_URL at another environment, or at http://localhost:8000 for a locally running API.

Login needs no configuration beyond the API URL. directory login asks the API for its Cognito hosted UI domain, client id and scopes (GET /.well-known/directory-cli). These optional variables override what the API publishes, e.g. against an API that doesn't publish it:

Env var Meaning
DIRECTORY_COGNITO_DOMAIN Hosted UI base URL, e.g. https://<prefix>.auth.<region>.amazoncognito.com
DIRECTORY_COGNITO_CLIENT_ID The public (no-secret) CLI app client id
DIRECTORY_OAUTH_SCOPES Space-separated scopes. Default: whatever the API publishes, else openid email
DIRECTORY_REDIRECT_PORT Default 8400 (must match the client's registered callback)

The API is only asked when DIRECTORY_COGNITO_DOMAIN and DIRECTORY_COGNITO_CLIENT_ID aren't both set.

Login

directory login     # opens a browser, caches the token in your OS keyring
directory logout    # clears the cached token for this API
directory token     # prints a current id token (refreshing if needed)

After directory login, me get / me update use the cached token automatically. Token precedence is --token then DIRECTORY_TOKEN then the keyring cache.

Tokens are cached per API URL, so you can be logged in to several environments at once and --api-url picks which token is used. The Cognito client that issued a token is cached with it, so refreshing the token doesn't call the API.

directory token is the bridge for agents/CI that can't open a browser: a human runs it and passes the value as DIRECTORY_TOKEN. The token is short-lived, so this suits short runs.

Usage

# Read your organisation
directory --token "$ACCESS_TOKEN" me get

# Same, token from the environment, compact JSON for piping
export DIRECTORY_TOKEN=...
directory --json me get | jq .identifier

# Partial update (only the flags you pass are sent — a merge-patch)
directory me update --street-address "1 New Road" --email ops@acme.example
directory me update --country GB --postal-code "AB1 2CD"

Editable fields: --email, --street-address, --locality, --region, --state, --postal-code, --country, --privacy-policy, --data-protection-url.

Organisations (owning more than one)

Most users own a single organisation and need nothing extra. Some own several — for example an energy data provider that also owns an example CAP organisation, which it acts as to generate test certificates. List the ones you own, then pass --organization <identifier> (or set DIRECTORY_ORGANIZATION) on any command to say which one you are acting as.

# List the organisations you own
directory me orgs

# Act as a specific organisation
directory --organization cap12345 me get
directory --organization cap12345 cert sign abc12345 client

# Or set it once for the session
export DIRECTORY_ORGANIZATION=cap12345
directory me get

If you own more than one organisation and don't pass a selector, the API returns an error asking you to pick one. There is no -o short flag for --organization because -o is the output-path flag on ca download and cert download.

Applications

# List your applications (optionally filter by scheme short name)
directory apps list
directory apps list --scheme perseus

# Read one application by identifier
directory apps get abc12345

# Create an application under a scheme (roles are repeatable role identifier URLs)
directory apps create --scheme perseus --title "My App" \
  --role https://registry.trust.ib1.org/scheme/perseus/role/data-provider \
  --home-page-url https://app.example.com

# Create with a data service (title, conforms-to and endpoint-url go together)
directory apps create --scheme perseus --title "My App" \
  --data-service-title "My Feed" \
  --data-service-conforms-to https://standard.example.com \
  --data-service-endpoint-url https://api.example.com

# Partial update (only the flags you pass are sent; --role replaces the whole set)
directory apps update abc12345 --title "Renamed" --support-url https://support.example.com

# Delete (destructive, so --yes is required; the API refuses with 409 if certificates exist)
directory apps delete abc12345 --yes

The publisher on a data service is set by the server to your organisation, so there is no flag for it. Application create/update accept --description, --home-page-url, --support-url, --message-delivery, --role, and the four --data-service-* flags.

Administration

Admin commands require your Cognito account to be in the directory admin group; other users get a 403.

# Onboard a new organisation (creates the org, its scheme membership + role, and the
# officer contacts). The scheme is fixed per environment; the role is a slug within it.
directory admin create-org \
  --legal-name "Acme Ltd" --email contact@acme.example \
  --street-address "1 Main St" --locality London --postal-code "AB1 2CD" \
  --company-number 12345678 --role energy-data-provider \
  --data-officer-name "Dana" --data-officer-email dana@acme.example \
  --licence-officer-name "Lee" --licence-officer-phone "+441234567890"

# Add a user to an organisation and send them a Cognito invite (they become an owner)
directory admin add-member <organization-identifier> --email new.owner@acme.example

Each officer needs an email or a phone. --region and --effective-date (ISO YYYY-MM-DD, default today) are optional. Onboarding = create-org, then add-member for each owner.

Certificates

# Sign a certificate for an application. With no --csr, a private key and CSR are
# generated locally; the key is written to disk (mode 0600) and the signed cert saved.
directory cert sign abc12345 client
# → my-app writes abc12345-client-key.pem and abc12345-client-cert.pem, prints the cert id

# Use your own CSR instead of generating one (no key is written):
directory cert sign abc12345 signing --csr my.csr --cert-out signing.pem

# Download a certificate by id (default filename comes from the server)
directory cert download <certificate-id> -o cert.pem

# Revoke a certificate (destructive, so --yes is required; this is a soft revoke)
directory cert revoke <certificate-id> --yes

cert sign takes the application identifier and the type (client or signing). The CA forces the certificate subject to your organisation regardless of the CSR, so a generated CSR's subject does not matter. Download the CA root/intermediate bundle with directory ca download <client|signing>.

Exit codes

Code Meaning
0 Success
1 API or transport error (4xx/5xx, connection failure)
2 Usage error (no token, update with no fields, delete without --yes, login against an API that publishes no login configuration)

Prerequisites for login (one-time, out of this repo)

Interactive login needs a public Cognito app client on the existing user pool:

  • no client secret
  • authorization-code grant with PKCE
  • callback URL http://localhost:8400/callback (the exact port must match DIRECTORY_REDIRECT_PORT)
  • scopes openid email

The API it logs in to must then be configured with:

  • COGNITO_ALLOWED_CLIENT_IDS including the client id, so the API accepts tokens it issues
  • COGNITO_DOMAIN and COGNITO_CLI_CLIENT_ID, so the API publishes them at /.well-known/directory-cli for the CLI to discover

These are deploy/infra steps (AWS and the deployments repo), not part of the CLI.

Tests

pip install -e ".[dev]"   # or: uv sync --extra dev
pytest                     # or: uv run pytest

About

Command-line client for the IB1 Directory member API

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages