Skip to content

feat(etcd): periodic auth token refresh to prevent expiry - #763

Open
okaybase wants to merge 5 commits into
api7:mainfrom
okaybase:etcd-token
Open

feat(etcd): periodic auth token refresh to prevent expiry#763
okaybase wants to merge 5 commits into
api7:mainfrom
okaybase:etcd-token

Conversation

@okaybase

@okaybase okaybase commented Jul 14, 2026

Copy link
Copy Markdown

Summary

The etcd auth token acquired at connect time was never refreshed. Once it expired (default 300s --auth-token-ttl), every subsequent Admin API write and etcd watch operation failed with etcdserver: invalid auth token.

Changes

  • aisix-etcd: add start_token_refresh_task — a background Tokio task that calls Client::refresh_token on a configurable interval (default 240s, leaving a 60s margin below etcd's default 300s TTL). No-ops when no credentials are configured, or when called outside a Tokio runtime.
  • aisix-core: add EtcdConfig.auth_token_refresh_secs field (default 240). Documented in config.example.yaml and config.managed.yaml.
  • aisix-server: thread auth_token_refresh_secs from config through EtcdConfigProvider::connect and EtcdConfigStore::new.
  • aisix-admin: EtcdConfigStore::new now spawns the refresh task for the admin write-path client, preventing Admin API writes from failing after token expiry.
  • Dependency: bump etcd-client from 0.14 to 0.19 to pick up Client::refresh_token and the merged WatchStream (no longer requires a separate Watcher handle).
  • Tests: add admin_write_survives_token_expiry and token_refresh_prevents_auth_expiry regression tests against an auth-enabled etcd with a 5s TTL, exercising the refresh loop.
  • CI: add etcd-auth service container (short TTL) and "Enable auth on etcd-auth" step to run the token-refresh tests.

Verification

  • cargo test --workspace passes
  • cargo clippy --workspace -- -D warnings clean
  • CI rust-unit job runs the new token-refresh tests against the auth-enabled etcd container
  • Manual: start gateway with etcd.user + password_env, verify Admin API writes still succeed after 5+ minutes

Summary by CodeRabbit

  • New Features

    • Added configurable etcd authentication-token refresh intervals.
    • Tokens refresh automatically to keep authenticated connections available beyond token expiry.
    • The default refresh interval is 240 seconds and can be overridden in configuration.
    • Added retry handling for temporary refresh failures.
  • Bug Fixes

    • Improved reliability for authenticated admin requests and watch operations.
  • Tests

    • Added integration coverage for token refresh, authentication expiry, and authenticated watch events.

@CLAassistant

CLAassistant commented Jul 14, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fbf54329-72c0-4caa-a982-483076ea26a4

📥 Commits

Reviewing files that changed from the base of the PR and between b3a1a3c and 01d1d9d.

📒 Files selected for processing (2)
  • crates/aisix-admin/tests/etcd_integration.rs
  • crates/aisix-etcd/src/etcd_provider.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/aisix-admin/tests/etcd_integration.rs
  • crates/aisix-etcd/src/etcd_provider.rs

📝 Walkthrough

Walkthrough

The change adds configurable etcd authentication-token refresh, updates provider and application wiring, upgrades etcd-client, adds authenticated integration tests, and provisions an auth-enabled etcd service in CI.

Changes

etcd authentication refresh

Layer / File(s) Summary
Refresh configuration contract
Cargo.toml, crates/aisix-core/src/config.rs, config*.yaml
Adds auth_token_refresh_secs with a default of 240 seconds, YAML override coverage, documented examples, and updates etcd-client to 0.19.
Provider refresh and watch behavior
crates/aisix-etcd/src/etcd_provider.rs, crates/aisix-etcd/src/lib.rs, crates/aisix-etcd/tests/watch_integration.rs
Adds configurable background token refresh, updates provider signatures and exports, adjusts watch-stream ownership, and tests refresh across token expiry.
Application and admin-store wiring
crates/aisix-server/src/main.rs, crates/aisix-server/src/export/mod.rs, crates/aisix-admin/src/etcd_store.rs, crates/aisix-admin/tests/etcd_integration.rs, crates/aisix-admin/Cargo.toml
Passes refresh configuration through server and admin-store construction and verifies authenticated admin writes and watches after token expiry.
Authenticated etcd CI environment
.github/workflows/ci.yml
Adds an auth-enabled etcd service, credentials and endpoints, and authentication bootstrap commands for integration tests.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Server
  participant EtcdConfigProvider
  participant EtcdClient
  participant AdminStore
  Server->>EtcdConfigProvider: connect with refresh interval
  EtcdConfigProvider->>EtcdClient: authenticate and start refresh task
  EtcdConfigProvider->>AdminStore: provide connected client
  AdminStore->>EtcdClient: write admin configuration
  EtcdConfigProvider->>EtcdClient: refresh token periodically
Loading
🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the PR's main change: periodic etcd authentication-token refresh to prevent token expiry.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
E2e Test Quality Review ✅ Passed Real etcd E2E tests cover Admin POST/GET and authenticated watch operations after TTL expiry; CI provisions auth etcd, and tests use explicit assertions with isolated prefixes.
Security Check ✅ Passed No security issue found: credentials are read from the environment into ConnectOptions, while refresh logs contain only interval, attempt, and error fields; no secret persistence or authorization/T...
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@moonming

Copy link
Copy Markdown
Collaborator

Thanks for working on this — the underlying issue is real, and periodically refreshing credential-based etcd auth is valuable. The overall direction looks reasonable.

Before this is ready to merge, please address the following blocking items:

  1. Sync with the latest main and restore workspace compilation.
    The current PR changes EtcdConfigProvider::connect_with_policy to take a fifth refresh_secs argument. After combining the PR with the latest main, crates/aisix-server/src/export/mod.rs still calls it with four arguments, and cargo check --workspace fails with E0061. Please update that call (the export path should likely pass None) or preserve the existing API and add a separate refresh-aware method.

  2. Retry promptly after a token-refresh failure.
    The current loop logs a failed refresh and then waits until the next full interval. With the default 240s refresh interval and a 300s token TTL, a transient failure at the first refresh can let the current token expire and leave the process unauthenticated until the next tick (up to roughly 180s after expiry). Please add a short bounded retry/backoff after failures, then return to the normal interval after a successful refresh.

  3. Exercise the authenticated watch path in the regression test.
    token_refresh_prevents_auth_expiry currently waits past the TTL and calls load_all(), so it only verifies a range/get request. Please create/recreate provider.watch(...) after the TTL window, write an event, and assert that the stream receives it. This is especially important because the PR also changes the WatchStream ownership/API while claiming to fix watch operations.

After updating the branch, please ensure the new fork workflow run is approved and actually executes all jobs. The current workflow runs are action_required with no jobs, so CodeRabbit and CLA are currently the only reported checks. At minimum, the updated branch should pass:

cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo check --workspace

Once these items are addressed, this PR should be worth proceeding with.

@okaybase

Copy link
Copy Markdown
Author

@moonming Thanks for the detailed review! All blocking items have been addressed — compilation fix, retry logic, watch path coverage, and sync with main. Please take another look.

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.

3 participants