Skip to content

feat(auth): add scoped temporary credentials - #5

Open
acking-you wants to merge 15 commits into
masterfrom
feat/temporary-credential-auth
Open

feat(auth): add scoped temporary credentials#5
acking-you wants to merge 15 commits into
masterfrom
feat/temporary-credential-auth

Conversation

@acking-you

@acking-you acking-you commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Summary

Add expiring, renewable temporary credentials without changing the existing persistent-control and on-demand data-connection topology. The administrator key remains the sole root credential, while temporary credentials can register, connect to, and inspect only their own namespace.

Related Issues

No linked issue.

Change Type

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Build / CI / Release / Scripts

What Changed

  • Add the V2 authenticated encryption frame with directional keys, counters, AAD, replay filtering, stable errors, and optional legacy-protocol acceptance.
  • Add compact server-managed temporary credential slots, encrypted WAL/snapshots, expiry timing wheel, renewal, revocation, GC, safe mode, and root rotation.
  • Isolate temporary credentials through key-scoped namespaces so identical service names do not collide; revoked or expired credentials immediately close active control and data connections.
  • Add administrator CLI commands for credential, service, connection, protocol, status, and reset management with human, JSON, and NDJSON output.
  • Update the Flutter credential input, systemd and Docker defaults, installers, deployment skills, release workflows, and bilingual operator/protocol documentation for v0.4.0.

Verification

  • cargo fmt --all
  • cargo clippy --all-targets -- -D warnings
  • Relevant tests passed
  • Manual verification completed

Commands run:

cargo fmt --all
cargo test --workspace --all-targets
cargo clippy --workspace --all-targets -- -D warnings
bash -n scripts/install-server-github.sh scripts/install-server-gitee.sh scripts/release/entrypoint/pb-mapper.sh

Additional checks:

  • YAML configuration parsing passed for workflows and Docker Compose.
  • Both deployment skills passed quick_validate.py.
  • Flutter static analysis and all 53 widget/unit tests passed in an isolated compatibility checkout. The local Flutter 3.35.1 installation cannot resolve the repository exact toastification dependency, which requires Flutter 3.38 or newer; CI uses Flutter 3.44.9.
  • A fresh server initialization produced a 0700 auth state directory and 0600 administrator-key and instance-ID files.

Compatibility / Risk

  • Upgrade the relay before upgrading register/connect clients because new clients always use V2.
  • v0.4 servers temporarily accept legacy framing by default for rolling upgrades; malformed explicit policy values fail closed, operators should switch to deny after legacy counters reach zero, and temporary credentials are V2-only.
  • An existing /var/lib/pb-mapper-server/msg_header_key is migrated automatically when no new administrator key or environment override exists.
  • Revocation and expiry are intentionally hard failures and terminate all active connections in the affected temporary namespace.

Screenshots / Logs

Not applicable; the user-facing change is limited to credential validation text and the setup flow.

Comment thread src/pb_server/client.rs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 50f54c6b87

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/pb_server/mod.rs Outdated
Comment thread src/common/message/secure.rs Outdated
Comment thread src/common/message/secure.rs Outdated
Comment thread src/pb_server/mod.rs Outdated
Comment thread src/common/auth.rs Outdated
Comment thread src/common/checksum.rs Outdated
Comment thread src/bin/pb-mapper.rs Outdated

@acking-you acking-you left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Review

The slot table, derived secrets, namespace scoping, and WAL-before-expose path are in good shape. Temporary keys cannot reach admin operations, and same-name services in different namespaces do not collide.

Two issues should be fixed before merge: root rotation does not bind the decrypted first frame to the current administrator key, and first-frame replay protection is too weak for non-idempotent admin mutations.

Note on the existing inline comment in src/pb_server/client.rs: subscriber revocation is already raced at the subscribe dispatch site (tokio::select! around handle_client_conn). That path looks correct. Please still add a regression where credential A only connects to a service registered by B, then A is revoked — the current data-stream test uses one credential for both sides.

Suggested test additions

  • In-flight V2 admin handshake that has already sent the prefix / derived the old key, then root-key rotate, then completes the frame: must fail, must not bind the new admin lease.
  • Replay of a captured key issue first frame after the bloom window (or after a relay restart): must not mint a second credential.
  • Cross-credential subscribe revoke, as above.

Comment thread src/common/message/secure.rs
Comment thread src/common/message/secure.rs Outdated
Comment thread tests/regression.rs
Comment thread src/bin/pb-mapper.rs Outdated
Comment thread src/common/auth.rs Outdated
Comment thread src/bin/pb-mapper.rs
Comment thread src/common/auth/runtime.rs Outdated
Comment thread src/common/auth/timing_wheel.rs
Comment thread src/bin/pb-mapper.rs
Comment thread src/common/auth.rs Outdated
Comment thread src/common/auth/timing_wheel.rs Outdated
Comment thread src/common/auth/timing_wheel.rs
Comment thread src/common/auth/actor.rs
Comment thread src/common/auth/persistence.rs
Comment thread src/common/auth/actor.rs Outdated
Comment thread src/common/auth/runtime.rs Outdated
Comment thread src/bin/pb-mapper.rs
Comment thread src/common/auth/actor.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17217795df

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/bin/pb-mapper.rs Outdated
Comment thread src/bin/pb-mapper/admin.rs Outdated
Comment thread ui/native/pb_mapper_ffi/src/state/runtime.rs Outdated
Comment thread src/pb_server/admin.rs Outdated
Comment thread scripts/release/entrypoint/pb-mapper.sh Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 54e28d756c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +76 to +77
if [ ! -s "$ADMIN_KEY_PATH" ] && [ -s "$LEGACY_KEY_PATH" ]; then
install -m 0600 "$LEGACY_KEY_PATH" "$ADMIN_KEY_PATH"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Respect configured keys before installer migration

On an upgrade where /etc/pb-mapper/server.env explicitly supplies a new MSG_HEADER_KEY, the legacy key file still exists, and admin.key does not, this installer copies the legacy key before starting the service. The runtime then gives the newly created admin.key precedence over the environment credential, locking out clients configured with the intended key. The Docker entrypoint's equivalent migration now checks MSG_HEADER_KEY, but both GitHub and Gitee install scripts still omit that guard; leave migration to the runtime or account for the configured environment file.

Useful? React with 👍 / 👎.

),
response_session: None,
})?;
if !valid_checksum(datalen, checksum) || datalen > MAX_MSG_LEN {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate legacy frames against the isolated relay key

When the Flutter embedded relay is running with its isolated app-local administrator key and the UI process has a different outbound credential, this check validates legacy framing with valid_checksum, which reads the process-global credential hash rather than the relay's key loaded immediately above. Consequently, a legacy client using the embedded relay's correct administrator key is rejected before decryption unless the unrelated outbound credential happens to have the same checksum. Compute the legacy checksum from the isolated relay key instead of global process state.

Useful? React with 👍 / 👎.

Comment on lines +44 to +47
const DEFAULT_REPLAY_WINDOW_SECONDS: u64 = 60;
const DEFAULT_REPLAY_FILTER_BYTES: usize = 1024 * 1024;
const MAX_INITIAL_PLAINTEXT_LEN: u32 = 64 * 1024;
const MAX_CONNECTION_CLOCK_SKEW_SECONDS: u64 = 5 * 60;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Retain replay fingerprints for the full timestamp window

The two 60-second Bloom windows forget an accepted first flight after at most 120 seconds, while the same frame remains timestamp-valid for 300 seconds. An on-path observer can therefore wait for the filters to rotate and replay a captured Subcribe request without knowing the credential; for the default non-codec service, the attacker can discard the encrypted setup response and then use the raw forwarded connection to reach the registered service. Make replay retention cover the entire accepted clock-skew interval, or reduce timestamp acceptance to the cache's guaranteed lifetime.

Useful? React with 👍 / 👎.

Comment thread src/common/auth.rs
};

pub const ADMIN_NAMESPACE: u64 = 0;
pub const DEFAULT_AUTH_STATE_DIR: &str = "/var/lib/pb-mapper/auth";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Choose a writable cross-platform authentication directory

When the released macOS or Windows binary is run as a normal user with pb-mapper server --port 7666, the new default attempts to create /var/lib/pb-mapper/auth; on macOS this is a root-owned system location, and the analogous drive-root path on Windows is not a reliable user-writable application directory. Authentication initialization therefore fails before the listener binds, making the default server command unusable on supported non-Linux release targets unless users discover and supply --auth-state-dir. Select a platform-appropriate writable state directory outside Linux system-service deployments.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant