Skip to content
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
98 changes: 84 additions & 14 deletions reference/cli/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@ Available since: v4.1.0; expanded in: v4.3.0

For remote operations (operations executed on a remote Harper instance via the `target` parameter), you must provide authentication credentials.

### Authentication Precedence

<VersionBadge type="changed" version="v5.2.0" />

For remote Operations API commands, the CLI uses the first complete authentication source in this order:

1. Dedicated `auth_username=` and `auth_password=` command parameters
2. Credentials embedded in the `target` URL
3. `HARPER_CLI_USERNAME` and `HARPER_CLI_PASSWORD` environment variables
4. Legacy `CLI_TARGET_USERNAME` and `CLI_TARGET_PASSWORD` environment variables
5. A token saved by `harper login`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The list omits a rung. cliOperations.ts resolves seven tiers: after the four basic-credential sources it reads HARPER_CLI_OPERATION_TOKEN/HARPER_CLI_REFRESH_TOKEN (falling back to the CLI_TARGET_* namespace, chosen as a unit) and only then ~/.harperdb/credentials.json. So the env-token tier sits between your #4 and #5.

These vars are new in 5.2 — origin/v5.1 has no OPERATION_TOKEN — and harper login --for-ci prints HARPER_CLI_REFRESH_TOKEN as the durable CI secret. Yet they appear in zero markdown files in this repo, so this page is the only place a reader would look.

Concretely: a CI runner holding both a refresh token and HARPER_CLI_USERNAME/PASSWORD gets basic auth, not the token, and this list can't tell them that. One extra rung plus a sentence naming the vars closes it.

6. `username=` and `password=` operation parameters (legacy fallback)

Credentials are resolved as a pair and are never combined across sources. An incomplete pair supplied with dedicated authentication parameters or in the target URL causes the command to fail. An incomplete environment-variable pair is skipped with a warning so that a saved login token can still be used.

Before v5.2.0, `username=` and `password=` operation parameters took precedence over environment variables and saved login tokens. This could authenticate an operation as the wrong user when those fields were part of the operation payload, such as the user being created by `add_user`.

### Authentication Methods

#### Method 1: Persistent Login (Recommended for Local Development)
Expand Down Expand Up @@ -62,15 +79,23 @@ harper logout https://server.com:9925
- Simplifies frequent remote operations
- No need to maintain environment variables in multiple terminal sessions

A complete environment-variable credential pair takes precedence over a saved login token. Check the [authentication precedence](#authentication-precedence) when a project `.env` file and `harper login` are both configured for the same target.

#### Method 2: Environment Variables (Recommended for CI/CD)

<VersionBadge type="changed" version="v5.2.0" />

The CLI supports loading environment variables from your shell environment (or optionally from a `.env` file in the current directory). This is the recommended method for CI/CD pipelines and for pre-populating the `target` parameter for specific projects.

Starting in v5.2.0, a complete environment-variable credential pair takes precedence over a saved login token and the legacy `username=` and `password=` fallback. This makes the configured CI identity authoritative even when the operation payload also contains username or password fields.

**Supported Variables**:

- `HARPER_CLI_TARGET` (or `CLI_TARGET`) - Sets the default `target` for CLI commands.
- `HARPER_CLI_USERNAME` (or `CLI_TARGET_USERNAME`) - Harper admin username for the target.
- `HARPER_CLI_PASSWORD` (or `CLI_TARGET_PASSWORD`) - Harper admin password for the target.
- `HARPER_CLI_TARGET` - Sets the default `target` for CLI commands. `CLI_TARGET` is the legacy equivalent.
- `HARPER_CLI_USERNAME` and `HARPER_CLI_PASSWORD` - Preferred credential pair for the target.
- `CLI_TARGET_USERNAME` and `CLI_TARGET_PASSWORD` - Lower-priority legacy credential pair.

Each credential namespace is independent. For example, the CLI never combines `HARPER_CLI_USERNAME` with `CLI_TARGET_PASSWORD`. If either namespace supplies only a username or only a password, that incomplete pair is skipped with a warning.

**Example `.env` file**:

Expand All @@ -94,7 +119,6 @@ export HARPER_CLI_PASSWORD=password
- Credentials not visible in command history
- More secure for scripting and CI/CD systems
- Can be set once per session or project directory
- Automatically populated by `harper login`

**Automatic `.env` Updates**:

Expand Down Expand Up @@ -127,31 +151,64 @@ export HARPER_CLI_PASSWORD=$SECURE_PASSWORD # from secret manager
# Execute operations without passing credentials or target (if set)
harper deploy target=https://prod-server.com:9925 replicated=true
harper restart target=https://prod-server.com:9925 replicated=true

# The environment variables authenticate the admin; username/password remain payload fields.
# NEW_USER_PASSWORD is provided by a secret manager.
harper add_user \

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Small hardening thought: the auth credentials here are properly protected, but the new user's password= still lands in argv — "$NEW_USER_PASSWORD" keeps it out of shell history, yet the expanded value is visible in process listings. That's inherent to CLI add_user rather than anything this PR introduces, but since this page is the security guidance, a one-line caveat under these examples would keep it airtight.

role=app \
active=true \
username=svc_app \
password="$NEW_USER_PASSWORD" \
target=https://prod-server.com:9925
```

#### Method 3: Command Parameters
#### Method 3: Dedicated Authentication Parameters

<VersionBadge version="v5.2.0" />

Provide credentials directly as command parameters:
Use `auth_username=` and `auth_password=` to authenticate a single command explicitly. These parameters are used only for transport authentication and are not included in the Operations API request body.

```bash
harper describe_database \
database=dev \
# NEW_USER_PASSWORD is provided by a secret manager.
harper add_user \
role=app \
active=true \
username=svc_app \
password="$NEW_USER_PASSWORD" \
target=https://server.com:9925 \
username=HDB_ADMIN \
password=password
auth_username=HDB_ADMIN \
auth_password="$ADMIN_PASSWORD"
```

**Parameters**:
In this example, `auth_username` and `auth_password` identify the administrator making the request. The plain `username` and `password` fields remain in the `add_user` payload and identify the user being created.

- `username=<username>` - Harper admin username
- `password=<password>` - Harper admin password
**Authentication Parameters**:

- `auth_username=<username>` - Username used to authenticate the request
- `auth_password=<password>` - Password used to authenticate the request

**Cautions**:

- Credentials visible in command history
- Less secure for production environments
- Exposed in process listings
- Not recommended for scripts
- For scripts, prefer environment-variable authentication

#### Legacy `username` and `password` Fallback

<VersionBadge type="changed" version="v5.2.0" />

For backward compatibility, the CLI can use `username=` and `password=` as transport credentials when both are present and no higher-priority source is available:

```bash
harper describe_database \
database=dev \
target=https://server.com:9925 \
username=HDB_ADMIN \
password=password
```

These names are also legitimate payload fields for operations such as `add_user`, `alter_user`, and `create_authentication_tokens`. Use environment variables, a saved login, or the dedicated `auth_` parameters whenever the payload user differs from the user authenticating the request.

### Target Parameter

Expand All @@ -172,6 +229,14 @@ target=http://localhost:9925
target=https://server.example.com:8080
```

The target URL can also contain a complete username and password, which the CLI ranks above environment variables:

```bash
target=https://username:password@server.example.com:9925
```

Percent-encode reserved characters in either value (`@` becomes `%40`, for example). Avoid this form when possible: the URL can be exposed in shell history and process listings, and `harper login` can save its target to the project `.env` file. Prefer environment variables or a saved login for routine use.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This advice can't work against current harper main. WHATWG URL getters return userinfo still percent-encodednew URL('https://admin:p%40ss@host').password === 'p%40ss', and a raw @ gets re-encoded the same way — and the CLI feeds parsedTarget.username/password verbatim into the Basic header (cliOperations.ts:399basicAuthHeader) with no decodeURIComponent anywhere; normalizeTarget preserves the encoding too.

So a real password p@ss goes out as p%40ss and authentication fails — encoded or not, the URL form simply can't carry reserved-character passwords right now. I verified the URL behavior with Node directly. harper#1873's tests don't cover encoded userinfo.

Two ways forward: harper decodes userinfo the way curl does (feasible before 5.2 ships), or this sentence is replaced with an explicit limitation note scoping the URL form to reserved-character-free credentials. Either way it shouldn't ship as-is.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Corroborating this — I verified it independently and it holds.

extractTargetCredentials (bin/cliCredentials.ts:28) returns WHATWG URL.username/.password, which stay percent-encoded, and resolveTransportCredentials passes them verbatim to basicAuthHeader with no decodeURIComponent anywhere on the path. Confirmed in Node: new URL('https://admin:p%40ss@host').password === 'p%40ss', and a raw @ re-encodes to the same thing.

So a password of p@ss goes out as the literal p%40ss and 401s — following this advice causes the failure it claims to prevent, and not following it fails too.

Either harper decodes userinfo before 5.2 ships, or the sentence becomes a limitation note scoping the URL form to credentials without reserved characters. I'd block on it not shipping as written rather than on which of the two fixes you pick.


## Security Best Practices

### 1. Use Environment Variables
Expand Down Expand Up @@ -260,6 +325,11 @@ If you receive authentication errors:
- Ensure the user has permission to execute the operation
- Check user roles and permissions

5. **Clear or override a stale saved token**:
- If a token in `~/.harperdb/credentials.json` expires and cannot be refreshed, the command can fail authentication without trying the legacy `username=` and `password=` fallback because the saved token has higher precedence
- Run `harper logout <target>` and then `harper login <target>` to replace the saved token
- For a one-off command, use a complete environment-variable pair or provide `auth_username=` and `auth_password=` to take precedence over the saved token

### Environment Variable Issues

If environment variables aren't working:
Expand Down
16 changes: 11 additions & 5 deletions reference/cli/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,19 @@ See [Operations API Commands](./operations-api-commands.md) for the complete lis

The CLI can execute operations on remote Harper instances by passing the `target` parameter with the HTTP address of the remote instance.

**Authentication**: Provide credentials via:
### Authentication

- **Persistent Login**: `harper login` to store tokens (recommended for local development)
<VersionBadge type="changed" version="v5.2.0" />

Provide credentials via:

- **Dedicated authentication parameters**: Use `auth_username=<user> auth_password=<pass>` for one-off commands
- **Target URL credentials**: Embed a complete username and password in the URL (supported, but not recommended because URLs are easily exposed)
- **Environment variables and `.env` files**: Use `HARPER_CLI_TARGET`, `HARPER_CLI_USERNAME`, and `HARPER_CLI_PASSWORD` (recommended for CI/CD and project-specific configuration)
- **Parameters**: `username=<user> password=<pass>`
- **Persistent Login**: `harper login` to store tokens (recommended for local development)
- **Legacy parameters**: `username=<user> password=<pass>` remain a fallback when no higher-priority authentication source is available

See [CLI Authentication](./authentication.md) for detailed information on authentication methods and best practices.
Starting in v5.2.0, these sources are resolved in the order shown. See [CLI Authentication](./authentication.md#authentication-precedence) for the complete order, including the preferred and legacy environment-variable namespaces.

**Example: Persistent Login and `.env`**:

Expand All @@ -183,7 +189,7 @@ harper describe_database database=dev target=https://server.com:9925
**Example: CLI Options**:

```bash
harper describe_database database=dev target=https://server.com:9925 username=HDB_ADMIN password=password
harper describe_database database=dev target=https://server.com:9925 auth_username=HDB_ADMIN auth_password="$ADMIN_PASSWORD"
```

## Development Mode
Expand Down
12 changes: 9 additions & 3 deletions reference/components/applications.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,25 @@ harper deploy \
replicated=true
```

Or directly via command parameters (not recommended for production):
### Dedicated Authentication Parameters

<VersionBadge version="v5.2.0" />

For one-off remote commands, dedicated authentication parameters are also available (not recommended for production):

```sh
harper deploy \
project=<name> \
package=<package> \
username=<username> \
password=<password> \
auth_username=<username> \
auth_password=<password> \
target=<remote> \
restart=true \
replicated=true
```

Dedicated authentication parameters take precedence over environment variables and saved login tokens. See [CLI Authentication](../cli/authentication.md#authentication-precedence) for the full order and security guidance.

### Package Sources

When deploying remotely, the `package` field can be any valid npm dependency value:
Expand Down
6 changes: 6 additions & 0 deletions release-notes/v5-lincoln/5.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ Components can now declare recurring jobs in their configuration with a new buil

The `set_configuration` operation now accepts `"replicated": true` to apply a configuration change to all cluster nodes in a single Operations API call, with per-node outcomes reported in the response's `replicated` array. Only cluster-appropriate parameters should be replicated — see [Configuration Operations](/reference/v5/configuration/operations#set-configuration).

## CLI

### Explicit Authentication for Operations API Commands

CLI Operations API commands now accept dedicated `auth_username=` and `auth_password=` parameters, allowing commands such as `add_user` and `alter_user` to authenticate as an administrator while keeping the affected user's `username=` and `password=` in the operation payload. Environment-variable credentials and saved `harper login` tokens now take precedence over the legacy `username=` and `password=` authentication fallback. Credential pairs are also resolved within one environment-variable namespace, preventing a username from `HARPER_CLI_*` from being combined with a password from legacy `CLI_TARGET_*` variables. See [CLI Authentication](/reference/v5/cli/authentication#authentication-precedence).

## HTTP

### Middleware routing and ordering
Expand Down
Loading