Skip to content

Add ndx CLI for Portal Backend management, with OIDC discovery and named profiles #549

Description

@mushrafmim

Problem

Operators of OpenNDX (Portal Backend) have no way to manage members, schemas, applications, and application policies except by hand-crafting authenticated HTTP calls against Portal Backend's API - there's no CLI, and no browser-based operator login.

On top of that gap, a first cut at such a CLI still forces an operator to retype a full set of identity-provider flags (--auth-url, --token-url, --client-id, --scopes, --callback-port) on every login, even though:

  • Most OIDC-compliant identity providers publish their authorization_endpoint/token_endpoint via a standard discovery document, so only a base issuer URL should be needed.
  • Every environment this CLI targets (local ThunderID, an Asgardeo tenant, a partner's deployment) needs the same set of values repeated verbatim on every invocation, with no way to save and switch between them.

Proposed Solution

Add ndx, a Go CLI for OpenNDX management operations against Portal Backend:

  • cmd/cli - entry point wiring ndx login, ndx members create, ndx schemas create, ndx applications create/list/get, and ndx policy update.
  • internal/cli/auth - browser-based OAuth2 Authorization Code + PKCE login (RFC 8252), local token cache with refresh, and OIDC Discovery support: an --issuer/NDX_ISSUER flag that derives --auth-url/--token-url from {issuer}/.well-known/openid-configuration, so standards-compliant IDPs only need a base URL (explicit --auth-url/--token-url still work and take precedence for IDPs that don't serve discovery at the standard path).
  • internal/cli/pbclient - a Portal Backend API client for the management operations above, reusing internal/pb/v1/models types.
  • internal/cli/profile - named profiles (ndx profile list/use/set) bundling issuer, client ID, scopes, callback port, Portal Backend URL, and TLS verification per environment, with a built-in local profile matching this repo's ThunderID docker-compose stack so ndx login works with zero flags out of the box. Any explicit flag still overrides the active profile; --profile/NDX_PROFILE selects a profile for a single invocation without changing the default. Each non-default profile gets its own cached-token file so switching profiles can't pick up a token cached against a different identity provider.
  • thunderid/bootstrap/*.yaml - registers the NDX_CLI OAuth2 client, an ndx-admin operator user, and the OpenNDX_Admin role/group needed for ndx login to work end-to-end against the local ThunderID stack.

Alternatives

  • Require every IDP endpoint flag explicitly, with no discovery. Rejected - it works, but is needless friction for every IDP that already publishes a discovery document, and doesn't reduce as new environments are added.
  • Hardcode one IDP's endpoints/client ID into the binary. Rejected - the CLI has to work against any OIDC-compatible IDP Portal Backend is configured to trust (ThunderID locally, Asgardeo elsewhere, potentially others later), and hardcoding would silently break every environment except the one baked in.
  • Configure everything via environment variables only, no profile file. Considered - env vars already work as flag defaults today, but they don't let an operator save and switch between several named environments without re-exporting every variable each time.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions